From ef6f3f182a54dea97f69bb2c7e8e3b8291c08813 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 4 Jan 2023 21:17:12 +0100 Subject: [PATCH 1/6] Fixed issue #1242 (KLayout 0.28.2 crashes when registering a plugin if a layout exists) Problem was twofold: first, events are triggered during construction of the plugin which met an uninitialized pointer. Second, the clearing of existing plugins failed because of iterating a vector while destroying it's members erased member of it. --- src/laybasic/laybasic/layLayoutViewBase.cc | 5 ++-- src/layview/layview/layLayoutView_qt.cc | 16 ++++++++--- testdata/ruby/layLayoutView.rb | 33 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index e27ee26b1..5bd487cbf 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -578,10 +578,11 @@ void LayoutViewBase::drop_url (const std::string &path_or_url) void LayoutViewBase::clear_plugins () { - for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + std::vector plugins; + mp_plugins.swap (plugins); + for (std::vector::iterator p = plugins.begin (); p != plugins.end (); ++p) { delete *p; } - mp_plugins.clear (); mp_active_plugin = 0; } diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index 495c9beab..90f7b6ea4 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -98,15 +98,23 @@ namespace lay // LayoutViewWidget implementation LayoutViewWidget::LayoutViewWidget (db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent, unsigned int options) - : QFrame (parent) + : QFrame (parent), mp_view (0) { - mp_view = new LayoutView (mgr, editable, plugin_parent, this, options); + // NOTE: construction the LayoutView may trigger events (script code executed etc.) which must + // not meet an invalid mp_view pointer (e.g. in eventFilter). Hence, mp_view is 0 first, and set only + // after the LayoutView is successfully constructed. + std::unique_ptr view (new LayoutView (mgr, editable, plugin_parent, this, options)); + mp_view = view.release (); } LayoutViewWidget::LayoutViewWidget (lay::LayoutView *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent, unsigned int options) - : QFrame (parent) + : QFrame (parent), mp_view (0) { - mp_view = new LayoutView (source, mgr, editable, plugin_parent, this, options); + // NOTE: construction the LayoutView may trigger events (script code executed etc.) which must + // not meet an invalid mp_view pointer (e.g. in eventFilter). Hence, mp_view is 0 first, and set only + // after the LayoutView is successfully constructed. + std::unique_ptr view (new LayoutView (source, mgr, editable, plugin_parent, this, options)); + mp_view = view.release (); } LayoutViewWidget::~LayoutViewWidget () diff --git a/testdata/ruby/layLayoutView.rb b/testdata/ruby/layLayoutView.rb index 6aeccd326..c22c891d8 100644 --- a/testdata/ruby/layLayoutView.rb +++ b/testdata/ruby/layLayoutView.rb @@ -498,6 +498,39 @@ class LAYLayoutView_TestClass < TestBase end + class DummyPlugin < RBA::Plugin + def initialize(manager, view) + self.manager = manager + self.view = view + end + end + + class DummyPluginFactory < RBA::PluginFactory + def initialize() + register(1000, "dummy_plugin", "Dummy Plugin") + end + def create_plugin(manager, unused, view) + DummyPlugin::new(manager, view) + end + end + + # issue-1242 + def test_6 + + # Create a new layout + main_window = RBA::MainWindow.instance() + main_window.close_all + main_window.create_layout(2) + + # Register plugin -> crashes in issue-1242 + dpi = DummyPluginFactory::new + + main_window.close_all + + dpi._destroy + + end + end load("test_epilogue.rb") From 500fee3ff6b56fea502f363325c28157460b0125 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 11 Jan 2023 23:31:09 +0100 Subject: [PATCH 2/6] Fixed issue #1245 by using a smarter implementation for the backward compatibility fallback. Added unit tests and new (old) GSI bindings for that purpose. --- .../net_tracer/db_plugin/dbNetTracerIO.cc | 2 + .../net_tracer/db_plugin/dbNetTracerIO.h | 11 +++ .../net_tracer/db_plugin/dbNetTracerPlugin.cc | 33 +++++-- .../db_plugin/gsiDeclDbNetTracer.cc | 55 +++++++++++ testdata/ruby/layTechnologies.rb | 91 ++++++++++++++++++- 5 files changed, 181 insertions(+), 11 deletions(-) diff --git a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.cc b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.cc index 124157793..132f9e5a3 100644 --- a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.cc +++ b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.cc @@ -498,6 +498,7 @@ NetTracerTechnologyComponent::NetTracerTechnologyComponent () // NetTracerConnectivity implementation NetTracerConnectivity::NetTracerConnectivity () + : m_is_fallback_default (false) { // .. nothing yet .. } @@ -510,6 +511,7 @@ NetTracerConnectivity::NetTracerConnectivity (const NetTracerConnectivity &d) NetTracerConnectivity &NetTracerConnectivity::operator= (const NetTracerConnectivity &d) { if (this != &d) { + m_is_fallback_default = d.m_is_fallback_default; m_connections = d.m_connections; m_symbols = d.m_symbols; m_name = d.m_name; diff --git a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.h b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.h index de4a10407..e8f7a8d9c 100644 --- a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.h +++ b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerIO.h @@ -369,6 +369,16 @@ public: NetTracerConnectivity (const NetTracerConnectivity &d); NetTracerConnectivity &operator= (const NetTracerConnectivity &d); + bool is_fallback_default () const + { + return m_is_fallback_default; + } + + void set_fallback_default (bool f) + { + m_is_fallback_default = f; + } + const std::string &name () const { return m_name; @@ -491,6 +501,7 @@ private: std::vector m_connections; std::vector m_symbols; std::string m_name, m_description; + bool m_is_fallback_default; }; class DB_PLUGIN_PUBLIC NetTracerTechnologyComponent diff --git a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc index 3444bbe24..d5ad41a84 100644 --- a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc +++ b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc @@ -68,6 +68,18 @@ namespace tl namespace { +static const db::NetTracerConnectivity * +get_fallback_default (const db::NetTracerTechnologyComponent &tc) +{ + for (auto d = tc.begin (); d != tc.end (); ++d) { + if (d->is_fallback_default ()) { + return d.operator-> (); + } + } + + return 0; +} + static const db::NetTracerConnectivity * get_default (const db::NetTracerTechnologyComponent &tc) { @@ -88,28 +100,29 @@ get_default (const db::NetTracerTechnologyComponent &tc) template struct FallbackXMLWriteAdaptor { - FallbackXMLWriteAdaptor (void (db::NetTracerConnectivity::*member) (const Value &), void (db::NetTracerConnectivity::*clear) ()) - : mp_member (member), mp_clear (clear) + FallbackXMLWriteAdaptor (void (db::NetTracerConnectivity::*member) (const Value &)) + : mp_member (member) { // .. nothing yet .. } void operator () (db::NetTracerTechnologyComponent &owner, tl::XMLReaderState &reader) const { - db::NetTracerConnectivity *stack = const_cast (get_default (owner)); - if (! stack) { + db::NetTracerConnectivity *stack = const_cast (get_fallback_default (owner)); + if (! stack && owner.begin () == owner.end ()) { owner.push_back (db::NetTracerConnectivity ()); stack = (owner.end () - 1).operator-> (); + stack->set_fallback_default (true); } - (stack->*mp_clear) (); - tl::XMLObjTag tag; - (stack->*mp_member) (*reader.back (tag)); + if (stack) { + tl::XMLObjTag tag; + (stack->*mp_member) (*reader.back (tag)); + } } private: void (db::NetTracerConnectivity::*mp_member) (const Value &); - void (db::NetTracerConnectivity::*mp_clear) (); }; template @@ -184,10 +197,10 @@ public: // Fallback readers for migrating pre-0.28 setups to 0.28 and backward compatibility tl::XMLMember, FallbackXMLWriteAdaptor , tl::XMLStdConverter > ( FallbackXMLReadAdaptor (&NetTracerConnectivity::begin, &NetTracerConnectivity::end), - FallbackXMLWriteAdaptor (&NetTracerConnectivity::add, &NetTracerConnectivity::clear_connections), "connection") + + FallbackXMLWriteAdaptor (&NetTracerConnectivity::add), "connection") + tl::XMLMember, FallbackXMLWriteAdaptor , tl::XMLStdConverter > ( FallbackXMLReadAdaptor (&NetTracerConnectivity::begin_symbols, &NetTracerConnectivity::end_symbols), - FallbackXMLWriteAdaptor (&NetTracerConnectivity::add_symbol, &NetTracerConnectivity::clear_symbols), "symbols") + FallbackXMLWriteAdaptor (&NetTracerConnectivity::add_symbol), "symbols") ); } }; diff --git a/src/plugins/tools/net_tracer/db_plugin/gsiDeclDbNetTracer.cc b/src/plugins/tools/net_tracer/db_plugin/gsiDeclDbNetTracer.cc index f9f4d1695..90fdab1ad 100644 --- a/src/plugins/tools/net_tracer/db_plugin/gsiDeclDbNetTracer.cc +++ b/src/plugins/tools/net_tracer/db_plugin/gsiDeclDbNetTracer.cc @@ -52,6 +52,41 @@ static void def_symbol (db::NetTracerConnectivity *tech, const std::string &name tech->add_symbol (db::NetTracerSymbolInfo (db::LayerProperties (name), expr)); } +static std::string get_layer_a (const db::NetTracerConnectionInfo *info) +{ + return info->layer_a ().to_string (); +} + +static std::string get_via_layer (const db::NetTracerConnectionInfo *info) +{ + return info->via_layer ().to_string (); +} + +static std::string get_layer_b (const db::NetTracerConnectionInfo *info) +{ + return info->layer_b ().to_string (); +} + +gsi::Class decl_NetTracerConnectionInfo ("db", "NetTracerConnectionInfo", + gsi::method_ext ("layer_a", &get_layer_a, "@brief Gets the expression for the A layer") + + gsi::method_ext ("via_layer", &get_via_layer, "@brief Gets the expression for the Via layer") + + gsi::method_ext ("layer_b", &get_layer_b, "@brief Gets the expression for the B layer"), + "@brief Represents a single connection info line for the net tracer technology definition\n" + "This class has been introduced in version 0.28.3." +); + +static std::string get_symbol (const db::NetTracerSymbolInfo *info) +{ + return info->symbol ().to_string (); +} + +gsi::Class decl_NetTracerSymbolInfo ("db", "NetTracerSymbolInfo", + gsi::method_ext ("symbol", &get_symbol, "@brief Gets the symbol") + + gsi::method ("expression", &db::NetTracerSymbolInfo::expression, "@brief Gets the expression"), + "@brief Represents a single symbol info line for the net tracer technology definition\n" + "This class has been introduced in version 0.28.3." +); + gsi::Class decl_NetTracerConnectivity ("db", "NetTracerConnectivity", gsi::method ("name", &db::NetTracerConnectivity::name, "@brief Gets the name of the connectivty definition\n" @@ -79,6 +114,14 @@ gsi::Class decl_NetTracerConnectivity ("db", "NetTrac "@brief Defines a symbol for use in the material expressions.\n" "Defines a sub-expression to be used in further symbols or material expressions. " "For the detailed notation of the expression see the description of the net tracer feature." + ) + + gsi::iterator ("each_connection", static_cast (&db::NetTracerConnectivity::begin), static_cast (&db::NetTracerConnectivity::end), + "@brief Gets the connection information.\n" + "This iterator method has been introduced in version 0.28.3.\n" + ) + + gsi::iterator ("each_symbol", static_cast (&db::NetTracerConnectivity::begin_symbols), static_cast (&db::NetTracerConnectivity::end_symbols), + "@brief Gets the symbol information.\n" + "This iterator method has been introduced in version 0.28.3.\n" ), "@brief A connectivity description for the net tracer\n" "\n" @@ -99,6 +142,18 @@ gsi::Class decl_NetTracerConnectivity ("db", "NetTrac "has been generalized.\n" ); +DB_PUBLIC gsi::Class &decl_dbTechnologyComponent (); + +gsi::Class decl_NetTracerTechnologyComponent (decl_dbTechnologyComponent (), "db", "NetTracerTechnologyComponent", + gsi::iterator ("each", static_cast (&db::NetTracerTechnologyComponent::begin), static_cast (&db::NetTracerTechnologyComponent::end), + "@brief Gets the connectivity definitions from the net tracer technology component.\n" + ), + "@brief Represents the technology information for the net tracer.\n" + "This class has been redefined in version 0.28 and re-introduced in version 0.28.3. Since version 0.28, " + "multiple stacks are supported and the individual stack definition is provided through a list of stacks. Use \\each " + "to iterate the stacks." +); + static void trace1 (db::NetTracer *net_tracer, const db::NetTracerConnectivity &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer) { db::NetTracerData tracer_data = tech.get_tracer_data (layout); diff --git a/testdata/ruby/layTechnologies.rb b/testdata/ruby/layTechnologies.rb index 26e215f9f..29ab17734 100644 --- a/testdata/ruby/layTechnologies.rb +++ b/testdata/ruby/layTechnologies.rb @@ -23,6 +23,14 @@ end load("test_prologue.rb") +def nt_tech_to_s(t) + t.each.collect do |s| + ([ "Stack [" + s.name + "]:" ] + + s.each_connection.collect { |c| " conn: " + c.layer_a + "," + c.via_layer + "," + c.layer_b } + + s.each_symbol.collect { |c| " symbol: " + c.symbol + "=" + c.expression }).join("\n") + end.join("\n") + "\n" +end + class LAYTechnologies_TestClass < TestBase def test_1 @@ -117,7 +125,88 @@ END assert_equal(tech.component_names.size > 0, true) assert_equal(tech.component_names.find("connectivity") != nil, true) - assert_equal(tech.component("connectivity").class.to_s, "RBA::TechnologyComponent") + assert_equal(tech.component("connectivity").class.to_s, "RBA::NetTracerTechnologyComponent") + + end + + # issue 1245 + def test_3 + + # empty connectivity + tech = RBA::Technology::technology_from_xml(< + X + + +END + + nt_tech = tech.component("connectivity") + + assert_equal(nt_tech_to_s(nt_tech), "\n") + + # 0.27 to 0.28 migration + tech = RBA::Technology::technology_from_xml(< + X + + 11,2,3 + 14,5,6 + AA=17 + BB=42 + + +END + + nt_tech = tech.component("connectivity") + + assert_equal(nt_tech_to_s(nt_tech), < + X + + + ST1 + 1,2,3 + 4,5,6 + A=17 + B=42 + + + ST2 + 1,2,3 + 4,5,7 + A=1 + + + 1,2,3 + 4,5,6 + AA=17 + BB=42 + + +END + + nt_tech = tech.component("connectivity") + + assert_equal(nt_tech_to_s(nt_tech), < Date: Thu, 12 Jan 2023 00:11:36 +0100 Subject: [PATCH 3/6] Fixed issue #1247. Problem was missing cache clean on assignment of stipple pattern and line styles --- src/laybasic/laybasic/layDitherPattern.cc | 50 ++++++++++++----------- src/laybasic/laybasic/layDitherPattern.h | 1 + src/laybasic/laybasic/layLineStyles.cc | 37 +++++++++-------- src/laybasic/laybasic/layLineStyles.h | 2 + 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/laybasic/laybasic/layDitherPattern.cc b/src/laybasic/laybasic/layDitherPattern.cc index 019ef76a5..53b14d052 100644 --- a/src/laybasic/laybasic/layDitherPattern.cc +++ b/src/laybasic/laybasic/layDitherPattern.cc @@ -462,6 +462,8 @@ static const char *dither_strings [] = { // --------------------------------------------------------------------- // DitherPatternInfo implementation +static tl::Mutex s_mutex; + DitherPatternInfo::DitherPatternInfo () : m_width (1), m_height (1), m_order_index (0) { @@ -482,23 +484,31 @@ DitherPatternInfo & DitherPatternInfo::operator= (const DitherPatternInfo &d) { if (&d != this) { - - m_order_index = d.m_order_index; - m_name = d.m_name; - m_width = d.m_width; - m_pattern_stride = d.m_pattern_stride; - m_height = d.m_height; - - for (size_t i = 0; i < sizeof (m_pattern) / sizeof (m_pattern [0]); ++i) { - m_pattern [i] = &m_buffer [0] + (d.m_pattern [i] - d.m_buffer); - } - memcpy (m_buffer, d.m_buffer, sizeof (m_buffer)); + tl::MutexLocker locker (& s_mutex); + assign_no_lock (d); } return *this; } -bool +void +DitherPatternInfo::assign_no_lock (const DitherPatternInfo &d) +{ + m_scaled_pattern.reset (); + + m_order_index = d.m_order_index; + m_name = d.m_name; + m_width = d.m_width; + m_pattern_stride = d.m_pattern_stride; + m_height = d.m_height; + + for (size_t i = 0; i < sizeof (m_pattern) / sizeof (m_pattern [0]); ++i) { + m_pattern [i] = &m_buffer [0] + (d.m_pattern [i] - d.m_buffer); + } + memcpy (m_buffer, d.m_buffer, sizeof (m_buffer)); +} + +bool DitherPatternInfo::same_bitmap (const DitherPatternInfo &d) const { if (m_width != d.m_width || m_height != d.m_height) { @@ -597,15 +607,11 @@ DitherPatternInfo::get_bitmap (int width, int height, int frame_width) const #endif -static tl::Mutex s_mutex; - void DitherPatternInfo::set_pattern (const uint32_t *pt, unsigned int w, unsigned int h) { - { - tl::MutexLocker locker (& s_mutex); - m_scaled_pattern.reset (0); - } + tl::MutexLocker locker (& s_mutex); + m_scaled_pattern.reset (0); set_pattern_impl (pt, w, h); } @@ -669,10 +675,8 @@ DitherPatternInfo::set_pattern_impl (const uint32_t *pt, unsigned int w, unsigne void DitherPatternInfo::set_pattern (const uint64_t *pt, unsigned int w, unsigned int h) { - { - tl::MutexLocker locker (& s_mutex); - m_scaled_pattern.reset (0); - } + tl::MutexLocker locker (& s_mutex); + m_scaled_pattern.reset (0); set_pattern_impl (pt, w, h); } @@ -752,7 +756,7 @@ DitherPatternInfo::scaled (unsigned int n) const } DitherPatternInfo &sp = (*m_scaled_pattern) [n]; - sp = *this; + sp.assign_no_lock (*this); sp.scale_pattern (n); return sp; } diff --git a/src/laybasic/laybasic/layDitherPattern.h b/src/laybasic/laybasic/layDitherPattern.h index 258180c08..1fac7169c 100644 --- a/src/laybasic/laybasic/layDitherPattern.h +++ b/src/laybasic/laybasic/layDitherPattern.h @@ -243,6 +243,7 @@ private: void set_pattern_impl (const uint32_t *pattern, unsigned int w, unsigned int h); void set_pattern_impl (const uint64_t *pattern, unsigned int w, unsigned int h); + void assign_no_lock (const DitherPatternInfo &other); }; /** diff --git a/src/laybasic/laybasic/layLineStyles.cc b/src/laybasic/laybasic/layLineStyles.cc index df9fb3bc4..a4a3856f8 100644 --- a/src/laybasic/laybasic/layLineStyles.cc +++ b/src/laybasic/laybasic/layLineStyles.cc @@ -75,6 +75,8 @@ static const char *style_strings [] = { // --------------------------------------------------------------------- // LineStyleInfo implementation +static tl::Mutex s_mutex; + LineStyleInfo::LineStyleInfo () : m_width (0), m_order_index (0) { @@ -92,19 +94,26 @@ LineStyleInfo & LineStyleInfo::operator= (const LineStyleInfo &d) { if (&d != this) { - - m_order_index = d.m_order_index; - m_name = d.m_name; - m_width = d.m_width; - m_pattern_stride = d.m_pattern_stride; - - memcpy (m_pattern, d.m_pattern, sizeof (m_pattern)); - + tl::MutexLocker locker (& s_mutex); + assign_no_lock (d); } return *this; } -bool +void +LineStyleInfo::assign_no_lock (const LineStyleInfo &d) +{ + m_scaled_pattern.reset (0); + + m_order_index = d.m_order_index; + m_name = d.m_name; + m_width = d.m_width; + m_pattern_stride = d.m_pattern_stride; + + memcpy (m_pattern, d.m_pattern, sizeof (m_pattern)); +} + +bool LineStyleInfo::same_bits (const LineStyleInfo &d) const { if (m_width != d.m_width) { @@ -201,15 +210,11 @@ LineStyleInfo::get_bitmap (int width, int height) const } #endif -static tl::Mutex s_mutex; - void LineStyleInfo::set_pattern (uint32_t pt, unsigned int w) { - { - tl::MutexLocker locker (& s_mutex); - m_scaled_pattern.reset (0); - } + tl::MutexLocker locker (& s_mutex); + m_scaled_pattern.reset (0); memset (m_pattern, 0, sizeof (m_pattern)); @@ -271,7 +276,7 @@ LineStyleInfo::scaled (unsigned int n) const } LineStyleInfo &sp = (*m_scaled_pattern) [n]; - sp = *this; + sp.assign_no_lock (*this); sp.scale_pattern (n); return sp; } diff --git a/src/laybasic/laybasic/layLineStyles.h b/src/laybasic/laybasic/layLineStyles.h index 6f54ee981..b29dbcb6e 100644 --- a/src/laybasic/laybasic/layLineStyles.h +++ b/src/laybasic/laybasic/layLineStyles.h @@ -216,6 +216,8 @@ private: unsigned int m_order_index; std::string m_name; mutable std::unique_ptr > m_scaled_pattern; + + void assign_no_lock (const LineStyleInfo &other); }; /** From 4b4556d3962b0caccf60de82c5cd0a63d4df5bcc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 12 Jan 2023 09:14:40 +0100 Subject: [PATCH 4/6] Preparations for 0.28.3 --- Changelog | 12 ++++++++++++ Changelog.Debian | 7 +++++++ version.sh | 4 ++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 9825f8a41..927ec7c76 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,15 @@ +0.28.3 (2023-01-12): +* Bugfix: %GITHUB%/issues/1247 Layer stipples not updated after editing custom stipples with high-DPI displays +* Bugfix: %GITHUB%/issues/1245 Connectivity not preserved when loading/saving technology +* Bugfix: %GITHUB%/issues/1242 KLayout 0.28.2 crashes when registering a plugin if a layout exists +* Bugfix: %GITHUB%/issues/1240 Layer is not activated from layer properties file on first creation +* Bugfix: %GITHUB%/issues/1238 Macro IDE: breakpoints not effective on Windows +* Bugfix: %GITHUB%/issues/1234 "Clone view": layer list is empty +* Enhancement: %GITHUB%/issues/1228 Add option to have Show parameter names on by default +* Enhancement: Improved performance of layer list with many layers +* Bugfix: Restored ability to build with Python 2.7 +* Enhancement: Compatibility with Qt 6.4.1 + 0.28.2 (2022-12-22): * Bugfix: %GITHUB%/issues/1230 LVS browser crashes diff --git a/Changelog.Debian b/Changelog.Debian index 519e964fd..dbc94f83d 100644 --- a/Changelog.Debian +++ b/Changelog.Debian @@ -1,3 +1,10 @@ +klayout (0.28.3-1) unstable; urgency=low + + * New features and bugfixes + - See changelog + + -- Matthias Köfferlein Thu, 12 Jan 2023 07:14:02 +0100 + klayout (0.28.2-1) unstable; urgency=low * New features and bugfixes diff --git a/version.sh b/version.sh index f24008ab1..3e7f78998 100644 --- a/version.sh +++ b/version.sh @@ -2,10 +2,10 @@ # This script is sourced to define the main version parameters # The main version -KLAYOUT_VERSION="0.28.2" +KLAYOUT_VERSION="0.28.3" # The version used for PyPI (don't use variables here!) -KLAYOUT_PYPI_VERSION="0.28.2" +KLAYOUT_PYPI_VERSION="0.28.3" # The build date KLAYOUT_VERSION_DATE=$(date "+%Y-%m-%d") From d79dfec25560869d39d64510b91f7e122cc9b35e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 12 Jan 2023 18:48:43 +0100 Subject: [PATCH 5/6] Fixed unit tests in non-Qt case --- testdata/ruby/layLayoutView.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testdata/ruby/layLayoutView.rb b/testdata/ruby/layLayoutView.rb index c22c891d8..14b4b621d 100644 --- a/testdata/ruby/layLayoutView.rb +++ b/testdata/ruby/layLayoutView.rb @@ -517,6 +517,10 @@ class LAYLayoutView_TestClass < TestBase # issue-1242 def test_6 + if !RBA.constants.member?(:MainWindow) + return + end + # Create a new layout main_window = RBA::MainWindow.instance() main_window.close_all From 33af2b8fcc7c734330f82ace8a399ec464dc797c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 12 Jan 2023 21:03:24 +0100 Subject: [PATCH 6/6] Avoid a segfault after explicitly destroying a custom plugin factory object --- src/laybasic/laybasic/gsiDeclLayPlugin.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/laybasic/laybasic/gsiDeclLayPlugin.cc b/src/laybasic/laybasic/gsiDeclLayPlugin.cc index 609feca01..7b9d449e2 100644 --- a/src/laybasic/laybasic/gsiDeclLayPlugin.cc +++ b/src/laybasic/laybasic/gsiDeclLayPlugin.cc @@ -291,6 +291,8 @@ public: gsi::Callback f_tracking_position; }; +static std::map s_factories; + class PluginFactoryBase : public lay::PluginDeclaration { @@ -304,6 +306,13 @@ public: ~PluginFactoryBase () { + for (auto f = s_factories.begin (); f != s_factories.end (); ++f) { + if (f->second == this) { + s_factories.erase (f); + break; + } + } + delete mp_registration; mp_registration = 0; } @@ -319,7 +328,6 @@ public: keep (); // remove an existing factory with the same name - static std::map s_factories; std::map ::iterator f = s_factories.find (name); if (f != s_factories.end ()) { delete f->second;