Merge pull request #2192 from KLayout/bugfix/issue-2191

Implemented a fix for issue #2191 (LIBNAME not saved)
This commit is contained in:
Matthias Köfferlein 2025-10-19 19:45:37 +02:00 committed by GitHub
commit 0ce335d8cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 246 additions and 198 deletions

View File

@ -35,6 +35,7 @@ GenericWriterOptions::GenericWriterOptions ()
db::SaveLayoutOptions save_options;
m_dbu = save_options.get_option_by_name ("dbu").to_double ();
m_libname = save_options.get_option_by_name ("libname").to_string ();
m_dont_write_empty_cells = save_options.get_option_by_name ("no_empty_cells").to_bool ();
m_keep_instances = save_options.get_option_by_name ("keep_instances").to_bool ();
@ -45,7 +46,6 @@ GenericWriterOptions::GenericWriterOptions ()
m_gds2_multi_xy_records = save_options.get_option_by_name ("gds2_multi_xy_records").to_bool ();
m_gds2_resolve_skew_arrays = save_options.get_option_by_name ("gds2_resolve_skew_arrays").to_bool ();
m_gds2_max_cellname_length = save_options.get_option_by_name ("gds2_max_cellname_length").to_uint ();
m_gds2_libname = save_options.get_option_by_name ("gds2_libname").to_string ();
m_gds2_user_units = save_options.get_option_by_name ("gds2_user_units").to_double ();
m_gds2_write_timestamps = save_options.get_option_by_name ("gds2_write_timestamps").to_bool ();
m_gds2_write_cell_properties = save_options.get_option_by_name ("gds2_write_cell_properties").to_bool ();
@ -98,6 +98,11 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin
"change physically because internally, the coordinates are scaled to match the "
"new database unit."
);
cmd << tl::arg (group +
"-ol|--libname=libname", &m_libname, "Uses the given library name",
"This option can specify the LIBNAME for the output file. By default, the original LIBNAME is "
"written. This option is generic, but currently only supported by GDS2."
);
}
cmd << tl::arg (group +
@ -178,11 +183,6 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin
"-on|--cellname-length=length", &m_gds2_max_cellname_length, "Limits cell names to the given length",
"If this option is given, long cell names will truncated if their length exceeds the given length."
)
<< tl::arg (group +
"-ol|--libname=libname", &m_gds2_libname, "Uses the given library name",
"This option can specify the GDS2 LIBNAME for the output file. By default, the original LIBNAME is "
"written."
)
<< tl::arg (group +
"#--user-units=unit", &m_gds2_user_units, "Specifies the user unit to use",
"Specifies the GDS2 user unit. By default micrometers are used for the user unit."
@ -374,6 +374,7 @@ GenericWriterOptions::configure (db::SaveLayoutOptions &save_options, const db::
{
save_options.set_scale_factor (m_scale_factor);
save_options.set_dbu (m_dbu);
save_options.set_libname (m_libname);
save_options.set_dont_write_empty_cells (m_dont_write_empty_cells);
save_options.set_keep_instances (m_keep_instances);
save_options.set_write_context_info (m_write_context_info);
@ -383,7 +384,6 @@ GenericWriterOptions::configure (db::SaveLayoutOptions &save_options, const db::
save_options.set_option_by_name ("gds2_multi_xy_records", m_gds2_multi_xy_records);
save_options.set_option_by_name ("gds2_resolve_skew_arrays", m_gds2_resolve_skew_arrays);
save_options.set_option_by_name ("gds2_max_cellname_length", m_gds2_max_cellname_length);
save_options.set_option_by_name ("gds2_libname", m_gds2_libname);
save_options.set_option_by_name ("gds2_user_units", m_gds2_user_units);
save_options.set_option_by_name ("gds2_write_timestamps", m_gds2_write_timestamps);
save_options.set_option_by_name ("gds2_write_cell_properties", m_gds2_write_cell_properties);

View File

@ -118,7 +118,7 @@ private:
bool m_gds2_multi_xy_records;
bool m_gds2_resolve_skew_arrays;
unsigned int m_gds2_max_cellname_length;
std::string m_gds2_libname;
std::string m_libname;
double m_gds2_user_units;
bool m_gds2_write_timestamps;
bool m_gds2_write_cell_properties;

View File

@ -43,13 +43,13 @@ TEST(1)
"--drop-empty-cells",
"--keep-instances",
"--no-context-info",
"-ol=MYLIBNAME",
// CIF
"--blank-separator",
"--dummy-calls",
// DXF
"-op=2",
// GDS2
"-ol=MYLIBNAME",
"-ov=250",
"--multi-xy-records",
"--no-timestamps",
@ -77,7 +77,7 @@ TEST(1)
EXPECT_EQ (stream_opt.get_option_by_name ("cif_blank_separator").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_dummy_calls").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_polygon_mode").to_int (), 0);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_libname").to_string (), "LIB");
EXPECT_EQ (stream_opt.get_option_by_name ("libname").to_string (), "");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_max_vertex_count").to_uint (), (unsigned int) 8000);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_multi_xy_records").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_timestamps").to_bool (), true);
@ -100,10 +100,11 @@ TEST(1)
EXPECT_EQ (stream_opt.dont_write_empty_cells (), true);
EXPECT_EQ (stream_opt.keep_instances (), true);
EXPECT_EQ (stream_opt.write_context_info (), false);
EXPECT_EQ (stream_opt.libname (), "MYLIBNAME");
EXPECT_EQ (stream_opt.get_option_by_name ("libname").to_string (), "MYLIBNAME");
EXPECT_EQ (stream_opt.get_option_by_name ("cif_blank_separator").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_dummy_calls").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_polygon_mode").to_int (), 2);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_libname").to_string (), "MYLIBNAME");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_max_vertex_count").to_uint (), (unsigned int) 250);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_multi_xy_records").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_timestamps").to_bool (), false);

