mirror of https://github.com/KLayout/klayout.git
WIP: started refactoring the plugin structure. Goal: standalone db module with it's own plugins like LEF/DEF, Gerber, MEBES including GSI bindings.
This commit is contained in:
parent
acacdc3997
commit
409392d561
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <windows.h>
|
||||
#else
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
static std::list<db::PluginDescriptor> s_plugins;
|
||||
|
||||
const std::list<db::PluginDescriptor> &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<dbp_init_func_t> (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<dbp_init_func_t> (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<std::string> &_paths)
|
||||
{
|
||||
std::vector<std::string> 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<std::string> modules;
|
||||
|
||||
for (std::vector<std::string>::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 ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
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<std::string> &paths = std::vector<std::string> ());
|
||||
|
||||
/**
|
||||
* @brief Gets a list of all plugins registered
|
||||
*/
|
||||
DB_PUBLIC const std::list<db::PluginDescriptor> &plugins ();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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<db::Layout &> (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<db::Layout &> (layout), stream, options);
|
||||
|
||||
options.set_format ("OASIS");
|
||||
}
|
||||
|
||||
tl::OutputStream stream (tmp_file.c_str ());
|
||||
db::Writer writer (options);
|
||||
writer.write (const_cast<db::Layout &> (layout), stream);
|
||||
|
||||
const db::Layout *subject = 0;
|
||||
db::Layout layout2;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include "dbLayoutDiff.h"
|
||||
#include "dbWriter.h"
|
||||
#include "dbCIFWriter.h"
|
||||
#include "dbGDS2Writer.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <QDir>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<db::Polygon> &q1, const std::vector<db::Polygon> &
|
|||
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 ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ SOURCES = \
|
|||
dbEdgeProcessor.cc \
|
||||
dbEdges.cc \
|
||||
dbEdgesToContours.cc \
|
||||
dbGDS2Reader.cc \
|
||||
dbGDS2Writer.cc \
|
||||
dbLayer.cc \
|
||||
dbLayerMapping.cc \
|
||||
dbLayout.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);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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<klp_init_func_t> (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<klp_init_func_t> (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<std::string> vv = tl::split (version, ".");
|
||||
|
|
@ -579,18 +540,17 @@ ApplicationBase::init_app ()
|
|||
}
|
||||
std::string short_arch_string = tl::join (as, "-");
|
||||
|
||||
std::vector<std::string> klp_paths;
|
||||
|
||||
for (std::vector <std::string>::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) {
|
||||
|
||||
std::set<std::string> modules;
|
||||
|
||||
std::vector<QString> 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<QString>::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 <lay::PluginDescriptor>::const_iterator p = m_native_plugins.begin (); p != m_native_plugins.end (); ++p) {
|
||||
for (std::list<lay::PluginDescriptor>::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 <lay::PluginDescriptor>::const_iterator p = m_native_plugins.begin (); p != m_native_plugins.end (); ++p) {
|
||||
for (std::list <lay::PluginDescriptor>::const_iterator p = lay::plugins ().begin (); p != lay::plugins ().end (); ++p) {
|
||||
if (p->autorun) {
|
||||
(*p->autorun) ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<PluginDescriptor> &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<PluginDescriptor> m_native_plugins;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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 <windows.h>
|
||||
#else
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
static std::list<lay::PluginDescriptor> s_plugins;
|
||||
|
||||
const std::list<lay::PluginDescriptor> &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<klp_init_func_t> (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<klp_init_func_t> (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<std::string> &_paths)
|
||||
{
|
||||
std::vector<std::string> 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<std::string> modules;
|
||||
|
||||
for (std::vector<std::string>::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 ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
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<std::string> &paths = std::vector<std::string> ());
|
||||
|
||||
/**
|
||||
* @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<lay::PluginDescriptor> &plugins ();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -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 += "</ul>";
|
||||
}
|
||||
|
||||
if (! lay::ApplicationBase::instance ()->native_plugins ().empty ()) {
|
||||
if (! lay::plugins ().empty () || ! db::plugins ().empty ()) {
|
||||
|
||||
s += "<p>";
|
||||
s += "<h4>";
|
||||
s += escape_xml (tl::to_string (QObject::tr ("Binary extensions:")));
|
||||
s += "</h4><ul>";
|
||||
for (std::vector<lay::PluginDescriptor>::const_iterator pd = lay::ApplicationBase::instance ()->native_plugins ().begin (); pd != lay::ApplicationBase::instance ()->native_plugins ().end (); ++pd) {
|
||||
|
||||
for (std::list<lay::PluginDescriptor>::const_iterator pd = lay::plugins ().begin (); pd != lay::plugins ().end (); ++pd) {
|
||||
s += "<li>";
|
||||
if (! pd->description.empty ()) {
|
||||
s += escape_xml (pd->description);
|
||||
|
|
@ -5675,7 +5679,22 @@ HelpAboutDialog::HelpAboutDialog (QWidget *parent)
|
|||
}
|
||||
s += "</li>";
|
||||
}
|
||||
|
||||
for (std::list<db::PluginDescriptor>::const_iterator pd = db::plugins ().begin (); pd != db::plugins ().end (); ++pd) {
|
||||
s += "<li>";
|
||||
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 += "</li>";
|
||||
}
|
||||
|
||||
s += "</ul>";
|
||||
|
||||
}
|
||||
|
||||
s += "</body></html>";
|
||||
|
|
|
|||
|
|
@ -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 <QFrame>
|
||||
|
||||
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<const db::GDS2ReaderOptions *> (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<db::GDS2ReaderOptions *> (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<db::GDS2ReaderOptions> ("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<lay::PluginDeclaration> 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<db::GDS2ReaderOptions> ().box_mode = n;
|
||||
}
|
||||
|
||||
static unsigned int get_gds2_box_mode (const db::LoadLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2ReaderOptions> ().box_mode;
|
||||
}
|
||||
|
||||
static void set_gds2_allow_multi_xy_records (db::LoadLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2ReaderOptions> ().allow_multi_xy_records = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_allow_multi_xy_records (const db::LoadLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2ReaderOptions> ().allow_multi_xy_records;
|
||||
}
|
||||
|
||||
static void set_gds2_allow_big_records (db::LoadLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2ReaderOptions> ().allow_big_records = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_allow_big_records (const db::LoadLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2ReaderOptions> ().allow_big_records;
|
||||
}
|
||||
|
||||
// extend lay::LoadLayoutOptions with the GDS2 options
|
||||
static
|
||||
gsi::ClassExt<db::LoadLayoutOptions> 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"
|
||||
),
|
||||
""
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 <QFrame>
|
||||
|
||||
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<const db::GDS2WriterOptions *> (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<db::GDS2WriterOptions *> (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<db::GDS2WriterOptions> ("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<db::GDS2WriterOptions *> (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<lay::PluginDeclaration> plugin_decl1 (new lay::GDS2WriterPluginDeclaration (), 10000, "GDS2Writer");
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> 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<db::GDS2WriterOptions> ().max_vertex_count = n;
|
||||
}
|
||||
|
||||
static unsigned int get_gds2_max_vertex_count (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().max_vertex_count;
|
||||
}
|
||||
|
||||
static void set_gds2_max_cellname_length (db::SaveLayoutOptions *options, unsigned int n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().max_cellname_length = n;
|
||||
}
|
||||
|
||||
static unsigned int get_gds2_max_cellname_length (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().max_cellname_length;
|
||||
}
|
||||
|
||||
static void set_gds2_multi_xy_records (db::SaveLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().multi_xy_records = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_multi_xy_records (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().multi_xy_records;
|
||||
}
|
||||
|
||||
static void set_gds2_write_file_properties (db::SaveLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().write_file_properties = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_write_file_properties (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().write_file_properties;
|
||||
}
|
||||
|
||||
static void set_gds2_write_cell_properties (db::SaveLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().write_cell_properties = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_write_cell_properties (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().write_cell_properties;
|
||||
}
|
||||
|
||||
static void set_gds2_no_zero_length_paths (db::SaveLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().no_zero_length_paths = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_no_zero_length_paths (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().no_zero_length_paths;
|
||||
}
|
||||
|
||||
static void set_gds2_write_timestamps (db::SaveLayoutOptions *options, bool n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().write_timestamps = n;
|
||||
}
|
||||
|
||||
static bool get_gds2_write_timestamps (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().write_timestamps;
|
||||
}
|
||||
|
||||
static void set_gds2_libname (db::SaveLayoutOptions *options, const std::string &n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().libname = n;
|
||||
}
|
||||
|
||||
static std::string get_gds2_libname (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().libname;
|
||||
}
|
||||
|
||||
static void set_gds2_user_units (db::SaveLayoutOptions *options, double n)
|
||||
{
|
||||
options->get_options<db::GDS2WriterOptions> ().user_units = n;
|
||||
}
|
||||
|
||||
static double get_gds2_user_units (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::GDS2WriterOptions> ().user_units;
|
||||
}
|
||||
|
||||
// extend lay::SaveLayoutOptions with the GDS2 options
|
||||
static
|
||||
gsi::ClassExt<db::SaveLayoutOptions> 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"
|
||||
),
|
||||
""
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -93,8 +93,5 @@ class GDS2TextFormatDeclaration
|
|||
|
||||
static tl::RegisteredClass<db::StreamFormatDeclaration> format_txt_decl (new GDS2TextFormatDeclaration(), 1, "GDS2Text");
|
||||
|
||||
// provide a symbol to force linking against
|
||||
int force_link_GDS2Text = 0;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +69,5 @@ class GDS2FormatDeclaration
|
|||
|
||||
static tl::RegisteredClass<db::StreamFormatDeclaration> format_decl (new GDS2FormatDeclaration (), 0, "GDS2");
|
||||
|
||||
// provide a symbol to force linking against
|
||||
int force_link_GDS2 = 0;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -26,9 +26,6 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
{
|
||||
|
||||
|
|
@ -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 <QFrame>
|
||||
|
||||
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<const db::GDS2ReaderOptions *> (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<db::GDS2ReaderOptions *> (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<db::GDS2ReaderOptions> ("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<lay::PluginDeclaration> plugin_decl (new lay::GDS2ReaderPluginDeclaration (), 10000, "GDS2Reader");
|
||||
|
||||
}
|
||||
|
|
@ -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 <QFrame>
|
||||
|
||||
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<const db::GDS2WriterOptions *> (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<db::GDS2WriterOptions *> (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<db::GDS2WriterOptions> ("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<db::GDS2WriterOptions *> (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<lay::PluginDeclaration> plugin_decl1 (new lay::GDS2WriterPluginDeclaration (), 10000, "GDS2Writer");
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> plugin_decl2 (new lay::GDS2TextWriterPluginDeclaration (), 10001, "GDS2TextWriter");
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
Loading…
Reference in New Issue