diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d9598516d..09215828c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: HOST_CCACHE_DIR="$(ccache -k cache_dir)" mkdir -p $HOST_CCACHE_DIR - name: Build wheels # check https://cibuildwheel.readthedocs.io/en/stable/setup/#github-actions - uses: pypa/cibuildwheel@v2.5.0 + uses: pypa/cibuildwheel@v2.11.3 # to supply options, put them in 'env', like: # env: # CIBW_SOME_OPTION: value diff --git a/Changelog b/Changelog index 10ebaa80e..b9389c6d6 100644 --- a/Changelog +++ b/Changelog @@ -87,6 +87,7 @@ Changes (list may not be complete): - Box/DBox square and rectangle convenience constructor - Box#enlarge convenience isotropic variant - Region#in_and_out, Edges#in_and_out + - New class NetTracerConnectivity introduced for multi-stack support in NetTracerTechnology, substitutes connectivity part NetTracerTechnology 0.27.13 (2022-11-30): * Bugfixes: diff --git a/Jenkinsfile b/Jenkinsfile index e3033ad39..03bf27089 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -54,7 +54,7 @@ node("master") { withDockerContainer(image: "jenkins-${target}-basic") { // from shared library - installtest(target, target_dir) + installtest_nopython(target, target_dir) } }) diff --git a/Jenkinsfile-msvc2017 b/Jenkinsfile-msvc2017 new file mode 100644 index 000000000..036f6bc2a --- /dev/null +++ b/Jenkinsfile-msvc2017 @@ -0,0 +1,59 @@ + +@Library("osconfig") _ + +properties([disableConcurrentBuilds()]) + +// from shared library +target = osconfig() + +currentBuild.description = "Pipelined " + target + +node("master") { + + artefacts = pwd() + "/artefacts" + target_dir = artefacts + "/" + target + + stage("Checkout sources") { + + checkout scm + checkout_private() + + } + + stage("Building target ${target}") { + + // from shared library + build(target, target_dir) + + } + + stage("Publish and test") { + + parallel( + "Publish": { + + // from shared library - only publish for normal branch, not for PR + if (! BRANCH_NAME.startsWith('PR')) { + publish(BRANCH_NAME, target, target_dir) + } + + }, + "Unit testing": { + + ut_result = "no-result" + ut_result = run_ut(target) + + junit(testResults: ut_result) + + }, + "Installtest": { + + // from shared library + installtest_nopython(target, target_dir) + + }) + + } + +} + diff --git a/scripts/makedeb.sh b/scripts/makedeb.sh index 760fe0e19..81fc8291d 100755 --- a/scripts/makedeb.sh +++ b/scripts/makedeb.sh @@ -55,10 +55,6 @@ sharedir="usr/share" bindir="usr/bin" libdir="usr/lib/klayout" -# TODO: is there a better way to produce this path? -distpackdir="usr/lib/python3/dist-packages" -pylibdir="$distpackdir/klayout" - # clean bin directory rm -rf $bininstdir @@ -97,7 +93,6 @@ mkdir -p makedeb-tmp/${sharedir}/applications mkdir -p makedeb-tmp/${sharedir}/pixmaps mkdir -p makedeb-tmp/${libdir}/db_plugins mkdir -p makedeb-tmp/${libdir}/lay_plugins -mkdir -p makedeb-tmp/${pylibdir} mkdir -p makedeb-tmp/${bindir} cp etc/klayout.desktop makedeb-tmp/${sharedir}/applications @@ -111,13 +106,6 @@ cp -pd $bininstdir/klayout makedeb-tmp/${bindir} cp -pd $bininstdir/lib*so* makedeb-tmp/${libdir} cp -pd $bininstdir/db_plugins/lib*so* makedeb-tmp/${libdir}/db_plugins cp -pd $bininstdir/lay_plugins/lib*so* makedeb-tmp/${libdir}/lay_plugins -cp -pd $bininstdir/pymod/klayout/*so makedeb-tmp/${pylibdir} -cp -pd $bininstdir/pymod/klayout/*py makedeb-tmp/${pylibdir} -for d in db tl rdb lib; do - mkdir -p makedeb-tmp/${pylibdir}/$d - cp -pd $bininstdir/pymod/klayout/$d/*py makedeb-tmp/${pylibdir}/$d -done -sed "s/%VERSION%/$version/g" makedeb-tmp/${distpackdir}/klayout.egg-info cd makedeb-tmp @@ -141,7 +129,6 @@ grep -q $version ${sharedir}/doc/klayout/changelog.Debian || ( echo "Modifying control file .." strip ${bindir}/* -strip ${pylibdir}/*.so strip ${libdir}/db_plugins/*.so* strip ${libdir}/lay_plugins/*.so* diff --git a/scripts/rpm-data/klayout.spec b/scripts/rpm-data/klayout.spec index 71f29855b..c7024b50c 100644 --- a/scripts/rpm-data/klayout.spec +++ b/scripts/rpm-data/klayout.spec @@ -45,7 +45,6 @@ Requires: qt5-qttools >= 5.11.1 Requires: qt5-qttools-devel >= 5.11.1 %define buildopt -j2 -%define pylib %{python_sitearch} %define __python /usr/bin/python3 %endif @@ -55,7 +54,6 @@ Requires: ruby >= 2.0.0 Requires: python3 >= 3.6.0 Requires: qt-x11 >= 4.8.5 %define buildopt -j2 -%define pylib %{python3_sitearch} %endif %if "%{target_system}" == "centos6" @@ -65,7 +63,6 @@ Requires: ruby >= 1.8.7 Requires: python >= 2.6.6 Requires: qt-x11 >= 4.6.2 %define buildopt -libcurl -j2 -%define pylib %{python_sitearch} %endif %if "%{target_system}" == "opensuse42_2" @@ -74,7 +71,6 @@ Requires: ruby2.3 >= 2.3.1 Requires: python3 >= 3.4.6 Requires: libqt4-x11 >= 4.8.6 %define buildopt -j2 -%define pylib %{python3_sitearch} %endif %if "%{target_system}" == "opensuse42_3" @@ -83,7 +79,6 @@ Requires: ruby2.3 >= 2.3.1 Requires: python3 >= 3.4.6 Requires: libqt4-x11 >= 4.8.6 %define buildopt -j2 -%define pylib %{python3_sitearch} %endif %if "%{target_system}" == "opensuse15" @@ -92,7 +87,6 @@ Requires: ruby >= 2.5 Requires: python3 >= 3.6 Requires: libqt4-x11 >= 4.8.7 %define buildopt -j2 -%define pylib %{python3_sitearch} %endif %if "%{target_system}" == "opensuse15" @@ -148,17 +142,6 @@ strip %{_builddir}/bin.$TARGET/strm* TARGET="linux-release" -# create and populate pylib -mkdir -p %{buildroot}%{pylib}/klayout -cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/*.so %{buildroot}%{pylib}/klayout -cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/*.py %{buildroot}%{pylib}/klayout -chmod 644 %{buildroot}%{pylib}/klayout/* -for d in tl db rdb lib; do - mkdir -p %{buildroot}%{pylib}/klayout/$d - cp -pd %{_builddir}/bin.$TARGET/pymod/klayout/$d/*.py %{buildroot}%{pylib}/klayout/$d - chmod 644 %{buildroot}%{pylib}/klayout/$d/* -done - # create and populate libdir mkdir -p %{buildroot}%{_libdir}/klayout mkdir -p %{buildroot}%{_libdir}/klayout/db_plugins @@ -191,7 +174,6 @@ install -Dm644 %{_sourcedir}/etc/logo.png %{buildroot}%{_datadir}/pixmaps/%{name %doc CONTRIB %{_bindir}/klayout %{_bindir}/strm* -%{pylib}/klayout/* %{_libdir}/klayout/* %{_datadir}/applications/%{name}.desktop %{_datadir}/pixmaps/%{name}.png diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 16f2caffb..dc634cd78 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -39,6 +39,7 @@ SOURCES = \ dbLayerMapping.cc \ dbLayerProperties.cc \ dbLayout.cc \ + dbLayoutLayers.cc \ dbLayoutContextHandler.cc \ dbLayoutDiff.cc \ dbLayoutQuery.cc \ @@ -138,85 +139,85 @@ SOURCES = \ gsiDeclDbVector.cc \ gsiDeclDbLayoutDiff.cc \ gsiDeclDbGlyphs.cc \ - dbConverters.cc \ - dbAsIfFlatRegion.cc \ - dbEmptyRegion.cc \ - dbFlatRegion.cc \ - dbOriginalLayerRegion.cc \ - dbRegionDelegate.cc \ - dbEdgesDelegate.cc \ - dbEmptyEdges.cc \ - dbAsIfFlatEdges.cc \ - dbFlatEdges.cc \ - dbEdgeBoolean.cc \ - dbOriginalLayerEdges.cc \ - dbAsIfFlatEdgePairs.cc \ - dbEmptyEdgePairs.cc \ - dbFlatEdgePairs.cc \ - dbOriginalLayerEdgePairs.cc \ - dbEdgePairsDelegate.cc \ - dbDeepShapeStore.cc \ - dbHierarchyBuilder.cc \ - dbLocalOperation.cc \ - dbHierProcessor.cc \ - dbDeepRegion.cc \ - dbHierNetworkProcessor.cc \ - dbNetlist.cc \ - gsiDeclDbNetlist.cc \ - dbNetlistDeviceClasses.cc \ - dbNetlistDeviceExtractor.cc \ - dbNetlistExtractor.cc \ - gsiDeclDbNetlistDeviceClasses.cc \ - gsiDeclDbNetlistDeviceExtractor.cc \ - gsiDeclDbHierNetworkProcessor.cc \ - dbNetlistDeviceExtractorClasses.cc \ - dbLayoutToNetlist.cc \ - gsiDeclDbLayoutToNetlist.cc \ - dbCircuit.cc \ - dbDevice.cc \ - dbDeviceClass.cc \ - dbNet.cc \ - dbSubCircuit.cc \ - dbPin.cc \ - dbLayoutToNetlistReader.cc \ - dbLayoutToNetlistWriter.cc \ - dbLayoutToNetlistFormatDefs.cc \ - dbDeviceAbstract.cc \ - dbLocalOperationUtils.cc \ - gsiDeclDbDeepShapeStore.cc \ - dbNetlistSpiceWriter.cc \ - dbNetlistWriter.cc \ - dbCellVariants.cc \ - dbDeepEdges.cc \ - dbDeepEdgePairs.cc \ - dbRegionUtils.cc \ - dbEdgesUtils.cc \ - dbRegionProcessors.cc \ - dbNetlistCompare.cc \ - dbNetlistReader.cc \ - dbNetlistSpiceReader.cc \ - gsiDeclDbNetlistCompare.cc \ - dbNetlistCrossReference.cc \ - dbLayoutVsSchematicWriter.cc \ - dbLayoutVsSchematicReader.cc \ - dbLayoutVsSchematicFormatDefs.cc \ - dbLayoutVsSchematic.cc \ - gsiDeclDbNetlistCrossReference.cc \ - gsiDeclDbLayoutVsSchematic.cc \ - dbNetlistObject.cc \ - gsiDeclDbTexts.cc \ - dbTexts.cc \ - dbDeepTexts.cc \ - dbAsIfFlatTexts.cc \ - dbTextsDelegate.cc \ - dbEmptyTexts.cc \ - dbFlatTexts.cc \ - dbTextsUtils.cc \ - dbOriginalLayerTexts.cc \ - dbNetShape.cc \ - dbShapeCollection.cc \ - gsiDeclDbShapeCollection.cc \ - dbShapeCollectionUtils.cc + dbConverters.cc \ + dbAsIfFlatRegion.cc \ + dbEmptyRegion.cc \ + dbFlatRegion.cc \ + dbOriginalLayerRegion.cc \ + dbRegionDelegate.cc \ + dbEdgesDelegate.cc \ + dbEmptyEdges.cc \ + dbAsIfFlatEdges.cc \ + dbFlatEdges.cc \ + dbEdgeBoolean.cc \ + dbOriginalLayerEdges.cc \ + dbAsIfFlatEdgePairs.cc \ + dbEmptyEdgePairs.cc \ + dbFlatEdgePairs.cc \ + dbOriginalLayerEdgePairs.cc \ + dbEdgePairsDelegate.cc \ + dbDeepShapeStore.cc \ + dbHierarchyBuilder.cc \ + dbLocalOperation.cc \ + dbHierProcessor.cc \ + dbDeepRegion.cc \ + dbHierNetworkProcessor.cc \ + dbNetlist.cc \ + gsiDeclDbNetlist.cc \ + dbNetlistDeviceClasses.cc \ + dbNetlistDeviceExtractor.cc \ + dbNetlistExtractor.cc \ + gsiDeclDbNetlistDeviceClasses.cc \ + gsiDeclDbNetlistDeviceExtractor.cc \ + gsiDeclDbHierNetworkProcessor.cc \ + dbNetlistDeviceExtractorClasses.cc \ + dbLayoutToNetlist.cc \ + gsiDeclDbLayoutToNetlist.cc \ + dbCircuit.cc \ + dbDevice.cc \ + dbDeviceClass.cc \ + dbNet.cc \ + dbSubCircuit.cc \ + dbPin.cc \ + dbLayoutToNetlistReader.cc \ + dbLayoutToNetlistWriter.cc \ + dbLayoutToNetlistFormatDefs.cc \ + dbDeviceAbstract.cc \ + dbLocalOperationUtils.cc \ + gsiDeclDbDeepShapeStore.cc \ + dbNetlistSpiceWriter.cc \ + dbNetlistWriter.cc \ + dbCellVariants.cc \ + dbDeepEdges.cc \ + dbDeepEdgePairs.cc \ + dbRegionUtils.cc \ + dbEdgesUtils.cc \ + dbRegionProcessors.cc \ + dbNetlistCompare.cc \ + dbNetlistReader.cc \ + dbNetlistSpiceReader.cc \ + gsiDeclDbNetlistCompare.cc \ + dbNetlistCrossReference.cc \ + dbLayoutVsSchematicWriter.cc \ + dbLayoutVsSchematicReader.cc \ + dbLayoutVsSchematicFormatDefs.cc \ + dbLayoutVsSchematic.cc \ + gsiDeclDbNetlistCrossReference.cc \ + gsiDeclDbLayoutVsSchematic.cc \ + dbNetlistObject.cc \ + gsiDeclDbTexts.cc \ + dbTexts.cc \ + dbDeepTexts.cc \ + dbAsIfFlatTexts.cc \ + dbTextsDelegate.cc \ + dbEmptyTexts.cc \ + dbFlatTexts.cc \ + dbTextsUtils.cc \ + dbOriginalLayerTexts.cc \ + dbNetShape.cc \ + dbShapeCollection.cc \ + gsiDeclDbShapeCollection.cc \ + dbShapeCollectionUtils.cc HEADERS = \ dbArray.h \ @@ -256,6 +257,7 @@ HEADERS = \ dbLayerProperties.h \ dbLayoutDiff.h \ dbLayout.h \ + dbLayoutLayers.h \ dbLayoutQuery.h \ dbLayoutStateModel.h \ dbLayoutUtils.h \ @@ -321,76 +323,76 @@ HEADERS = \ dbForceLink.h \ dbPlugin.h \ dbInit.h \ - dbConverters.h \ - dbAsIfFlatRegion.h \ - dbEmptyRegion.h \ - dbFlatRegion.h \ - dbOriginalLayerRegion.h \ - dbRegionDelegate.h \ - dbEdgesDelegate.h \ - dbEmptyEdges.h \ - dbAsIfFlatEdges.h \ - dbFlatEdges.h \ - dbEdgeBoolean.h \ - dbOriginalLayerEdges.h \ - dbAsIfFlatEdgePairs.h \ - dbEmptyEdgePairs.h \ - dbFlatEdgePairs.h \ - dbOriginalLayerEdgePairs.h \ - dbEdgePairsDelegate.h \ - dbDeepShapeStore.h \ - dbHierarchyBuilder.h \ - dbLocalOperation.h \ - dbHierProcessor.h \ - dbNetlist.h \ - dbNetlistDeviceClasses.h \ - dbNetlistDeviceExtractor.h \ - dbNetlistExtractor.h \ - dbNetlistDeviceExtractorClasses.h \ - dbLayoutToNetlist.h \ - dbHierNetworkProcessor.h \ - dbNetlistUtils.h \ - dbNet.h \ - dbCircuit.h \ - dbDevice.h \ - dbDeviceClass.h \ - dbPin.h \ - dbSubCircuit.h \ - dbLayoutToNetlistReader.h \ - dbLayoutToNetlistWriter.h \ - dbLayoutToNetlistFormatDefs.h \ - dbDeviceAbstract.h \ - dbLocalOperationUtils.h \ - dbDeepRegion.h \ - dbNetlistSpiceWriter.h \ - dbNetlistWriter.h \ - dbCellVariants.h \ - dbDeepEdges.h \ - dbDeepEdgePairs.h \ - dbRegionUtils.h \ - dbEdgesUtils.h \ - dbRegionProcessors.h \ - gsiDeclDbHelpers.h \ - dbNetlistCompare.h \ - dbNetlistReader.h \ - dbNetlistSpiceReader.h \ - dbNetlistCrossReference.h \ - dbLayoutVsSchematicWriter.h \ - dbLayoutVsSchematicReader.h \ - dbLayoutVsSchematicFormatDefs.h \ - dbLayoutVsSchematic.h \ - dbNetlistObject.h \ - dbTexts.h \ - dbDeepTexts.h \ - dbAsIfFlatTexts.h \ - dbTextsDelegate.h \ - dbEmptyTexts.h \ - dbFlatTexts.h \ - dbTextsUtils.h \ - dbOriginalLayerTexts.h \ - dbNetShape.h \ - dbShapeCollection.h \ - dbShapeCollectionUtils.h + dbConverters.h \ + dbAsIfFlatRegion.h \ + dbEmptyRegion.h \ + dbFlatRegion.h \ + dbOriginalLayerRegion.h \ + dbRegionDelegate.h \ + dbEdgesDelegate.h \ + dbEmptyEdges.h \ + dbAsIfFlatEdges.h \ + dbFlatEdges.h \ + dbEdgeBoolean.h \ + dbOriginalLayerEdges.h \ + dbAsIfFlatEdgePairs.h \ + dbEmptyEdgePairs.h \ + dbFlatEdgePairs.h \ + dbOriginalLayerEdgePairs.h \ + dbEdgePairsDelegate.h \ + dbDeepShapeStore.h \ + dbHierarchyBuilder.h \ + dbLocalOperation.h \ + dbHierProcessor.h \ + dbNetlist.h \ + dbNetlistDeviceClasses.h \ + dbNetlistDeviceExtractor.h \ + dbNetlistExtractor.h \ + dbNetlistDeviceExtractorClasses.h \ + dbLayoutToNetlist.h \ + dbHierNetworkProcessor.h \ + dbNetlistUtils.h \ + dbNet.h \ + dbCircuit.h \ + dbDevice.h \ + dbDeviceClass.h \ + dbPin.h \ + dbSubCircuit.h \ + dbLayoutToNetlistReader.h \ + dbLayoutToNetlistWriter.h \ + dbLayoutToNetlistFormatDefs.h \ + dbDeviceAbstract.h \ + dbLocalOperationUtils.h \ + dbDeepRegion.h \ + dbNetlistSpiceWriter.h \ + dbNetlistWriter.h \ + dbCellVariants.h \ + dbDeepEdges.h \ + dbDeepEdgePairs.h \ + dbRegionUtils.h \ + dbEdgesUtils.h \ + dbRegionProcessors.h \ + gsiDeclDbHelpers.h \ + dbNetlistCompare.h \ + dbNetlistReader.h \ + dbNetlistSpiceReader.h \ + dbNetlistCrossReference.h \ + dbLayoutVsSchematicWriter.h \ + dbLayoutVsSchematicReader.h \ + dbLayoutVsSchematicFormatDefs.h \ + dbLayoutVsSchematic.h \ + dbNetlistObject.h \ + dbTexts.h \ + dbDeepTexts.h \ + dbAsIfFlatTexts.h \ + dbTextsDelegate.h \ + dbEmptyTexts.h \ + dbFlatTexts.h \ + dbTextsUtils.h \ + dbOriginalLayerTexts.h \ + dbNetShape.h \ + dbShapeCollection.h \ + dbShapeCollectionUtils.h !equals(HAVE_QT, "0") || !equals(HAVE_PYTHON, "0") { diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index 51f249d58..b181bd2e0 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -255,33 +255,6 @@ private: bool m_insert; }; -// ----------------------------------------------------------------- -// Implementation of the LayerIterator class - -LayerIterator::LayerIterator (unsigned int layer_index, const db::Layout &layout) - : m_layer_index (layer_index), m_layout (layout) -{ - while (m_layer_index < m_layout.layers () && ! m_layout.is_valid_layer (m_layer_index)) { - ++m_layer_index; - } -} - -LayerIterator & -LayerIterator::operator++() -{ - do { - ++m_layer_index; - } while (m_layer_index < m_layout.layers () && ! m_layout.is_valid_layer (m_layer_index)); - - return *this; -} - -std::pair -LayerIterator::operator*() const -{ - return std::pair (m_layer_index, &m_layout.get_properties (m_layer_index)); -} - // ----------------------------------------------------------------- // Implementation of the ProxyContextInfo class @@ -353,9 +326,6 @@ Layout::Layout (db::Manager *manager) m_dbu (0.001), m_prop_id (0), m_properties_repository (this), - m_guiding_shape_layer (-1), - m_waste_layer (-1), - m_error_layer (-1), m_do_cleanup (false), m_editable (db::default_editable_mode ()) { @@ -371,9 +341,6 @@ Layout::Layout (bool editable, db::Manager *manager) m_dbu (0.001), m_prop_id (0), m_properties_repository (this), - m_guiding_shape_layer (-1), - m_waste_layer (-1), - m_error_layer (-1), m_do_cleanup (false), m_editable (editable) { @@ -393,9 +360,6 @@ Layout::Layout (const db::Layout &layout) m_dbu (0.001), m_prop_id (0), m_properties_repository (this), - m_guiding_shape_layer (-1), - m_waste_layer (-1), - m_error_layer (-1), m_do_cleanup (false), m_editable (layout.m_editable) { @@ -437,8 +401,7 @@ Layout::clear () m_top_down_list.clear (); - m_free_indices.clear (); - m_layer_states.clear (); + m_layers.clear (); for (std::vector::const_iterator p = m_cell_names.begin (); p != m_cell_names.end (); ++p) { if (*p) { @@ -459,10 +422,6 @@ Layout::clear () m_pcells.clear (); m_pcell_ids.clear (); - m_guiding_shape_layer = -1; - m_waste_layer = -1; - m_error_layer = -1; - m_lib_proxy_map.clear (); m_meta_info.clear (); } @@ -476,9 +435,8 @@ Layout::operator= (const Layout &d) clear (); - m_guiding_shape_layer = d.m_guiding_shape_layer; - m_waste_layer = d.m_waste_layer; - m_error_layer = d.m_error_layer; + m_layers = d.m_layers; + m_editable = d.m_editable; m_pcell_ids = d.m_pcell_ids; @@ -504,9 +462,6 @@ Layout::operator= (const Layout &d) } m_properties_repository = d.m_properties_repository; // because the cell assign operator does not map property ID's .. - m_free_indices = d.m_free_indices; - m_layer_states = d.m_layer_states; - m_layer_props = d.m_layer_props; m_top_down_list = d.m_top_down_list; m_top_cells = d.m_top_cells; @@ -720,14 +675,13 @@ Layout::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat); } + m_layers.mem_stat (stat, purpose, cat, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_cell_ptrs, true, (void *) this); db::mem_stat (stat, purpose, cat, m_free_cell_indices, true, (void *) this); db::mem_stat (stat, purpose, cat, m_top_down_list, true, (void *) this); - db::mem_stat (stat, purpose, cat, m_free_indices, true, (void *) this); - db::mem_stat (stat, purpose, cat, m_layer_states, true, (void *) this); db::mem_stat (stat, purpose, cat, m_cell_names, true, (void *) this); db::mem_stat (stat, purpose, cat, m_cell_map, true, (void *) this); - db::mem_stat (stat, purpose, cat, m_layer_props, true, (void *) this); db::mem_stat (stat, purpose, cat, m_pcells, true, (void *) this); db::mem_stat (stat, purpose, cat, m_pcell_ids, true, (void *) this); db::mem_stat (stat, purpose, cat, m_lib_proxy_map, true, (void *) this); @@ -1839,8 +1793,8 @@ Layout::meta_info_value (const std::string &name) const void Layout::swap_layers (unsigned int a, unsigned int b) { - tl_assert (a < layers () && m_layer_states [a] != Free); - tl_assert (b < layers () && m_layer_states [b] != Free); + tl_assert (m_layers.layer_state (a) != LayoutLayers::Free); + tl_assert (m_layers.layer_state (b) != LayoutLayers::Free); // clear the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1851,8 +1805,8 @@ Layout::swap_layers (unsigned int a, unsigned int b) void Layout::move_layer (unsigned int src, unsigned int dest) { - tl_assert (src < layers () && m_layer_states [src] != Free); - tl_assert (dest < layers () && m_layer_states [dest] != Free); + tl_assert (m_layers.layer_state (src) != LayoutLayers::Free); + tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free); // move the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1863,8 +1817,8 @@ Layout::move_layer (unsigned int src, unsigned int dest) void Layout::copy_layer (unsigned int src, unsigned int dest) { - tl_assert (src < layers () && m_layer_states [src] != Free); - tl_assert (dest < layers () && m_layer_states [dest] != Free); + tl_assert (m_layers.layer_state (src) != LayoutLayers::Free); + tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free); // copy the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1875,7 +1829,7 @@ Layout::copy_layer (unsigned int src, unsigned int dest) void Layout::clear_layer (unsigned int n) { - tl_assert (n < layers () && m_layer_states [n] != Free); + tl_assert (m_layers.layer_state (n) != LayoutLayers::Free); // clear the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1886,14 +1840,13 @@ Layout::clear_layer (unsigned int n) void Layout::delete_layer (unsigned int n) { - tl_assert (n < layers () && m_layer_states [n] != Free); + tl_assert (m_layers.layer_state (n) != LayoutLayers::Free); if (manager () && manager ()->transacting ()) { - manager ()->queue (this, new InsertRemoveLayerOp (n, m_layer_props [n], false /*delete*/)); + manager ()->queue (this, new InsertRemoveLayerOp (n, m_layers.get_properties (n), false /*delete*/)); } - m_free_indices.push_back (n); - m_layer_states [n] = Free; + m_layers.delete_layer (n); // clear the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1906,11 +1859,7 @@ Layout::delete_layer (unsigned int n) unsigned int Layout::insert_layer (const LayerProperties &props) { - unsigned int i = do_insert_layer (); - while (m_layer_props.size () <= i) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [i] = props; + unsigned int i = m_layers.insert_layer (props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/)); @@ -1924,11 +1873,7 @@ Layout::insert_layer (const LayerProperties &props) void Layout::insert_layer (unsigned int index, const LayerProperties &props) { - do_insert_layer (index); - while (m_layer_props.size () <= index) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [index] = props; + m_layers.insert_layer (index, props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/)); @@ -1937,71 +1882,10 @@ Layout::insert_layer (unsigned int index, const LayerProperties &props) layer_properties_changed (); } -unsigned int -Layout::get_layer (const db::LayerProperties &lp) -{ - if (lp.is_null ()) { - // for a null layer info always create a layer - return insert_layer (); - } else { - // if we have a layer with the requested properties already, return this. - for (db::Layout::layer_iterator li = begin_layers (); li != end_layers (); ++li) { - if ((*li).second->log_equal (lp)) { - return (*li).first; - } - } - // otherwise create a new layer - return insert_layer (lp); - } -} - -unsigned int -Layout::error_layer () const -{ - if (m_error_layer < 0) { - // create the waste layer (since that layer is cached we can do - // this in a "const" fashion. - db::Layout *self = const_cast (this); - self->m_error_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); - } - - return (unsigned int) m_error_layer; -} - -unsigned int -Layout::waste_layer () const -{ - if (m_waste_layer < 0) { - // create the waste layer (since that layer is cached we can do - // this in a "const" fashion. - db::Layout *self = const_cast (this); - self->m_waste_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); - } - - return (unsigned int) m_waste_layer; -} - -unsigned int -Layout::guiding_shape_layer () const -{ - if (m_guiding_shape_layer < 0) { - // create the guiding shape layer (since that layer is cached we can do - // this in a "const" fashion. - db::Layout *self = const_cast (this); - self->m_guiding_shape_layer = (int) self->insert_special_layer (db::LayerProperties ("GUIDING_SHAPES")); - } - - return (unsigned int) m_guiding_shape_layer; -} - unsigned int Layout::insert_special_layer (const LayerProperties &props) { - unsigned int i = do_insert_layer (true /*special*/); - while (m_layer_props.size () <= i) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [i] = props; + unsigned int i = m_layers.insert_special_layer (props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/)); @@ -2013,13 +1897,13 @@ Layout::insert_special_layer (const LayerProperties &props) void Layout::set_properties (unsigned int i, const LayerProperties &props) { - if (m_layer_props [i] != props) { + if (m_layers.get_properties (i) != props) { if (manager () && manager ()->transacting ()) { - manager ()->queue (this, new SetLayerPropertiesOp (i, props, m_layer_props [i])); + manager ()->queue (this, new SetLayerPropertiesOp (i, props, m_layers.get_properties (i))); } - m_layer_props [i] = props; + m_layers.set_properties (i, props); layer_properties_changed (); @@ -2029,60 +1913,13 @@ Layout::set_properties (unsigned int i, const LayerProperties &props) void Layout::insert_special_layer (unsigned int index, const LayerProperties &props) { - do_insert_layer (index, true /*special*/); - while (m_layer_props.size () <= index) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [index] = props; + m_layers.insert_special_layer (index, props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/)); } } -unsigned int -Layout::do_insert_layer (bool special) -{ - if (m_free_indices.size () > 0) { - unsigned int i = m_free_indices.back (); - m_free_indices.pop_back (); - m_layer_states [i] = special ? Special : Normal; - return i; - } else { - m_layer_states.push_back (special ? Special : Normal); - unsigned int i = layers () - 1; - return i; - } -} - -void -Layout::do_insert_layer (unsigned int index, bool special) -{ - if (index >= layers ()) { - - // add layer to the end of the list. - // add as may freelist entries as required. - while (index > layers ()) { - m_free_indices.push_back (layers ()); - m_layer_states.push_back (Free); - } - m_layer_states.push_back (special ? Special : Normal); - - } else { - - tl_assert (m_layer_states [index] == Free); - m_layer_states [index] = special ? Special : Normal; - - } - -} - -void -Layout::reserve_layers (unsigned int n) -{ - m_layer_states.reserve (n); -} - static const std::vector &gauge_parameters (const std::vector &p, const db::PCellDeclaration *pcell_decl, std::vector &buffer) { const std::vector &pcp = pcell_decl->parameter_declarations (); @@ -2354,8 +2191,8 @@ Layout::convert_cell_to_static (db::cell_index_type ci) new_cell.set_cell_index (ret_ci); // remove guiding shapes. - if (m_guiding_shape_layer >= 0) { - new_cell.shapes (m_guiding_shape_layer).clear (); + if (m_layers.guiding_shape_layer_maybe () >= 0) { + new_cell.shapes (m_layers.guiding_shape_layer_maybe ()).clear (); } } diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index 450f8ba80..7b7cc1278 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -32,6 +32,7 @@ #include "dbText.h" #include "dbCell.h" #include "dbLayoutStateModel.h" +#include "dbLayoutLayers.h" #include "dbLayerProperties.h" #include "dbMetaInfo.h" #include "dbCellInst.h" @@ -192,7 +193,7 @@ public: * @brief Default constructor */ cell_list_const_iterator (cell_list_iterator iter) - : mp_cell (& (*iter)) + : mp_cell (iter.operator-> ()) { } /** @@ -393,50 +394,6 @@ private: cell_type *mp_first, *mp_last; }; -/** - * @brief A layer iterator (for valid layers) - * - * The layer iterator delivers layer indices and layer properties of layer layers. - */ -class DB_PUBLIC LayerIterator -{ -public: - /** - * @brief Constructor - */ - LayerIterator (unsigned int layer_index, const db::Layout &layout); - - /** - * @brief Increment operator - */ - LayerIterator &operator++(); - - /** - * @brief Equality - */ - bool operator== (const LayerIterator &i) - { - return i.m_layer_index == m_layer_index; - } - - /** - * @brief Inequality - */ - bool operator!= (const LayerIterator &i) - { - return i.m_layer_index != m_layer_index; - } - - /** - * @brief Access operator - */ - std::pair operator*() const; - -private: - unsigned int m_layer_index; - const db::Layout &m_layout; -}; - /** * @brief An interface that is used to map layer between libraries and PCells and the layout */ @@ -1426,7 +1383,7 @@ public: */ bool is_valid_layer (unsigned int n) const { - return (n < layers () && m_layer_states [n] == Normal); + return m_layers.layer_state (n) == db::LayoutLayers::Normal; } /** @@ -1434,7 +1391,7 @@ public: */ bool is_free_layer (unsigned int n) const { - return (n >= layers () || m_layer_states [n] == Free); + return m_layers.layer_state (n) == db::LayoutLayers::Free; } /** @@ -1442,7 +1399,7 @@ public: */ bool is_special_layer (unsigned int n) const { - return (n < layers () && m_layer_states [n] == Special); + return m_layers.layer_state (n) == db::LayoutLayers::Special; } /** @@ -1454,7 +1411,7 @@ public: */ unsigned int layers () const { - return (cell_index_type) m_layer_states.size (); + return m_layers.layers (); } /** @@ -1462,7 +1419,7 @@ public: */ layer_iterator begin_layers () const { - return layer_iterator (0, *this); + return m_layers.begin_layers (); } /** @@ -1470,13 +1427,16 @@ public: */ layer_iterator end_layers () const { - return layer_iterator (layers (), *this); + return m_layers.end_layers (); } /** * @brief Reserve space for n layers */ - void reserve_layers (unsigned int n); + void reserve_layers (unsigned int n) + { + m_layers.reserve_layers (n); + } /** * @brief begin iterator of the unsorted cell list @@ -1684,7 +1644,18 @@ public: * If there already is a layer matching the given properties, it's index will be * returned. Otherwise a new layer with these properties is created. */ - unsigned int get_layer (const db::LayerProperties &props); + unsigned int get_layer (const db::LayerProperties &props) + { + return m_layers.get_layer (props); + } + + /** + * @brief Gets the layer with the given properties or -1 if such a layer does not exist + */ + int get_layer_maybe (const db::LayerProperties &props) + { + return m_layers.get_layer_maybe (props); + } /** * @brief Insert a new special layer with the given properties @@ -1705,21 +1676,30 @@ public: * * The guiding shape layer is used to store the guiding shapes of PCells */ - unsigned int guiding_shape_layer () const; + unsigned int guiding_shape_layer () const + { + return m_layers.guiding_shape_layer (); + } /** * @brief Gets the waste layer * * The waste layer is used to store shapes that should not be visible and can be cleared at any time. */ - unsigned int waste_layer () const; + unsigned int waste_layer () const + { + return m_layers.waste_layer (); + } /** * @brief Gets the error layer * * The error layer is used to display error messages. */ - unsigned int error_layer () const; + unsigned int error_layer () const + { + return m_layers.error_layer (); + } /** * @brief Set the properties for a specified layer @@ -1731,7 +1711,7 @@ public: */ const LayerProperties &get_properties (unsigned int i) const { - return m_layer_props [i]; + return m_layers.get_properties (i); } /** @@ -1877,8 +1857,6 @@ protected: virtual void do_update (); private: - enum LayerState { Normal, Free, Special }; - db::Library *mp_library; cell_list m_cells; size_t m_cells_size; @@ -1887,11 +1865,9 @@ private: mutable unsigned int m_invalid; cell_index_vector m_top_down_list; size_t m_top_cells; - std::vector m_free_indices; - std::vector m_layer_states; + LayoutLayers m_layers; std::vector m_cell_names; cell_map_type m_cell_map; - std::vector m_layer_props; double m_dbu; db::properties_id_type m_prop_id; StringRepository m_string_repository; @@ -1901,9 +1877,6 @@ private: std::vector m_pcells; pcell_name_map m_pcell_ids; lib_proxy_map m_lib_proxy_map; - int m_guiding_shape_layer; - int m_waste_layer; - int m_error_layer; bool m_do_cleanup; bool m_editable; meta_info m_meta_info; @@ -1937,21 +1910,6 @@ private: */ cell_index_type allocate_new_cell (); - /** - * @brief Insert a new layer - * - * This creates a new index number, either from the free list - * of by creating a new one. - */ - unsigned int do_insert_layer (bool special = false); - - /** - * @brief Insert a new layer at the given index - * - * If the index is unused, create a new layer there. - */ - void do_insert_layer (unsigned int index, bool special = false); - /** * @brief Implementation of prune_cell and prune_subcells */ diff --git a/src/db/db/dbLayoutLayers.cc b/src/db/db/dbLayoutLayers.cc new file mode 100644 index 000000000..e6f8eb251 --- /dev/null +++ b/src/db/db/dbLayoutLayers.cc @@ -0,0 +1,318 @@ + +/* + + KLayoutLayers LayoutLayers Viewer + Copyright (C) 2006-2022 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 "dbLayoutLayers.h" + +namespace db +{ + +// ----------------------------------------------------------------- +// Implementation of the LayerIterator class + +LayerIterator::LayerIterator (unsigned int layer_index, const db::LayoutLayers &layout) + : m_layer_index (layer_index), m_layout (layout) +{ + while (m_layer_index < m_layout.layers () && m_layout.layer_state (m_layer_index) != db::LayoutLayers::Normal) { + ++m_layer_index; + } +} + +LayerIterator & +LayerIterator::operator++() +{ + do { + ++m_layer_index; + } while (m_layer_index < m_layout.layers () && m_layout.layer_state (m_layer_index) != db::LayoutLayers::Normal); + + return *this; +} + +std::pair +LayerIterator::operator*() const +{ + return std::pair (m_layer_index, &m_layout.get_properties (m_layer_index)); +} + +// ----------------------------------------------------------------- +// Implementation of the LayoutLayers class + +LayoutLayers::LayoutLayers () + : m_guiding_shape_layer (-1), + m_waste_layer (-1), + m_error_layer (-1) +{ + // .. nothing yet .. +} + +LayoutLayers::LayoutLayers (const db::LayoutLayers &layout) + : m_guiding_shape_layer (-1), + m_waste_layer (-1), + m_error_layer (-1) +{ + *this = layout; +} + +LayoutLayers::~LayoutLayers () +{ + // .. nothing yet .. +} + +void +LayoutLayers::clear () +{ + m_free_indices.clear (); + m_layer_states.clear (); + m_layer_props.clear (); + m_layers_by_props.clear (); + + m_guiding_shape_layer = -1; + m_waste_layer = -1; + m_error_layer = -1; +} + +LayoutLayers & +LayoutLayers::operator= (const LayoutLayers &d) +{ + if (&d != this) { + + m_guiding_shape_layer = d.m_guiding_shape_layer; + m_waste_layer = d.m_waste_layer; + m_error_layer = d.m_error_layer; + + m_free_indices = d.m_free_indices; + m_layer_states = d.m_layer_states; + m_layer_props = d.m_layer_props; + m_layers_by_props = d.m_layers_by_props; + + } + return *this; +} + +void +LayoutLayers::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const +{ + if (!no_self) { + stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat); + } + + db::mem_stat (stat, purpose, cat, m_free_indices, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_layer_states, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_layer_props, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_layers_by_props, true, (void *) this); +} + +void +LayoutLayers::delete_layer (unsigned int n) +{ + const db::LayerProperties &lp = m_layer_props [n]; + if (! lp.is_null ()) { + for (auto i = m_layers_by_props.find (lp); i != m_layers_by_props.end () && i->first.log_equal (lp); ++i) { + if (i->second == n) { + m_layers_by_props.erase (i); + break; + } + } + } + + m_free_indices.push_back (n); + m_layer_props [n] = db::LayerProperties (); + m_layer_states [n] = Free; +} + +unsigned int +LayoutLayers::insert_layer (const LayerProperties &props) +{ + unsigned int i = do_insert_layer (); + set_properties (i, props); + return i; +} + +void +LayoutLayers::insert_layer (unsigned int index, const LayerProperties &props) +{ + if (layer_state (index) == Normal) { + delete_layer (index); + } + do_insert_layer (index); + set_properties (index, props); +} + +unsigned int +LayoutLayers::get_layer (const db::LayerProperties &lp) +{ + if (lp.is_null ()) { + // for a null layer info always create a layer + return insert_layer (); + } else { + auto i = m_layers_by_props.find (lp); + if (i != m_layers_by_props.end () && i->first.log_equal (lp)) { + return i->second; + } else { + // otherwise create a new layer + return insert_layer (lp); + } + } +} + +int +LayoutLayers::get_layer_maybe (const db::LayerProperties &lp) +{ + if (lp.is_null ()) { + return -1; + } else { + auto i = m_layers_by_props.find (lp); + if (i != m_layers_by_props.end () && i->first.log_equal (lp)) { + return int (i->second); + } else { + return -1; + } + } +} + +unsigned int +LayoutLayers::error_layer () const +{ + if (m_error_layer < 0) { + // create the waste layer (since that layer is cached we can do + // this in a "const" fashion. + db::LayoutLayers *self = const_cast (this); + self->m_error_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); + } + + return (unsigned int) m_error_layer; +} + +unsigned int +LayoutLayers::waste_layer () const +{ + if (m_waste_layer < 0) { + // create the waste layer (since that layer is cached we can do + // this in a "const" fashion. + db::LayoutLayers *self = const_cast (this); + self->m_waste_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); + } + + return (unsigned int) m_waste_layer; +} + +unsigned int +LayoutLayers::guiding_shape_layer () const +{ + if (m_guiding_shape_layer < 0) { + // create the guiding shape layer (since that layer is cached we can do + // this in a "const" fashion. + db::LayoutLayers *self = const_cast (this); + self->m_guiding_shape_layer = (int) self->insert_special_layer (db::LayerProperties ("GUIDING_SHAPES")); + } + + return (unsigned int) m_guiding_shape_layer; +} + +unsigned int +LayoutLayers::insert_special_layer (const LayerProperties &props) +{ + unsigned int i = do_insert_layer (true /*special*/); + set_properties (i, props); + return i; +} + +void +LayoutLayers::insert_special_layer (unsigned int index, const LayerProperties &props) +{ + if (layer_state (index) == Normal) { + delete_layer (index); + } + + do_insert_layer (index, true /*special*/); + set_properties (index, props); +} + +unsigned int +LayoutLayers::do_insert_layer (bool special) +{ + if (m_free_indices.size () > 0) { + unsigned int i = m_free_indices.back (); + m_free_indices.pop_back (); + m_layer_states [i] = special ? Special : Normal; + return i; + } else { + m_layer_states.push_back (special ? Special : Normal); + unsigned int i = layers () - 1; + return i; + } +} + +void +LayoutLayers::do_insert_layer (unsigned int index, bool special) +{ + if (index >= layers ()) { + + // add layer to the end of the list. + // add as may freelist entries as required. + while (index > layers ()) { + m_free_indices.push_back (layers ()); + m_layer_states.push_back (Free); + } + m_layer_states.push_back (special ? Special : Normal); + + } else { + + tl_assert (m_layer_states [index] == Free); + m_layer_states [index] = special ? Special : Normal; + + } + +} + +void +LayoutLayers::reserve_layers (unsigned int n) +{ + m_layer_states.reserve (n); +} + +void +LayoutLayers::set_properties (unsigned int n, const LayerProperties &props) +{ + while (m_layer_props.size () <= n) { + m_layer_props.push_back (LayerProperties ()); + } + + const db::LayerProperties &lp = m_layer_props [n]; + if (! lp.is_null ()) { + for (auto i = m_layers_by_props.find (lp); i != m_layers_by_props.end () && i->first.log_equal (lp); ++i) { + if (i->second == n) { + m_layers_by_props.erase (i); + break; + } + } + } + + m_layer_props [n] = props; + + if (! props.is_null ()) { + m_layers_by_props.insert (std::make_pair (props, n)); + } +} + +} + diff --git a/src/db/db/dbLayoutLayers.h b/src/db/db/dbLayoutLayers.h new file mode 100644 index 000000000..fbe0988bf --- /dev/null +++ b/src/db/db/dbLayoutLayers.h @@ -0,0 +1,282 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2022 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_dbLayoutLayers +#define HDR_dbLayoutLayers + +#include "dbCommon.h" + +#include "dbLayerProperties.h" +#include "dbMemStatistics.h" + +#include +#include + +namespace db +{ + +class MemStatistics; +class LayoutLayers; + +/** + * @brief A layer iterator (for valid layers) + * + * The layer iterator delivers layer indices and layer properties of layer layers. + */ +class DB_PUBLIC LayerIterator +{ +public: + /** + * @brief Constructor + */ + LayerIterator (unsigned int layer_index, const db::LayoutLayers &layout); + + /** + * @brief Increment operator + */ + LayerIterator &operator++(); + + /** + * @brief Equality + */ + bool operator== (const LayerIterator &i) + { + return i.m_layer_index == m_layer_index; + } + + /** + * @brief Inequality + */ + bool operator!= (const LayerIterator &i) + { + return i.m_layer_index != m_layer_index; + } + + /** + * @brief Access operator + */ + std::pair operator*() const; + +private: + unsigned int m_layer_index; + const db::LayoutLayers &m_layout; +}; + +/** + * @brief The layoutLayers object + * + * This object wraps the layer list and manages layer properties, + * layer states and the free layer list. + */ + +class DB_PUBLIC LayoutLayers +{ +public: + typedef LayerIterator layer_iterator; + enum LayerState { Normal, Free, Special }; + + /** + * @brief Standard constructor + */ + LayoutLayers (); + + /** + * @brief The copy ctor + */ + LayoutLayers (const LayoutLayers &d); + + /** + * @brief Destructor + */ + ~LayoutLayers (); + + /** + * @brief Assignment operator + */ + LayoutLayers &operator= (const LayoutLayers &d); + + /** + * @brief Clears the layout layers + */ + void clear (); + + /** + * @brief Deletes a layer + */ + void delete_layer (unsigned int n); + + /** + * @brief Gets the layer's state + */ + LayerState layer_state (unsigned int l) const + { + return l < (unsigned int) m_layer_states.size () ? m_layer_states [l] : Free; + } + + /** + * @brief Gets the number of layers defined so far + * + * TODO: the list of 0 to nlayers-1 also contains the free layers - + * we should get a vector containing the layers that are actually + * allocated. + */ + unsigned int layers () const + { + return (unsigned int) m_layer_states.size (); + } + + /** + * @brief The iterator of valid layers: begin + */ + layer_iterator begin_layers () const + { + return layer_iterator (0, *this); + } + + /** + * @brief The iterator of valid layers: end + */ + layer_iterator end_layers () const + { + return layer_iterator (layers (), *this); + } + + /** + * @brief Reserve space for n layers + */ + void reserve_layers (unsigned int n); + + /** + * @brief Inserts a new layer with the given properties + */ + unsigned int insert_layer (const LayerProperties &props = LayerProperties ()); + + /** + * @brief Inserts a new layer with the given properties at the given index + */ + void insert_layer (unsigned int index, const LayerProperties &props = LayerProperties ()); + + /** + * @brief Gets or creates a layer with the given properties + * + * If there already is a layer matching the given properties, it's index will be + * returned. Otherwise a new layer with these properties is created. + */ + unsigned int get_layer (const db::LayerProperties &props); + + /** + * @brief Gets the layer with the given properties or -1 if such a layer does not exist. + */ + int get_layer_maybe (const db::LayerProperties &props); + + /** + * @brief Insert a new special layer with the given properties + * + * A special layers is used for example to represent rulers. + */ + unsigned int insert_special_layer (const LayerProperties &props = LayerProperties ()); + + /** + * @brief Insert a new layer with the given properties at the given index + * + * A special layers is used for example to represent rulers. + */ + void insert_special_layer (unsigned int index, const LayerProperties &props = LayerProperties ()); + + /** + * @brief Gets the guiding shape layer or -1 if none is set yet. + */ + int guiding_shape_layer_maybe () const + { + return m_guiding_shape_layer; + } + + /** + * @brief Gets the guiding shape layer + * + * The guiding shape layer is used to store the guiding shapes of PCells + */ + unsigned int guiding_shape_layer () const; + + /** + * @brief Gets the waste layer + * + * The waste layer is used to store shapes that should not be visible and can be cleared at any time. + */ + unsigned int waste_layer () const; + + /** + * @brief Gets the error layer + * + * The error layer is used to display error messages. + */ + unsigned int error_layer () const; + + /** + * @brief Sets the properties for a specified layer + */ + void set_properties (unsigned int i, const LayerProperties &props); + + /** + * @brief Gets the properties for a specified layer + */ + const LayerProperties &get_properties (unsigned int i) const + { + return m_layer_props [i]; + } + + /** + * @brief Collects memory statistics + */ + void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const; + +private: + std::vector m_free_indices; + std::vector m_layer_states; + std::vector m_layer_props; + std::multimap m_layers_by_props; + int m_guiding_shape_layer; + int m_waste_layer; + int m_error_layer; + + /** + * @brief Insert a new layer + * + * This creates a new index number, either from the free list + * of by creating a new one. + */ + unsigned int do_insert_layer (bool special = false); + + /** + * @brief Insert a new layer at the given index + * + * If the index is unused, create a new layer there. + */ + void do_insert_layer (unsigned int index, bool special = false); +}; + +} + +#endif + + diff --git a/src/db/unit_tests/dbLayoutTests.cc b/src/db/unit_tests/dbLayoutTests.cc index f36e3125a..1d4829e23 100644 --- a/src/db/unit_tests/dbLayoutTests.cc +++ b/src/db/unit_tests/dbLayoutTests.cc @@ -664,3 +664,70 @@ TEST(6) EXPECT_EQ (l2s (l), "begin_lib 0.001\nbegin_cell {CIRCLE}\nboundary 1 0 {-2071 -5000} {-5000 -2071} {-5000 2071} {-2071 5000} {2071 5000} {5000 2071} {5000 -2071} {2071 -5000} {-2071 -5000}\nend_cell\nend_lib\n"); } } + +TEST(7_LayerProperties) +{ + db::Manager m; + db::Layout l (&m); + + EXPECT_EQ (l.is_valid_layer (0), false); + EXPECT_EQ (l.guiding_shape_layer (), 0); + EXPECT_EQ (l.is_special_layer (0), true); + EXPECT_EQ (int (l.layers ()), 1); + + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), -1); + unsigned int l1 = l.get_layer (db::LayerProperties (1, 0)); + EXPECT_EQ (1, int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), -1); + EXPECT_EQ (int (l.layers ()), 2); + + unsigned int l2 = l.get_layer (db::LayerProperties (2, 0)); + EXPECT_EQ (2, int (l2)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), int (l2)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (3, 0)), -1); + EXPECT_EQ (int (l.layers ()), 3); + + l.insert_layer (l2, db::LayerProperties (3, 0)); + EXPECT_EQ (int (l.layers ()), 3); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), -1); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (3, 0)), int (l2)); + EXPECT_EQ (l.get_properties (l2).to_string (), "3/0"); + + l.transaction (std::string ()); + l.delete_layer (l2); + l.commit (); + + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), -1); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (3, 0)), -1); + + m.undo (); + EXPECT_EQ (int (l.layers ()), 3); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), -1); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (3, 0)), int (l2)); + + auto li = l.begin_layers (); + EXPECT_EQ (li != l.end_layers (), true); + EXPECT_EQ ((*li).second->to_string (), "1/0"); + ++li; + EXPECT_EQ (li != l.end_layers (), true); + EXPECT_EQ ((*li).second->to_string (), "3/0"); + ++li; + EXPECT_EQ (li == l.end_layers (), true); + + l.set_properties (l2, db::LayerProperties (10, 0)); + EXPECT_EQ (int (l.layers ()), 3); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), int (l1)); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), -1); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (3, 0)), -1); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (10, 0)), int (l2)); + + l.clear (); + EXPECT_EQ (int (l.layers ()), 0); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (1, 0)), -1); + EXPECT_EQ (l.get_layer_maybe (db::LayerProperties (2, 0)), -1); +} diff --git a/src/lay/lay/layHelpSource.h b/src/lay/lay/layHelpSource.h index 222a85cd5..62ca4ca8e 100644 --- a/src/lay/lay/layHelpSource.h +++ b/src/lay/lay/layHelpSource.h @@ -70,7 +70,7 @@ std::string escape_xml (const std::string &s); /** * @brief A specialization of BrowserSource for delivering the generated documentation */ -class HelpSource +class LAY_PUBLIC HelpSource : public BrowserSource { public: diff --git a/src/lay/unit_tests/layHelpIndexTest.cc b/src/lay/unit_tests/layHelpIndexTest.cc new file mode 100644 index 000000000..ddd243fe0 --- /dev/null +++ b/src/lay/unit_tests/layHelpIndexTest.cc @@ -0,0 +1,33 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2022 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 "layHelpSource.h" +#include "tlUnitTest.h" + +TEST (1) +{ + // tests whether the index can be built - i.e. all XML files + // are valid. + lay::HelpSource help_source (false /*don't load index file*/); + help_source.scan (); +} diff --git a/src/lay/unit_tests/unit_tests.pro b/src/lay/unit_tests/unit_tests.pro index 2452b866f..bd437bdbb 100644 --- a/src/lay/unit_tests/unit_tests.pro +++ b/src/lay/unit_tests/unit_tests.pro @@ -8,7 +8,8 @@ include($$PWD/../../lib_ut.pri) SOURCES = \ laySalt.cc \ - laySessionTests.cc + layHelpIndexTest.cc \ + laySessionTests.cc INCLUDEPATH += $$LAY_INC $$TL_INC $$LAYBASIC_INC $$LAYUI_INC $$LAYVIEW_INC $$DB_INC $$GSI_INC $$ANT_INC $$IMG_INC $$RDB_INC DEPENDPATH += $$LAY_INC $$TL_INC $$LAYBASIC_INC $$LAYUI_INC $$LAYVIEW_INC $$DB_INC $$GSI_INC $$ANT_INC $$IMG_INC $$RDB_INC diff --git a/src/laybasic/laybasic/layLayerProperties.cc b/src/laybasic/laybasic/layLayerProperties.cc index 7ee412e6c..61dc43359 100644 --- a/src/laybasic/laybasic/layLayerProperties.cc +++ b/src/laybasic/laybasic/layLayerProperties.cc @@ -629,11 +629,7 @@ LayerProperties::do_realize (const LayoutViewBase *view) const // lookup the layer with the given name/layer/datatype if (m_layer_index < 0 && ! m_source_real.is_wildcard_layer ()) { - for (unsigned int i = 0; i < cv->layout ().layers () && m_layer_index < 0; ++i) { - if (cv->layout ().is_valid_layer (i) && m_source_real.match (cv->layout ().get_properties (i))) { - m_layer_index = int (i); - } - } + m_layer_index = cv->layout ().get_layer_maybe (m_source_real.layer_props ()); } } diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index b2e3a805d..a879417d7 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -239,6 +239,7 @@ const double animation_interval = 0.5; LayoutViewBase::LayoutViewBase (db::Manager *manager, bool editable, lay::Plugin *plugin_parent, unsigned int options) : lay::Dispatcher (plugin_parent, false /*not standalone*/), mp_ui (0), + dm_redraw (this, &LayoutViewBase::redraw), m_editable (editable), m_options (options), m_annotation_shapes (manager) @@ -252,6 +253,7 @@ LayoutViewBase::LayoutViewBase (db::Manager *manager, bool editable, lay::Plugin LayoutViewBase::LayoutViewBase (lay::LayoutView *ui, db::Manager *manager, bool editable, lay::Plugin *plugin_parent, unsigned int options) : lay::Dispatcher (plugin_parent, false /*not standalone*/), mp_ui (ui), + dm_redraw (this, &LayoutViewBase::redraw), m_editable (editable), m_options (options), m_annotation_shapes (manager) @@ -265,6 +267,7 @@ LayoutViewBase::LayoutViewBase (lay::LayoutView *ui, db::Manager *manager, bool LayoutViewBase::LayoutViewBase (lay::LayoutView *ui, lay::LayoutViewBase *source, db::Manager *manager, bool editable, lay::Plugin *plugin_parent, unsigned int options) : lay::Dispatcher (plugin_parent, false /*not standalone*/), mp_ui (ui), + dm_redraw (this, &LayoutViewBase::redraw), m_editable (editable), m_options (options), m_annotation_shapes (manager) @@ -769,7 +772,7 @@ LayoutViewBase::configure (const std::string &name, const std::string &value) // keep a shadow state to correctly issue the redraw call m_default_font_size = df; lay::FixedFont::set_default_font_size (df); - redraw (); + redraw_later (); } // do not take - let others have the event for the redraw call return false; @@ -1814,7 +1817,7 @@ LayoutViewBase::set_properties (unsigned int index, const LayerPropertiesList &p if (index == current_layer_list ()) { end_layer_updates (); layer_list_changed_event (3); - redraw (); + redraw_later (); m_prop_changed = true; } } @@ -1875,7 +1878,7 @@ LayoutViewBase::replace_layer_node (unsigned int index, const LayerPropertiesCon end_layer_updates (); layer_list_changed_event (2); // TODO: check, if redraw is actually necessary (this is complex!) - redraw (); + redraw_later (); m_prop_changed = true; } } @@ -1909,7 +1912,7 @@ LayoutViewBase::set_properties (unsigned int index, const LayerPropertiesConstIt layer_list_changed_event (1); if (need_redraw) { - redraw (); + redraw_later (); } if (visible_changed) { @@ -1945,7 +1948,7 @@ LayoutViewBase::insert_layer (unsigned int index, const LayerPropertiesConstIter if (index == current_layer_list ()) { end_layer_updates (); layer_list_changed_event (2); - redraw (); + redraw_later (); m_prop_changed = true; } @@ -1978,7 +1981,7 @@ LayoutViewBase::delete_layer (unsigned int index, LayerPropertiesConstIterator & if (index == current_layer_list ()) { end_layer_updates (); layer_list_changed_event (2); - redraw (); + redraw_later (); m_prop_changed = true; } @@ -2174,7 +2177,7 @@ void LayoutViewBase::signal_hier_changed () { // schedule a redraw request for all layers - redraw (); + redraw_later (); // forward this event to our observers hier_changed_event (); } @@ -2206,7 +2209,7 @@ void LayoutViewBase::signal_bboxes_changed () { // schedule a redraw request for all layers - redraw (); + redraw_later (); // forward this event to our observers geom_changed_event (); @@ -2216,7 +2219,7 @@ void LayoutViewBase::signal_cell_name_changed () { cell_visibility_changed_event (); // HINT: that is not what actually is intended, but it serves the function ... - redraw (); // needs redraw + redraw_later (); // needs redraw } void @@ -2229,7 +2232,7 @@ LayoutViewBase::signal_layer_properties_changed () } // schedule a redraw request - since the layer views might not have changed, this is necessary - redraw (); + redraw_later (); } void @@ -2271,7 +2274,7 @@ LayoutViewBase::finish_cellviews_changed () cellviews_changed_event (); - redraw (); + redraw_later (); } std::list::iterator @@ -3896,6 +3899,12 @@ LayoutViewBase::redraw_deco_layer () do_redraw (lay::draw_custom_queue_entry); } +void +LayoutViewBase::redraw_later () +{ + dm_redraw (); +} + void LayoutViewBase::redraw () { @@ -5463,6 +5472,7 @@ LayoutViewBase::current_pos (double /*x*/, double /*y*/) void LayoutViewBase::stop_redraw () { + dm_redraw.cancel (); mp_canvas->stop_redraw (); } diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index a45056f80..3419f76c9 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -51,6 +51,7 @@ #include "tlException.h" #include "tlEvents.h" #include "tlTimer.h" +#include "tlDeferredExecution.h" #include "dbInstElement.h" namespace rdb { @@ -2650,6 +2651,7 @@ public: // called by children and owner void redraw (); + void redraw_later (); void redraw_layer (unsigned int index); void redraw_deco_layer (); void redraw_cell_boxes (); @@ -2700,6 +2702,7 @@ private: private: lay::LayoutView *mp_ui; + tl::DeferredMethod dm_redraw; bool m_editable; int m_disabled_edits; unsigned int m_options; diff --git a/src/layui/layui/layLayerControlPanel.cc b/src/layui/layui/layLayerControlPanel.cc index 1ff0370c8..66fece100 100644 --- a/src/layui/layui/layLayerControlPanel.cc +++ b/src/layui/layui/layLayerControlPanel.cc @@ -70,6 +70,7 @@ LCPTreeWidget::LCPTreeWidget (QWidget *parent, lay::LayerTreeModel *model, const { setObjectName (QString::fromUtf8 (name)); setModel (model); + setUniformRowHeights (true); #if QT_VERSION >= 0x040200 setAllColumnsShowFocus (true); #endif @@ -1702,7 +1703,7 @@ LayerControlPanel::cancel_updates () void LayerControlPanel::end_updates () { - do_update_content (); + m_do_update_content_dm (); } void diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc index 3480e0530..a8c5f0dcc 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc @@ -559,41 +559,42 @@ OASISReader::mark_start_table () void OASISReader::read_offset_table () { - unsigned long of = 0; + unsigned int of = 0; of = get_uint (); - m_table_cellname = get_ulong (); + get (m_table_cellname); if (m_table_cellname != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("CELLNAME offset table has unexpected strict mode"))); } of = get_uint (); - m_table_textstring = get_ulong (); + get (m_table_textstring); if (m_table_textstring != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("TEXTSTRING offset table has unexpected strict mode"))); } of = get_uint (); - m_table_propname = get_ulong (); + get (m_table_propname); if (m_table_propname != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("PROPNAME offset table has unexpected strict mode"))); } of = get_uint (); - m_table_propstring = get_ulong (); + get (m_table_propstring); if (m_table_propstring != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("PROPSTRING offset table has unexpected strict mode"))); } of = get_uint (); - m_table_layername = get_ulong (); + get (m_table_layername); if (m_table_layername != 0 && m_expect_strict_mode >= 0 && ((of == 0) != (m_expect_strict_mode == 0))) { warn (tl::to_string (tr ("LAYERNAME offset table has unexpected strict mode"))); } // XNAME table ignored currently get_uint (); - get_ulong (); + size_t dummy = 0; + get (dummy); } static const char magic_bytes[] = { "%SEMI-OASIS\015\012" }; @@ -1084,8 +1085,9 @@ OASISReader::do_read (db::Layout &layout) error (tl::sprintf (tl::to_string (tr ("Invalid CBLOCK compression type %d")), type)); } - get_uint (); // uncomp-byte-count - not needed - get_uint (); // comp-byte-count - not needed + size_t dummy = 0; + get (dummy); // uncomp-byte-count - not needed + get (dummy); // comp-byte-count - not needed // put the stream into deflating mode m_stream.inflate (); @@ -1282,8 +1284,9 @@ OASISReader::read_element_properties (db::PropertiesRepository &rep, bool ignore error (tl::sprintf (tl::to_string (tr ("Invalid CBLOCK compression type %d")), type)); } - get_uint (); // uncomp-byte-count - not needed - get_uint (); // comp-byte-count - not needed + size_t dummy = 0; + get (dummy); // uncomp-byte-count - not needed + get (dummy); // comp-byte-count - not needed // put the stream into deflating mode m_stream.inflate (); @@ -1520,7 +1523,7 @@ OASISReader::read_pointlist (modal_variable > &pointlis bool OASISReader::read_repetition () { - unsigned char type = get_uint (); + unsigned int type = get_uint (); if (type == 0) { // reuse modal variable @@ -3308,8 +3311,9 @@ OASISReader::do_read_cell (db::cell_index_type cell_index, db::Layout &layout) error (tl::sprintf (tl::to_string (tr ("Invalid CBLOCK compression type %d")), type)); } - get_uint (); // uncomp-byte-count - not needed - get_uint (); // comp-byte-count - not needed + size_t dummy = 0; + get (dummy); // uncomp-byte-count - not needed + get (dummy); // comp-byte-count - not needed // put the stream into deflating mode m_stream.inflate (); diff --git a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc index 67cc68b9d..953e47119 100644 --- a/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc +++ b/src/plugins/tools/net_tracer/db_plugin/dbNetTracerPlugin.cc @@ -80,7 +80,8 @@ get_default (const db::NetTracerTechnologyComponent &tc) if (tc.begin () != tc.end ()) { return tc.begin ().operator-> (); } else { - return 0; + static db::NetTracerConnectivity s_empty; + return &s_empty; } } @@ -135,13 +136,8 @@ struct FallbackXMLReadAdaptor void start (const db::NetTracerTechnologyComponent &parent) { const db::NetTracerConnectivity *tn = get_default (parent); - if (! tn) { - m_iter = Iter (); - m_end = Iter (); - } else { - m_iter = (tn->*mp_begin) (); - m_end = (tn->*mp_end) (); - } + m_iter = (tn->*mp_begin) (); + m_end = (tn->*mp_end) (); } void next () diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc index ba1b49639..c525c28ec 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25View.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25View.cc @@ -125,6 +125,10 @@ bool D25View::configure(const std::string &name, const std::string &value) tl::Color bg; lc.from_string (value, bg); + if (! bg.is_valid ()) { + bg = view () ? view ()->background_color () : Qt::white; + } + QPalette palette = mp_ui->material_list->palette (); palette.setColor (QPalette::Base, bg.to_qc ()); palette.setColor (QPalette::Text, bg.to_mono () ? Qt::black : Qt::white); diff --git a/src/tl/tl/tlClassRegistry.cc b/src/tl/tl/tlClassRegistry.cc index b208dc5b2..a02311d5b 100644 --- a/src/tl/tl/tlClassRegistry.cc +++ b/src/tl/tl/tlClassRegistry.cc @@ -23,35 +23,36 @@ #include "tlClassRegistry.h" -#include +#include +#include +#include namespace tl { -struct ti_compare_f -{ - bool operator() (const std::type_info *a, const std::type_info *b) const - { - return a->before (*b); - } -}; +typedef std::map inst_map_type; -typedef std::map inst_map_type; -static inst_map_type s_inst_map; +// Used to fix https://en.cppreference.com/w/cpp/language/siof segfault +// on some systems. +inst_map_type& s_inst_map() { + static inst_map_type s_inst_map; + return s_inst_map; +} TL_PUBLIC void set_registrar_instance_by_type (const std::type_info &ti, RegistrarBase *rb) { if (rb) { - s_inst_map[&ti] = rb; + s_inst_map()[std::type_index(ti)] = rb; } else { - s_inst_map.erase (&ti); + s_inst_map().erase (std::type_index(ti)); } } TL_PUBLIC RegistrarBase *registrar_instance_by_type (const std::type_info &ti) { - inst_map_type::const_iterator im = s_inst_map.find (&ti); - if (im != s_inst_map.end ()) { + inst_map_type map = s_inst_map(); + inst_map_type::const_iterator im = map.find (std::type_index(ti)); + if (im != map.end ()) { return im->second; } else { return 0; diff --git a/src/unit_tests/unit_test_main.cc b/src/unit_tests/unit_test_main.cc index 32640b046..fce23b5a5 100644 --- a/src/unit_tests/unit_test_main.cc +++ b/src/unit_tests/unit_test_main.cc @@ -41,6 +41,10 @@ // This hard-links the GSI test classes #include "../gsi_test/gsiTestForceLink.h" +// For testing the document structure +#include "docForceLink.h" +#include "iconsForceLink.h" + #include "version.h" #if defined(HAVE_QT) diff --git a/src/unit_tests/unit_tests.pro b/src/unit_tests/unit_tests.pro index 0e01149cb..230b1bd8b 100644 --- a/src/unit_tests/unit_tests.pro +++ b/src/unit_tests/unit_tests.pro @@ -4,6 +4,13 @@ DESTDIR = $$OUT_PWD/.. include($$PWD/../klayout.pri) include($$PWD/../with_all_libs.pri) +# NOTE: doc is needed for testing help sources + +INCLUDEPATH += $$DOC_INC $$ICONS_INC +DEPENDPATH += $$DOC_INC $$ICONS_INC + +LIBS += -lklayout_doc -lklayout_icons + TEMPLATE = app # Don't build the ut_runner app as ordinary command line tool on MacOS