View File

@ -61,6 +61,7 @@ SaveLayoutOptions::operator= (const SaveLayoutOptions &d)
m_all_cells = d.m_all_cells;
m_dbu = d.m_dbu;
m_scale_factor = d.m_scale_factor;
m_libname = d.m_libname;
m_keep_instances = d.m_keep_instances;
m_write_context_info = d.m_write_context_info;
m_dont_write_empty_cells = d.m_dont_write_empty_cells;
@ -220,6 +221,12 @@ SaveLayoutOptions::set_dbu (double dbu)
m_dbu = dbu;
}
void
SaveLayoutOptions::set_libname (const std::string &libname)
{
m_libname = libname;
}
void
SaveLayoutOptions::set_scale_factor (double f)
{

View File

@ -194,6 +194,19 @@ public:
return m_scale_factor;
}
/**
* @brief Sets the libname
*/
void set_libname (const std::string &libname);
/**
* @brief Gets the libname
*/
const std::string &libname () const
{
return m_libname;
}
/**
* @brief Set the "don't write empty cells flag"
*/
@ -440,6 +453,7 @@ private:
bool m_all_cells;
double m_dbu;
double m_scale_factor;
std::string m_libname;
bool m_keep_instances;
bool m_write_context_info;
bool m_dont_write_empty_cells;

View File

