mirror of
https://github.com/KLayout/klayout.git
synced 2026-08-30 17:53:00 +02:00
409 lines
16 KiB
C++
409 lines
16 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 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"
|
|
),
|
|
""
|
|
);
|
|
|
|
}
|
|
|
|
|