From 409392d56193ed6e25a5b5cbaf8ad7ecd3c60d89 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 13 Jun 2018 00:33:43 +0200 Subject: [PATCH] WIP: started refactoring the plugin structure. Goal: standalone db module with it's own plugins like LEF/DEF, Gerber, MEBES including GSI bindings. --- src/buddies/src/bd/bd.pro | 6 + src/buddies/src/bd/bdReaderOptions.h | 2 +- src/buddies/unit_tests/unit_tests.pro | 6 + src/db/db/db.pro | 26 +- src/db/db/dbForceLinkStreams.cc | 4 - src/db/db/dbInit.cc | 191 ++++++++ src/db/db/{contrib/dbGDS2Text.h => dbInit.h} | 43 +- src/db/db/dbPlugin.cc | 0 src/db/db/dbPlugin.h | 70 +++ src/db/db/dbTestSupport.cc | 23 +- src/db/unit_tests/dbCIFReader.cc | 6 +- src/db/unit_tests/dbEdgeProcessor.cc | 10 +- src/db/unit_tests/dbOASISWriter.cc | 8 +- src/db/unit_tests/unit_tests.pro | 2 - src/ext/unit_tests/extLEFDEFImport.cc | 7 +- src/klayout_main/klayout_main/klayout.cc | 4 + src/lay/lay/lay.pro | 6 +- src/lay/lay/layApplication.cc | 112 ++--- src/lay/lay/layApplication.h | 27 -- src/lay/lay/layInit.cc | 192 +++++++++ src/lay/lay/layInit.h | 75 ++++ src/lay/lay/layMainWindow.cc | 23 +- src/laybasic/laybasic/layGDS2ReaderPlugin.cc | 195 --------- src/laybasic/laybasic/layGDS2WriterPlugin.cc | 408 ------------------ src/laybasic/laybasic/laybasic.pro | 6 - src/plugins/db_plugin.pri | 9 + src/plugins/lay_plugin.pri | 8 + src/plugins/plugin.pri | 25 -- src/plugins/plugins.pro | 4 +- .../db_plugin}/contrib/dbGDS2Converter.cc | 0 .../gds2/db_plugin}/contrib/dbGDS2Converter.h | 0 .../gds2/db_plugin}/contrib/dbGDS2Text.cc | 3 - .../db_plugin}/contrib/dbGDS2TextReader.cc | 0 .../db_plugin}/contrib/dbGDS2TextReader.h | 0 .../db_plugin}/contrib/dbGDS2TextWriter.cc | 0 .../db_plugin}/contrib/dbGDS2TextWriter.h | 0 .../streamers/gds2/db_plugin}/dbGDS2.cc | 3 - .../streamers/gds2/db_plugin}/dbGDS2.h | 3 - .../streamers/gds2/db_plugin}/dbGDS2Reader.cc | 0 .../streamers/gds2/db_plugin}/dbGDS2Reader.h | 0 .../gds2/db_plugin}/dbGDS2ReaderBase.cc | 0 .../gds2/db_plugin}/dbGDS2ReaderBase.h | 0 .../streamers/gds2/db_plugin}/dbGDS2Writer.cc | 0 .../streamers/gds2/db_plugin}/dbGDS2Writer.h | 0 .../gds2/db_plugin}/dbGDS2WriterBase.cc | 0 .../gds2/db_plugin}/dbGDS2WriterBase.h | 0 .../gds2/lay_plugin}/GDS2ReaderOptionPage.ui | 0 .../gds2/lay_plugin}/GDS2WriterOptionPage.ui | 0 .../gds2/lay_plugin/layGDS2ReaderPlugin.cc | 114 +++++ .../gds2/lay_plugin}/layGDS2ReaderPlugin.h | 0 .../gds2/lay_plugin/layGDS2WriterPlugin.cc | 186 ++++++++ .../gds2/lay_plugin}/layGDS2WriterPlugin.h | 0 .../gds2}/unit_tests/dbGDS2Reader.cc | 22 +- .../gds2}/unit_tests/dbGDS2Writer.cc | 17 +- 54 files changed, 1000 insertions(+), 846 deletions(-) create mode 100644 src/db/db/dbInit.cc rename src/db/db/{contrib/dbGDS2Text.h => dbInit.h} (51%) create mode 100644 src/db/db/dbPlugin.cc create mode 100644 src/db/db/dbPlugin.h create mode 100644 src/lay/lay/layInit.cc create mode 100644 src/lay/lay/layInit.h delete mode 100644 src/laybasic/laybasic/layGDS2ReaderPlugin.cc delete mode 100644 src/laybasic/laybasic/layGDS2WriterPlugin.cc create mode 100644 src/plugins/db_plugin.pri create mode 100644 src/plugins/lay_plugin.pri delete mode 100644 src/plugins/plugin.pri rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2Converter.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2Converter.h (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2Text.cc (96%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2TextReader.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2TextReader.h (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2TextWriter.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/contrib/dbGDS2TextWriter.h (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2.cc (96%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2.h (96%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2Reader.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2Reader.h (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2ReaderBase.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2ReaderBase.h (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2Writer.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2Writer.h (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2WriterBase.cc (100%) rename src/{db/db => plugins/streamers/gds2/db_plugin}/dbGDS2WriterBase.h (100%) rename src/{laybasic/laybasic => plugins/streamers/gds2/lay_plugin}/GDS2ReaderOptionPage.ui (100%) rename src/{laybasic/laybasic => plugins/streamers/gds2/lay_plugin}/GDS2WriterOptionPage.ui (100%) create mode 100644 src/plugins/streamers/gds2/lay_plugin/layGDS2ReaderPlugin.cc rename src/{laybasic/laybasic => plugins/streamers/gds2/lay_plugin}/layGDS2ReaderPlugin.h (100%) create mode 100644 src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc rename src/{laybasic/laybasic => plugins/streamers/gds2/lay_plugin}/layGDS2WriterPlugin.h (100%) rename src/{db => plugins/streamers/gds2}/unit_tests/dbGDS2Reader.cc (98%) rename src/{db => plugins/streamers/gds2}/unit_tests/dbGDS2Writer.cc (98%) diff --git a/src/buddies/src/bd/bd.pro b/src/buddies/src/bd/bd.pro index 1b80e94f2..8040de640 100644 --- a/src/buddies/src/bd/bd.pro +++ b/src/buddies/src/bd/bd.pro @@ -35,6 +35,12 @@ INCLUDEPATH += $$TL_INC $$GSI_INC $$VERSION_INC $$DB_INC $$LIB_INC $$RDB_INC DEPENDPATH += $$TL_INC $$GSI_INC $$VERSION_INC $$DB_INC $$LIB_INC $$RDB_INC LIBS += -L$$DESTDIR -lklayout_tl -lklayout_db -lklayout_gsi -lklayout_lib -lklayout_rdb +PLUGINPATH += \ + $$PWD/../../../plugins/streamers/gds2/db_plugin \ + +INCLUDEPATH += $$PLUGINPATH +DEPENDPATH += $$PLUGINPATH + INCLUDEPATH += $$RBA_INC DEPENDPATH += $$RBA_INC diff --git a/src/buddies/src/bd/bdReaderOptions.h b/src/buddies/src/bd/bdReaderOptions.h index ed4b7a78b..9ff79067d 100644 --- a/src/buddies/src/bd/bdReaderOptions.h +++ b/src/buddies/src/bd/bdReaderOptions.h @@ -24,8 +24,8 @@ #define HDR_bdReaderOptions #include "bdCommon.h" -#include "dbGDS2Reader.h" #include "dbCommonReader.h" +#include "dbGDS2Reader.h" #include "dbOASISReader.h" #include "dbDXFReader.h" #include "dbCIFReader.h" diff --git a/src/buddies/unit_tests/unit_tests.pro b/src/buddies/unit_tests/unit_tests.pro index 928ae46a3..d3147143d 100644 --- a/src/buddies/unit_tests/unit_tests.pro +++ b/src/buddies/unit_tests/unit_tests.pro @@ -20,3 +20,9 @@ INCLUDEPATH += $$BD_INC $$DB_INC $$TL_INC $$GSI_INC DEPENDPATH += $$BD_INC $$DB_INC $$TL_INC $$GSI_INC LIBS += -L$$DESTDIR_UT -lklayout_bd -lklayout_db -lklayout_tl -lklayout_gsi + +PLUGINPATH += \ + $$PWD/../../plugins/streamers/gds2/db_plugin \ + +INCLUDEPATH += $$PLUGINPATH +DEPENDPATH += $$PLUGINPATH diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 3e3e13f88..152c76902 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -35,11 +35,6 @@ SOURCES = \ dbFillTool.cc \ dbForceLinkStreams.cc \ dbFuzzyCellMapping.cc \ - dbGDS2.cc \ - dbGDS2ReaderBase.cc \ - dbGDS2Reader.cc \ - dbGDS2WriterBase.cc \ - dbGDS2Writer.cc \ dbGlyphs.cc \ dbHershey.cc \ dbInstances.cc \ @@ -94,10 +89,6 @@ SOURCES = \ dbVector.cc \ dbWriter.cc \ dbWriterTools.cc \ - contrib/dbGDS2Converter.cc \ - contrib/dbGDS2Text.cc \ - contrib/dbGDS2TextReader.cc \ - contrib/dbGDS2TextWriter.cc \ gsiDeclDbBox.cc \ gsiDeclDbCell.cc \ gsiDeclDbCellMapping.cc \ @@ -132,7 +123,9 @@ SOURCES = \ dbVariableWidthPath.cc \ dbNamedLayerReader.cc \ dbEdgesToContours.cc \ - dbForceLink.cc + dbForceLink.cc \ + dbPlugin.cc \ + dbInit.cc HEADERS = \ dbArray.h \ @@ -163,11 +156,6 @@ HEADERS = \ dbEdgesToContours.h \ dbFillTool.h \ dbFuzzyCellMapping.h \ - dbGDS2.h \ - dbGDS2ReaderBase.h \ - dbGDS2Reader.h \ - dbGDS2WriterBase.h \ - dbGDS2Writer.h \ dbHash.h \ dbHersheyFont.h \ dbHershey.h \ @@ -226,16 +214,14 @@ HEADERS = \ dbVector.h \ dbWriter.h \ dbWriterTools.h \ - contrib/dbGDS2Converter.h \ - contrib/dbGDS2Text.h \ - contrib/dbGDS2TextReader.h \ - contrib/dbGDS2TextWriter.h \ dbCommonReader.h \ dbGlyphs.h \ dbCommon.h \ dbVariableWidthPath.h \ dbNamedLayerReader.h \ - dbForceLink.h + dbForceLink.h \ + dbPlugin.h \ + dbInit.h RESOURCES = \ dbResources.qrc diff --git a/src/db/db/dbForceLinkStreams.cc b/src/db/db/dbForceLinkStreams.cc index 150e318ff..25df4b893 100644 --- a/src/db/db/dbForceLinkStreams.cc +++ b/src/db/db/dbForceLinkStreams.cc @@ -25,17 +25,13 @@ // of the objects by using the macros provided when we build tools from common.a. #include "dbOASIS.h" -#include "dbGDS2.h" #include "dbCIF.h" #include "dbDXF.h" -#include "contrib/dbGDS2Text.h" namespace db { FORCE_LINK_OASIS -FORCE_LINK_GDS2 -FORCE_LINK_GDS2_TXT FORCE_LINK_CIF FORCE_LINK_DXF diff --git a/src/db/db/dbInit.cc b/src/db/db/dbInit.cc new file mode 100644 index 000000000..ac2c28a21 --- /dev/null +++ b/src/db/db/dbInit.cc @@ -0,0 +1,191 @@ + +/* + + 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 "dbInit.h" +#include "dbPlugin.h" +#include "tlException.h" +#include "tlLog.h" +#include "tlString.h" + +#ifdef _WIN32 +# include +#else +# include +#endif + +#include +#include +#include +#include + +namespace db +{ + +static std::list s_plugins; + +const std::list &plugins () +{ + return s_plugins; +} + +static PluginDescriptor load_plugin (const std::string &pp) +{ + PluginDescriptor desc; + desc.path = pp; + + dbp_init_func_t init_func = 0; + static const char *init_func_name = "dbp_init"; + +#if defined(_WIN32) + + // there is no "dlopen" on mingw, so we need to emulate it. + HINSTANCE handle = LoadLibraryW ((const wchar_t *) tl::to_qstring (pp).constData ()); + if (! handle) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to load plugin: %s with error message: %s ")), pp, GetLastError ()); + return; + } + init_func = reinterpret_cast (GetProcAddress (handle, init_func_name)); + +#else + + void *handle; + handle = dlopen (tl::string_to_system (pp).c_str (), RTLD_LAZY); + if (! handle) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to load plugin: %s")), pp); + } + init_func = reinterpret_cast (dlsym (handle, init_func_name)); + +#endif + + // If present, call the initialization function to fetch some details from the plugin + if (init_func) { + const char *version = 0; + const char *description = 0; + (*init_func) (&version, &description); + if (version) { + desc.version = version; + } + if (description) { + desc.description = description; + } + } + + tl::log << tl::sprintf (tl::to_string (QObject::tr ("Loaded plugin: %s")), pp); + return desc; +} + +/** + * @brief Gets the path to the current module + */ +static std::string +get_module_path () +{ +#if defined(_WIN32) + + HMODULE h_module = NULL; + if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR) &init, &h_module)) { + + wchar_t buffer[MAX_PATH]; + int len; + if ((len = GetModuleFileName(h_module, buffer, MAX_PATH)) > 0) { + QFileInfo fi (QString::fromUtf16 ((const ushort *) buffer, len)); + return tl::to_string (fi.absolutePath ()); + } + + } + + // no way to get module file path + return std::string (); + +#else + + Dl_info info = { }; + if (dladdr ((void *) &init, &info)) { + QFileInfo fi (QString::fromLocal8Bit (info.dli_fname)); + return tl::to_string (fi.absolutePath ()); + } else { + return std::string (); + } + +#endif +} + +void init (const std::vector &_paths) +{ + std::vector paths = _paths; + if (paths.empty ()) { + std::string module_path = get_module_path (); + if (! module_path.empty ()) { + paths.push_back (module_path); + } + } + + if (paths.empty ()) { + // nothing to do + return; + } + + std::set modules; + + for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { + + // look next to the db library, but in "db_plugins" directory + const char *db_plugin_dir = "db_plugins"; + std::string pp = tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 (db_plugin_dir))); + + QStringList name_filters; +#if defined(_WIN32) + name_filters << QString::fromUtf8 ("*.dll"); +#else + name_filters << QString::fromUtf8 ("*.so"); +#endif + + QStringList inst_modules = QDir (tl::to_qstring (pp)).entryList (name_filters); + inst_modules.sort (); + + for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { + + QFileInfo dbp_file (tl::to_qstring (pp), *im); + if (dbp_file.exists () && dbp_file.isReadable ()) { + + std::string mn = tl::to_string (dbp_file.fileName ()); + if (modules.find (mn) == modules.end ()) { + + std::string m = tl::to_string (dbp_file.absoluteFilePath ()); + try { + s_plugins.push_back (load_plugin (m)); + modules.insert (mn); + } catch (tl::Exception (&ex)) { + tl::error << ex.msg (); + } + + } + + } + + } + + } +} + +} diff --git a/src/db/db/contrib/dbGDS2Text.h b/src/db/db/dbInit.h similarity index 51% rename from src/db/db/contrib/dbGDS2Text.h rename to src/db/db/dbInit.h index fdd78d089..11f9f93a1 100644 --- a/src/db/db/contrib/dbGDS2Text.h +++ b/src/db/db/dbInit.h @@ -21,11 +21,44 @@ */ -#ifndef HDR_dbGDS2Text -#define HDR_dbGDS2Text +#ifndef HDR_dbInit +#define HDR_dbInit -// place this macro to force linking of GDS2Text plugin -#define FORCE_LINK_GDS2_TXT void force_link_GDS2Text_f () { extern int force_link_GDS2Text; force_link_GDS2Text = 0; } +#include "dbCommon.h" + +#include +#include +#include + +namespace db +{ + +/** + * @brief A tiny structure describing a db plugin + */ +struct PluginDescriptor +{ + std::string version; + std::string path; + std::string description; + + PluginDescriptor () + { } +}; + +/** + * @brief The main initialization function for the "db" module + * This function needs to be called initially by all code using the db + * module. It will load the plugins and perform initialization of all + * of them. + */ +DB_PUBLIC void init (const std::vector &paths = std::vector ()); + +/** + * @brief Gets a list of all plugins registered + */ +DB_PUBLIC const std::list &plugins (); + +} #endif - diff --git a/src/db/db/dbPlugin.cc b/src/db/db/dbPlugin.cc new file mode 100644 index 000000000..e69de29bb diff --git a/src/db/db/dbPlugin.h b/src/db/db/dbPlugin.h new file mode 100644 index 000000000..be4502c94 --- /dev/null +++ b/src/db/db/dbPlugin.h @@ -0,0 +1,70 @@ + +/* + + 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_dbPlugin +#define HDR_dbPlugin + +/** + * @brief A struct to hold the data of the plugin + * + * Use it like this: + * + * @code + * static DbPlugin plugin_desc = { + * "1.0", // (const char *) version information - should be given at least + * 0 // (const char *) description or 0/empty if no description is given + * }; + * DECLARE_DB_PLUGIN (plugin_desc); + * @endcode + */ +struct DbPlugin +{ + const char *version; + const char *description; +}; + +/** + * @brief A typedef for the initialization function a plugin is supposed to expose. + */ +typedef void (*dbp_init_func_t) (const char **version, const char **description); + +# if defined _WIN32 || defined __CYGWIN__ +# define DBP_PUBLIC __declspec(dllexport) +# else +# if __GNUC__ >= 4 || defined(__clang__) +# define DBP_PUBLIC __attribute__ ((visibility ("default"))) +# else +# define DBP_PUBLIC +# endif + +# endif + +#define DECLARE_DB_PLUGIN(desc) \ + extern "C" { \ + DBP_PUBLIC void dbp_init (const char **version, const char **description) { \ + *version = desc.version; \ + *description = desc.description; \ + } \ + } + +#endif diff --git a/src/db/db/dbTestSupport.cc b/src/db/db/dbTestSupport.cc index 41236adcc..71a78af10 100644 --- a/src/db/db/dbTestSupport.cc +++ b/src/db/db/dbTestSupport.cc @@ -24,8 +24,6 @@ #include "dbStreamLayers.h" #include "dbReader.h" #include "dbWriter.h" -#include "dbGDS2Writer.h" -#include "dbOASISWriter.h" #include "dbCommonReader.h" #include "dbCell.h" #include "dbCellInst.h" @@ -54,27 +52,20 @@ void compare_layouts (tl::TestBase *_this, const db::Layout &layout, const std:: } std::string tmp_file; + db::SaveLayoutOptions options; if (norm == WriteGDS2) { - tmp_file = _this->tmp_file (tl::sprintf ("tmp_%x.gds", hash)); - - tl::OutputStream stream (tmp_file.c_str ()); - db::GDS2Writer writer; - db::SaveLayoutOptions options; - writer.write (const_cast (layout), stream, options); - + options.set_format ("GDS2"); } else { - tmp_file = _this->tmp_file (tl::sprintf ("tmp_%x.oas", hash)); - - tl::OutputStream stream (tmp_file.c_str ()); - db::OASISWriter writer; - db::SaveLayoutOptions options; - writer.write (const_cast (layout), stream, options); - + options.set_format ("OASIS"); } + tl::OutputStream stream (tmp_file.c_str ()); + db::Writer writer (options); + writer.write (const_cast (layout), stream); + const db::Layout *subject = 0; db::Layout layout2; diff --git a/src/db/unit_tests/dbCIFReader.cc b/src/db/unit_tests/dbCIFReader.cc index a6d542baa..8d5a842f1 100644 --- a/src/db/unit_tests/dbCIFReader.cc +++ b/src/db/unit_tests/dbCIFReader.cc @@ -25,7 +25,6 @@ #include "dbLayoutDiff.h" #include "dbWriter.h" #include "dbCIFWriter.h" -#include "dbGDS2Writer.h" #include "tlUnitTest.h" #include @@ -81,9 +80,10 @@ static void run_test (tl::TestBase *_this, const std::string &base, const char * { tl::OutputStream stream (tmp_gds_file); - db::GDS2Writer writer; db::SaveLayoutOptions options; - writer.write (layout, stream, options); + options.set_format ("GDS2"); + db::Writer writer (options); + writer.write (layout, stream); } { diff --git a/src/db/unit_tests/dbEdgeProcessor.cc b/src/db/unit_tests/dbEdgeProcessor.cc index f5fe79a34..a7abc8de4 100644 --- a/src/db/unit_tests/dbEdgeProcessor.cc +++ b/src/db/unit_tests/dbEdgeProcessor.cc @@ -29,9 +29,9 @@ #include "dbReader.h" #include "dbCommonReader.h" #include "dbLayoutDiff.h" -#include "dbGDS2Writer.h" -#include "dbGDS2Writer.h" #include "dbTestSupport.h" +#include "dbSaveLayoutOptions.h" +#include "dbWriter.h" #include "tlStream.h" #include "tlTimer.h" @@ -616,9 +616,11 @@ void write (const std::vector &q1, const std::vector & cell->shapes (lb).insert (*p); } - db::GDS2Writer writer; + db::SaveLayoutOptions options; + options.set_format ("GDS2"); + db::Writer writer (options); tl::OutputStream stream (fn); - writer.write (out, stream, db::SaveLayoutOptions ()); + writer.write (out, stream); printf ("%s written.\n", fn.c_str ()); } diff --git a/src/db/unit_tests/dbOASISWriter.cc b/src/db/unit_tests/dbOASISWriter.cc index edc6a82cc..4893e48fe 100644 --- a/src/db/unit_tests/dbOASISWriter.cc +++ b/src/db/unit_tests/dbOASISWriter.cc @@ -22,9 +22,7 @@ #include "dbOASISWriter.h" -#include "dbGDS2Writer.h" #include "dbOASISReader.h" -#include "dbGDS2Reader.h" #include "dbLayoutDiff.h" #include "dbWriter.h" #include "dbTextWriter.h" @@ -266,8 +264,10 @@ void run_test (tl::TestBase *_this, const char *file, bool scaling_test, int com { tl::OutputStream stream (tmp1_file); - db::GDS2Writer writer; - writer.write (layout, stream, options); + db::SaveLayoutOptions gds2_options; + gds2_options.set_format ("GDS2"); + db::Writer writer (gds2_options); + writer.write (layout, stream); } { diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index 5f88cde6f..16512a9d2 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -26,8 +26,6 @@ SOURCES = \ dbEdgeProcessor.cc \ dbEdges.cc \ dbEdgesToContours.cc \ - dbGDS2Reader.cc \ - dbGDS2Writer.cc \ dbLayer.cc \ dbLayerMapping.cc \ dbLayout.cc \ diff --git a/src/ext/unit_tests/extLEFDEFImport.cc b/src/ext/unit_tests/extLEFDEFImport.cc index a43f3a526..776bed2df 100644 --- a/src/ext/unit_tests/extLEFDEFImport.cc +++ b/src/ext/unit_tests/extLEFDEFImport.cc @@ -23,8 +23,6 @@ #include "dbLayoutDiff.h" #include "dbWriter.h" -#include "dbOASISWriter.h" -#include "dbGDS2Writer.h" #include "extDEFImporter.h" #include "extLEFImporter.h" @@ -107,9 +105,10 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file { tl::OutputStream stream (tmp_file); - db::OASISWriter writer; db::SaveLayoutOptions options; - writer.write (layout, stream, options); + options.set_format ("OASIS"); + db::Writer writer (options); + writer.write (layout, stream); } { diff --git a/src/klayout_main/klayout_main/klayout.cc b/src/klayout_main/klayout_main/klayout.cc index 29cb382b7..7050f0074 100644 --- a/src/klayout_main/klayout_main/klayout.cc +++ b/src/klayout_main/klayout_main/klayout.cc @@ -235,6 +235,7 @@ klayout_main_cont (int &argc, char **argv) try { + // initialize the Python interpreter pya::PythonInterpreter::initialize (); // this registers the gsi definitions @@ -259,7 +260,10 @@ klayout_main_cont (int &argc, char **argv) lay::enable_signal_handler_gui (true); } + // configures the application with the command line arguments app->parse_cmd (argc, argv); + + // initialize the application app->init_app (); /* TODO: this kills valgrind diff --git a/src/lay/lay/lay.pro b/src/lay/lay/lay.pro index 78d7262ea..32325e7e9 100644 --- a/src/lay/lay/lay.pro +++ b/src/lay/lay/lay.pro @@ -59,7 +59,8 @@ HEADERS = \ laySystemPaths.h \ layMacroEditorSetupPage.h \ layPasswordDialog.h \ - layForceLink.h + layForceLink.h \ + layInit.h FORMS = \ ClipDialog.ui \ @@ -165,7 +166,8 @@ SOURCES = \ laySystemPaths.cc \ layMacroEditorSetupPage.cc \ layPasswordDialog.cc \ - layForceLink.cc + layForceLink.cc \ + layInit.cc RESOURCES = layBuildInMacros.qrc \ layHelpResources.qrc \ diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 5058823e0..3a31a6282 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -39,6 +39,7 @@ #include "laySaltController.h" #include "laySystemPaths.h" #include "layPasswordDialog.h" +#include "layInit.h" #include "lymMacro.h" #include "gtf.h" #include "gsiDecl.h" @@ -49,6 +50,7 @@ #include "dbStatic.h" #include "dbLibrary.h" #include "dbLibraryManager.h" +#include "dbInit.h" #include "tlExceptions.h" #include "tlException.h" #include "tlAssert.h" @@ -174,49 +176,6 @@ static void ui_exception_handler_def (QWidget *parent) static ApplicationBase *ms_instance = 0; -static PluginDescriptor load_plugin (const std::string &pp) -{ - PluginDescriptor desc; - desc.path = pp; - - klp_init_func_t init_func = 0; - static const char *init_func_name = "klp_init"; - - // NOTE: since we are using a different suffix ("*.klp"), we can't use QLibrary. -#ifdef _WIN32 - // there is no "dlopen" on mingw, so we need to emulate it. - HINSTANCE handle = LoadLibraryW ((const wchar_t *) tl::to_qstring (pp).constData ()); - if (! handle) { - throw tl::Exception (tl::to_string (QObject::tr ("Unable to load plugin: %s with error message: %s ")), pp, GetLastError ()); - } - init_func = reinterpret_cast (GetProcAddress (handle, init_func_name)); -#else - void *handle; - handle = dlopen (tl::string_to_system (pp).c_str (), RTLD_LAZY); - if (! handle) { - throw tl::Exception (tl::to_string (QObject::tr ("Unable to load plugin: %s")), pp); - } - init_func = reinterpret_cast (dlsym (handle, init_func_name)); -#endif - - // If present, call the initialization function to fetch some details from the plugin - if (init_func) { - const char *version = 0; - const char *description = 0; - (*init_func) (&desc.autorun, &desc.autorun_early, &version, &description); - if (version) { - desc.version = version; - } - if (description) { - desc.description = description; - } - } - - tl::log << "Loaded plugin '" << pp << "'"; - - return desc; -} - // -------------------------------------------------------------------------------- // ApplicationBase implementation @@ -449,7 +408,7 @@ ApplicationBase::parse_cmd (int &argc, char **argv) } else if (a == "-p" && (i + 1) < argc) { - m_native_plugins.push_back (load_plugin (args [++i])); + lay::load_plugin (args [++i]); } else if (a == "-s") { @@ -560,14 +519,16 @@ ApplicationBase::parse_cmd (int &argc, char **argv) void ApplicationBase::init_app () { - // Try to locate the native plugins: - // Native plugins are DLL's or SO's disguised as "*.klp" files. + // Try to locate the plugins: // The are installed either // - directly in one of the KLAYOUT_PATH directories // - in a folder named by the architecture (i.e. "i686-win32-mingw" or "x86_64-linux-gcc") below // one of these folders // - in one of the Salt packages // - in one of the Salt packages, in a folder named after the architecture + // Below this, the following folders are looked up: + // - db_plugins for db module plugins + // - lay_plugins for lay module plugins std::string version = lay::Version::version (); std::vector vv = tl::split (version, "."); @@ -579,18 +540,17 @@ ApplicationBase::init_app () } std::string short_arch_string = tl::join (as, "-"); + std::vector klp_paths; + for (std::vector ::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) { - std::set modules; - - std::vector klp_paths; - klp_paths.push_back (tl::to_qstring (*p)); - klp_paths.push_back (QDir (klp_paths.back ()).filePath (tl::to_qstring (tl::arch_string ()))); + klp_paths.push_back (*p); + klp_paths.push_back (tl::to_string (QDir (tl::to_qstring (klp_paths.back ())).filePath (tl::to_qstring (tl::arch_string ())))); lay::Salt salt; salt.add_location (tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 ("salt")))); - // Build the search path for the *.klp files. The search priority is for example: + // Build the search path for the plugin locations. The search priority is for example: // salt/mypackage/x86_64-linux-gcc-0.25.1 // salt/mypackage/x86_64-linux-gcc-0.25 // salt/mypackage/x86_64-linux-gcc-0 @@ -600,47 +560,25 @@ ApplicationBase::init_app () for (lay::Salt::flat_iterator g = salt.begin_flat (); g != salt.end_flat (); ++g) { QDir dir = QDir (tl::to_qstring ((*g)->path ())); - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + lay::Version::version()))); + klp_paths.push_back (tl::to_string (dir.filePath (tl::to_qstring (arch_string + "-" + lay::Version::version())))); if (vv.size () >= 2) { - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0] + "." + vv[1]))); + klp_paths.push_back (tl::to_string (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0] + "." + vv[1])))); } if (vv.size () >= 1) { - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0]))); + klp_paths.push_back (tl::to_string (dir.filePath (tl::to_qstring (arch_string + "-" + vv[0])))); } - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string + "-" + tl::to_string (lay::Version::version ())))); - klp_paths.push_back (dir.filePath (tl::to_qstring (arch_string))); - klp_paths.push_back (dir.filePath (tl::to_qstring (short_arch_string))); - klp_paths.push_back (tl::to_qstring ((*g)->path ())); - } - - QStringList name_filters; - name_filters << QString::fromUtf8 ("*.klp"); - - for (std::vector::const_iterator p = klp_paths.begin (); p != klp_paths.end (); ++p) { - - QStringList inst_modules = QDir (*p).entryList (name_filters); - inst_modules.sort (); - - for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { - QFileInfo klp_file (*p, *im); - if (klp_file.exists () && klp_file.isReadable ()) { - std::string m = tl::to_string (klp_file.absoluteFilePath ()); - std::string mn = tl::to_string (klp_file.fileName ()); - if (modules.find (mn) == modules.end ()) { - try { - m_native_plugins.push_back (load_plugin (m)); - modules.insert (mn); - } catch (tl::Exception &ex) { - tl::error << tl::to_string (QObject::tr ("Unable to load plugin %1: %2").arg (tl::to_qstring (m)).arg (tl::to_qstring (ex.msg ()))); - } - } - } - } - + klp_paths.push_back (tl::to_string (dir.filePath (tl::to_qstring (arch_string + "-" + tl::to_string (lay::Version::version ()))))); + klp_paths.push_back (tl::to_string (dir.filePath (tl::to_qstring (arch_string)))); + klp_paths.push_back (tl::to_string (dir.filePath (tl::to_qstring (short_arch_string)))); + klp_paths.push_back ((*g)->path ()); } } + // initialize the modules (load their plugins from the paths) + db::init (klp_paths); + lay::init (klp_paths); + // initialize the GSI class system (Variant binding, Expression support) // We have to do this now since plugins may register GSI classes and before the // ruby interpreter, because it depends on a proper class system. @@ -800,7 +738,7 @@ ApplicationBase::init_app () tl::Eval::set_global_var ("klayout_path", kp); // call "autorun_early" on all plugins that wish so - for (std::vector ::const_iterator p = m_native_plugins.begin (); p != m_native_plugins.end (); ++p) { + for (std::list::const_iterator p = lay::plugins ().begin (); p != lay::plugins ().end (); ++p) { if (p->autorun_early) { (*p->autorun_early) (); } @@ -1212,7 +1150,7 @@ void ApplicationBase::autorun () { // call "autorun" on all plugins that wish so - for (std::vector ::const_iterator p = m_native_plugins.begin (); p != m_native_plugins.end (); ++p) { + for (std::list ::const_iterator p = lay::plugins ().begin (); p != lay::plugins ().end (); ++p) { if (p->autorun) { (*p->autorun) (); } diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h index 370b07424..1aa7633ba 100644 --- a/src/lay/lay/layApplication.h +++ b/src/lay/lay/layApplication.h @@ -61,24 +61,6 @@ class PluginRoot; class ProgressReporter; class ProgressBar; -/** - * @brief A tiny struct describing a native plugin - */ -struct PluginDescriptor -{ - typedef void (*runner_func_t) (); - - runner_func_t autorun; - runner_func_t autorun_early; - std::string version; - std::string path; - std::string description; - - PluginDescriptor () - : autorun (0), autorun_early (0) - { } -}; - /** * @brief The application base class * @@ -316,14 +298,6 @@ public: return m_klayout_path; } - /** - * @brief Gets the native plugin descriptors - */ - const std::vector &native_plugins () const - { - return m_native_plugins; - } - /** * @brief Parses the given command line arguments and configures the application object accordingly. */ @@ -395,7 +369,6 @@ private: // in order to maintain a valid MainWindow reference for ruby scripts and Ruby's GC all the time. gsi::Interpreter *mp_ruby_interpreter; gsi::Interpreter *mp_python_interpreter; - std::vector m_native_plugins; }; /** diff --git a/src/lay/lay/layInit.cc b/src/lay/lay/layInit.cc new file mode 100644 index 000000000..fbdaa7c73 --- /dev/null +++ b/src/lay/lay/layInit.cc @@ -0,0 +1,192 @@ + +/* + + 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 "layInit.h" +#include "layPlugin.h" +#include "tlException.h" +#include "tlLog.h" +#include "tlString.h" + +#ifdef _WIN32 +# include +#else +# include +#endif + +#include +#include +#include + +namespace lay +{ + +static std::list s_plugins; + +const std::list &plugins () +{ + return s_plugins; +} + +static PluginDescriptor do_load_plugin (const std::string &pp) +{ + PluginDescriptor desc; + desc.path = pp; + + klp_init_func_t init_func = 0; + static const char *init_func_name = "klp_init"; + + // NOTE: since we are using a different suffix ("*.klp"), we can't use QLibrary. +#ifdef _WIN32 + // there is no "dlopen" on mingw, so we need to emulate it. + HINSTANCE handle = LoadLibraryW ((const wchar_t *) tl::to_qstring (pp).constData ()); + if (! handle) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to load plugin: %s with error message: %s ")), pp, GetLastError ()); + } + init_func = reinterpret_cast (GetProcAddress (handle, init_func_name)); +#else + void *handle; + handle = dlopen (tl::string_to_system (pp).c_str (), RTLD_LAZY); + if (! handle) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to load plugin: %s")), pp); + } + init_func = reinterpret_cast (dlsym (handle, init_func_name)); +#endif + + // If present, call the initialization function to fetch some details from the plugin + if (init_func) { + const char *version = 0; + const char *description = 0; + (*init_func) (&desc.autorun, &desc.autorun_early, &version, &description); + if (version) { + desc.version = version; + } + if (description) { + desc.description = description; + } + } + + tl::log << "Loaded plugin '" << pp << "'"; + + return desc; +} + +void load_plugin (const std::string &pp) +{ + s_plugins.push_back (do_load_plugin (pp)); +} + +/** + * @brief Gets the path to the current module + */ +static std::string +get_module_path () +{ +#if defined(_WIN32) + + HMODULE h_module = NULL; + if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR) &init, &h_module)) { + + wchar_t buffer[MAX_PATH]; + int len; + if ((len = GetModuleFileName(h_module, buffer, MAX_PATH)) > 0) { + QFileInfo fi (QString::fromUtf16 ((const ushort *) buffer, len)); + return tl::to_string (fi.absolutePath ()); + } + + } + + // no way to get module file path + return std::string (); + +#else + + Dl_info info = { }; + if (dladdr ((void *) &init, &info)) { + QFileInfo fi (QString::fromLocal8Bit (info.dli_fname)); + return tl::to_string (fi.absolutePath ()); + } else { + return std::string (); + } + +#endif +} + +void init (const std::vector &_paths) +{ + std::vector paths = _paths; + if (paths.empty ()) { + std::string module_path = get_module_path (); + if (! module_path.empty ()) { + paths.push_back (module_path); + } + } + + if (paths.empty ()) { + // nothing to do + return; + } + + std::set modules; + + for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { + + // look next to the db library, but in "lay_plugins" directory + const char *db_plugin_dir = "lay_plugins"; + std::string pp = tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 (db_plugin_dir))); + + QStringList name_filters; +#if defined(_WIN32) + name_filters << QString::fromUtf8 ("*.dll"); +#else + name_filters << QString::fromUtf8 ("*.so"); +#endif + + QStringList inst_modules = QDir (tl::to_qstring (pp)).entryList (name_filters); + inst_modules.sort (); + + for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { + + QFileInfo layp_file (tl::to_qstring (pp), *im); + if (layp_file.exists () && layp_file.isReadable ()) { + + std::string mn = tl::to_string (layp_file.fileName ()); + if (modules.find (mn) == modules.end ()) { + + std::string m = tl::to_string (layp_file.absoluteFilePath ()); + try { + s_plugins.push_back (do_load_plugin (m)); + modules.insert (mn); + } catch (tl::Exception (&ex)) { + tl::error << ex.msg (); + } + + } + + } + + } + + } + +} + +} diff --git a/src/lay/lay/layInit.h b/src/lay/lay/layInit.h new file mode 100644 index 000000000..3a89e0d02 --- /dev/null +++ b/src/lay/lay/layInit.h @@ -0,0 +1,75 @@ + +/* + + 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_layInit +#define HDR_layInit + +#include "layCommon.h" +#include "layNativePlugin.h" + +#include +#include +#include + +namespace lay +{ + +/** + * @brief A tiny struct describing a native plugin + */ +struct PluginDescriptor +{ + typedef void (*runner_func_t) (); + + runner_func_t autorun; + runner_func_t autorun_early; + std::string version; + std::string path; + std::string description; + + PluginDescriptor () + : autorun (0), autorun_early (0) + { } +}; + +/** + * @brief The main initialization function for the "db" module + * This function needs to be called initially by all code using the db + * module. It will load the plugins and perform initialization of all + * of them. + */ +LAY_PUBLIC void init (const std::vector &paths = std::vector ()); + +/** + * @brief Explicitly load a specific plugin + */ +LAY_PUBLIC void load_plugin (const std::string &pp); + +/** + * @brief Gets a list of all plugins registered + */ +LAY_PUBLIC const std::list &plugins (); + +} + +#endif diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 27261d341..059a011c6 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -58,6 +58,7 @@ #include "dbLibraryManager.h" #include "dbLibrary.h" #include "dbStatic.h" +#include "dbInit.h" #include "edtConfig.h" #include "laySession.h" #include "layApplication.h" @@ -91,6 +92,7 @@ #include "layLayoutPropertiesForm.h" #include "layLayoutStatisticsForm.h" #include "layMacroController.h" +#include "layInit.h" #include "antObject.h" #include "antService.h" #include "ui_HelpAboutDialog.h" @@ -5658,12 +5660,14 @@ HelpAboutDialog::HelpAboutDialog (QWidget *parent) s += ""; } - if (! lay::ApplicationBase::instance ()->native_plugins ().empty ()) { + if (! lay::plugins ().empty () || ! db::plugins ().empty ()) { + s += "