@ -3022,7 +3022,7 @@ Class<db::SaveLayoutOptions> decl_SaveLayoutOptions ("db", "SaveLayoutOptions",
"This method was introduced in version 0.23.\n"
) +
gsi::method ("dbu=", &db::SaveLayoutOptions::set_dbu, gsi::arg ("dbu"),
"@brief Set the database unit to be used in the stream file\n"
"@brief Sets the database unit to be used in the stream file\n"
"\n"
"By default, the database unit of the layout is used. This method allows one to explicitly use a different\n"
"database unit. A scale factor is introduced automatically which scales all layout objects accordingly so their physical dimensions remain the same. "
@ -3030,7 +3030,7 @@ Class<db::SaveLayoutOptions> decl_SaveLayoutOptions ("db", "SaveLayoutOptions",
"layout may become slightly distorted."
) +
gsi::method ("dbu", &db::SaveLayoutOptions::dbu,
"@brief Get the explicit database unit if one is set\n"
"@brief Gets the explicit database unit if one is set\n"
"\n"
"See \\dbu= for a description of that attribute.\n"
) +
@ -3044,8 +3044,24 @@ Class<db::SaveLayoutOptions> decl_SaveLayoutOptions ("db", "SaveLayoutOptions",
gsi::method ("no_empty_cells?", &db::SaveLayoutOptions::dont_write_empty_cells,
"@brief Returns a flag indicating whether empty cells are not written.\n"
) +
gsi::method ("libname=|#gds2_libname=", &db::SaveLayoutOptions::set_libname, gsi::arg ("libname"),
"@brief Sets the library name\n"
"\n"
"The library name is an attribute and specifies a formal name for a library, if the layout files is to be used as one.\n"
"Currently, this attribute is only supported by the GDS2 format. Hence the alias.\n"
"\n"
"By default or if the libname is an empty string, the current library name of the layout or 'LIB' is used.\n"
"\n"
"The 'libname' alias has been introduced in version 0.30.5. The original name \\gds2_libname= is still available."
) +
gsi::method ("libname|#gds2_libname", &db::SaveLayoutOptions::libname,
"@brief Gets the library name\n"
"\n"
"See \\libname= for details.\n"
"The 'libname' alias has been introduced in version 0.30.5. The original name \\gds2_libname is still available."
) +
gsi::method ("scale_factor=", &db::SaveLayoutOptions::set_scale_factor, gsi::arg ("scale_factor"),
"@brief Set the scaling factor for the saving \n"
"@brief Sets the scaling factor for the saving \n"
"\n"
"Using a scaling factor will scale all objects accordingly. "
"This scale factor adds to a potential scaling implied by using an explicit database unit.\n"

View File

@ -2315,8 +2315,17 @@ MainWindow::do_save (bool as)
options.set_format (cv->save_options ().format ());
}
// preconfigure options with current values
options.set_dbu (cv->layout ().dbu ());
if (cv->layout ().has_meta_info ("libname")) {
tl::Variant libname = cv->layout ().meta_info ("libname").value;
if (libname.is_a_string ()) {
options.set_libname (libname.to_stdstring ());
}
}
if (as || options.format ().empty ()) {
options.set_format_from_filename (fn);
}

View File

@ -319,7 +319,6 @@ LayoutHandle::update_save_options (db::SaveLayoutOptions &options)
}
if (specific_options.get ()) {
decl->initialize_options_from_layout_handle (specific_options.get (), *this);
options.set_options (specific_options.release ());
}

View File

@ -258,18 +258,6 @@ public:
{
return 0;
}
/**
* @brief Initialize the writer options from a layout handle
*
* The layout handle carries information about meta data read and similar. This
* method gives the plugin a chance to modify the options based on the meta data
* of the layout.
*/
virtual void initialize_options_from_layout_handle (db::FormatSpecificWriterOptions * /*options*/, const lay::LayoutHandle & /*lh*/) const
{
// the default implementation does nothing.
}
};
}

View File

@ -152,10 +152,10 @@
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="2">
<widget class="QLabel" name="label_7">
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>µm</string>
<string>Cell context</string>
</property>
</widget>
</item>
@ -166,16 +166,23 @@
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="sf_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="4" column="1" colspan="6">
<widget class="QCheckBox" name="store_context_cb">
<property name="text">
<string>1.0</string>
<string>Store PCell and library context information (format specific)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cell tree</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
@ -195,14 +202,7 @@
</property>
</spacer>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Scaling factor</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="6">
<item row="3" column="1" colspan="6">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -278,6 +278,46 @@
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>µm</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Scaling factor</string>
</property>
</widget>
</item>
<item row="1" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="sf_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>1.0</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
@ -304,29 +344,6 @@
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cell tree</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="1" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="dbu_le">
<property name="sizePolicy">
@ -337,20 +354,13 @@
</property>
</widget>
</item>
<item row="3" column="1" colspan="6">
<widget class="QCheckBox" name="store_context_cb">
<property name="text">
<string>Store PCell and library context information (format specific)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<item row="2" column="1" colspan="5">
<widget class="QLineEdit" name="libname_le"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<item row="2" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cell context</string>
<string>Library name</string>
</property>
</widget>
</item>

View File

@ -462,6 +462,7 @@ SaveLayoutAsOptionsDialog::get_options (lay::LayoutViewBase *view, unsigned int
mp_ui->compression->setCurrentIndex (om_to_index (om));
mp_ui->dbu_le->setText (tl::to_qstring (tl::to_string (options.dbu ())));
mp_ui->libname_le->setText (tl::to_qstring (options.libname ()));
mp_ui->fmt_cbx->setCurrentIndex (0);
fmt_cbx_changed (0);
@ -490,8 +491,6 @@ SaveLayoutAsOptionsDialog::get_options (lay::LayoutViewBase *view, unsigned int
specific_options.reset (decl->create_specific_options ());
}
decl->initialize_options_from_layout_handle (specific_options.get (), *cv.handle ());
if (page->first) {
page->first->setup (specific_options.get (), mp_tech);
}
@ -524,6 +523,7 @@ SaveLayoutAsOptionsDialog::get_options (lay::LayoutViewBase *view, unsigned int
options.set_dbu (dbu);
options.set_scale_factor (sf);
options.set_libname (tl::to_string (mp_ui->libname_le->text ()));
options.set_dont_write_empty_cells (mp_ui->no_empty_cells_cb->isChecked ());
options.set_keep_instances (mp_ui->keep_instances_cb->isChecked ());
options.set_write_context_info (mp_ui->store_context_cb->isChecked ());

View File

@ -77,8 +77,7 @@ class GDS2FormatDeclaration
tl::make_member (&db::GDS2WriterOptions::multi_xy_records, "multi-xy-records") +
tl::make_member (&db::GDS2WriterOptions::resolve_skew_arrays, "resolve-skew-arrays") +
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")
tl::make_member (&db::GDS2WriterOptions::max_cellname_length, "max-cellname-length")
);
}

View File

@ -111,7 +111,6 @@ public:
multi_xy_records (false),
resolve_skew_arrays (false),
max_cellname_length (32000),
libname ("LIB"),
user_units (1.0),
write_timestamps (true),
write_cell_properties (false),
@ -163,13 +162,6 @@ public:
*/
unsigned int max_cellname_length;
/**
* @brief The library name
*
* This property describes that library name written to the LIBNAME record.
*/
std::string libname;
/**
* @brief The user units to use
*

View File

@ -435,9 +435,20 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
db::GDS2WriterOptions gds2_options = options.get_options<db::GDS2WriterOptions> ();
m_libname = options.libname ();
if (m_libname.empty () && layout.has_meta_info ("libname")) {
tl::Variant libname = layout.meta_info ("libname").value;
if (libname.is_a_string ()) {
m_libname = libname.to_stdstring ();
}
}
if (m_libname.empty ()) {
m_libname = "LIB";
}
layout.add_meta_info ("dbuu", MetaInfo (tl::to_string (tr ("Database unit in user units")), tl::to_string (m_dbu / std::max (1e-9, gds2_options.user_units))));
layout.add_meta_info ("dbum", MetaInfo (tl::to_string (tr ("Database unit in meter")), tl::to_string (m_dbu * 1e-6)));
layout.add_meta_info ("libname", MetaInfo (tl::to_string (tr ("Library name")), gds2_options.libname));
layout.add_meta_info ("libname", MetaInfo (tl::to_string (tr ("Library name")), m_libname));
std::vector <std::pair <unsigned int, db::LayerProperties> > layers;
options.get_valid_layers (layout, layers, db::SaveLayoutOptions::LP_AssignNumber);
@ -517,7 +528,7 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
write_time (time_data);
try {
write_string_record (sLIBNAME, gds2_options.libname);
write_string_record (sLIBNAME, m_libname);
} catch (tl::Exception &ex) {
throw tl::Exception (ex.msg () + tl::to_string (tr (", writing LIBNAME")));
}

View File

@ -168,6 +168,7 @@ protected:
private:
db::WriterCellNameMap m_cell_name_map;
double m_dbu;
std::string m_libname;
bool m_resolve_skew_arrays;
bool m_multi_xy;
bool m_no_zero_length_paths;

View File

@ -126,16 +126,6 @@ static tl::Variant get_gds2_default_text_size (const db::SaveLayoutOptions *opti
return ts < 0.0 ? tl::Variant () : tl::Variant (ts);
}
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;
@ -263,18 +253,6 @@ gsi::ClassExt<db::SaveLayoutOptions> gds2_writer_options (
"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, gsi::arg ("libname"),
"@brief Set the library name\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, gsi::arg ("uu"),
"@brief Set the users units to write into the GDS file\n"
"\n"

View File

@ -50,55 +50,45 @@
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="libname_le"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<item row="3" column="2">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Max. cell name length</string>
<string>µm (empty for no size)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="cell_name_length_le"/>
</item>
<item row="7" column="0" colspan="3">
<widget class="QCheckBox" name="no_zero_length_paths">
<property name="text">
<string>Eliminate zero-length paths (convert to BOUNDARY)</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>(&lt;4000 recommended, absolute limit 8191)</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="resolve_skew_arrays_cbx">
<property name="text">
<string>Resolve skew (non-orthogonal) arrays into single instances</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="3">
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Default text size</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="max_vertex_le"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Max. cell name length</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QCheckBox" name="write_timestamps">
<property name="text">
<string>Write current time to time stamps (BGNLIB, BGNSTR)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Library name</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<item row="2" column="1" colspan="3">
<widget class="QCheckBox" name="multi_xy_cbx">
<property name="text">
<string>Multi-XY record mode for boundaries
@ -106,24 +96,7 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>(keep empty for unspecified limit)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Max. vertices</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="max_vertex_le"/>
</item>
<item row="5" column="0" colspan="3">
<item row="4" column="0" colspan="3">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -188,20 +161,37 @@
</layout>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="default_text_size_le"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_9">
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Default text size</string>
<string>Max. vertices</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="label_10">
<item row="3" column="1">
<widget class="QLineEdit" name="default_text_size_le"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>µm (empty for no size)</string>
<string>(&lt;4000 recommended, absolute limit 8191)</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<widget class="QCheckBox" name="no_zero_length_paths">
<property name="text">
<string>Eliminate zero-length paths (convert to BOUNDARY)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="cell_name_length_le"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>(keep empty for unspecified limit)</string>
</property>
</widget>
</item>
@ -224,7 +214,6 @@
</layout>
</widget>
<tabstops>
<tabstop>libname_le</tabstop>
<tabstop>cell_name_length_le</tabstop>
<tabstop>max_vertex_le</tabstop>
<tabstop>multi_xy_cbx</tabstop>

View File

@ -66,7 +66,6 @@ GDS2WriterOptionPage::setup (const db::FormatSpecificWriterOptions *o, const db:
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->default_text_size_le->setText (tl::to_qstring (options->default_text_size >= 0.0 ? tl::to_string (options->default_text_size) : std::string ()));
mp_ui->libname_le->setText (tl::to_qstring (tl::to_string (options->libname)));
}
}
@ -118,8 +117,6 @@ GDS2WriterOptionPage::commit (db::FormatSpecificWriterOptions *o, const db::Tech
}
options->max_cellname_length = n;
options->libname = tl::to_string (mp_ui->libname_le->text ());
}
}
@ -153,20 +150,6 @@ public:
{
return new db::GDS2WriterOptions ();
}
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) {
db::Layout::meta_info_name_id_type libname_name_id = lh.layout().meta_info_name_id ("libname");
for (db::Layout::meta_info_iterator meta = lh.layout().begin_meta (); meta != lh.layout().end_meta (); ++meta) {
if (meta->first == libname_name_id && !meta->second.value.is_nil ()) {
options->libname = meta->second.value.to_string ();
}
}
}
}
};
}

View File

@ -1487,6 +1487,49 @@ class DBLayoutTests2_TestClass < TestBase
end
def test_gds2_libname
ly = RBA::Layout::new
options = RBA::SaveLayoutOptions::new
options.format = "GDS2"
byte_buffer = ly.write_bytes(options)
# undefined libname is written as "LIB"
ly2 = RBA::Layout::new
ly2.read_bytes(byte_buffer)
assert_equal(ly2.meta_info_value("libname").to_s, "LIB")
options.libname = "ABC"
ly.remove_meta_info("libname")
byte_buffer = ly.write_bytes(options)
# libname is taken from options
ly2 = RBA::Layout::new
ly2.read_bytes(byte_buffer)
assert_equal(ly2.meta_info_value("libname").to_s, "ABC")
ly.remove_meta_info("libname")
ly.add_meta_info(RBA::LayoutMetaInfo::new("libname", "X"))
options.libname = ""
byte_buffer = ly.write_bytes(options)
# libname from layout is used
ly2 = RBA::Layout::new
ly2.read_bytes(byte_buffer)
assert_equal(ly2.meta_info_value("libname").to_s, "X")
options.libname = "Z"
byte_buffer = ly.write_bytes(options)
# libname from options has priority
ly2 = RBA::Layout::new
ly2.read_bytes(byte_buffer)
assert_equal(ly2.meta_info_value("libname").to_s, "Z")
# ... and replaces the info in the source layout
assert_equal(ly.meta_info_value("libname").to_s, "Z")
end
end
load("test_epilogue.rb")

View File

@ -41,10 +41,18 @@ class SaveLayoutOptions_TestClass < TestBase
opt.select_all_cells
opt.select_all_layers
assert_equal(opt.dbu, 0.0)
opt.dbu = 0.5
assert_equal(opt.dbu, 0.5)
assert_equal(opt.libname, "")
opt.libname = "ABC"
assert_equal(opt.libname, "ABC")
assert_equal(opt.gds2_libname, "ABC")
opt.gds2_libname = "X"
assert_equal(opt.libname, "X")
assert_equal(opt.gds2_libname, "X")
opt.scale_factor = 1.5
assert_equal(opt.scale_factor, 1.5)