"; s += "

"; s += escape_xml (tl::to_string (QObject::tr ("Binary extensions:"))); s += "

    "; - for (std::vector::const_iterator pd = lay::ApplicationBase::instance ()->native_plugins ().begin (); pd != lay::ApplicationBase::instance ()->native_plugins ().end (); ++pd) { + + for (std::list::const_iterator pd = lay::plugins ().begin (); pd != lay::plugins ().end (); ++pd) { s += "
  • "; if (! pd->description.empty ()) { s += escape_xml (pd->description); @@ -5675,7 +5679,22 @@ HelpAboutDialog::HelpAboutDialog (QWidget *parent) } s += "
  • "; } + + for (std::list::const_iterator pd = db::plugins ().begin (); pd != db::plugins ().end (); ++pd) { + s += "
  • "; + if (! pd->description.empty ()) { + s += escape_xml (pd->description); + } else { + s += escape_xml (pd->path); + } + if (! pd->version.empty ()) { + s += " (" + escape_xml (pd->version) + ")"; + } + s += "
  • "; + } + s += "
"; + } s += ""; diff --git a/src/laybasic/laybasic/layGDS2ReaderPlugin.cc b/src/laybasic/laybasic/layGDS2ReaderPlugin.cc deleted file mode 100644 index 5d7a94b24..000000000 --- a/src/laybasic/laybasic/layGDS2ReaderPlugin.cc +++ /dev/null @@ -1,195 +0,0 @@ - -/* - - 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 "dbGDS2.h" -#include "dbGDS2Reader.h" -#include "dbLoadLayoutOptions.h" -#include "layGDS2ReaderPlugin.h" -#include "ui_GDS2ReaderOptionPage.h" -#include "gsiDecl.h" - -#include - -namespace lay -{ - -// --------------------------------------------------------------- -// GDS2ReaderOptionPage definition and implementation - -GDS2ReaderOptionPage::GDS2ReaderOptionPage (QWidget *parent) - : StreamReaderOptionsPage (parent) -{ - mp_ui = new Ui::GDS2ReaderOptionPage (); - mp_ui->setupUi (this); -} - -GDS2ReaderOptionPage::~GDS2ReaderOptionPage () -{ - delete mp_ui; - mp_ui = 0; -} - -void -GDS2ReaderOptionPage::setup (const db::FormatSpecificReaderOptions *o, const lay::Technology * /*tech*/) -{ - static const db::GDS2ReaderOptions default_options; - const db::GDS2ReaderOptions *options = dynamic_cast (o); - if (!options) { - options = &default_options; - } - - mp_ui->big_records_cbx->setChecked (! options->allow_big_records); - mp_ui->big_poly_cbx->setChecked (! options->allow_multi_xy_records); - mp_ui->box_mode_cb->setCurrentIndex (options->box_mode); -} - -void -GDS2ReaderOptionPage::commit (db::FormatSpecificReaderOptions *o, const lay::Technology * /*tech*/) -{ - db::GDS2ReaderOptions *options = dynamic_cast (o); - if (options) { - - options->allow_big_records = ! mp_ui->big_records_cbx->isChecked (); - options->allow_multi_xy_records = ! mp_ui->big_poly_cbx->isChecked (); - options->box_mode = mp_ui->box_mode_cb->currentIndex (); - - } -} - -// --------------------------------------------------------------- -// GDS2ReaderPluginDeclaration definition and implementation - -class GDS2ReaderPluginDeclaration - : public StreamReaderPluginDeclaration -{ -public: - GDS2ReaderPluginDeclaration () - : StreamReaderPluginDeclaration (db::GDS2ReaderOptions ().format_name ()) - { - // .. nothing yet .. - } - - StreamReaderOptionsPage *format_specific_options_page (QWidget *parent) const - { - return new GDS2ReaderOptionPage (parent); - } - - db::FormatSpecificReaderOptions *create_specific_options () const - { - return new db::GDS2ReaderOptions (); - } - - virtual tl::XMLElementBase *xml_element () const - { - return new lay::ReaderOptionsXMLElement ("gds2", - tl::make_member (&db::GDS2ReaderOptions::box_mode, "box-mode") + - tl::make_member (&db::GDS2ReaderOptions::allow_big_records, "allow-big-records") + - tl::make_member (&db::GDS2ReaderOptions::allow_multi_xy_records, "allow-multi-xy-records") - ); - } -}; - -static tl::RegisteredClass plugin_decl (new lay::GDS2ReaderPluginDeclaration (), 10000, "GDS2Reader"); - -// --------------------------------------------------------------- -// gsi Implementation of specific methods - -static void set_gds2_box_mode (db::LoadLayoutOptions *options, unsigned int n) -{ - options->get_options ().box_mode = n; -} - -static unsigned int get_gds2_box_mode (const db::LoadLayoutOptions *options) -{ - return options->get_options ().box_mode; -} - -static void set_gds2_allow_multi_xy_records (db::LoadLayoutOptions *options, bool n) -{ - options->get_options ().allow_multi_xy_records = n; -} - -static bool get_gds2_allow_multi_xy_records (const db::LoadLayoutOptions *options) -{ - return options->get_options ().allow_multi_xy_records; -} - -static void set_gds2_allow_big_records (db::LoadLayoutOptions *options, bool n) -{ - options->get_options ().allow_big_records = n; -} - -static bool get_gds2_allow_big_records (const db::LoadLayoutOptions *options) -{ - return options->get_options ().allow_big_records; -} - -// extend lay::LoadLayoutOptions with the GDS2 options -static -gsi::ClassExt gds2_reader_options ( - gsi::method_ext ("gds2_box_mode=", &set_gds2_box_mode, - "@brief Sets a value specifying how to treat BOX records\n" - "This property specifies how BOX records are treated.\n" - "Allowed values are 0 (ignore), 1 (treat as rectangles), 2 (treat as boundaries) or 3 (treat as errors). The default is 1.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_box_mode", &get_gds2_box_mode, - "@brief Gets a value specifying how to treat BOX records\n" - "See \\gds2_box_mode= method for a description of this mode." - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_allow_multi_xy_records=", &set_gds2_allow_multi_xy_records, - "@brief Allows the use of multiple XY records in BOUNDARY elements for unlimited large polygons\n" - "\n" - "Setting this property to true allows big polygons that span over multiple XY records.\n" - "For strict compatibility with the standard, this property should be set to false. The default is true.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_allow_multi_xy_records?|#gds2_allow_multi_xy_records", &get_gds2_allow_multi_xy_records, - "@brief Gets a value specifying whether to allow big polygons with multiple XY records.\n" - "See \\gds2_allow_multi_xy_records= method for a description of this property." - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_allow_big_records=", &set_gds2_allow_big_records, - "@brief Allows big records with more than 32767 bytes\n" - "\n" - "Setting this property to true allows larger records by treating the record length as unsigned short, which for example " - "allows larger polygons (~8000 points rather than ~4000 points) without using multiple XY records.\n" - "For strict compatibility with the standard, this property should be set to false. The default is true.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_allow_big_records?|#gds2_allow_big_records", &get_gds2_allow_big_records, - "@brief Gets a value specifying whether to allow big records with a length of 32768 to 65535 bytes.\n" - "See \\gds2_allow_big_records= method for a description of this property." - "\nThis property has been added in version 0.18.\n" - ), - "" -); - -} - - - - - diff --git a/src/laybasic/laybasic/layGDS2WriterPlugin.cc b/src/laybasic/laybasic/layGDS2WriterPlugin.cc deleted file mode 100644 index 6cb43f429..000000000 --- a/src/laybasic/laybasic/layGDS2WriterPlugin.cc +++ /dev/null @@ -1,408 +0,0 @@ - -/* - - 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 "dbGDS2.h" -#include "dbGDS2Writer.h" -#include "dbSaveLayoutOptions.h" -#include "layCellView.h" -#include "layGDS2WriterPlugin.h" -#include "ui_GDS2WriterOptionPage.h" -#include "gsiDecl.h" - -#include - -namespace lay -{ - -// --------------------------------------------------------------- -// GDS2WriterOptionPage definition and implementation - -GDS2WriterOptionPage::GDS2WriterOptionPage (QWidget *parent) - : StreamWriterOptionsPage (parent) -{ - mp_ui = new Ui::GDS2WriterOptionPage (); - mp_ui->setupUi (this); - - connect (mp_ui->multi_xy_cbx, SIGNAL (clicked ()), this, SLOT (multi_xy_clicked ())); -} - -GDS2WriterOptionPage::~GDS2WriterOptionPage () -{ - delete mp_ui; - mp_ui = 0; -} - -void -GDS2WriterOptionPage::setup (const db::FormatSpecificWriterOptions *o, const lay::Technology * /*tech*/) -{ - const db::GDS2WriterOptions *options = dynamic_cast (o); - if (options) { - mp_ui->write_timestamps->setChecked (options->write_timestamps); - mp_ui->write_cell_properties->setChecked (options->write_cell_properties); - mp_ui->write_file_properties->setChecked (options->write_file_properties); - mp_ui->no_zero_length_paths->setChecked (options->no_zero_length_paths); - mp_ui->multi_xy_cbx->setChecked (options->multi_xy_records); - mp_ui->max_vertex_le->setEnabled (! options->multi_xy_records); - mp_ui->max_vertex_le->setText (tl::to_qstring (tl::to_string (options->max_vertex_count))); - mp_ui->cell_name_length_le->setText (tl::to_qstring (tl::to_string (options->max_cellname_length))); - mp_ui->libname_le->setText (tl::to_qstring (tl::to_string (options->libname))); - } -} - -void -GDS2WriterOptionPage::commit (db::FormatSpecificWriterOptions *o, const lay::Technology * /*tech*/, bool /*gzip*/) -{ - db::GDS2WriterOptions *options = dynamic_cast (o); - if (options) { - - unsigned int n; - options->multi_xy_records = mp_ui->multi_xy_cbx->isChecked (); - options->write_timestamps = mp_ui->write_timestamps->isChecked (); - options->write_cell_properties = mp_ui->write_cell_properties->isChecked (); - options->write_file_properties = mp_ui->write_file_properties->isChecked (); - options->no_zero_length_paths = mp_ui->no_zero_length_paths->isChecked (); - - tl::from_string (tl::to_string (mp_ui->max_vertex_le->text ()), n); - if (! options->multi_xy_records) { - if (n > 8191) { - throw tl::Exception (tl::to_string (QObject::tr ("Maximum number of vertices must not exceed 8191"))); - } - if (n < 4) { - throw tl::Exception (tl::to_string (QObject::tr ("Maximum number of vertices must be 4 at least"))); - } - } - options->max_vertex_count = n; - - n = 32000; - tl::from_string (tl::to_string (mp_ui->cell_name_length_le->text ()), n); - if (n > 32000) { - throw tl::Exception (tl::to_string (QObject::tr ("Maximum cell name length must not exceed 32000"))); - } - if (n < 8) { - throw tl::Exception (tl::to_string (QObject::tr ("Maximum cell name length must be 8 at least"))); - } - options->max_cellname_length = n; - - options->libname = tl::to_string (mp_ui->libname_le->text ()); - - } -} - -void -GDS2WriterOptionPage::multi_xy_clicked () -{ - mp_ui->max_vertex_le->setEnabled (! mp_ui->multi_xy_cbx->isChecked ()); -} - -// --------------------------------------------------------------- -// GDS2WriterPluginDeclaration definition and implementation - -class GDS2WriterPluginDeclaration - : public StreamWriterPluginDeclaration -{ -public: - GDS2WriterPluginDeclaration () - : StreamWriterPluginDeclaration (db::GDS2WriterOptions ().format_name ()) - { - // .. nothing yet .. - } - - StreamWriterOptionsPage *format_specific_options_page (QWidget *parent) const - { - return new GDS2WriterOptionPage (parent); - } - - db::FormatSpecificWriterOptions *create_specific_options () const - { - return new db::GDS2WriterOptions (); - } - - virtual tl::XMLElementBase *xml_element () const - { - return new lay::WriterOptionsXMLElement ("gds2", - tl::make_member (&db::GDS2WriterOptions::write_timestamps, "write-timestamps") + - tl::make_member (&db::GDS2WriterOptions::write_cell_properties, "write-cell-properties") + - tl::make_member (&db::GDS2WriterOptions::write_file_properties, "write-file-properties") + - tl::make_member (&db::GDS2WriterOptions::no_zero_length_paths, "no-zero-length-paths") + - tl::make_member (&db::GDS2WriterOptions::multi_xy_records, "multi-xy-records") + - tl::make_member (&db::GDS2WriterOptions::max_vertex_count, "max-vertex-count") + - tl::make_member (&db::GDS2WriterOptions::max_cellname_length, "max-cellname-length") + - tl::make_member (&db::GDS2WriterOptions::libname, "libname") - ); - } - - void initialize_options_from_layout_handle (db::FormatSpecificWriterOptions *o, const lay::LayoutHandle &lh) const - { - // Initialize the libname property from meta data with key "libname". - db::GDS2WriterOptions *options = dynamic_cast (o); - if (options) { - for (db::Layout::meta_info_iterator meta = lh.layout().begin_meta (); meta != lh.layout().end_meta (); ++meta) { - if (meta->name == "libname" && !meta->value.empty ()) { - options->libname = meta->value; - } - } - } - } -}; - -/** - * @brief A dummy plugin for GDS2Text - * - * GDS2Text shares the options with GDS2, although some limitations do not exist. - * There is not specific option set for GDS2Text. The writer will take the options from GDS2. - */ -class GDS2TextWriterPluginDeclaration - : public StreamWriterPluginDeclaration -{ -public: - GDS2TextWriterPluginDeclaration () - : StreamWriterPluginDeclaration ("GDS2Text") - { - // .. nothing yet .. - } -}; - -static tl::RegisteredClass plugin_decl1 (new lay::GDS2WriterPluginDeclaration (), 10000, "GDS2Writer"); -static tl::RegisteredClass plugin_decl2 (new lay::GDS2TextWriterPluginDeclaration (), 10001, "GDS2TextWriter"); - -// --------------------------------------------------------------- -// gsi Implementation of specific methods - -static void set_gds2_max_vertex_count (db::SaveLayoutOptions *options, unsigned int n) -{ - options->get_options ().max_vertex_count = n; -} - -static unsigned int get_gds2_max_vertex_count (const db::SaveLayoutOptions *options) -{ - return options->get_options ().max_vertex_count; -} - -static void set_gds2_max_cellname_length (db::SaveLayoutOptions *options, unsigned int n) -{ - options->get_options ().max_cellname_length = n; -} - -static unsigned int get_gds2_max_cellname_length (const db::SaveLayoutOptions *options) -{ - return options->get_options ().max_cellname_length; -} - -static void set_gds2_multi_xy_records (db::SaveLayoutOptions *options, bool n) -{ - options->get_options ().multi_xy_records = n; -} - -static bool get_gds2_multi_xy_records (const db::SaveLayoutOptions *options) -{ - return options->get_options ().multi_xy_records; -} - -static void set_gds2_write_file_properties (db::SaveLayoutOptions *options, bool n) -{ - options->get_options ().write_file_properties = n; -} - -static bool get_gds2_write_file_properties (const db::SaveLayoutOptions *options) -{ - return options->get_options ().write_file_properties; -} - -static void set_gds2_write_cell_properties (db::SaveLayoutOptions *options, bool n) -{ - options->get_options ().write_cell_properties = n; -} - -static bool get_gds2_write_cell_properties (const db::SaveLayoutOptions *options) -{ - return options->get_options ().write_cell_properties; -} - -static void set_gds2_no_zero_length_paths (db::SaveLayoutOptions *options, bool n) -{ - options->get_options ().no_zero_length_paths = n; -} - -static bool get_gds2_no_zero_length_paths (const db::SaveLayoutOptions *options) -{ - return options->get_options ().no_zero_length_paths; -} - -static void set_gds2_write_timestamps (db::SaveLayoutOptions *options, bool n) -{ - options->get_options ().write_timestamps = n; -} - -static bool get_gds2_write_timestamps (const db::SaveLayoutOptions *options) -{ - return options->get_options ().write_timestamps; -} - -static void set_gds2_libname (db::SaveLayoutOptions *options, const std::string &n) -{ - options->get_options ().libname = n; -} - -static std::string get_gds2_libname (const db::SaveLayoutOptions *options) -{ - return options->get_options ().libname; -} - -static void set_gds2_user_units (db::SaveLayoutOptions *options, double n) -{ - options->get_options ().user_units = n; -} - -static double get_gds2_user_units (const db::SaveLayoutOptions *options) -{ - return options->get_options ().user_units; -} - -// extend lay::SaveLayoutOptions with the GDS2 options -static -gsi::ClassExt gds2_writer_options ( - gsi::method_ext ("gds2_max_vertex_count=", &set_gds2_max_vertex_count, - "@brief Set the maximum number of vertices for polygons to write\n" - "@args count\n" - "This property describes the maximum number of point for polygons in GDS2 files.\n" - "Polygons with more points will be split.\n" - "The minimum value for this property is 4. The maximum allowed value is about 4000 or 8000, depending on the\n" - "GDS2 interpretation. If \\gds2_multi_xy_records is true, this\n" - "property is not used. Instead, the number of points is unlimited.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_max_vertex_count", &get_gds2_max_vertex_count, - "@brief Get the maximum number of vertices for polygons to write\n" - "See \\gds2_max_vertex_count= method for a description of the maximum vertex count." - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_multi_xy_records=", &set_gds2_multi_xy_records, - "@brief Use multiple XY records in BOUNDARY elements for unlimited large polygons\n" - "@args flag\n" - "\n" - "Setting this property to true allows to produce unlimited polygons \n" - "at the cost of incompatible formats. Setting it to true disables the \\gds2_max_vertex_count setting.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_multi_xy_records?", &get_gds2_multi_xy_records, - "@brief Get the property enabling multiple XY records for BOUNDARY elements\n" - "See \\gds2_multi_xy_records= method for a description of this property." - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_write_timestamps=", &set_gds2_write_timestamps, - "@brief Write the current time into the GDS2 timestamps if set to true\n" - "@args flag\n" - "\n" - "If this property is set to false, the time fields will all be zero. This somewhat simplifies compare and diff " - "applications.\n" - "\n" - "\nThis property has been added in version 0.21.16.\n" - ) + - gsi::method_ext ("gds2_write_timestamps?", &get_gds2_write_timestamps, - "@brief Gets a value indicating whether the current time is written into the GDS2 timestamp fields\n" - "\nThis property has been added in version 0.21.16.\n" - ) + - gsi::method_ext ("gds2_no_zero_length_paths=", &set_gds2_no_zero_length_paths, - "@brief Eliminates zero-length paths if true\n" - "@args flag\n" - "\n" - "If this property is set to true, paths with zero length will be converted to BOUNDARY objects.\n" - "\n" - "\nThis property has been added in version 0.23.\n" - ) + - gsi::method_ext ("gds2_no_zero_length_paths?|#gds2_no_zero_length_paths", &get_gds2_no_zero_length_paths, - "@brief Gets a value indicating whether zero-length paths are eliminated\n" - "\nThis property has been added in version 0.23.\n" - ) + - gsi::method_ext ("gds2_write_cell_properties=", &set_gds2_write_cell_properties, - "@brief Enables writing of cell properties if set to true\n" - "@args flag\n" - "\n" - "If this property is set to true, cell properties will be written as PROPATTR/PROPVALUE records immediately " - "following the BGNSTR records. This is a non-standard extension and is therefore disabled by default.\n" - "\n" - "\nThis property has been added in version 0.23.\n" - ) + - gsi::method_ext ("gds2_write_cell_properties?|#gds2_write_cell_properties", &get_gds2_write_cell_properties, - "@brief Gets a value indicating whether cell properties are written\n" - "\nThis property has been added in version 0.23.\n" - ) + - gsi::method_ext ("gds2_write_file_properties=", &set_gds2_write_file_properties, - "@brief Enables writing of file properties if set to true\n" - "@args flag\n" - "\n" - "If this property is set to true, layout properties will be written as PROPATTR/PROPVALUE records immediately " - "following the BGNLIB records. This is a non-standard extension and is therefore disabled by default.\n" - "\n" - "\nThis property has been added in version 0.24.\n" - ) + - gsi::method_ext ("gds2_write_file_properties?|#gds2_write_file_properties", &get_gds2_write_file_properties, - "@brief Gets a value indicating whether layout properties are written\n" - "\nThis property has been added in version 0.24.\n" - ) + - gsi::method_ext ("gds2_max_cellname_length=", &set_gds2_max_cellname_length, - "@brief Maximum length of cell names\n" - "@args length\n" - "\n" - "This property describes the maximum number of characters for cell names. \n" - "Longer cell names will be shortened.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_max_cellname_length", &get_gds2_max_cellname_length, - "@brief Get the maximum length of cell names\n" - "See \\gds2_max_cellname_length= method for a description of the maximum cell name length." - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_libname=", &set_gds2_libname, - "@brief Set the library name\n" - "@args libname\n" - "\n" - "The library name is the string written into the LIBNAME records of the GDS file.\n" - "The library name should not be an empty string and is subject to certain limitations in the character choice.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_libname", &get_gds2_libname, - "@brief Get the library name\n" - "See \\gds2_libname= method for a description of the library name." - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_user_units=", &set_gds2_user_units, - "@brief Set the users units to write into the GDS file\n" - "@args uu\n" - "\n" - "The user units of a GDS file are rarely used and usually are set to 1 (micron).\n" - "The intention of the user units is to specify the display units. KLayout ignores the user unit and uses microns as the display unit.\n" - "The user unit must be larger than zero.\n" - "\nThis property has been added in version 0.18.\n" - ) + - gsi::method_ext ("gds2_user_units", &get_gds2_user_units, - "@brief Get the user units\n" - "See \\gds2_user_units= method for a description of the user units." - "\nThis property has been added in version 0.18.\n" - ), - "" -); - -} - - diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index 7b6f6b0cc..cf37b1dc3 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -27,8 +27,6 @@ FORMS = \ DuplicateLayerDialog.ui \ EditStipplesForm.ui \ FlattenInstOptionsDialog.ui \ - GDS2ReaderOptionPage.ui \ - GDS2WriterOptionPage.ui \ GridNetConfigPage.ui \ LayerMappingWidget.ui \ LayerSourceDialog.ui \ @@ -121,8 +119,6 @@ SOURCES = \ layFileDialog.cc \ layFinder.cc \ layFixedFont.cc \ - layGDS2ReaderPlugin.cc \ - layGDS2WriterPlugin.cc \ layGridNet.cc \ layHierarchyControlPanel.cc \ layLayerControlPanel.cc \ @@ -215,8 +211,6 @@ HEADERS = \ layFileDialog.h \ layFinder.h \ layFixedFont.h \ - layGDS2ReaderPlugin.h \ - layGDS2WriterPlugin.h \ layGridNet.h \ layHierarchyControlPanel.h \ layLayerControlPanel.h \ diff --git a/src/plugins/db_plugin.pri b/src/plugins/db_plugin.pri new file mode 100644 index 000000000..1160627e0 --- /dev/null +++ b/src/plugins/db_plugin.pri @@ -0,0 +1,9 @@ + +include($$PWD/../klayout.pri) + +TEMPLATE = lib + +INCLUDEPATH += $$DB_INC $$TL_INC $$GSI_INC +DEPENDPATH += $$DB_INC $$TL_INC $$GSI_INC +LIBS += -L$$DESTDIR/.. -lklayout_db -lklayout_tl -lklayout_gsi + diff --git a/src/plugins/lay_plugin.pri b/src/plugins/lay_plugin.pri new file mode 100644 index 000000000..86ca9d6d5 --- /dev/null +++ b/src/plugins/lay_plugin.pri @@ -0,0 +1,8 @@ + +include($$PWD/../klayout.pri) + +TEMPLATE = lib + +INCLUDEPATH += $$DB_INC $$TL_INC $$GSI_INC $$LAYBASIC_INC $$LAY_INC +DEPENDPATH += $$DB_INC $$TL_INC $$GSI_INC $$LAYBASIC_INC $$LAY_INC +LIBS += -L$$DESTDIR/.. -lklayout_db -lklayout_tl -lklayout_gsi -lklayout_laybasic -lklayout_lay diff --git a/src/plugins/plugin.pri b/src/plugins/plugin.pri deleted file mode 100644 index 3d9ff3494..000000000 --- a/src/plugins/plugin.pri +++ /dev/null @@ -1,25 +0,0 @@ - -DESTDIR_KLP = $$OUT_PWD/../../.. -DESTDIR = $$OUT_PWD/.. - -include($$PWD/../klayout.pri) - -TEMPLATE = lib - -INCLUDEPATH += $$DB_INC $$TL_INC $$GSI_INC $$LAYBASIC_INC $$LAY_INC -DEPENDPATH += $$DB_INC $$TL_INC $$GSI_INC $$LAYBASIC_INC $$LAY_INC -LIBS += -L$$DESTDIR_KLP -lklayout_db -lklayout_tl -lklayout_gsi -lklayout_laybasic -lklayout_lay - -# Only on Windows, DESTDIR_TARGET is usable. On this platform, a blank happens to appear between -# $(DESTDIR) and $(TARGET) -win32 { - - QMAKE_POST_LINK += $(COPY) $(DESTDIR_TARGET) $$DESTDIR_KLP/$${TARGET}.klp - - # to avoid the major version being appended to the dll name - in this case -lxyz won't link it again - # because the library is called xyx0.dll. - CONFIG += skip_target_version_ext - -} else { - QMAKE_POST_LINK += $(COPY) $(DESTDIR)$(TARGET) $$DESTDIR_KLP/$${TARGET}.klp -} diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 5089832df..298182841 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -3,7 +3,7 @@ TEMPLATE = subdirs # Automatically include all sub-folders, but not the .pro file SUBDIR_LIST = $$files($$PWD/*) SUBDIR_LIST -= $$PWD/plugins.pro -SUBDIR_LIST -= $$PWD/plugin.pri -SUBDIR_LIST -= $$PWD/plugin_ut.pri +SUBDIR_LIST -= $$PWD/db_plugin.pri +SUBDIR_LIST -= $$PWD/lay_plugin.pri SUBDIRS = $$SUBDIR_LIST diff --git a/src/db/db/contrib/dbGDS2Converter.cc b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Converter.cc similarity index 100% rename from src/db/db/contrib/dbGDS2Converter.cc rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Converter.cc diff --git a/src/db/db/contrib/dbGDS2Converter.h b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Converter.h similarity index 100% rename from src/db/db/contrib/dbGDS2Converter.h rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Converter.h diff --git a/src/db/db/contrib/dbGDS2Text.cc b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Text.cc similarity index 96% rename from src/db/db/contrib/dbGDS2Text.cc rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Text.cc index 9ac7fed00..8f3b1711a 100644 --- a/src/db/db/contrib/dbGDS2Text.cc +++ b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2Text.cc @@ -93,8 +93,5 @@ class GDS2TextFormatDeclaration static tl::RegisteredClass format_txt_decl (new GDS2TextFormatDeclaration(), 1, "GDS2Text"); -// provide a symbol to force linking against -int force_link_GDS2Text = 0; - } diff --git a/src/db/db/contrib/dbGDS2TextReader.cc b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.cc similarity index 100% rename from src/db/db/contrib/dbGDS2TextReader.cc rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.cc diff --git a/src/db/db/contrib/dbGDS2TextReader.h b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.h similarity index 100% rename from src/db/db/contrib/dbGDS2TextReader.h rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextReader.h diff --git a/src/db/db/contrib/dbGDS2TextWriter.cc b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextWriter.cc similarity index 100% rename from src/db/db/contrib/dbGDS2TextWriter.cc rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextWriter.cc diff --git a/src/db/db/contrib/dbGDS2TextWriter.h b/src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextWriter.h similarity index 100% rename from src/db/db/contrib/dbGDS2TextWriter.h rename to src/plugins/streamers/gds2/db_plugin/contrib/dbGDS2TextWriter.h diff --git a/src/db/db/dbGDS2.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2.cc similarity index 96% rename from src/db/db/dbGDS2.cc rename to src/plugins/streamers/gds2/db_plugin/dbGDS2.cc index fd65fc8a1..7ee9d5637 100644 --- a/src/db/db/dbGDS2.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2.cc @@ -69,8 +69,5 @@ class GDS2FormatDeclaration static tl::RegisteredClass format_decl (new GDS2FormatDeclaration (), 0, "GDS2"); -// provide a symbol to force linking against -int force_link_GDS2 = 0; - } diff --git a/src/db/db/dbGDS2.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2.h similarity index 96% rename from src/db/db/dbGDS2.h rename to src/plugins/streamers/gds2/db_plugin/dbGDS2.h index 1b70bc2df..a37dffa5d 100644 --- a/src/db/db/dbGDS2.h +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2.h @@ -26,9 +26,6 @@ #include -// place this macro to force linking of GDS2 plugin -#define FORCE_LINK_GDS2 void force_link_GDS2_f () { extern int force_link_GDS2; force_link_GDS2 = 0; } - namespace db { diff --git a/src/db/db/dbGDS2Reader.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.cc similarity index 100% rename from src/db/db/dbGDS2Reader.cc rename to src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.cc diff --git a/src/db/db/dbGDS2Reader.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.h similarity index 100% rename from src/db/db/dbGDS2Reader.h rename to src/plugins/streamers/gds2/db_plugin/dbGDS2Reader.h diff --git a/src/db/db/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc similarity index 100% rename from src/db/db/dbGDS2ReaderBase.cc rename to src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc diff --git a/src/db/db/dbGDS2ReaderBase.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.h similarity index 100% rename from src/db/db/dbGDS2ReaderBase.h rename to src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.h diff --git a/src/db/db/dbGDS2Writer.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2Writer.cc similarity index 100% rename from src/db/db/dbGDS2Writer.cc rename to src/plugins/streamers/gds2/db_plugin/dbGDS2Writer.cc diff --git a/src/db/db/dbGDS2Writer.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2Writer.h similarity index 100% rename from src/db/db/dbGDS2Writer.h rename to src/plugins/streamers/gds2/db_plugin/dbGDS2Writer.h diff --git a/src/db/db/dbGDS2WriterBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.cc similarity index 100% rename from src/db/db/dbGDS2WriterBase.cc rename to src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.cc diff --git a/src/db/db/dbGDS2WriterBase.h b/src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.h similarity index 100% rename from src/db/db/dbGDS2WriterBase.h rename to src/plugins/streamers/gds2/db_plugin/dbGDS2WriterBase.h diff --git a/src/laybasic/laybasic/GDS2ReaderOptionPage.ui b/src/plugins/streamers/gds2/lay_plugin/GDS2ReaderOptionPage.ui similarity index 100% rename from src/laybasic/laybasic/GDS2ReaderOptionPage.ui rename to src/plugins/streamers/gds2/lay_plugin/GDS2ReaderOptionPage.ui diff --git a/src/laybasic/laybasic/GDS2WriterOptionPage.ui b/src/plugins/streamers/gds2/lay_plugin/GDS2WriterOptionPage.ui similarity index 100% rename from src/laybasic/laybasic/GDS2WriterOptionPage.ui rename to src/plugins/streamers/gds2/lay_plugin/GDS2WriterOptionPage.ui diff --git a/src/plugins/streamers/gds2/lay_plugin/layGDS2ReaderPlugin.cc b/src/plugins/streamers/gds2/lay_plugin/layGDS2ReaderPlugin.cc new file mode 100644 index 000000000..62a82339a --- /dev/null +++ b/src/plugins/streamers/gds2/lay_plugin/layGDS2ReaderPlugin.cc @@ -0,0 +1,114 @@ + +/* + + 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 "dbGDS2.h" +#include "dbGDS2Reader.h" +#include "dbLoadLayoutOptions.h" +#include "layGDS2ReaderPlugin.h" +#include "ui_GDS2ReaderOptionPage.h" + +#include + +namespace lay +{ + +// --------------------------------------------------------------- +// GDS2ReaderOptionPage definition and implementation + +GDS2ReaderOptionPage::GDS2ReaderOptionPage (QWidget *parent) + : StreamReaderOptionsPage (parent) +{ + mp_ui = new Ui::GDS2ReaderOptionPage (); + mp_ui->setupUi (this); +} + +GDS2ReaderOptionPage::~GDS2ReaderOptionPage () +{ + delete mp_ui; + mp_ui = 0; +} + +void +GDS2ReaderOptionPage::setup (const db::FormatSpecificReaderOptions *o, const lay::Technology * /*tech*/) +{ + static const db::GDS2ReaderOptions default_options; + const db::GDS2ReaderOptions *options = dynamic_cast (o); + if (!options) { + options = &default_options; + } + + mp_ui->big_records_cbx->setChecked (! options->allow_big_records); + mp_ui->big_poly_cbx->setChecked (! options->allow_multi_xy_records); + mp_ui->box_mode_cb->setCurrentIndex (options->box_mode); +} + +void +GDS2ReaderOptionPage::commit (db::FormatSpecificReaderOptions *o, const lay::Technology * /*tech*/) +{ + db::GDS2ReaderOptions *options = dynamic_cast (o); + if (options) { + + options->allow_big_records = ! mp_ui->big_records_cbx->isChecked (); + options->allow_multi_xy_records = ! mp_ui->big_poly_cbx->isChecked (); + options->box_mode = mp_ui->box_mode_cb->currentIndex (); + + } +} + +// --------------------------------------------------------------- +// GDS2ReaderPluginDeclaration definition and implementation + +class GDS2ReaderPluginDeclaration + : public StreamReaderPluginDeclaration +{ +public: + GDS2ReaderPluginDeclaration () + : StreamReaderPluginDeclaration (db::GDS2ReaderOptions ().format_name ()) + { + // .. nothing yet .. + } + + StreamReaderOptionsPage *format_specific_options_page (QWidget *parent) const + { + return new GDS2ReaderOptionPage (parent); + } + + db::FormatSpecificReaderOptions *create_specific_options () const + { + return new db::GDS2ReaderOptions (); + } + + virtual tl::XMLElementBase *xml_element () const + { + return new lay::ReaderOptionsXMLElement ("gds2", + tl::make_member (&db::GDS2ReaderOptions::box_mode, "box-mode") + + tl::make_member (&db::GDS2ReaderOptions::allow_big_records, "allow-big-records") + + tl::make_member (&db::GDS2ReaderOptions::allow_multi_xy_records, "allow-multi-xy-records") + ); + } +}; + +static tl::RegisteredClass plugin_decl (new lay::GDS2ReaderPluginDeclaration (), 10000, "GDS2Reader"); + +} diff --git a/src/laybasic/laybasic/layGDS2ReaderPlugin.h b/src/plugins/streamers/gds2/lay_plugin/layGDS2ReaderPlugin.h similarity index 100% rename from src/laybasic/laybasic/layGDS2ReaderPlugin.h rename to src/plugins/streamers/gds2/lay_plugin/layGDS2ReaderPlugin.h diff --git a/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc b/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc new file mode 100644 index 000000000..5f86ee3e1 --- /dev/null +++ b/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc @@ -0,0 +1,186 @@ + +/* + + 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 "dbGDS2.h" +#include "dbGDS2Writer.h" +#include "dbSaveLayoutOptions.h" +#include "layCellView.h" +#include "layGDS2WriterPlugin.h" +#include "ui_GDS2WriterOptionPage.h" + +#include + +namespace lay +{ + +// --------------------------------------------------------------- +// GDS2WriterOptionPage definition and implementation + +GDS2WriterOptionPage::GDS2WriterOptionPage (QWidget *parent) + : StreamWriterOptionsPage (parent) +{ + mp_ui = new Ui::GDS2WriterOptionPage (); + mp_ui->setupUi (this); + + connect (mp_ui->multi_xy_cbx, SIGNAL (clicked ()), this, SLOT (multi_xy_clicked ())); +} + +GDS2WriterOptionPage::~GDS2WriterOptionPage () +{ + delete mp_ui; + mp_ui = 0; +} + +void +GDS2WriterOptionPage::setup (const db::FormatSpecificWriterOptions *o, const lay::Technology * /*tech*/) +{ + const db::GDS2WriterOptions *options = dynamic_cast (o); + if (options) { + mp_ui->write_timestamps->setChecked (options->write_timestamps); + mp_ui->write_cell_properties->setChecked (options->write_cell_properties); + mp_ui->write_file_properties->setChecked (options->write_file_properties); + mp_ui->no_zero_length_paths->setChecked (options->no_zero_length_paths); + mp_ui->multi_xy_cbx->setChecked (options->multi_xy_records); + mp_ui->max_vertex_le->setEnabled (! options->multi_xy_records); + mp_ui->max_vertex_le->setText (tl::to_qstring (tl::to_string (options->max_vertex_count))); + mp_ui->cell_name_length_le->setText (tl::to_qstring (tl::to_string (options->max_cellname_length))); + mp_ui->libname_le->setText (tl::to_qstring (tl::to_string (options->libname))); + } +} + +void +GDS2WriterOptionPage::commit (db::FormatSpecificWriterOptions *o, const lay::Technology * /*tech*/, bool /*gzip*/) +{ + db::GDS2WriterOptions *options = dynamic_cast (o); + if (options) { + + unsigned int n; + options->multi_xy_records = mp_ui->multi_xy_cbx->isChecked (); + options->write_timestamps = mp_ui->write_timestamps->isChecked (); + options->write_cell_properties = mp_ui->write_cell_properties->isChecked (); + options->write_file_properties = mp_ui->write_file_properties->isChecked (); + options->no_zero_length_paths = mp_ui->no_zero_length_paths->isChecked (); + + tl::from_string (tl::to_string (mp_ui->max_vertex_le->text ()), n); + if (! options->multi_xy_records) { + if (n > 8191) { + throw tl::Exception (tl::to_string (QObject::tr ("Maximum number of vertices must not exceed 8191"))); + } + if (n < 4) { + throw tl::Exception (tl::to_string (QObject::tr ("Maximum number of vertices must be 4 at least"))); + } + } + options->max_vertex_count = n; + + n = 32000; + tl::from_string (tl::to_string (mp_ui->cell_name_length_le->text ()), n); + if (n > 32000) { + throw tl::Exception (tl::to_string (QObject::tr ("Maximum cell name length must not exceed 32000"))); + } + if (n < 8) { + throw tl::Exception (tl::to_string (QObject::tr ("Maximum cell name length must be 8 at least"))); + } + options->max_cellname_length = n; + + options->libname = tl::to_string (mp_ui->libname_le->text ()); + + } +} + +void +GDS2WriterOptionPage::multi_xy_clicked () +{ + mp_ui->max_vertex_le->setEnabled (! mp_ui->multi_xy_cbx->isChecked ()); +} + +// --------------------------------------------------------------- +// GDS2WriterPluginDeclaration definition and implementation + +class GDS2WriterPluginDeclaration + : public StreamWriterPluginDeclaration +{ +public: + GDS2WriterPluginDeclaration () + : StreamWriterPluginDeclaration (db::GDS2WriterOptions ().format_name ()) + { + // .. nothing yet .. + } + + StreamWriterOptionsPage *format_specific_options_page (QWidget *parent) const + { + return new GDS2WriterOptionPage (parent); + } + + db::FormatSpecificWriterOptions *create_specific_options () const + { + return new db::GDS2WriterOptions (); + } + + virtual tl::XMLElementBase *xml_element () const + { + return new lay::WriterOptionsXMLElement ("gds2", + tl::make_member (&db::GDS2WriterOptions::write_timestamps, "write-timestamps") + + tl::make_member (&db::GDS2WriterOptions::write_cell_properties, "write-cell-properties") + + tl::make_member (&db::GDS2WriterOptions::write_file_properties, "write-file-properties") + + tl::make_member (&db::GDS2WriterOptions::no_zero_length_paths, "no-zero-length-paths") + + tl::make_member (&db::GDS2WriterOptions::multi_xy_records, "multi-xy-records") + + tl::make_member (&db::GDS2WriterOptions::max_vertex_count, "max-vertex-count") + + tl::make_member (&db::GDS2WriterOptions::max_cellname_length, "max-cellname-length") + + tl::make_member (&db::GDS2WriterOptions::libname, "libname") + ); + } + + void initialize_options_from_layout_handle (db::FormatSpecificWriterOptions *o, const lay::LayoutHandle &lh) const + { + // Initialize the libname property from meta data with key "libname". + db::GDS2WriterOptions *options = dynamic_cast (o); + if (options) { + for (db::Layout::meta_info_iterator meta = lh.layout().begin_meta (); meta != lh.layout().end_meta (); ++meta) { + if (meta->name == "libname" && !meta->value.empty ()) { + options->libname = meta->value; + } + } + } + } +}; + +/** + * @brief A dummy plugin for GDS2Text + * + * GDS2Text shares the options with GDS2, although some limitations do not exist. + * There is not specific option set for GDS2Text. The writer will take the options from GDS2. + */ +class GDS2TextWriterPluginDeclaration + : public StreamWriterPluginDeclaration +{ +public: + GDS2TextWriterPluginDeclaration () + : StreamWriterPluginDeclaration ("GDS2Text") + { + // .. nothing yet .. + } +}; + +static tl::RegisteredClass plugin_decl1 (new lay::GDS2WriterPluginDeclaration (), 10000, "GDS2Writer"); +static tl::RegisteredClass plugin_decl2 (new lay::GDS2TextWriterPluginDeclaration (), 10001, "GDS2TextWriter"); + +} diff --git a/src/laybasic/laybasic/layGDS2WriterPlugin.h b/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.h similarity index 100% rename from src/laybasic/laybasic/layGDS2WriterPlugin.h rename to src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.h diff --git a/src/db/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc similarity index 98% rename from src/db/unit_tests/dbGDS2Reader.cc rename to src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc index 5b16c10ba..aed6d9931 100644 --- a/src/db/unit_tests/dbGDS2Reader.cc +++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc @@ -20,8 +20,6 @@ */ - - #include "dbGDS2Reader.h" #include "dbLayoutDiff.h" #include "dbTestSupport.h" @@ -227,11 +225,11 @@ TEST(1) db::Manager m; db::Layout layout (&m); tl::InputStream file (im); - db::GDS2Reader reader (file); + db::Reader reader (file); db::LayerMap map = reader.read (layout); EXPECT_EQ (fabs (layout.dbu () / 0.001 - 1.0) < 1e-6, true); - EXPECT_EQ (reader.libname (), "LIB.DB"); + EXPECT_EQ (layout.meta_info_value ("libname"), "LIB.DB"); EXPECT_EQ (layout.layers (), size_t (11)); EXPECT_EQ (map.mapping_str (0), "2/0 : 2/0"); @@ -272,7 +270,7 @@ TEST(2) db::LayerMap map_full; { tl::InputStream file (im); - db::GDS2Reader reader (file); + db::Reader reader (file); map_full = reader.read (layout); } @@ -288,10 +286,10 @@ TEST(2) im.reset (); options = empty_options; tl::InputStream file (im); - db::GDS2Reader reader (file); + db::Reader reader (file); map = reader.read (layout_none, options); EXPECT_EQ (fabs (layout_none.dbu () / 0.001 - 1.0) < 1e-6, true); - EXPECT_EQ (reader.libname (), "LIB.DB"); + EXPECT_EQ (layout.meta_info_value ("libname"), "LIB.DB"); } EXPECT_EQ (layout_none.layers (), size_t (0)); @@ -324,7 +322,7 @@ TEST(2) im.reset (); tl::InputStream file (im); - db::GDS2Reader reader (file); + db::Reader reader (file); reader.read (layout_layer, options); EXPECT_EQ (layout_layer.layers (), size_t (1)); @@ -358,13 +356,13 @@ TEST(Bug_121_1) { tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121a.gds"); - db::GDS2Reader reader (file); + db::Reader reader (file); reader.read (layout); } { tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121b.gds"); - db::GDS2Reader reader (file); + db::Reader reader (file); reader.read (layout); } @@ -379,13 +377,13 @@ TEST(Bug_121_2) { tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121a.gds"); - db::GDS2Reader reader (file); + db::Reader reader (file); reader.read (layout); } { tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121c.gds"); - db::GDS2Reader reader (file); + db::Reader reader (file); reader.read (layout); } diff --git a/src/db/unit_tests/dbGDS2Writer.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc similarity index 98% rename from src/db/unit_tests/dbGDS2Writer.cc rename to src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc index 7c4f37358..ba3716637 100644 --- a/src/db/unit_tests/dbGDS2Writer.cc +++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc @@ -49,10 +49,11 @@ void run_test (tl::TestBase *_this, const char *file, const char *file_ref, bool { tl::OutputStream stream (tmp_file); - db::GDS2Writer writer; db::SaveLayoutOptions options; + options.set_format ("GDS2"); options.set_options (new db::GDS2WriterOptions (opt)); - writer.write (layout_org, stream, options); + db::Writer writer (options); + writer.write (layout_org, stream); } db::Layout layout_read (&m); @@ -108,13 +109,13 @@ TEST(2) { tl::OutputStream stream (tmp_file); - db::GDS2Writer writer; db::SaveLayoutOptions options; db::GDS2WriterOptions *opt = new db::GDS2WriterOptions (); opt->multi_xy_records = true; options.set_options (opt); options.set_format (opt->format_name ()); - writer.write (layout_org, stream, options); + db::Writer writer (options); + writer.write (layout_org, stream); } db::Layout layout_read (&m); @@ -145,13 +146,13 @@ TEST(3) { tl::OutputStream stream (tmp_file); - db::GDS2Writer writer; db::SaveLayoutOptions options; db::GDS2WriterOptions *opt = new db::GDS2WriterOptions (); opt->max_vertex_count = 4; options.set_options (opt); options.set_format (opt->format_name ()); - writer.write (layout_org, stream, options); + db::Writer writer (options); + writer.write (layout_org, stream); } db::Layout layout_read (&m); @@ -211,9 +212,9 @@ TEST(4) { tl::OutputStream stream (tmp_file); - db::GDS2Writer writer; db::SaveLayoutOptions options; - writer.write (layout_org, stream, options); + db::Writer writer (options); + writer.write (layout_org, stream); } db::Layout layout_read (&m);