diff --git a/Changelog b/Changelog
index 3e90f46bc..23d35b08d 100644
--- a/Changelog
+++ b/Changelog
@@ -2,17 +2,34 @@
* Enhancement: %GITHUB%/issues/521
Enhanced API for ObjectInstPath
-* Bugfix: %GITHUB%/issues/524
- Failed queries leave layout in undefined state
+* Enhancement: %GITHUB%/issues/558
+ Edges#extents, Texts#extents and EdgePairs#extents now
+ work hierarchically in deep mode. In DRC, this means,
+ "extents" is a deep-enabled method now.
+* Enhancement: %GITHUB%/issues/563
+ True support for text objects in DRC/LVS (text layers)
+* Enhancement: ability to utilize a LayoutView as a Widget
+ Standalone instantiation of a LayoutView object is
+ supported now. So it becomes possible to create
+ custom MainWindow UIs and embed a layout view there.
0.26.5 (2020-xx-xx):
+* Bugfix: %GITHUB%/issues/539
+ An internal error happened on netlist flatten sometimes
+* Bugfix: %GITHUB%/issues/524
+ Failed queries leave layout in undefined state
* Bugfix: %GITHUB%/issues/525
Report true source line in DRC and LVS verbose mode
* Bugfix: %GITHUB%/issues/526
Makes script debugging more reliable
* Enhancement: %GITHUB%/issues/527
Wildcard layer mapping for stream readers
+* Bugfix: %GITHUB%/issues/544
+ Duplicate .global statements in SPICE netlists created
+ duplicate pins
+* Bugfix: diff tool bug with paths
+ Differences in path points where no reported
* Enhancement: documentation clarifications and typos fixed
0.26.4 (2020-03-02):
diff --git a/Jenkinsfile b/Jenkinsfile
index 93d1a813e..e3033ad39 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -16,6 +16,7 @@ node("master") {
stage("Checkout sources") {
checkout scm
+ checkout_private()
}
diff --git a/etc/klayout.metainfo.xml b/etc/klayout.metainfo.xml
new file mode 100644
index 000000000..27f21c37a
--- /dev/null
+++ b/etc/klayout.metainfo.xml
@@ -0,0 +1,28 @@
+
+
+ de.klayout.KLayout
+
+ KLayout
+ KLayout, viewer and editor for mask layouts
+
+ CC0-1.0
+ GPL-3.0-or-later
+
+
+
+ Mask layout viewer and editor for the chip design engineer.
+
+
+
+ klayout.desktop
+
+
+ https://www.klayout.de/intro-image.png
+
+
+
+ Matthias Köfferlein
+
+ klayout
+
+
diff --git a/macbuild/ReadMe.md b/macbuild/ReadMe.md
index 1ca45ab36..4f87e9616 100644
--- a/macbuild/ReadMe.md
+++ b/macbuild/ReadMe.md
@@ -1,4 +1,4 @@
-Relevant KLayout version: 0.26.4
+Relevant KLayout version: 0.26.5
# 1. Introduction
This directory **`macbuild`** contains different files required for building KLayout (http://www.klayout.de/) version 0.26.1 or later for different 64-bit Mac OSXs including:
@@ -26,6 +26,11 @@ Alternatively, you can use "Qt5" from Homebrew (https://brew.sh/) which is usual
$HOME/opt/anaconda3/pkgs/qt-{version}
```
+If you have installed Anaconda3 under $HOME/opt/anaconda3/, make a symbolic link:
+```
+/Applications/anaconda3/ ---> $HOME/opt/anaconda3/
+```
+
# 3. Script language support: Ruby and Python
By default, supported script languages, i.e., Ruby and Python, are those standard ones bundled with the OS.
As for Catalina (10.15),
@@ -220,8 +225,8 @@ $ cd /where/'build.sh'/exists
$ ./makeDMG4mac.py -p ST-qt5MP.pkg.macos-Catalina-release-RsysPsys -m
```
This command will generate the two files below:
-* **`ST-klayout-0.26.4-macOS-Catalina-1-qt5MP-RsysPsys.dmg`** ---(1) the main DMG file
-* **`ST-klayout-0.26.4-macOS-Catalina-1-qt5MP-RsysPsys.dmg.md5`** ---(2) MD5-value text file
+* **`ST-klayout-0.26.5-macOS-Catalina-1-qt5MP-RsysPsys.dmg`** ---(1) the main DMG file
+* **`ST-klayout-0.26.5-macOS-Catalina-1-qt5MP-RsysPsys.dmg.md5`** ---(2) MD5-value text file
# Known issues
Because we assume some specific versions of non-OS-standard Ruby and Python, updating MacPorts, Homebrew, or Anaconda3 may cause build- and link errors.
diff --git a/macbuild/Resources/KLayoutDMG-Back.logoist b/macbuild/Resources/KLayoutDMG-Back.logoist
index b459680cf..336c51a9e 100644
Binary files a/macbuild/Resources/KLayoutDMG-Back.logoist and b/macbuild/Resources/KLayoutDMG-Back.logoist differ
diff --git a/macbuild/Resources/KLayoutDMG-Back.png b/macbuild/Resources/KLayoutDMG-Back.png
index 898fc448d..88e0a1108 100644
Binary files a/macbuild/Resources/KLayoutDMG-Back.png and b/macbuild/Resources/KLayoutDMG-Back.png differ
diff --git a/macbuild/Resources/icon-resources/klayout-Ports.icns b/macbuild/Resources/icon-resources/klayout-Ports.icns
new file mode 100644
index 000000000..0d5463fe7
Binary files /dev/null and b/macbuild/Resources/icon-resources/klayout-Ports.icns differ
diff --git a/macbuild/Resources/icon-resources/klayout-Ports.logoist b/macbuild/Resources/icon-resources/klayout-Ports.logoist
new file mode 100644
index 000000000..ca4525ab4
Binary files /dev/null and b/macbuild/Resources/icon-resources/klayout-Ports.logoist differ
diff --git a/macbuild/Resources/icon-resources/klayout-Ports.png b/macbuild/Resources/icon-resources/klayout-Ports.png
new file mode 100644
index 000000000..c8400ee7f
Binary files /dev/null and b/macbuild/Resources/icon-resources/klayout-Ports.png differ
diff --git a/macbuild/Resources/script-bundle-A.zip b/macbuild/Resources/script-bundle-A.zip
new file mode 100644
index 000000000..990050af7
Binary files /dev/null and b/macbuild/Resources/script-bundle-A.zip differ
diff --git a/macbuild/Resources/script-bundle-B.zip b/macbuild/Resources/script-bundle-B.zip
new file mode 100644
index 000000000..253e8ae6b
Binary files /dev/null and b/macbuild/Resources/script-bundle-B.zip differ
diff --git a/macbuild/Resources/script-bundle-P.zip b/macbuild/Resources/script-bundle-P.zip
new file mode 100644
index 000000000..d8b11fa06
Binary files /dev/null and b/macbuild/Resources/script-bundle-P.zip differ
diff --git a/macbuild/Resources/script-bundles.zip b/macbuild/Resources/script-bundles.zip
index 72ebeecef..bb82e0847 100644
Binary files a/macbuild/Resources/script-bundles.zip and b/macbuild/Resources/script-bundles.zip differ
diff --git a/macbuild/Resources/template-KLayoutDMG.applescript b/macbuild/Resources/template-KLayoutDMG.applescript
index a8672081e..78d5b00d7 100644
--- a/macbuild/Resources/template-KLayoutDMG.applescript
+++ b/macbuild/Resources/template-KLayoutDMG.applescript
@@ -3,19 +3,20 @@
* Template File:
* macbuild/Resources/template-KLayoutDMG.applescript
*
- * On the runtime, "makeDMG4mac.py" will generate the actual AppleScrip File:
+ * On the runtime, "makeDMG4mac.py" will generate the actual AppleScrip File
* "macbuild/Resources/KLayoutDMG.applescript"
* from this template. Hence, the generated actual scrip file does not need
* to be version controlled by Git.
*
* Description:
- * A template AppleScript to make a fancy DMG installer of KLayout
- * (http://www.klayout.de/index.php) bundles.
+ * This is a template AppleScript to make a fancy DMG installer of KLayout
+ * (http://www.klayout.de/index.php) application bundles.
* "makeDMG4mac.py" will read this template and generate the actual AppleScript to execute.
- * Values to be found and replaced by "makeDMG4mac.py" are marked by ${KEYWORD}.
+ * Those values to be found and replaced by "makeDMG4mac.py" are marked by ${KEYWORD} in this
+ * template file.
*
- * The background image was designed using Logoist3 (http://www.syniumsoftware.com/en/logoist)
- * and exported to a PNG file of 1000 x 500 pix size.
+ * The background PNG image file (1000 x 500 pix size) was designed by using Logoist3
+ * (http://www.syniumsoftware.com/en/logoist).
*-----------------------------------------------------------------------------------------------
* This is a derivative work of Ref. 2) below. Refer to "macbuild/LICENSE" file.
* Ref.
@@ -65,14 +66,16 @@ on run (volumeName) -- most likely, the volume name is "KLayout"
set arrangement to not arranged
end tell
- -- [6] Set the background PNG image (1000 x 700 pix) file name stored
+ -- [6] Set the background PNG image file name stored
set background picture of opts to file ".background:${BACKGROUND_PNG_FILE}"
-- [7] Set positions of each icon
-- ITEM_1 = klayout.app {860, 165}
-- ITEM_2 = Applications {860, 345}
+ -- ITEM_3 = AUX. holder {700, 450}
set position of item "${ITEM_1}" to {${X1}, ${Y1}}
set position of item "${ITEM_2}" to {${X2}, ${Y2}}
+ ${ITEM_3}
-- [8] Update the contents of container
close
diff --git a/macbuild/build4mac.py b/macbuild/build4mac.py
index cd9dafe32..d5bc8732a 100755
--- a/macbuild/build4mac.py
+++ b/macbuild/build4mac.py
@@ -441,14 +441,16 @@ def RunMainBuildBash():
global DeploymentF
global DeploymentP
global PackagePrefix
- global MacPkgDir # relative path to package directory
- global MacBinDir # relative path to binary directory
- global MacBuildDir # relative path to build directory
- global MacBuildLog # relative path to build log file
- global AbsMacPkgDir # absolute path to package directory
- global AbsMacBinDir # absolute path to binary directory
- global AbsMacBuildDir # absolute path to build directory
- global AbsMacBuildLog # absolute path to build log file
+ global MacPkgDir # relative path to package directory
+ global MacBinDir # relative path to binary directory
+ global MacBuildDir # relative path to build directory
+ global MacBuildDirQAT # relative path to build directory for QATest
+ global MacBuildLog # relative path to build log file
+ global AbsMacPkgDir # absolute path to package directory
+ global AbsMacBinDir # absolute path to binary directory
+ global AbsMacBuildDir # absolute path to build directory
+ global AbsMacBuildDirQAT # absolute path to build directory for QATest
+ global AbsMacBuildLog # absolute path to build log file
#-----------------------------------------------------
# [1] Set parameters passed to the main Bash script
@@ -468,14 +470,16 @@ def RunMainBuildBash():
ruby_python = "R%sP%s" % ( ruby.lower(), python.lower() )
# (C) Target directories and files
- MacPkgDir = "./%s%s.pkg.macos-%s-%s-%s" % (PackagePrefix, qt, Platform, mode, ruby_python)
- MacBinDir = "./%s.bin.macos-%s-%s-%s" % ( qt, Platform, mode, ruby_python)
- MacBuildDir = "./%s.build.macos-%s-%s-%s" % ( qt, Platform, mode, ruby_python)
- MacBuildLog = "./%s.build.macos-%s-%s-%s.log" % ( qt, Platform, mode, ruby_python)
- AbsMacPkgDir = "%s/%s%s.pkg.macos-%s-%s-%s" % (ProjectDir, PackagePrefix, qt, Platform, mode, ruby_python)
- AbsMacBinDir = "%s/%s.bin.macos-%s-%s-%s" % (ProjectDir, qt, Platform, mode, ruby_python)
- AbsMacBuildDir = "%s/%s.build.macos-%s-%s-%s" % (ProjectDir, qt, Platform, mode, ruby_python)
- AbsMacBuildLog = "%s/%s.build.macos-%s-%s-%s.log" % (ProjectDir, qt, Platform, mode, ruby_python)
+ MacPkgDir = "./%s%s.pkg.macos-%s-%s-%s" % (PackagePrefix, qt, Platform, mode, ruby_python)
+ MacBinDir = "./%s.bin.macos-%s-%s-%s" % ( qt, Platform, mode, ruby_python)
+ MacBuildDir = "./%s.build.macos-%s-%s-%s" % ( qt, Platform, mode, ruby_python)
+ MacBuildLog = "./%s.build.macos-%s-%s-%s.log" % ( qt, Platform, mode, ruby_python)
+ AbsMacPkgDir = "%s/%s%s.pkg.macos-%s-%s-%s" % (ProjectDir, PackagePrefix, qt, Platform, mode, ruby_python)
+ AbsMacBinDir = "%s/%s.bin.macos-%s-%s-%s" % (ProjectDir, qt, Platform, mode, ruby_python)
+ AbsMacBuildDir = "%s/%s.build.macos-%s-%s-%s" % (ProjectDir, qt, Platform, mode, ruby_python)
+ AbsMacBuildLog = "%s/%s.build.macos-%s-%s-%s.log" % (ProjectDir, qt, Platform, mode, ruby_python)
+ MacBuildDirQAT = MacBuildDir + ".macQAT"
+ AbsMacBuildDirQAT = AbsMacBuildDir + ".macQAT"
# (D) Qt5
if ModuleQt == 'Qt5MacPorts':
@@ -554,6 +558,45 @@ def RunMainBuildBash():
print( "### <%s>: successfully built KLayout" % myscript, file=sys.stderr )
print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
print( "", file=sys.stderr )
+
+ #------------------------------------------------------------------------
+ # [4] Prepare "*.macQAT/" directory for the QATest.
+ # Binaries under "*.macQAT/" such as *.dylib will be touched later.
+ #------------------------------------------------------------------------
+ print( "### Preparing <%s>" % MacBuildDirQAT )
+ if os.path.isdir( MacBuildDirQAT ):
+ shutil.rmtree( MacBuildDirQAT )
+
+ os.chdir( MacBuildDir )
+ tarFile = "../macQATest.tar"
+ tarCmdC = "tar cf %s ." % tarFile
+ if subprocess.call( tarCmdC, shell=True ) != 0:
+ print( "", file=sys.stderr )
+ print( "-------------------------------------------------------------", file=sys.stderr )
+ print( "!!! <%s>: failed to create <%s>" % (myscript, tarFile), file=sys.stderr )
+ print( "-------------------------------------------------------------", file=sys.stderr )
+ print( "", file=sys.stderr )
+ return 1
+
+ os.chdir( "../" )
+ os.mkdir( MacBuildDirQAT )
+ os.chdir( MacBuildDirQAT )
+ tarCmdX = "tar xf %s" % tarFile
+ if subprocess.call( tarCmdX, shell=True ) != 0:
+ print( "", file=sys.stderr )
+ print( "-------------------------------------------------------------", file=sys.stderr )
+ print( "!!! <%s>: failed to unpack <%s>" % (myscript, tarFile), file=sys.stderr )
+ print( "-------------------------------------------------------------", file=sys.stderr )
+ print( "", file=sys.stderr )
+ return 1
+
+ os.remove( tarFile )
+ os.chdir( "../" )
+ shutil.copy2( "macbuild/macQAT.sh", MacBuildDirQAT )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "### <%s>: prepared the initial *.macQAT/" % myscript, file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "", file=sys.stderr )
return 0
#------------------------------------------------------------------------------
@@ -573,10 +616,12 @@ def DeployBinariesForBundle():
global MacPkgDir
global MacBinDir
global MacBuildDir
+ global MacBuildDirQAT
global MacBuildLog
global AbsMacPkgDir
global AbsMacBinDir
global AbsMacBuildDir
+ global AbsMacBuildDirQAT
global AbsMacBuildLog
global Version
global DeployVerbose
diff --git a/macbuild/build4mac_env.py b/macbuild/build4mac_env.py
index 621acd1ed..033e574d9 100755
--- a/macbuild/build4mac_env.py
+++ b/macbuild/build4mac_env.py
@@ -42,11 +42,12 @@ Qt5Brew = { 'qmake' : '/usr/local/opt/qt/bin/qmake',
'deploy': '/usr/local/opt/qt/bin/macdeployqt'
}
-# Qt5 bundled with anaconda3 installed under $HOME/opt/anaconda3/
-# installed by the standard installation package
+# Qt5 bundled with anaconda3 installed under /Applications/anaconda3/
+# The standard installation deploys the tool under $HOME/opt/anaconda3/.
+# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/
# [Key Type Name] = 'Qt5Ana3'
-Qt5Ana3 = { 'qmake' : '%s/opt/anaconda3/bin/qmake' % MyHome,
- 'deploy': '%s/opt/anaconda3/bin/macdeployqt' % MyHome
+Qt5Ana3 = { 'qmake' : '/Applications/anaconda3/bin/qmake',
+ 'deploy': '/Applications/anaconda3/bin/macdeployqt'
}
#-----------------------------------------------------
@@ -120,18 +121,19 @@ Ruby26MacPorts = { 'exe': '/opt/local/bin/ruby2.6',
# Ruby 2.7 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
# install with 'brew install ruby'
# [Key Type Name] = 'HB27'
-HBRuby27Path = '/usr/local/Cellar/ruby/2.7.0'
+HBRuby27Path = '/usr/local/opt/ruby'
Ruby27Brew = { 'exe': '%s/bin/ruby' % HBRuby27Path,
'inc': '%s/include/ruby-2.7.0' % HBRuby27Path,
'lib': '%s/lib/libruby.2.7.dylib' % HBRuby27Path
}
-# Ruby 2.5 bundled with anaconda3 installed under $HOME/opt/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
-# install with 'conda install ruby'
+# Ruby 2.5 bundled with anaconda3 installed under /Applications/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
+# The standard installation deploys the tool under $HOME/opt/anaconda3/.
+# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/
# [Key Type Name] = 'Ana3'
-RubyAnaconda3 = { 'exe': '%s/opt/anaconda3/bin/ruby' % MyHome,
- 'inc': '%s/opt/anaconda3/include/ruby-2.5.0' % MyHome,
- 'lib': '%s/opt/anaconda3/lib/libruby.2.5.1.dylib' % MyHome
+RubyAnaconda3 = { 'exe': '/Applications/anaconda3/bin/ruby',
+ 'inc': '/Applications/anaconda3/include/ruby-2.5.0',
+ 'lib': '/Applications/anaconda3/lib/libruby.2.5.1.dylib'
}
# Consolidated dictionary kit for Ruby
@@ -213,18 +215,19 @@ Python37MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versi
# Python 3.7 from Homebrew *+*+*+ EXPERIMENTAL *+*+*+
# install with 'brew install python'
# [Key Type Name] = 'HB37'
-HBPython37FrameworkPath = '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework'
+HBPython37FrameworkPath = '/usr/local/opt/python3/Frameworks/Python.framework'
Python37Brew = { 'exe': '%s/Versions/3.7/bin/python3.7m' % HBPython37FrameworkPath,
'inc': '%s/Versions/3.7/include/python3.7m' % HBPython37FrameworkPath,
'lib': '%s/Versions/3.7/lib/libpython3.7m.dylib' % HBPython37FrameworkPath
}
-# Python 3.7 bundled with anaconda3 installed under $HOME/opt/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
-# installed by the standard installation package
+# Python 3.7 bundled with anaconda3 installed under /Applications/anaconda3/ *+*+*+ EXPERIMENTAL *+*+*+
+# The standard installation deploys the tool under $HOME/opt/anaconda3/.
+# If so, you need to make a symbolic link: /Applications/anaconda3 ---> $HOME/opt/anaconda3/
# [Key Type Name] = 'Ana3'
-PythonAnaconda3 = { 'exe': '%s/opt/anaconda3/bin/python3.7m' % MyHome,
- 'inc': '%s/opt/anaconda3/include/python3.7m' % MyHome,
- 'lib': '%s/opt/anaconda3/lib/libpython3.7m.dylib' % MyHome
+PythonAnaconda3 = { 'exe': '/Applications/anaconda3/bin/python3.7m',
+ 'inc': '/Applications/anaconda3/include/python3.7m',
+ 'lib': '/Applications/anaconda3/lib/libpython3.7m.dylib'
}
# Consolidated dictionary kit for Python
diff --git a/macbuild/macQAT.sh b/macbuild/macQAT.sh
new file mode 100755
index 000000000..36ac52e3e
--- /dev/null
+++ b/macbuild/macQAT.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+#===============================================================================
+# File: "macbuild/macQAT.sh"
+#
+# The top Bash script to run "ut_runner" after building KLayout
+# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
+# ßMac OSX platforms.
+#
+# This script must be copied to a "*.macQAT/" directory to run.
+#===============================================================================
+
+#----------------------------------------------------------------
+# Functions
+#----------------------------------------------------------------
+function GetPresentDir() {
+ path=$1
+ array=( `echo $path | tr -s '/' ' '`)
+ last_index=`expr ${#array[@]} - 1`
+ echo ${array[${last_index}]}
+ return 0
+}
+
+function HidePrivateDir() {
+ if [ -d "../private" ]; then
+ ret=$(/bin/mv ../private ../private.stash)
+ fi
+}
+
+function ShowPrivateDir() {
+ if [ -d "../private.stash" ]; then
+ ret=$(/bin/mv ../private.stash ../private)
+ fi
+}
+
+#----------------------------------------------------------------
+# Variables
+#----------------------------------------------------------------
+gitSHA1=$(git rev-parse --short HEAD 2>/dev/null)
+timestamp=$(date "+%Y_%m%d_%H%M")
+presentDir=$(GetPresentDir `pwd`)
+logfile=QATest_${gitSHA1}_${timestamp}__${presentDir}.log
+
+#----------------------------------------------------------------
+# Environment variables for "ut_runner"
+#----------------------------------------------------------------
+export TESTSRC=..
+export TESTTMP=QATest_${gitSHA1}_${timestamp}__${presentDir}
+export DYLD_LIBRARY_PATH=$(pwd):$(pwd)/db_plugins
+
+#----------------------------------------------------------------
+# Environment variables for "ut_runner"
+#----------------------------------------------------------------
+if [ $# -eq 1 ]; then
+ if [ "$1" == "-h" ]; then
+ ./ut_runner -h
+ exit 0
+ fi
+ if [ "$1" == "-r" ]; then
+ echo "### Dumping the log to" $logfile "..."
+ HidePrivateDir
+ ./ut_runner -x pymod -c 2>&1 | tee $logfile
+ ShowPrivateDir
+ exit 0
+ else
+ echo ""
+ echo " Git SHA1 = ${gitSHA1}"
+ echo " Time stamp = ${timestamp}"
+ echo " Log file = ${logfile}"
+ echo " Usage:"
+ echo " ./QATest.sh -h: to get the help of 'ut_runner'"
+ echo " ./QATest.sh -r: to run the tests with '-c' option: continues after an error"
+ echo ""
+ exit 0
+ fi
+else
+ echo ""
+ echo " Git SHA1 = ${gitSHA1}"
+ echo " Time stamp = ${timestamp}"
+ echo " Log file = ${logfile}"
+ echo " Usage:"
+ echo " ./QATest.sh -h: to get the help of 'ut_runner'"
+ echo " ./QATest.sh -r: to run the tests with '-c' option: continues after an error"
+ echo ""
+ exit 0
+fi
+
+#--------------
+# End of File
+#--------------
diff --git a/macbuild/makeDMG4mac.py b/macbuild/makeDMG4mac.py
index 7fea13cd6..c2429c785 100755
--- a/macbuild/makeDMG4mac.py
+++ b/macbuild/makeDMG4mac.py
@@ -17,6 +17,7 @@ import sys
import os
import re
import shutil
+import zipfile
import glob
import platform
import optparse
@@ -36,6 +37,7 @@ from build4mac_util import *
def SetGlobals():
global ProjectDir # project directory where "build.sh" exists
global Usage # string on usage
+ global LatestOS # the latest generic OS name
global GenOSName # generic OS name
global Platform # platform
global PkgDir # the package directory where "klayout.app" exists
@@ -47,7 +49,7 @@ def SetGlobals():
global PackagePrefix # the package prefix: 'ST-', 'LW-', 'HW-', or 'EX-'
global QtIdentification # Qt identification
global RubyPythonID # Ruby- and Python-identification
- global Version # KLayout's version
+ global KLVersion # KLayout's version
global OccupiedDS # approx. occupied disc space
global BackgroundPNG # the background PNG image file
global VolumeIcons # the volume icon file
@@ -56,6 +58,11 @@ def SetGlobals():
global VolumeDMG # the volume name of DMG
global TargetDMG # the name of target DMG file
global RootApplications # reserved directory name for applications
+ global LatestOSMacPorts # True if 'LatestOS with MacPorts'
+ global LatestOSHomebrew # True if 'LatestOS with Homebrew'
+ global LatestOSAnaconda3 # True if 'LatestOS with Anaconda3'
+ global DicLightWeight # dictionary for LW-* packages
+ global Item3AppleScript # ITEM_3 in the Apple script
# auxiliary variables on platform
global System # 6-tuple from platform.uname()
global Node # - do -
@@ -93,9 +100,11 @@ def SetGlobals():
quit()
release = int( Release.split(".")[0] ) # take the first of ['19', '0', '0']
+ LatestOS = ""
if release == 19:
GenOSName = "macOS"
Platform = "Catalina"
+ LatestOS = Platform
elif release == 18:
GenOSName = "macOS"
Platform = "Mojave"
@@ -130,7 +139,7 @@ def SetGlobals():
PackagePrefix = ""
QtIdentification = ""
RubyPythonID = ""
- Version = GetKLayoutVersionFrom( "./version.sh" )
+ KLVersion = GetKLayoutVersionFrom( "./version.sh" )
OccupiedDS = -1
BackgroundPNG = "KLayoutDMG-Back.png"
VolumeIcons = "KLayoutHDD.icns"
@@ -139,6 +148,30 @@ def SetGlobals():
VolumeDMG = "KLayout"
TargetDMG = ""
RootApplications = "/Applications"
+ LatestOSMacPorts = False
+ LatestOSHomebrew = False
+ LatestOSAnaconda3 = False
+ DicLightWeight = dict()
+ Item3AppleScript = ""
+ # Populate DicLightWeight
+ DicLightWeight[ "ports" ] = dict()
+ DicLightWeight[ "brew" ] = dict()
+ DicLightWeight[ "ana3" ] = dict()
+
+ DicLightWeight[ "ports" ]["zip"] = "macbuild/Resources/script-bundle-P.zip"
+ DicLightWeight[ "ports" ]["src"] = "script-bundle-P"
+ DicLightWeight[ "ports" ]["des"] = "MacPortsUser-ReadMeFirst"
+ DicLightWeight[ "ports" ]["item3"] = 'set position of item "MacPortsUser-ReadMeFirst" to {700, 400}'
+
+ DicLightWeight[ "brew" ]["zip"] = "macbuild/Resources/script-bundle-B.zip"
+ DicLightWeight[ "brew" ]["src"] = "script-bundle-B"
+ DicLightWeight[ "brew" ]["des"] = "HomebrewUser-ReadMeFirst"
+ DicLightWeight[ "brew" ]["item3"] = 'set position of item "HomebrewUser-ReadMeFirst" to {700, 400}'
+
+ DicLightWeight[ "ana3" ]["zip"] = "macbuild/Resources/script-bundle-A.zip"
+ DicLightWeight[ "ana3" ]["src"] = "script-bundle-A"
+ DicLightWeight[ "ana3" ]["des"] = "Anaconda3User-ReadMeFirst"
+ DicLightWeight[ "ana3" ]["item3"] = 'set position of item "Anaconda3User-ReadMeFirst" to {700, 400}'
#------------------------------------------------------------------------------
## To check the contents of the package directory
@@ -156,11 +189,19 @@ def SetGlobals():
# on failure, -1
#------------------------------------------------------------------------------
def CheckPkgDirectory():
+ global Platform
+ global OpClean
+ global OpMake
global DefaultBundleName
global BundleName
global PackagePrefix
global QtIdentification
global RubyPythonID
+ global LatestOSMacPorts
+ global LatestOSHomebrew
+ global LatestOSAnaconda3
+ global DicLightWeight
+ global Item3AppleScript
#-----------------------------------------------------------------------------
# [1] Check the contents of the package directory
@@ -175,30 +216,12 @@ def CheckPkgDirectory():
print( "" )
return -1
- os.chdir(PkgDir)
- if not os.path.isdir( DefaultBundleName ):
- print( "! The package directory <%s> does not hold <%s> bundle" % (PkgDir, DefaultBundleName), file=sys.stderr )
- print( "" )
- os.chdir(ProjectDir)
- return -1
-
- command = "\du -sm %s" % DefaultBundleName
- sizeApp = int( os.popen(command).read().strip("\n").split("\t")[0] )
-
#-----------------------------------------------------------------------------
- # [2] Change the application bundle name on demand
- #-----------------------------------------------------------------------------
- if BundleName == "":
- BundleName = DefaultBundleName
- else:
- os.rename( DefaultBundleName, BundleName )
- os.chdir(ProjectDir)
-
- #-----------------------------------------------------------------------------
- # [3] Identify (Qt, Ruby, Python)
+ # [2] Identify (Qt, Ruby, Python) from PkgDir
#
# * ST-qt5MP.pkg.macos-Catalina-release-RsysPsys
# * LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3
+ # * LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37
# * HW-qt5Brew.pkg.macos-Catalina-release-RsysPhb37
# * EX-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37
#-----------------------------------------------------------------------------
@@ -213,7 +236,93 @@ def CheckPkgDirectory():
PackagePrefix = pkgdirComponents[0]
QtIdentification = pkgdirComponents[2]
RubyPythonID = pkgdirComponents[5]
- return sizeApp
+
+ #-----------------------------------------------------------------------------
+ # [3] Check if the "LatestOS" with MacPorts / Homebrew / Anaconda3
+ #-----------------------------------------------------------------------------
+ LatestOSMacPorts = Platform == LatestOS
+ LatestOSMacPorts &= PackagePrefix == "LW"
+ LatestOSMacPorts &= QtIdentification == "qt5MP"
+ LatestOSMacPorts &= RubyPythonID == "Rmp26Pmp37"
+
+ LatestOSHomebrew = Platform == LatestOS
+ LatestOSHomebrew &= PackagePrefix == "LW"
+ LatestOSHomebrew &= QtIdentification == "qt5Brew"
+ LatestOSHomebrew &= RubyPythonID == "Rhb27Phb37"
+
+ LatestOSAnaconda3 = Platform == LatestOS
+ LatestOSAnaconda3 &= PackagePrefix == "LW"
+ LatestOSAnaconda3 &= QtIdentification == "qt5Ana3"
+ LatestOSAnaconda3 &= RubyPythonID == "Rana3Pana3"
+
+ if LatestOSMacPorts:
+ mydic = DicLightWeight["ports"]
+ srcDir = PkgDir + "/" + mydic["src"]
+ desDir = PkgDir + "/" + mydic["des"]
+ if OpMake:
+ with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
+ zip_ref.extractall(PkgDir)
+ os.rename( srcDir, desDir )
+ if OpClean:
+ if os.path.isdir(srcDir):
+ shutil.rmtree(srcDir)
+ if os.path.isdir(desDir):
+ shutil.rmtree(desDir)
+ Item3AppleScript = mydic["item3"]
+
+ if LatestOSHomebrew:
+ mydic = DicLightWeight["brew"]
+ srcDir = PkgDir + "/" + mydic["src"]
+ desDir = PkgDir + "/" + mydic["des"]
+ if OpMake:
+ with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
+ zip_ref.extractall(PkgDir)
+ os.rename( srcDir, desDir )
+ if OpClean:
+ if os.path.isdir(srcDir):
+ shutil.rmtree(srcDir)
+ if os.path.isdir(desDir):
+ shutil.rmtree(desDir)
+ Item3AppleScript = mydic["item3"]
+
+ if LatestOSAnaconda3:
+ mydic = DicLightWeight["ana3"]
+ srcDir = PkgDir + "/" + mydic["src"]
+ desDir = PkgDir + "/" + mydic["des"]
+ if OpMake:
+ with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
+ zip_ref.extractall(PkgDir)
+ os.rename( srcDir, desDir )
+ if OpClean:
+ if os.path.isdir(srcDir):
+ shutil.rmtree(srcDir)
+ if os.path.isdir(desDir):
+ shutil.rmtree(desDir)
+ Item3AppleScript = mydic["item3"]
+
+ #------------------------------------------------------
+ # [4] Check the presence of the default bundle
+ #------------------------------------------------------
+ os.chdir(PkgDir)
+ if not os.path.isdir( DefaultBundleName ):
+ print( "! The package directory <%s> does not hold <%s> bundle" % (PkgDir, DefaultBundleName), file=sys.stderr )
+ print( "" )
+ os.chdir(ProjectDir)
+ return -1
+
+ #------------------------------------------------------
+ # [5] Check the occupied disk space
+ #------------------------------------------------------
+ command = "\du -sm %s" % DefaultBundleName
+ sizeApp = int( os.popen(command).read().strip("\n").split("\t")[0] )
+
+ #------------------------------------------------------
+ # [6] Change the application bundle name if required
+ #------------------------------------------------------
+ if OpMake and BundleName != "" and BundleName != DefaultBundleName:
+ os.rename( DefaultBundleName, BundleName )
+ os.chdir(ProjectDir)
+ return sizeApp
#------------------------------------------------------------------------------
## To get command line parameters
@@ -231,7 +340,7 @@ def ParseCommandLineArguments():
global PackagePrefix
global QtIdentification
global RubyPythonID
- global Version
+ global KLVersion
global OccupiedDS
global TargetDMG
@@ -290,7 +399,7 @@ def ParseCommandLineArguments():
base, ext = os.path.splitext( os.path.basename(opt.bundle_name) )
BundleName = base + ".app"
else:
- BundleName = ""
+ BundleName = DefaultBundleName
if (OpClean and OpMake) or (not OpClean and not OpMake):
print( "! Specify <-c|--clean> OR <-m|--make>", file=sys.stderr )
@@ -307,7 +416,7 @@ def ParseCommandLineArguments():
quit()
else:
TargetDMG = "%s-klayout-%s-%s-%s-%d-%s-%s.dmg" \
- % (PackagePrefix, Version, GenOSName, Platform, DMGSerialNum, QtIdentification, RubyPythonID)
+ % (PackagePrefix, KLVersion, GenOSName, Platform, DMGSerialNum, QtIdentification, RubyPythonID)
return
#------------------------------------------------------------------------------
@@ -362,8 +471,9 @@ def MakeTargetDMGFile(msg=""):
WIN_WIDTH='1000', WIN_HEIGHT='500',
FULL_PATH_DS_STORE='/Volumes/%s/.DS_Store' % VolumeDMG,
BACKGROUND_PNG_FILE=BackgroundPNG,
- ITEM_1='%s' % BundleName, X1='860', Y1='165',
- ITEM_2='Applications', X2='860', Y2='345',
+ ITEM_1='%s' % BundleName, X1='900', Y1='165',
+ ITEM_2='Applications', X2='900', Y2='345',
+ ITEM_3=Item3AppleScript,
CHECK_BASH='[ -f " & dotDSStore & " ]; echo $?'
)
try:
@@ -523,10 +633,10 @@ def MakeTargetDMGFile(msg=""):
print( " generated MD5 checksum file <%s>" % md5TargetDMG )
print( "" )
- #-------------------------------------------------------------
- # [3] Rename the application bundle if required
- #-------------------------------------------------------------
- if not BundleName == DefaultBundleName:
+ #-------------------------------------------------------------------------
+ # [3] Rename back the application bundle to the default name if required
+ #-------------------------------------------------------------------------
+ if BundleName != "" and BundleName != DefaultBundleName:
dirPresent = "%s/%s" % (PkgDir, BundleName)
dirDefault = "%s/%s" % (PkgDir, DefaultBundleName)
os.rename( dirPresent, dirDefault )
diff --git a/macbuild/nightyCatalina.py b/macbuild/nightyCatalina.py
new file mode 100755
index 000000000..38badd7c3
--- /dev/null
+++ b/macbuild/nightyCatalina.py
@@ -0,0 +1,251 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function # to use print() of Python 3 in Python >= 2.7
+import sys
+import os
+import shutil
+import glob
+import platform
+import optparse
+import subprocess
+
+Variation = [ 'std', 'ports', 'brew', 'ana3' ]
+
+Usage = "\n"
+Usage += "------------------------------------------------------------------------------------------\n"
+Usage += " nightyCatalina.py [EXPERIMENTAL] \n"
+Usage += " << To execute the jobs for making KLatyout's DMGs for macOS Catalina >> \n"
+Usage += "\n"
+Usage += "$ [python] nightyCatalina.py \n"
+Usage += " option & argument : comment on option if any | default value\n"
+Usage += " -------------------------------------------------------------------+--------------\n"
+Usage += " [--build] : build and deploy | disabled\n"
+Usage += " [--makedmg ] : make DMG | disabled\n"
+Usage += " [--cleandmg ] : clean DMG | disabled\n"
+Usage += " [--upload ] : upload to $HOME/Dropbox/klayout/ | disabled\n"
+Usage += " [-?|--?] : print this usage and exit | disabled\n"
+Usage += "----------------------------------------------------------------------+-------------------\n"
+
+def ParseCommandLineArguments():
+ global Usage
+ global Build # operation flag
+ global MakeDMG # operation flag
+ global CleanDMG # operation flag
+ global Upload # operation flag
+ global SrlDMG # DMG serial number
+ global Dropbox # Dropbox directory
+
+ p = optparse.OptionParser( usage=Usage )
+ p.add_option( '--build',
+ action='store_true',
+ dest='build',
+ default=False,
+ help='build and deploy' )
+
+ p.add_option( '--makedmg',
+ dest='makedmg',
+ help='make DMG' )
+
+ p.add_option( '--cleandmg',
+ dest='cleandmg',
+ help='clean DMG' )
+
+ p.add_option( '--upload',
+ dest='upload',
+ help='upload to Dropbox' )
+
+ p.add_option( '-?', '--??',
+ action='store_true',
+ dest='checkusage',
+ default=False,
+ help='check usage (false)' )
+
+ p.set_defaults( build = False,
+ makedmg = "",
+ cleandmg = "",
+ upload = "",
+ checkusage = False )
+
+ opt, args = p.parse_args()
+ if opt.checkusage:
+ print(Usage)
+ quit()
+
+ Build = False
+ MakeDMG = False
+ CleanDMG = False
+ Upload = False
+
+ Build = opt.build
+
+ if not opt.makedmg == "":
+ MakeDMG = True
+ CleanDMG = False
+ SrlDMG = int(opt.makedmg)
+
+ if not opt.cleandmg == "":
+ MakeDMG = False
+ CleanDMG = True
+ SrlDMG = int(opt.cleandmg)
+
+ if not opt.upload == "":
+ Upload = True
+ Dropbox = opt.upload
+
+ if not (Build or MakeDMG or CleanDMG or Upload):
+ print( "! No option selected" )
+ print(Usage)
+ quit()
+
+
+def BuildDeploy():
+ PyBuild = "./build4mac.py"
+
+ Build = dict()
+ Build["std"] = [ '-q', 'Qt5MacPorts', '-r', 'sys', '-p', 'sys' ]
+ Build["ports"] = [ '-q', 'Qt5MacPorts', '-r', 'MP26', '-p', 'MP37' ]
+ Build["brew"] = [ '-q', 'Qt5Brew', '-r', 'HB27', '-p', 'HB37' ]
+ Build["ana3"] = [ '-q', 'Qt5Ana3', '-r', 'Ana3', '-p', 'Ana3' ]
+
+ for key in Variation:
+ command1 = [ PyBuild ] + Build[key]
+ if key == "std":
+ command2 = [ PyBuild ] + Build[key] + ['-y']
+ else:
+ command2 = [ PyBuild ] + Build[key] + ['-Y']
+ print(command1)
+ print(command2)
+ #continue
+
+ if subprocess.call( command1, shell=False ) != 0:
+ print( "", file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "!!! <%s>: failed to build KLayout" % PyBuild, file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "", file=sys.stderr )
+ sys.exit(1)
+ else:
+ print( "", file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "### <%s>: successfully built KLayout" % PyBuild, file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "", file=sys.stderr )
+
+ if subprocess.call( command2, shell=False ) != 0:
+ print( "", file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "!!! <%s>: failed to deploy KLayout" % PyBuild, file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "", file=sys.stderr )
+ sys.exit(1)
+ else:
+ print( "", file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "### <%s>: successfully deployed KLayout" % PyBuild, file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "", file=sys.stderr )
+
+
+def DMG_Make( srlDMG ):
+ PyDMG = "./makeDMG4mac.py"
+ Stash = "./DMGStash"
+
+ Pack = dict()
+ Pack["std"] = [ '-p', 'ST-qt5MP.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '-m' ]
+ Pack["ports"] = [ '-p', 'LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37', '-s', '%d' % srlDMG, '-m' ]
+ Pack["brew"] = [ '-p', 'LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37', '-s', '%d' % srlDMG, '-m' ]
+ Pack["ana3"] = [ '-p', 'LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3', '-s', '%d' % srlDMG, '-m' ]
+
+ if os.path.isdir( Stash ):
+ shutil.rmtree( Stash )
+ os.mkdir( Stash )
+
+ for key in Variation:
+ command3 = [ PyDMG ] + Pack[key]
+ print(command3)
+ #continue
+
+ if subprocess.call( command3, shell=False ) != 0:
+ print( "", file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "!!! <%s>: failed to make KLayout DMG" % PyDMG, file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "", file=sys.stderr )
+ sys.exit(1)
+ else:
+ print( "", file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "### <%s>: successfully made KLayout DMG" % PyDMG, file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "", file=sys.stderr )
+
+ dmgs = glob.glob( "*.dmg*" )
+ for item in dmgs:
+ shutil.move( item, Stash )
+
+
+def DMG_Clean( srlDMG ):
+ PyDMG = "./makeDMG4mac.py"
+ Stash = "./DMGStash"
+
+ Pack = dict()
+ Pack["std"] = [ '-p', 'ST-qt5MP.pkg.macos-Catalina-release-RsysPsys', '-s', '%d' % srlDMG, '-c' ]
+ Pack["ports"] = [ '-p', 'LW-qt5MP.pkg.macos-Catalina-release-Rmp26Pmp37', '-s', '%d' % srlDMG, '-c' ]
+ Pack["brew"] = [ '-p', 'LW-qt5Brew.pkg.macos-Catalina-release-Rhb27Phb37', '-s', '%d' % srlDMG, '-c' ]
+ Pack["ana3"] = [ '-p', 'LW-qt5Ana3.pkg.macos-Catalina-release-Rana3Pana3', '-s', '%d' % srlDMG, '-c' ]
+
+ if os.path.isdir( Stash ):
+ shutil.rmtree( Stash )
+
+ for key in Variation:
+ command3 = [ PyDMG ] + Pack[key]
+ print(command3)
+ #continue
+
+ if subprocess.call( command3, shell=False ) != 0:
+ print( "", file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "!!! <%s>: failed to clean KLayout DMG" % PyDMG, file=sys.stderr )
+ print( "-----------------------------------------------------------------", file=sys.stderr )
+ print( "", file=sys.stderr )
+ sys.exit(1)
+ else:
+ print( "", file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "### <%s>: successfully cleaned KLayout DMG" % PyDMG, file=sys.stderr )
+ print( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", file=sys.stderr )
+ print( "", file=sys.stderr )
+
+
+def UploadToDropbox( targetdir ):
+ Stash = "./DMGStash"
+
+ distDir = os.environ["HOME"] + "/Dropbox/klayout/" + targetdir
+ if not os.path.isdir(distDir):
+ os.makedirs(distDir)
+
+ dmgs = glob.glob( "%s/*.dmg*" % Stash )
+ for item in dmgs:
+ shutil.copy2( item, distDir )
+
+
+def Main():
+ ParseCommandLineArguments()
+
+ if Build:
+ BuildDeploy()
+ elif MakeDMG:
+ DMG_Make( SrlDMG )
+ elif CleanDMG:
+ DMG_Clean( SrlDMG )
+ elif Upload:
+ UploadToDropbox( Dropbox )
+
+#===================================================================================
+if __name__ == "__main__":
+ Main()
+
+#---------------
+# End of file
+#---------------
diff --git a/scripts/create_drc_samples.rb b/scripts/create_drc_samples.rb
index 962c026ac..b8ea6665a 100644
--- a/scripts/create_drc_samples.rb
+++ b/scripts/create_drc_samples.rb
@@ -2,9 +2,45 @@
# Run with:
# ./klayout -z -r ./create_drc_samples.rb -t -c klayoutrc_drc_samples
+class QRCGenerator
+
+ def res_path
+ "src/lay/lay"
+ end
+
+ def img_path
+ "doc/images"
+ end
+
+ def initialize
+ @path = res_path + "/" + "layDRCLVSHelpResources.qrc"
+ @file = File.open(@path, "w")
+ @file.puts("")
+ @file.puts(" ")
+ end
+
+ def <<(str)
+ @file.puts(str)
+ end
+
+ def finish
+ @file.puts(" ")
+ @file.puts("")
+ @file.close
+ puts "---> resource file written to #{@path}"
+ end
+
+ def self.instance
+ @@inst ||= QRCGenerator::new
+ @@inst
+ end
+
+end
+
def run_demo(gen, cmd, out)
- img_path = "src/lay/lay/doc/images"
+ res_path = QRCGenerator::instance.res_path
+ img_path = QRCGenerator::instance.img_path
mw = RBA::Application::instance::main_window
@@ -81,7 +117,9 @@ def run_demo(gen, cmd, out)
input1 = input(1, 0)
input = input1
input2 = input(2, 0)
- #{cmd}.data
+ labels1 = labels(1, 0)
+ labels = labels1
+ (#{cmd}).data
SCRIPT
if data.is_a?(RBA::Region)
@@ -101,15 +139,19 @@ SCRIPT
elsif data.is_a?(RBA::EdgePairs)
cell.shapes(lout_poly).insert_as_polygons(data, 1)
cell.shapes(lout).insert(data.edges)
+ elsif data.is_a?(RBA::Texts)
+ cell.shapes(lout).insert(data)
end
view.update_content
- view.save_image(img_path + "/" + out, 400, 400)
+ view.save_image(res_path + "/" + img_path + "/" + out, 400, 400)
- puts "---> written #{img_path}/#{out}"
+ puts "---> written #{res_path}/#{img_path}/#{out}"
mw.close_all
+ QRCGenerator::instance << " #{img_path}/#{out}"
+
end
class Gen
@@ -631,3 +673,41 @@ run_demo gen, "input.corners.sized(0.1)", "drc_corners1.png"
run_demo gen, "input.corners(90.0).sized(0.1)", "drc_corners2.png"
run_demo gen, "input.corners(-90.0 .. -45.0).sized(0.1)", "drc_corners3.png"
+
+class Gen
+ def produce(s1, s2)
+ s1.insert(RBA::Text::new("ABC", RBA::Trans::new(RBA::Vector::new(0, 2000))))
+ s1.insert(RBA::Text::new("A", RBA::Trans::new(RBA::Vector::new(0, 6000))))
+ s1.insert(RBA::Text::new("XYZ", RBA::Trans::new(RBA::Vector::new(4000, 2000))))
+ s1.insert(RBA::Text::new("A*", RBA::Trans::new(RBA::Vector::new(4000, 6000))))
+ end
+end
+
+gen = Gen::new
+
+run_demo gen, "labels.texts(\"A*\")", "drc_texts1.png"
+run_demo gen, "labels.texts(text(\"A*\"))", "drc_texts2.png"
+
+class Gen
+ def produce(s1, s2)
+ s1.insert(RBA::Text::new("T1", RBA::Trans::new(RBA::Vector::new(0, 2000))))
+ s1.insert(RBA::Text::new("T2", RBA::Trans::new(RBA::Vector::new(2000, 2000))))
+ s1.insert(RBA::Text::new("T3", RBA::Trans::new(RBA::Vector::new(4000, 2000))))
+ pts = [
+ RBA::Point::new(2000, 0),
+ RBA::Point::new(2000, 4000),
+ RBA::Point::new(6000, 4000),
+ RBA::Point::new(6000, 0)
+ ];
+ s2.insert(RBA::Polygon::new(pts))
+ end
+end
+
+gen = Gen::new
+
+run_demo gen, "labels & input2", "drc_textpoly1.png"
+run_demo gen, "labels - input2", "drc_textpoly2.png"
+
+
+QRCGenerator::instance.finish
+
diff --git a/scripts/makedeb.sh b/scripts/makedeb.sh
index e4a6dc5f4..3013f0492 100755
--- a/scripts/makedeb.sh
+++ b/scripts/makedeb.sh
@@ -24,6 +24,9 @@ ubuntu16)
ubuntu18)
depends="libqt4-designer (>= 4.8.7), libqt4-xml (>= 4.8.7), libqt4-sql (>= 4.8.7), libqt4-network (>= 4.8.7), libqtcore4 (>= 4.8.7), libqtgui4 (>= 4.8.7), zlib1g (>= 1.2.11), libruby2.5 (>= 2.5.1), python3 (>= 3.6.5), libpython3.6 (>= 3.6.5), libstdc++6 (>= 8), libc6 (>= 2.27)"
;;
+ubuntu20)
+ depends="libqt5core5a (>= 5.12.8), libqt5designer5 (>= 5.12.8), libqt5gui5 (>= 5.12.8), libqt5multimedia5 (>= 5.12.8), libqt5multimediawidgets5 (>= 5.12.8), libqt5network5 (>= 5.12.8), libqt5opengl5 (>= 5.12.8), libqt5printsupport5 (>= 5.12.8), libqt5sql5 (>= 5.12.8), libqt5svg5 (>= 5.12.8), libqt5widgets5 (>= 5.12.8), libqt5xml5 (>= 5.12.8), libqt5xmlpatterns5 (>= 5.12.8), zlib1g (>= 1.2.11), libruby2.7 (>= 2.7.0), python3 (>= 3.8.2), libpython3.8 (>= 3.8.2), libstdc++6 (>=10), libc6 (>= 2.31)"
+ ;;
*)
echo "Unknown target '$target' (given as first argument)"
exit 1
diff --git a/scripts/mkqtdecl_common/produce.rb b/scripts/mkqtdecl_common/produce.rb
index cd0fe496e..89484364c 100755
--- a/scripts/mkqtdecl_common/produce.rb
+++ b/scripts/mkqtdecl_common/produce.rb
@@ -2798,8 +2798,8 @@ END
ofile.puts("}")
ofile.puts("")
- mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@hide\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var});"
- mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@brief Virtual method #{sig}\\nThis method can be reimplemented in a derived class.\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var}, &_set_callback_cbs_#{mn}_#{hk}_#{i_var});"
+ mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@brief Virtual method #{sig}\\nThis method can be reimplemented in a derived class.\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var});"
+ mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@hide\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var}, &_set_callback_cbs_#{mn}_#{hk}_#{i_var});"
end
diff --git a/src/buddies/src/bd/strmrun.cc b/src/buddies/src/bd/strmrun.cc
index 796966259..f76976389 100644
--- a/src/buddies/src/bd/strmrun.cc
+++ b/src/buddies/src/bd/strmrun.cc
@@ -87,5 +87,6 @@ BD_PUBLIC int strmrun (int argc, char *argv[])
lym::Macro macro;
macro.load_from (script);
+ macro.set_file_path (script);
return macro.run ();
}
diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc
index 8c4b03a33..211cef593 100644
--- a/src/buddies/src/bd/strmxor.cc
+++ b/src/buddies/src/bd/strmxor.cc
@@ -331,6 +331,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[])
xor_data.threads = threads;
xor_data.tile_size = tile_size;
xor_data.output_layout = output_layout.get ();
+ xor_data.output_cell = output_top;
xor_data.l2l_map = l2l_map;
xor_data.results = &results;
diff --git a/src/db/db/db.pro b/src/db/db/db.pro
index 81ca2b2c5..94c5d291b 100644
--- a/src/db/db/db.pro
+++ b/src/db/db/db.pro
@@ -185,7 +185,20 @@ SOURCES = \
gsiDeclDbNetlistCrossReference.cc \
gsiDeclDbLayoutVsSchematic.cc \
dbNetlistObject.cc \
- dbD25TechnologyComponent.cc
+ dbD25TechnologyComponent.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 \
@@ -333,7 +346,18 @@ HEADERS = \
dbLayoutVsSchematicFormatDefs.h \
dbLayoutVsSchematic.h \
dbNetlistObject.h \
- dbD25TechnologyComponent.h
+ dbD25TechnologyComponent.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") {
diff --git a/src/db/db/dbArray.h b/src/db/db/dbArray.h
index 8b55c6c35..1a2de4246 100644
--- a/src/db/db/dbArray.h
+++ b/src/db/db/dbArray.h
@@ -70,7 +70,11 @@ struct basic_array_iterator
virtual long index_a () const { return -1; }
virtual long index_b () const { return -1; }
-
+
+ virtual size_t quad_id () const { return 0; }
+ virtual box_type quad_box () const { return box_type::world (); }
+ virtual void skip_quad () { }
+
virtual disp_type get () const = 0;
virtual basic_array_iterator *clone () const = 0;
@@ -111,8 +115,12 @@ struct ArrayBase
virtual bool equal (const ArrayBase *) const = 0;
+ virtual bool fuzzy_equal (const ArrayBase *) const = 0;
+
virtual bool less (const ArrayBase *) const = 0;
+ virtual bool fuzzy_less (const ArrayBase *) const = 0;
+
virtual void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const = 0;
bool in_repository;
@@ -554,6 +562,12 @@ struct regular_array
return (m_a == d->m_a && m_b == d->m_b && m_amax == d->m_amax && m_bmax == d->m_bmax);
}
+ virtual bool fuzzy_equal (const ArrayBase *b) const
+ {
+ const regular_array *d = static_cast *> (b);
+ return (m_a.equal (d->m_a) && m_b.equal (d->m_b) && m_amax == d->m_amax && m_bmax == d->m_bmax);
+ }
+
virtual bool less (const ArrayBase *b) const
{
const regular_array *d = static_cast *> (b);
@@ -562,6 +576,14 @@ struct regular_array
m_amax < d->m_amax || (m_amax == d->m_amax && m_bmax < d->m_bmax)))));
}
+ virtual bool fuzzy_less (const ArrayBase *b) const
+ {
+ const regular_array *d = static_cast *> (b);
+ return m_a.less (d->m_a) || (m_a.equal (d->m_a) && (
+ m_b.less (d->m_b) || (m_b.equal (d->m_b) && (
+ m_amax < d->m_amax || (m_amax == d->m_amax && m_bmax < d->m_bmax)))));
+ }
+
virtual bool is_regular_array (vector_type &a, vector_type &b, unsigned long &amax, unsigned long &bmax) const
{
a = m_a;
@@ -702,6 +724,18 @@ struct regular_complex_array
return regular_array::equal (b);
}
+ virtual bool fuzzy_equal (const ArrayBase *b) const
+ {
+ const regular_complex_array *d = static_cast *> (b);
+ if (fabs (m_acos - d->m_acos) > epsilon) {
+ return false;
+ }
+ if (fabs (m_mag - d->m_mag) > epsilon) {
+ return false;
+ }
+ return regular_array::fuzzy_equal (b);
+ }
+
virtual bool less (const ArrayBase *b) const
{
const regular_complex_array *d = static_cast *> (b);
@@ -714,6 +748,18 @@ struct regular_complex_array
return regular_array::less (b);
}
+ virtual bool fuzzy_less (const ArrayBase *b) const
+ {
+ const regular_complex_array *d = static_cast *> (b);
+ if (fabs (m_acos - d->m_acos) > epsilon) {
+ return m_acos < d->m_acos;
+ }
+ if (fabs (m_mag - d->m_mag) > epsilon) {
+ return m_mag < d->m_mag;
+ }
+ return regular_array::fuzzy_less (b);
+ }
+
virtual void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (!no_self) {
@@ -806,6 +852,21 @@ struct iterated_array_iterator
return new iterated_array_iterator (*this);
}
+ virtual size_t quad_id () const
+ {
+ return m_t.quad_id ();
+ }
+
+ virtual box_type quad_box () const
+ {
+ return m_t.quad_box ();
+ }
+
+ virtual void skip_quad ()
+ {
+ m_t.skip_quad ();
+ }
+
private:
box_tree_const_iterator m_b, m_e;
box_tree_touching_iterator m_t;
@@ -964,6 +1025,20 @@ struct iterated_array
return true;
}
+ virtual bool fuzzy_equal (const ArrayBase *b) const
+ {
+ const iterated_array *d = static_cast *> (b);
+ if (m_v.size () != d->m_v.size ()) {
+ return false;
+ }
+ for (const_iterator p1 = m_v.begin (), p2 = d->m_v.begin (); p1 != m_v.end (); ++p1, ++p2) {
+ if (! p1->equal (*p2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
virtual bool less (const ArrayBase *b) const
{
const iterated_array *d = static_cast *> (b);
@@ -978,6 +1053,20 @@ struct iterated_array
return false;
}
+ virtual bool fuzzy_less (const ArrayBase *b) const
+ {
+ const iterated_array *d = static_cast *> (b);
+ if (m_v.size () != d->m_v.size ()) {
+ return (m_v.size () < d->m_v.size ());
+ }
+ for (const_iterator p1 = m_v.begin (), p2 = d->m_v.begin (); p1 != m_v.end (); ++p1, ++p2) {
+ if (! p1->equal (*p2)) {
+ return (p1->less (*p2));
+ }
+ }
+ return false;
+ }
+
virtual void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (!no_self) {
@@ -1085,6 +1174,18 @@ struct iterated_complex_array
return iterated_array::equal (b);
}
+ virtual bool fuzzy_equal (const ArrayBase *b) const
+ {
+ const iterated_complex_array *d = static_cast *> (b);
+ if (fabs (m_acos - d->m_acos) > epsilon) {
+ return false;
+ }
+ if (fabs (m_mag - d->m_mag) > epsilon) {
+ return false;
+ }
+ return iterated_array::fuzzy_equal (b);
+ }
+
virtual bool less (const ArrayBase *b) const
{
const iterated_complex_array *d = static_cast *> (b);
@@ -1097,6 +1198,18 @@ struct iterated_complex_array
return iterated_array::less (b);
}
+ virtual bool fuzzy_less (const ArrayBase *b) const
+ {
+ const iterated_complex_array *d = static_cast *> (b);
+ if (fabs (m_acos - d->m_acos) > epsilon) {
+ return m_acos < d->m_acos;
+ }
+ if (fabs (m_mag - d->m_mag) > epsilon) {
+ return m_mag < d->m_mag;
+ }
+ return iterated_array::fuzzy_less (b);
+ }
+
virtual complex_trans_type complex_trans (const simple_trans_type &s) const
{
return complex_trans_type (s, m_acos, m_mag);
@@ -1187,7 +1300,12 @@ struct single_complex_inst
return true;
}
- virtual bool less (const ArrayBase *b) const
+ virtual bool fuzzy_equal (const ArrayBase *b) const
+ {
+ return equal (b);
+ }
+
+ virtual bool less (const ArrayBase *b) const
{
const double epsilon = 1e-10;
const single_complex_inst *d = static_cast *> (b);
@@ -1200,6 +1318,11 @@ struct single_complex_inst
return false;
}
+ virtual bool fuzzy_less (const ArrayBase *b) const
+ {
+ return less (b);
+ }
+
virtual void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (!no_self) {
@@ -1420,6 +1543,36 @@ struct array_iterator
return mp_base ? mp_base->index_b () : -1;
}
+ /**
+ * @brief For iterators supporting quads (iterated arrays), this method will return the quad ID
+ */
+ size_t quad_id () const
+ {
+ return mp_base ? mp_base->quad_id () : 0;
+ }
+
+ /**
+ * @brief For iterators supporting quads (iterated arrays), this method will return the quad bounding box
+ *
+ * Note that this method will only return a valid quad box is the quad_id is non-null.
+ *
+ * This method will return the bounding box of all array offsets in the quad.
+ */
+ db::box quad_box () const
+ {
+ return mp_base ? mp_base->quad_box () : db::box::world ();
+ }
+
+ /**
+ * @brief For iterators supporting quads (iterated arrays), this method will skip the current quad
+ */
+ void skip_quad ()
+ {
+ if (mp_base) {
+ mp_base->skip_quad ();
+ }
+ }
+
private:
trans_type m_trans;
basic_array_iterator *mp_base;
@@ -1592,6 +1745,32 @@ struct array
// .. nothing yet ..
}
+ /**
+ * @brief The iterated array constructor
+ *
+ * This is basically a convenience function that creates
+ * an appropriate basic_array object.
+ */
+ template
+ array (const Obj &obj, const trans_type &trans, Iter from, Iter to)
+ : m_obj (obj), m_trans (trans), mp_base (new iterated_array (from, to))
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief The complex iterated array constructor
+ *
+ * This is basically a convenience function that creates
+ * an appropriate basic_array object.
+ */
+ template
+ array (const Obj &obj, const complex_trans_type &ct, Iter from, Iter to)
+ : m_obj (obj), m_trans (ct), mp_base (new iterated_complex_array (ct.rcos (), ct.mag (), from, to))
+ {
+ // .. nothing yet ..
+ }
+
/**
* @brief The singular complex instance constructor
*
@@ -1835,6 +2014,32 @@ struct array
}
}
+ /**
+ * @brief Gets the bounding box from the iterator's current quad
+ *
+ * The bounding box is that of all objects in the current quad and
+ * is confined to the array's total bounding box.
+ */
+ template
+ box_type quad_box (const Iter &iter, const BoxConv &bc) const
+ {
+ box_type bb;
+ if (mp_base) {
+ bb = mp_base->bbox (box_type (0, 0, 0, 0));
+ }
+ bb &= iter.quad_box ();
+
+ if (mp_base) {
+ if (mp_base->is_complex ()) {
+ return bb * box_type (mp_base->complex_trans (simple_trans_type (m_trans)) * bc (m_obj));
+ } else {
+ return bb * (m_trans * bc (m_obj));
+ }
+ } else {
+ return bb * (m_trans * bc (m_obj));
+ }
+ }
+
/**
* @brief The number of single instances in the array
*/
@@ -1918,6 +2123,21 @@ struct array
}
}
+ /**
+ * @brief Compare operator for equality (fuzzy version)
+ */
+ bool equal (const array &d) const
+ {
+ if (! mp_base) {
+ return (m_trans.equal (d.m_trans) && m_obj == d.m_obj && ! d.mp_base);
+ } else {
+ if (! m_trans.equal (d.m_trans) || ! (m_obj == d.m_obj) || type () != d.type ()) {
+ return false;
+ }
+ return mp_base && mp_base->fuzzy_equal (d.mp_base);
+ }
+ }
+
/**
* @brief A sorting order criterion
*/
@@ -1943,6 +2163,31 @@ struct array
}
}
+ /**
+ * @brief A fuzzy sorting order criterion
+ */
+ bool less (const array &d) const
+ {
+ if (! (m_obj == d.m_obj)) {
+ return (m_obj < d.m_obj);
+ }
+ if (! m_trans.equal (d.m_trans)) {
+ return m_trans.less (d.m_trans);
+ }
+ if (type () != d.type ()) {
+ return (type () < d.type ());
+ }
+ if (mp_base == d.mp_base) {
+ return false;
+ } else if (! mp_base) {
+ return true;
+ } else if (! d.mp_base) {
+ return false;
+ } else {
+ return mp_base->fuzzy_less (d.mp_base);
+ }
+ }
+
/**
* @brief Compare operator
*
@@ -2263,7 +2508,7 @@ struct array
}
db::mem_stat (stat, purpose, cat, m_obj, true, (void *) this);
if (mp_base) {
- db::mem_stat (stat, purpose, cat, *mp_base, false, (void *) this);
+ mp_base->mem_stat (stat, purpose, cat, false, (void *) this);
}
}
diff --git a/src/db/db/dbAsIfFlatEdgePairs.cc b/src/db/db/dbAsIfFlatEdgePairs.cc
index bac1a9495..88bf9241f 100644
--- a/src/db/db/dbAsIfFlatEdgePairs.cc
+++ b/src/db/db/dbAsIfFlatEdgePairs.cc
@@ -43,6 +43,12 @@ AsIfFlatEdgePairs::AsIfFlatEdgePairs ()
// .. nothing yet ..
}
+AsIfFlatEdgePairs::AsIfFlatEdgePairs (const AsIfFlatEdgePairs &other)
+ : EdgePairsDelegate (other), m_bbox_valid (other.m_bbox_valid), m_bbox (other.m_bbox)
+{
+ // .. nothing yet ..
+}
+
AsIfFlatEdgePairs::~AsIfFlatEdgePairs ()
{
// .. nothing yet ..
@@ -75,7 +81,7 @@ AsIfFlatEdgePairs::in (const EdgePairs &other, bool invert) const
op.insert (*o);
}
- std::auto_ptr new_edge_pairs (new FlatEdgePairs (false));
+ std::auto_ptr new_edge_pairs (new FlatEdgePairs ());
for (EdgePairsIterator o (begin ()); ! o.at_end (); ++o) {
if ((op.find (*o) == op.end ()) == invert) {
@@ -125,6 +131,28 @@ void AsIfFlatEdgePairs::invalidate_bbox ()
m_bbox_valid = false;
}
+RegionDelegate *
+AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const
+{
+ std::auto_ptr region (new FlatRegion ());
+
+ if (filter.result_must_not_be_merged ()) {
+ region->set_merged_semantics (false);
+ }
+
+ std::vector res_polygons;
+
+ for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
+ res_polygons.clear ();
+ filter.process (*e, res_polygons);
+ for (std::vector::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
+ region->insert (*pr);
+ }
+ }
+
+ return region.release ();
+}
+
EdgePairsDelegate *
AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
{
diff --git a/src/db/db/dbAsIfFlatEdgePairs.h b/src/db/db/dbAsIfFlatEdgePairs.h
index d379cefbb..7d047e5d4 100644
--- a/src/db/db/dbAsIfFlatEdgePairs.h
+++ b/src/db/db/dbAsIfFlatEdgePairs.h
@@ -38,6 +38,7 @@ class DB_PUBLIC AsIfFlatEdgePairs
{
public:
AsIfFlatEdgePairs ();
+ AsIfFlatEdgePairs (const AsIfFlatEdgePairs &other);
virtual ~AsIfFlatEdgePairs ();
virtual size_t size () const;
@@ -51,6 +52,8 @@ public:
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const;
+ virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const;
+
virtual EdgePairsDelegate *add_in_place (const EdgePairs &other)
{
return add (other);
diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc
index 26bfe7689..3a0cc5405 100644
--- a/src/db/db/dbAsIfFlatEdges.cc
+++ b/src/db/db/dbAsIfFlatEdges.cc
@@ -59,6 +59,22 @@ AsIfFlatEdges::~AsIfFlatEdges ()
// .. nothing yet ..
}
+AsIfFlatEdges::AsIfFlatEdges (const AsIfFlatEdges &other)
+ : EdgesDelegate (other), m_bbox_valid (false)
+{
+ operator= (other);
+}
+
+AsIfFlatEdges &
+AsIfFlatEdges::operator= (const AsIfFlatEdges &other)
+{
+ if (this != &other) {
+ m_bbox_valid = other.m_bbox_valid;
+ m_bbox = other.m_bbox;
+ }
+ return *this;
+}
+
std::string
AsIfFlatEdges::to_string (size_t nmax) const
{
@@ -170,7 +186,7 @@ AsIfFlatEdges::pull_generic (const Edges &edges) const
{
db::box_scanner scanner (report_progress (), progress_desc ());
- AddressableEdgeDelivery e (begin (), true);
+ AddressableEdgeDelivery e (begin (), has_valid_edges ());
for ( ; ! e.at_end (); ++e) {
scanner.insert (e.operator-> (), 1);
@@ -497,7 +513,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
db::box_scanner scanner (report_progress (), progress_desc ());
scanner.reserve (size () + (other ? other->size () : 0));
- AddressableEdgeDelivery e (begin_merged (), has_valid_edges ());
+ AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
size_t n = 0;
for ( ; ! e.at_end (); ++e) {
diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h
index 7a94c35c5..57e2d0fd7 100644
--- a/src/db/db/dbAsIfFlatEdges.h
+++ b/src/db/db/dbAsIfFlatEdges.h
@@ -185,10 +185,10 @@ protected:
virtual RegionDelegate *pull_generic (const Region ®ion) const;
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool inverse) const;
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool inverse) const;
+ AsIfFlatEdges &operator= (const AsIfFlatEdges &other);
+ AsIfFlatEdges (const AsIfFlatEdges &other);
private:
- AsIfFlatEdges &operator= (const AsIfFlatEdges &other);
-
mutable bool m_bbox_valid;
mutable db::Box m_bbox;
diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc
index 0a9278df1..fc4373f16 100644
--- a/src/db/db/dbAsIfFlatRegion.cc
+++ b/src/db/db/dbAsIfFlatRegion.cc
@@ -25,6 +25,7 @@
#include "dbFlatRegion.h"
#include "dbFlatEdgePairs.h"
#include "dbFlatEdges.h"
+#include "dbFlatTexts.h"
#include "dbEmptyRegion.h"
#include "dbEmptyEdgePairs.h"
#include "dbEmptyEdges.h"
@@ -55,6 +56,23 @@ AsIfFlatRegion::~AsIfFlatRegion ()
// .. nothing yet ..
}
+AsIfFlatRegion::AsIfFlatRegion (const AsIfFlatRegion &other)
+ : RegionDelegate (other), m_bbox_valid (false)
+{
+ operator= (other);
+}
+
+AsIfFlatRegion &
+AsIfFlatRegion::operator= (const AsIfFlatRegion &other)
+{
+ if (this != &other) {
+ m_bbox_valid = other.m_bbox_valid;
+ m_bbox = other.m_bbox;
+ }
+
+ return *this;
+}
+
std::string
AsIfFlatRegion::to_string (size_t nmax) const
{
@@ -364,6 +382,50 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
return output.release ();
}
+RegionDelegate *
+AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse) const
+{
+ if (other.empty ()) {
+ if (! inverse) {
+ return new EmptyRegion ();
+ } else {
+ return clone ();
+ }
+ } else if (empty ()) {
+ return clone ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+ scanner.reserve1 (size ());
+ scanner.reserve2 (other.size ());
+
+ std::auto_ptr output (new FlatRegion (true));
+ region_to_text_interaction_filter filter (*output, inverse);
+
+ AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert1 (p.operator-> (), 0);
+ if (inverse) {
+ filter.preset (p.operator-> ());
+ }
+ }
+
+ AddressableTextDelivery e (other.addressable_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert2 (e.operator-> (), 0);
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ if (inverse) {
+ filter.fill_output ();
+ }
+
+ return output.release ();
+}
+
RegionDelegate *
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const
{
@@ -440,7 +502,7 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
std::auto_ptr output (new FlatEdges (false));
region_to_edge_interaction_filter filter (output->raw_edges (), false);
- AddressablePolygonDelivery p (begin (), has_valid_merged_polygons ());
+ AddressablePolygonDelivery p (begin (), has_valid_polygons ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
@@ -457,6 +519,39 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
return output.release ();
}
+TextsDelegate *
+AsIfFlatRegion::pull_generic (const Texts &other) const
+{
+ if (other.empty ()) {
+ return other.delegate ()->clone ();
+ } else if (empty ()) {
+ return new EmptyTexts ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+ scanner.reserve1 (size ());
+ scanner.reserve2 (other.size ());
+
+ std::auto_ptr output (new FlatTexts (false));
+ region_to_text_interaction_filter filter (output->raw_texts (), false);
+
+ AddressablePolygonDelivery p (begin (), has_valid_polygons ());
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert1 (p.operator-> (), 0);
+ }
+
+ AddressableTextDelivery e (other.addressable_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert2 (e.operator-> (), 0);
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ return output.release ();
+}
+
RegionDelegate *
AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) const
{
diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h
index ed232d858..ed7b53227 100644
--- a/src/db/db/dbAsIfFlatRegion.h
+++ b/src/db/db/dbAsIfFlatRegion.h
@@ -202,6 +202,16 @@ public:
return selected_interacting_generic (other, true);
}
+ virtual RegionDelegate *selected_interacting (const Texts &other) const
+ {
+ return selected_interacting_generic (other, false);
+ }
+
+ virtual RegionDelegate *selected_not_interacting (const Texts &other) const
+ {
+ return selected_interacting_generic (other, true);
+ }
+
virtual RegionDelegate *selected_overlapping (const Region &other) const
{
return selected_interacting_generic (other, 0, false, false);
@@ -227,6 +237,11 @@ public:
return pull_generic (other);
}
+ virtual TextsDelegate *pull_interacting (const Texts &other) const
+ {
+ return pull_generic (other);
+ }
+
virtual RegionDelegate *pull_overlapping (const Region &other) const
{
return pull_generic (other, 0, false);
@@ -247,16 +262,20 @@ protected:
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
+ virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
+ virtual TextsDelegate *pull_generic (const Texts &other) const;
template
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
template
static void produce_markers_for_angle_check (const db::Polygon &poly, const Trans &tr, double min, double max, bool inverse, db::Shapes &shapes);
-private:
AsIfFlatRegion &operator= (const AsIfFlatRegion &other);
+ AsIfFlatRegion (const AsIfFlatRegion &other);
+
+private:
mutable bool m_bbox_valid;
mutable db::Box m_bbox;
diff --git a/src/db/db/dbAsIfFlatTexts.cc b/src/db/db/dbAsIfFlatTexts.cc
new file mode 100644
index 000000000..205386328
--- /dev/null
+++ b/src/db/db/dbAsIfFlatTexts.cc
@@ -0,0 +1,412 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 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 "dbAsIfFlatTexts.h"
+#include "dbFlatTexts.h"
+#include "dbFlatRegion.h"
+#include "dbFlatEdges.h"
+#include "dbEmptyTexts.h"
+#include "dbEmptyRegion.h"
+#include "dbTexts.h"
+#include "dbBoxConvert.h"
+#include "dbRegion.h"
+#include "dbTextsUtils.h"
+
+#include
+
+namespace db
+{
+
+// -------------------------------------------------------------------------------------------------------------
+// AsIfFlagTexts implementation
+
+AsIfFlatTexts::AsIfFlatTexts ()
+ : TextsDelegate (), m_bbox_valid (false)
+{
+ // .. nothing yet ..
+}
+
+AsIfFlatTexts::AsIfFlatTexts (const AsIfFlatTexts &other)
+ : TextsDelegate (other), m_bbox_valid (other.m_bbox_valid), m_bbox (other.m_bbox)
+{
+ // .. nothing yet ..
+}
+
+AsIfFlatTexts::~AsIfFlatTexts ()
+{
+ // .. nothing yet ..
+}
+
+AsIfFlatTexts &
+AsIfFlatTexts::operator= (const AsIfFlatTexts &other)
+{
+ if (this != &other) {
+ m_bbox_valid = other.m_bbox_valid;
+ m_bbox = other.m_bbox;
+ }
+ return *this;
+}
+
+std::string
+AsIfFlatTexts::to_string (size_t nmax) const
+{
+ std::ostringstream os;
+ TextsIterator p (begin ());
+ bool first = true;
+ for ( ; ! p.at_end () && nmax != 0; ++p, --nmax) {
+ if (! first) {
+ os << ";";
+ }
+ first = false;
+ os << p->to_string ();
+ }
+ if (! p.at_end ()) {
+ os << "...";
+ }
+ return os.str ();
+}
+
+TextsDelegate *
+AsIfFlatTexts::in (const Texts &other, bool invert) const
+{
+ std::set op;
+ for (TextsIterator o (other.begin ()); ! o.at_end (); ++o) {
+ op.insert (*o);
+ }
+
+ std::auto_ptr new_texts (new FlatTexts ());
+
+ for (TextsIterator o (begin ()); ! o.at_end (); ++o) {
+ if ((op.find (*o) == op.end ()) == invert) {
+ new_texts->insert (*o);
+ }
+ }
+
+ return new_texts.release ();
+}
+
+size_t
+AsIfFlatTexts::size () const
+{
+ size_t n = 0;
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ ++n;
+ }
+ return n;
+}
+
+Box AsIfFlatTexts::bbox () const
+{
+ if (! m_bbox_valid) {
+ m_bbox = compute_bbox ();
+ m_bbox_valid = true;
+ }
+ return m_bbox;
+}
+
+Box AsIfFlatTexts::compute_bbox () const
+{
+ db::Box b;
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ b += t->box ();
+ }
+ return b;
+}
+
+void AsIfFlatTexts::update_bbox (const db::Box &b)
+{
+ m_bbox = b;
+ m_bbox_valid = true;
+}
+
+void AsIfFlatTexts::invalidate_bbox ()
+{
+ m_bbox_valid = false;
+}
+
+TextsDelegate *
+AsIfFlatTexts::filtered (const TextFilterBase &filter) const
+{
+ std::auto_ptr new_texts (new FlatTexts ());
+
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ if (filter.selected (*p)) {
+ new_texts->insert (*p);
+ }
+ }
+
+ return new_texts.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter) const
+{
+ std::auto_ptr region (new FlatRegion ());
+
+ if (filter.result_must_not_be_merged ()) {
+ region->set_merged_semantics (false);
+ }
+
+ std::vector res_polygons;
+
+ for (TextsIterator e (begin ()); ! e.at_end (); ++e) {
+ res_polygons.clear ();
+ filter.process (*e, res_polygons);
+ for (std::vector::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
+ region->insert (*pr);
+ }
+ }
+
+ return region.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::polygons (db::Coord e) const
+{
+ std::auto_ptr output (new FlatRegion ());
+
+ for (TextsIterator tp (begin ()); ! tp.at_end (); ++tp) {
+ db::Box box = tp->box ();
+ box.enlarge (db::Vector (e, e));
+ output->insert (db::Polygon (box));
+ }
+
+ return output.release ();
+}
+
+EdgesDelegate *
+AsIfFlatTexts::edges () const
+{
+ std::auto_ptr output (new FlatEdges ());
+
+ for (TextsIterator tp (begin ()); ! tp.at_end (); ++tp) {
+ db::Box box = tp->box ();
+ output->insert (db::Edge (box.p1 (), box.p2 ()));
+ }
+
+ return output.release ();
+}
+
+TextsDelegate *
+AsIfFlatTexts::add (const Texts &other) const
+{
+ FlatTexts *other_flat = dynamic_cast (other.delegate ());
+ if (other_flat) {
+
+ std::auto_ptr new_texts (new FlatTexts (*other_flat));
+ new_texts->invalidate_cache ();
+
+ size_t n = new_texts->raw_texts ().size () + size ();
+
+ new_texts->reserve (n);
+
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+
+ return new_texts.release ();
+
+ } else {
+
+ std::auto_ptr new_texts (new FlatTexts ());
+
+ size_t n = size () + other.size ();
+
+ new_texts->reserve (n);
+
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+ for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+
+ return new_texts.release ();
+
+ }
+}
+
+bool
+AsIfFlatTexts::equals (const Texts &other) const
+{
+ if (empty () != other.empty ()) {
+ return false;
+ }
+ if (size () != other.size ()) {
+ return false;
+ }
+ TextsIterator o1 (begin ());
+ TextsIterator o2 (other.begin ());
+ while (! o1.at_end () && ! o2.at_end ()) {
+ if (*o1 != *o2) {
+ return false;
+ }
+ ++o1;
+ ++o2;
+ }
+ return true;
+}
+
+bool
+AsIfFlatTexts::less (const Texts &other) const
+{
+ if (empty () != other.empty ()) {
+ return empty () < other.empty ();
+ }
+ if (size () != other.size ()) {
+ return (size () < other.size ());
+ }
+ TextsIterator o1 (begin ());
+ TextsIterator o2 (other.begin ());
+ while (! o1.at_end () && ! o2.at_end ()) {
+ if (*o1 != *o2) {
+ return *o1 < *o2;
+ }
+ ++o1;
+ ++o2;
+ }
+ return false;
+}
+
+void
+AsIfFlatTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
+{
+ // improves performance when inserting an original layout into the same layout
+ db::LayoutLocker locker (layout);
+
+ db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ shapes.insert (*t);
+ }
+}
+
+void
+AsIfFlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
+{
+ // improves performance when inserting an original layout into the same layout
+ db::LayoutLocker locker (layout);
+
+ db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ db::Box box = t->box ();
+ box.enlarge (db::Vector (enl, enl));
+ shapes.insert (db::SimplePolygon (box));
+ }
+}
+
+TextsDelegate *
+AsIfFlatTexts::selected_interacting_generic (const Region &other, bool inverse) const
+{
+ // shortcuts
+ if (other.empty () || empty ()) {
+ return new EmptyTexts ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+
+ AddressableTextDelivery e (begin (), has_valid_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert1 (e.operator-> (), 0);
+ }
+
+ AddressablePolygonDelivery p = other.addressable_polygons ();
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert2 (p.operator-> (), 1);
+ }
+
+ std::auto_ptr output (new FlatTexts ());
+
+ if (! inverse) {
+
+ text_to_region_interaction_filter filter (*output);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ } else {
+
+ std::set interacting;
+ text_to_region_interaction_filter, db::Text> filter (interacting);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ for (TextsIterator o (begin ()); ! o.at_end (); ++o) {
+ if (interacting.find (*o) == interacting.end ()) {
+ output->insert (*o);
+ }
+ }
+
+ }
+
+ return output.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::pull_generic (const Region &other) const
+{
+ // shortcuts
+ if (other.empty () || empty ()) {
+ return new EmptyRegion ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+
+ AddressableTextDelivery e (begin (), has_valid_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert1 (e.operator-> (), 0);
+ }
+
+ AddressablePolygonDelivery p = other.addressable_merged_polygons ();
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert2 (p.operator-> (), 1);
+ }
+
+ std::auto_ptr output (new FlatRegion (true));
+
+ text_to_region_interaction_filter filter (*output);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ return output.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::pull_interacting (const Region &other) const
+{
+ return pull_generic (other);
+}
+
+TextsDelegate *
+AsIfFlatTexts::selected_interacting (const Region &other) const
+{
+ return selected_interacting_generic (other, false);
+}
+
+TextsDelegate *
+AsIfFlatTexts::selected_not_interacting (const Region &other) const
+{
+ return selected_interacting_generic (other, true);
+}
+
+}
+
diff --git a/src/db/db/dbAsIfFlatTexts.h b/src/db/db/dbAsIfFlatTexts.h
new file mode 100644
index 000000000..1932588a3
--- /dev/null
+++ b/src/db/db/dbAsIfFlatTexts.h
@@ -0,0 +1,99 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 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_dbAsIfFlatTexts
+#define HDR_dbAsIfFlatTexts
+
+#include "dbCommon.h"
+
+#include "dbTextsDelegate.h"
+
+namespace db {
+
+class Region;
+
+/**
+ * @brief Provides default flat implementations
+ */
+class DB_PUBLIC AsIfFlatTexts
+ : public TextsDelegate
+{
+public:
+ AsIfFlatTexts ();
+ AsIfFlatTexts (const AsIfFlatTexts &other);
+ virtual ~AsIfFlatTexts ();
+
+ virtual size_t size () const;
+ virtual std::string to_string (size_t) const;
+ virtual Box bbox () const;
+
+ virtual TextsDelegate *filter_in_place (const TextFilterBase &filter)
+ {
+ return filtered (filter);
+ }
+
+ virtual TextsDelegate *filtered (const TextFilterBase &) const;
+
+ virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const;
+
+ virtual TextsDelegate *add_in_place (const Texts &other)
+ {
+ return add (other);
+ }
+
+ virtual TextsDelegate *add (const Texts &other) const;
+
+ virtual RegionDelegate *polygons (db::Coord e) const;
+ virtual EdgesDelegate *edges () const;
+
+ virtual TextsDelegate *in (const Texts &, bool) const;
+
+ virtual bool equals (const Texts &other) const;
+ virtual bool less (const Texts &other) const;
+
+ virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
+ virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
+
+ virtual RegionDelegate *pull_interacting (const Region &) const;
+ virtual TextsDelegate *selected_interacting (const Region &other) const;
+ virtual TextsDelegate *selected_not_interacting (const Region &other) const;
+
+protected:
+ void update_bbox (const db::Box &box);
+ void invalidate_bbox ();
+ AsIfFlatTexts &operator= (const AsIfFlatTexts &other);
+
+private:
+
+ mutable bool m_bbox_valid;
+ mutable db::Box m_bbox;
+
+ virtual db::Box compute_bbox () const;
+ virtual TextsDelegate *selected_interacting_generic (const Region &other, bool inverse) const;
+ virtual RegionDelegate *pull_generic (const Region &other) const;
+};
+
+}
+
+#endif
+
diff --git a/src/db/db/dbBoxTree.h b/src/db/db/dbBoxTree.h
index 0e3a8ae67..982993496 100644
--- a/src/db/db/dbBoxTree.h
+++ b/src/db/db/dbBoxTree.h
@@ -168,40 +168,43 @@ public:
typedef typename Tree::coord_type coord_type;
typedef typename Tree::box_type box_type;
- box_tree_node (box_tree_node *parent, const point_type ¢er, unsigned int quad)
- : m_center (center)
+ box_tree_node (box_tree_node *parent, const point_type ¢er, const box_type &qbox, unsigned int quad)
{
- for (int i = 0; i < 5; ++i) {
- m_lenq[i] = 0;
- }
- for (int i = 0; i < 4; ++i) {
- mp_children[i] = 0;
- }
- mp_parent = (box_tree_node *)((char *) parent + quad);
- if (parent) {
- parent->mp_children [quad] = this;
+ point_type corner;
+ if (quad == 0) {
+ corner = qbox.upper_right ();
+ } else if (quad == 1) {
+ corner = qbox.upper_left ();
+ } else if (quad == 2) {
+ corner = qbox.lower_left ();
+ } else if (quad == 3) {
+ corner = qbox.lower_right ();
}
+
+ init (parent, center, corner, quad);
}
~box_tree_node ()
{
for (int i = 0; i < 4; ++i) {
- if (mp_children [i]) {
- delete mp_children [i];
- mp_children [i] = 0;
+ box_tree_node *c = child (i);
+ if (c) {
+ delete c;
}
}
}
box_tree_node *clone (box_tree_node *parent = 0, unsigned int quad = 0) const
{
- box_tree_node *n = new box_tree_node (parent, m_center, quad);
- for (unsigned int i = 0; i < 5; ++i) {
- n->m_lenq[i] = m_lenq[i];
- }
+ box_tree_node *n = new box_tree_node (parent, m_center, m_corner, quad);
+ n->m_lenq = m_lenq;
+ n->m_len = m_len;
for (unsigned int i = 0; i < 4; ++i) {
- if (mp_children[i]) {
- mp_children[i]->clone (n, i);
+ box_tree_node *c = child (i);
+ if (c) {
+ c->clone (n, i);
+ } else {
+ n->m_childrefs [i] = m_childrefs [i];
}
}
return n;
@@ -209,17 +212,39 @@ public:
box_tree_node *child (int i) const
{
- return mp_children [i];
+ if ((m_childrefs [i] & 1) == 0) {
+ return reinterpret_cast (m_childrefs [i]);
+ } else {
+ return 0;
+ }
}
void lenq (int i, size_t l)
{
- m_lenq[i + 1] = l;
+ if (i < 0) {
+ m_lenq = l;
+ } else {
+ box_tree_node *c = child (i);
+ if (c) {
+ c->m_len = l;
+ } else {
+ m_childrefs [i] = l * 2 + 1;
+ }
+ }
}
size_t lenq (int i) const
{
- return m_lenq[i + 1];
+ if (i < 0) {
+ return m_lenq;
+ } else {
+ box_tree_node *c = child (i);
+ if (c) {
+ return c->m_len;
+ } else {
+ return m_childrefs [i] >> 1;
+ }
+ }
}
box_tree_node *parent () const
@@ -238,8 +263,8 @@ public:
stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat);
}
for (int i = 0; i < 4; ++i) {
- if (mp_children [i]) {
- mp_children [i]->mem_stat (stat, purpose, cat, no_self, parent);
+ if (child (i)) {
+ child (i)->mem_stat (stat, purpose, cat, no_self, parent);
}
}
}
@@ -249,14 +274,52 @@ public:
return m_center;
}
+ box_type quad_box (int quad) const
+ {
+ box_type qb = box_type::world ();
+ if (parent ()) {
+ qb = box_type (m_corner, parent ()->center ());
+ }
+
+ switch (quad) {
+ case 0: return box_type (m_center, qb.upper_right ());
+ case 1: return box_type (m_center, qb.upper_left ());
+ case 2: return box_type (m_center, qb.lower_left ());
+ case 3: return box_type (m_center, qb.lower_right ());
+ default: return qb;
+ }
+ }
+
private:
box_tree_node *mp_parent;
- size_t m_lenq [5];
- box_tree_node *mp_children [4];
- point_type m_center;
+ size_t m_lenq, m_len;
+ size_t m_childrefs [4];
+ point_type m_center, m_corner;
box_tree_node (const box_tree_node &d);
box_tree_node &operator= (const box_tree_node &d);
+
+ box_tree_node (box_tree_node *parent, const point_type ¢er, const point_type &corner, unsigned int quad)
+ {
+ init (parent, center, corner, quad);
+ }
+
+ void init (box_tree_node *parent, const point_type ¢er, const point_type &corner, unsigned int quad)
+ {
+ m_center = center;
+ m_corner = corner;
+
+ m_lenq = m_len = 0;
+ for (int i = 0; i < 4; ++i) {
+ m_childrefs [i] = 0;
+ }
+
+ mp_parent = (box_tree_node *)((char *) parent + quad);
+ if (parent) {
+ m_len = (parent->m_childrefs [quad] >> 1);
+ parent->m_childrefs [quad] = size_t (this);
+ }
+ }
};
/**
@@ -459,28 +522,9 @@ public:
box_type quad_box () const
{
if (! mp_node) {
-
return box_type::world ();
-
} else {
-
- point_type c = mp_node->center ();
- box_type qb;
- if (! mp_node->parent ()) {
- qb = box_type::world ();
- } else {
- point_type pc = mp_node->parent ()->center ();
- qb = box_type (c - (pc - c), pc);
- }
-
- switch (m_quad) {
- case 0: return box_type (c, qb.upper_right ());
- case 1: return box_type (c, qb.upper_left ());
- case 2: return box_type (c, qb.lower_left ());
- case 3: return box_type (c, qb.lower_right ());
- default: return qb;
- }
-
+ return mp_node->quad_box (m_quad);
}
}
@@ -577,12 +621,16 @@ private:
return m_quad < 4;
}
- // down one level
+ // down as many levels as required for the next non-empty quad
// returns true if this is possible
bool down ()
{
- box_tree_node *c = mp_node->child (m_quad);
- if (c) {
+ while (true) {
+
+ box_tree_node *c = mp_node->child (m_quad);
+ if (! c) {
+ return false;
+ }
mp_node = c;
m_quad = -1;
@@ -595,12 +643,11 @@ private:
// nothing to visit: up again
up ();
return false;
- } else {
+ } else if (m_quad < 0) {
+ // stay in main chunk
return true;
}
- } else {
- return false;
}
}
@@ -670,7 +717,7 @@ private:
* whose box overlaps or touches a specified test box.
*/
-template
+template
class box_tree
{
public:
@@ -1175,7 +1222,16 @@ private:
// the bins are: overall, ur, ul, ll, lr, empty
element_iterator qloc [6] = { from, from, from, from, from, from };
- point_type center (bbox.center ());
+ point_type center;
+ if (bbox.width () < bbox.height () / thin_aspect) {
+ // separate by height only
+ center = point_type (bbox.left (), bbox.bottom () + bbox.height () / 2);
+ } else if (bbox.height () < bbox.width () / thin_aspect) {
+ // separate by width only
+ center = point_type (bbox.left () + bbox.width () / 2, bbox.bottom ());
+ } else {
+ center = bbox.center ();
+ }
for (element_iterator e = from; e != to; ++e) {
@@ -1224,7 +1280,7 @@ private:
if (nn >= min_quads) {
// create a new node representing this tree
- box_tree_node *node = new box_tree_node (parent, center, quad);
+ box_tree_node *node = new box_tree_node (parent, center, bbox, quad);
if (parent == 0) {
mp_root = node;
}
@@ -1460,28 +1516,9 @@ public:
box_type quad_box () const
{
if (! mp_node) {
-
return box_type::world ();
-
} else {
-
- point_type c = mp_node->center ();
- box_type qb;
- if (! mp_node->parent ()) {
- qb = box_type::world ();
- } else {
- point_type pc = mp_node->parent ()->center ();
- qb = box_type (c - (pc - c), pc);
- }
-
- switch (m_quad) {
- case 0: return box_type (c, qb.upper_right ());
- case 1: return box_type (c, qb.upper_left ());
- case 2: return box_type (c, qb.lower_left ());
- case 3: return box_type (c, qb.lower_right ());
- default: return qb;
- }
-
+ return mp_node->quad_box (m_quad);
}
}
@@ -1578,12 +1615,16 @@ private:
return m_quad < 4;
}
- // down one level
+ // down as many levels as required for the next non-empty quad
// returns true if this is possible
bool down ()
{
- box_tree_node *c = mp_node->child (m_quad);
- if (c) {
+ while (true) {
+
+ box_tree_node *c = mp_node->child (m_quad);
+ if (! c) {
+ return false;
+ }
mp_node = c;
m_quad = -1;
@@ -1596,12 +1637,11 @@ private:
// nothing to visit: up again
up ();
return false;
- } else {
+ } else if (m_quad < 0) {
+ // stay in main chunk
return true;
}
- } else {
- return false;
}
}
@@ -1638,7 +1678,7 @@ private:
* is sorted.
*/
-template
+template
class unstable_box_tree
{
public:
@@ -2103,7 +2143,16 @@ private:
}
obj_iterator qloc [5] = { from, from, from, from, from };
- point_type center (bbox.center ());
+ point_type center;
+ if (bbox.width () < bbox.height () / thin_aspect) {
+ // separate by height only
+ center = point_type (bbox.left (), bbox.bottom () + bbox.height () / 2);
+ } else if (bbox.height () < bbox.width () / thin_aspect) {
+ // separate by width only
+ center = point_type (bbox.left () + bbox.width () / 2, bbox.bottom ());
+ } else {
+ center = bbox.center ();
+ }
for (obj_iterator e = from; e != to; ++e) {
@@ -2158,7 +2207,7 @@ private:
if (nn >= min_quads) {
// create a new node representing this tree
- box_tree_node *node = new box_tree_node (parent, center, quad);
+ box_tree_node *node = new box_tree_node (parent, center, bbox, quad);
if (parent == 0) {
mp_root = node;
}
diff --git a/src/db/db/dbCell.h b/src/db/db/dbCell.h
index e4b2f3a4a..56e5e6b9a 100644
--- a/src/db/db/dbCell.h
+++ b/src/db/db/dbCell.h
@@ -301,6 +301,30 @@ public:
return m_instances.transform_into (ref, t);
}
+ /**
+ * @brief Transforms the cell by the given transformation.
+ *
+ * The transformation is applied to all instances and shapes. Magnified transformations will
+ * render magnified instances. See \transform_into for a version which avoids this.
+ *
+ * @param t The transformation to apply
+ */
+ template
+ void transform (const Trans &t)
+ {
+ m_instances.transform (t);
+ for (typename shapes_map::iterator s = m_shapes_map.begin (); s != m_shapes_map.end (); ++s) {
+ if (! s->second.empty ()) {
+ // Note: don't use the copy ctor here - it will copy the attachment to the manager
+ // and create problems when destroyed. Plus: swap would be more efficient. But by using
+ // assign_transformed we get undo support for free.
+ shapes_type d;
+ d = s->second;
+ s->second.assign_transformed (d, t);
+ }
+ }
+ }
+
/**
* @brief Transforms the cell into a new coordinate system.
*
diff --git a/src/db/db/dbCellVariants.cc b/src/db/db/dbCellVariants.cc
index afb4a137f..1676d1641 100644
--- a/src/db/db/dbCellVariants.cc
+++ b/src/db/db/dbCellVariants.cc
@@ -57,6 +57,22 @@ db::Trans MagnificationReducer::reduce (const db::Trans &) const
// ------------------------------------------------------------------------------------------
+db::ICplxTrans XYAnisotropyAndMagnificationReducer::reduce (const db::ICplxTrans &trans) const
+{
+ double a = trans.angle ();
+ if (a > 180.0 - db::epsilon) {
+ a -= 180.0;
+ }
+ return db::ICplxTrans (trans.mag (), a, false, db::Vector ());
+}
+
+db::Trans XYAnisotropyAndMagnificationReducer::reduce (const db::Trans &trans) const
+{
+ return db::Trans (trans.angle () % 2, false, db::Vector ());
+}
+
+// ------------------------------------------------------------------------------------------
+
db::ICplxTrans MagnificationAndOrientationReducer::reduce (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
diff --git a/src/db/db/dbCellVariants.h b/src/db/db/dbCellVariants.h
index c1f639648..921f162c2 100644
--- a/src/db/db/dbCellVariants.h
+++ b/src/db/db/dbCellVariants.h
@@ -81,6 +81,18 @@ struct DB_PUBLIC MagnificationReducer
db::Trans reduce (const db::Trans &) const;
};
+/**
+ * @brief A reducer for magnification and XYAnisotropy
+ *
+ * This reducer is used for cases where an x and y-value is given, e.g. anisotropic size.
+ */
+struct DB_PUBLIC XYAnisotropyAndMagnificationReducer
+ : public TransformationReducer
+{
+ db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
+ db::Trans reduce (const db::Trans &trans) const;
+};
+
/**
* @brief A magnification and orientation reducer
*
diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc
index d0fea79ee..0c80b380a 100644
--- a/src/db/db/dbCircuit.cc
+++ b/src/db/db/dbCircuit.cc
@@ -333,17 +333,41 @@ void Circuit::remove_pin (size_t id)
void Circuit::add_net (Net *net)
{
+ if (! net) {
+ return;
+ }
+ if (net->circuit ()) {
+ throw tl::Exception (tl::to_string (tr ("Net already part of a circuit")));
+ }
+
m_nets.push_back (net);
net->set_circuit (this);
}
void Circuit::remove_net (Net *net)
{
+ if (! net) {
+ return;
+ }
+ if (net->circuit () != this) {
+ throw tl::Exception (tl::to_string (tr ("Net not withing given circuit")));
+ }
+
m_nets.erase (net);
}
void Circuit::join_nets (Net *net, Net *with)
{
+ if (! net) {
+ return;
+ }
+ if (net == with || ! with) {
+ return;
+ }
+ if (net->circuit () != this || with->circuit () != this) {
+ throw tl::Exception (tl::to_string (tr ("Nets not withing given circuit")));
+ }
+
while (with->begin_terminals () != with->end_terminals ()) {
db::Device *device = const_cast (with->begin_terminals ()->device ());
device->connect_terminal (with->begin_terminals ()->terminal_id (), net);
@@ -368,6 +392,13 @@ void Circuit::join_nets (Net *net, Net *with)
void Circuit::add_device (Device *device)
{
+ if (! device) {
+ return;
+ }
+ if (device->circuit ()) {
+ throw tl::Exception (tl::to_string (tr ("Device already in a circuit")));
+ }
+
device->set_circuit (this);
size_t id = 0;
@@ -382,11 +413,25 @@ void Circuit::add_device (Device *device)
void Circuit::remove_device (Device *device)
{
+ if (! device) {
+ return;
+ }
+ if (device->circuit () != this) {
+ throw tl::Exception (tl::to_string (tr ("Device not withing given circuit")));
+ }
+
m_devices.erase (device);
}
void Circuit::add_subcircuit (SubCircuit *subcircuit)
{
+ if (! subcircuit) {
+ return;
+ }
+ if (subcircuit->circuit ()) {
+ throw tl::Exception (tl::to_string (tr ("Subcircuit already in a circuit")));
+ }
+
subcircuit->set_circuit (this);
size_t id = 0;
@@ -401,6 +446,13 @@ void Circuit::add_subcircuit (SubCircuit *subcircuit)
void Circuit::remove_subcircuit (SubCircuit *subcircuit)
{
+ if (! subcircuit) {
+ return;
+ }
+ if (subcircuit->circuit () != this) {
+ throw tl::Exception (tl::to_string (tr ("Subcircuit not withing given circuit")));
+ }
+
m_subcircuits.erase (subcircuit);
}
@@ -416,7 +468,12 @@ void Circuit::unregister_ref (SubCircuit *r)
void Circuit::flatten_subcircuit (SubCircuit *subcircuit)
{
- tl_assert (subcircuit != 0);
+ if (! subcircuit) {
+ return;
+ }
+ if (subcircuit->circuit () != this) {
+ throw tl::Exception (tl::to_string (tr ("Subcircuit not withing given circuit")));
+ }
const db::Circuit *c = subcircuit->circuit_ref ();
@@ -426,15 +483,21 @@ void Circuit::flatten_subcircuit (SubCircuit *subcircuit)
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
- // TODO: cannot join pins through subcircuits currently
- tl_assert (n->pin_count () <= 1);
-
db::Net *outside_net = 0;
if (n->pin_count () > 0) {
- size_t pin_id = n->begin_pins ()->pin_id ();
- outside_net = subcircuit->net_for_pin (pin_id);
+ for (db::Net::const_pin_iterator p = n->begin_pins (); p != n->end_pins (); ++p) {
+
+ size_t pin_id = p->pin_id ();
+
+ if (outside_net) {
+ join_nets (outside_net, subcircuit->net_for_pin (pin_id));
+ } else {
+ outside_net = subcircuit->net_for_pin (pin_id);
+ }
+
+ }
} else {
diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc
index f0138a17c..00e2702f9 100644
--- a/src/db/db/dbDeepEdgePairs.cc
+++ b/src/db/db/dbDeepEdgePairs.cc
@@ -86,34 +86,33 @@ private:
DeepEdgePairs::DeepEdgePairs ()
- : AsIfFlatEdgePairs (), m_deep_layer ()
+ : AsIfFlatEdgePairs ()
{
// .. nothing yet ..
}
DeepEdgePairs::DeepEdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss)
- : AsIfFlatEdgePairs (), m_deep_layer (dss.create_edge_pair_layer (si))
+ : AsIfFlatEdgePairs ()
{
- // .. nothing yet ..
+ set_deep_layer (dss.create_edge_pair_layer (si));
}
DeepEdgePairs::DeepEdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans)
- : AsIfFlatEdgePairs (), m_deep_layer (dss.create_edge_pair_layer (si, trans))
+ : AsIfFlatEdgePairs ()
{
- // .. nothing yet ..
+ set_deep_layer (dss.create_edge_pair_layer (si, trans));
}
DeepEdgePairs::DeepEdgePairs (const DeepEdgePairs &other)
- : AsIfFlatEdgePairs (other),
- m_deep_layer (other.m_deep_layer.copy ())
+ : AsIfFlatEdgePairs (other), db::DeepShapeCollectionDelegateBase (other)
{
// .. nothing yet ..
}
DeepEdgePairs::DeepEdgePairs (const DeepLayer &dl)
- : AsIfFlatEdgePairs (), m_deep_layer (dl)
+ : AsIfFlatEdgePairs ()
{
- // .. nothing yet ..
+ set_deep_layer (dl);
}
DeepEdgePairs::~DeepEdgePairs ()
@@ -133,7 +132,7 @@ EdgePairsIteratorDelegate *DeepEdgePairs::begin () const
std::pair DeepEdgePairs::begin_iter () const
{
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
@@ -141,7 +140,7 @@ std::pair DeepEdgePairs::begin_iter
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
- db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
+ db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@@ -151,10 +150,10 @@ size_t DeepEdgePairs::size () const
{
size_t n = 0;
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
- n += cc.weight (*c) * layout.cell (*c).shapes (m_deep_layer.layer ()).size ();
+ n += cc.weight (*c) * layout.cell (*c).shapes (deep_layer ().layer ()).size ();
}
return n;
@@ -167,7 +166,7 @@ std::string DeepEdgePairs::to_string (size_t nmax) const
Box DeepEdgePairs::bbox () const
{
- return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
}
bool DeepEdgePairs::empty () const
@@ -241,14 +240,20 @@ EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) co
return AsIfFlatEdgePairs::filtered (filter);
}
+RegionDelegate *
+DeepEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const
+{
+ return shape_collection_processed_impl (deep_layer (), filter);
+}
+
RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
{
- db::DeepLayer new_layer = m_deep_layer.derived ();
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::DeepLayer new_layer = deep_layer ().derived ();
+ db::Layout &layout = const_cast (deep_layer ().layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::Shapes &output = c->shapes (new_layer.layer ());
- for (db::Shapes::shape_iterator s = c->shapes (m_deep_layer.layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
+ for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
db::Polygon poly = s->edge_pair ().normalized ().to_polygon (e);
if (poly.vertices () >= 3) {
output.insert (db::PolygonRef (poly, layout.shape_repository ()));
@@ -261,12 +266,12 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const
{
- db::DeepLayer new_layer = m_deep_layer.derived ();
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::DeepLayer new_layer = deep_layer ().derived ();
+ db::Layout &layout = const_cast (deep_layer ().layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::Shapes &output = c->shapes (new_layer.layer ());
- for (db::Shapes::shape_iterator s = c->shapes (m_deep_layer.layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
+ for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
db::EdgePair ep = s->edge_pair ();
if (first) {
output.insert (ep.first ());
@@ -304,8 +309,8 @@ EdgePairsDelegate *DeepEdgePairs::in (const EdgePairs &other, bool invert) const
bool DeepEdgePairs::equals (const EdgePairs &other) const
{
const DeepEdgePairs *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
- && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
return true;
} else {
return AsIfFlatEdgePairs::equals (other);
@@ -315,8 +320,8 @@ bool DeepEdgePairs::equals (const EdgePairs &other) const
bool DeepEdgePairs::less (const EdgePairs &other) const
{
const DeepEdgePairs *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
- return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
} else {
return AsIfFlatEdgePairs::less (other);
}
@@ -324,13 +329,12 @@ bool DeepEdgePairs::less (const EdgePairs &other) const
void DeepEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
- m_deep_layer.insert_into (layout, into_cell, into_layer);
+ deep_layer ().insert_into (layout, into_cell, into_layer);
}
void DeepEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
- m_deep_layer.insert_into_as_polygons (layout, into_cell, into_layer, enl);
+ deep_layer ().insert_into_as_polygons (layout, into_cell, into_layer, enl);
}
-
}
diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h
index a6d0732f1..a030652cc 100644
--- a/src/db/db/dbDeepEdgePairs.h
+++ b/src/db/db/dbDeepEdgePairs.h
@@ -36,7 +36,7 @@ namespace db {
* @brief Provides hierarchical edges implementation
*/
class DB_PUBLIC DeepEdgePairs
- : public db::AsIfFlatEdgePairs
+ : public db::AsIfFlatEdgePairs, public db::DeepShapeCollectionDelegateBase
{
public:
DeepEdgePairs ();
@@ -63,6 +63,7 @@ public:
virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter);
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const;
+ virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const;
virtual EdgePairsDelegate *add_in_place (const EdgePairs &other);
virtual EdgePairsDelegate *add (const EdgePairs &other) const;
@@ -80,21 +81,14 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
- const DeepLayer &deep_layer () const
+ virtual DeepShapeCollectionDelegateBase *deep ()
{
- return m_deep_layer;
- }
-
- DeepLayer &deep_layer ()
- {
- return m_deep_layer;
+ return this;
}
private:
DeepEdgePairs &operator= (const DeepEdgePairs &other);
- DeepLayer m_deep_layer;
-
void init ();
EdgesDelegate *generic_edges (bool first, bool second) const;
};
diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc
index 4b9eec059..5f0961b00 100644
--- a/src/db/db/dbDeepEdges.cc
+++ b/src/db/db/dbDeepEdges.cc
@@ -96,14 +96,16 @@ private:
// DeepEdges implementation
DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, bool as_edges)
- : AsIfFlatEdges (), m_deep_layer (dss.create_edge_layer (si, as_edges)), m_merged_edges ()
+ : AsIfFlatEdges (), m_merged_edges ()
{
+ set_deep_layer (dss.create_edge_layer (si, as_edges));
init ();
}
DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool as_edges, bool merged_semantics)
- : AsIfFlatEdges (), m_deep_layer (dss.create_edge_layer (si, as_edges, trans)), m_merged_edges ()
+ : AsIfFlatEdges (), m_merged_edges ()
{
+ set_deep_layer (dss.create_edge_layer (si, as_edges, trans));
init ();
set_merged_semantics (merged_semantics);
}
@@ -111,7 +113,7 @@ DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, con
DeepEdges::DeepEdges (const db::Edges &other, DeepShapeStore &dss)
: AsIfFlatEdges (), m_merged_edges ()
{
- m_deep_layer = dss.create_from_flat (other);
+ set_deep_layer (dss.create_from_flat (other));
init ();
set_merged_semantics (other.merged_semantics ());
@@ -124,8 +126,9 @@ DeepEdges::DeepEdges ()
}
DeepEdges::DeepEdges (const DeepLayer &dl)
- : AsIfFlatEdges (), m_deep_layer (dl)
+ : AsIfFlatEdges ()
{
+ set_deep_layer (dl);
init ();
}
@@ -135,8 +138,7 @@ DeepEdges::~DeepEdges ()
}
DeepEdges::DeepEdges (const DeepEdges &other)
- : AsIfFlatEdges (other),
- m_deep_layer (other.m_deep_layer.copy ()),
+ : AsIfFlatEdges (other), DeepShapeCollectionDelegateBase (other),
m_merged_edges_valid (other.m_merged_edges_valid),
m_is_merged (other.m_is_merged)
{
@@ -145,6 +147,25 @@ DeepEdges::DeepEdges (const DeepEdges &other)
}
}
+DeepEdges &
+DeepEdges::operator= (const DeepEdges &other)
+{
+ if (this != &other) {
+
+ AsIfFlatEdges::operator= (other);
+ DeepShapeCollectionDelegateBase::operator= (other);
+
+ m_merged_edges_valid = other.m_merged_edges_valid;
+ m_is_merged = other.m_is_merged;
+ if (m_merged_edges_valid) {
+ m_merged_edges = other.m_merged_edges;
+ }
+
+ }
+
+ return *this;
+}
+
void DeepEdges::init ()
{
m_merged_edges_valid = false;
@@ -182,7 +203,7 @@ DeepEdges::begin_merged () const
std::pair
DeepEdges::begin_iter () const
{
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
@@ -190,7 +211,7 @@ DeepEdges::begin_iter () const
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
- db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
+ db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@@ -262,8 +283,8 @@ DeepEdges::iter () const
bool DeepEdges::equals (const Edges &other) const
{
const DeepEdges *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
- && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
return true;
} else {
return AsIfFlatEdges::equals (other);
@@ -273,8 +294,8 @@ bool DeepEdges::equals (const Edges &other) const
bool DeepEdges::less (const Edges &other) const
{
const DeepEdges *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
- return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
} else {
return AsIfFlatEdges::less (other);
}
@@ -384,27 +405,27 @@ DeepEdges::ensure_merged_edges_valid () const
if (m_is_merged) {
// NOTE: this will reuse the deep layer reference
- m_merged_edges = m_deep_layer;
+ m_merged_edges = deep_layer ();
} else {
- m_merged_edges = m_deep_layer.derived ();
+ m_merged_edges = deep_layer ().derived ();
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::Layout &layout = const_cast (deep_layer ().layout ());
db::hier_clusters hc;
db::Connectivity conn;
- conn.connect (m_deep_layer);
+ conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity() + 10);
- hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Edges, conn);
+ hc.build (layout, deep_layer ().initial_cell (), conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
- ClusterMerger cm (m_deep_layer.layer (), hc, report_progress (), progress_desc ());
+ ClusterMerger cm (deep_layer ().layer (), hc, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity () + 10);
// TODO: iterate only over the called cells?
@@ -436,17 +457,17 @@ DeepEdges::set_is_merged (bool f)
void
DeepEdges::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
- m_deep_layer.insert_into (layout, into_cell, into_layer);
+ deep_layer ().insert_into (layout, into_cell, into_layer);
}
size_t DeepEdges::size () const
{
size_t n = 0;
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
- n += cc.weight (*c) * layout.cell (*c).shapes (m_deep_layer.layer ()).size ();
+ n += cc.weight (*c) * layout.cell (*c).shapes (deep_layer ().layer ()).size ();
}
return n;
@@ -454,7 +475,7 @@ size_t DeepEdges::size () const
Box DeepEdges::bbox () const
{
- return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
}
DeepEdges::length_type DeepEdges::length (const db::Box &box) const
@@ -504,157 +525,37 @@ EdgesDelegate *DeepEdges::process_in_place (const EdgeProcessorBase &filter)
EdgesDelegate *
DeepEdges::processed (const EdgeProcessorBase &filter) const
{
- return processed_impl (filter);
+ return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
EdgePairsDelegate *
DeepEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const
{
- return processed_impl (filter);
+ return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
RegionDelegate *
DeepEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const
{
- return processed_impl (filter);
-}
-
-namespace
-{
-
-template struct delivery;
-
-template <>
-struct delivery
-{
- delivery (db::Layout *layout, db::Shapes *shapes)
- : mp_layout (layout), mp_shapes (shapes)
- { }
-
- void put (const db::Polygon &result)
- {
- tl::MutexLocker locker (&mp_layout->lock ());
- mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
- }
-
-private:
- db::Layout *mp_layout;
- db::Shapes *mp_shapes;
-};
-
-template
-struct delivery
-{
- delivery (db::Layout *, db::Shapes *shapes)
- : mp_shapes (shapes)
- { }
-
- void put (const Result &result)
- {
- mp_shapes->insert (result);
- }
-
-private:
- db::Shapes *mp_shapes;
-};
-
-}
-
-template
-OutputContainer *
-DeepEdges::processed_impl (const edge_processor &filter) const
-{
- const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
-
- std::auto_ptr vars;
- if (filter.vars ()) {
-
- vars.reset (new db::VariantsCollectorBase (filter.vars ()));
-
- vars->collect (edges.layout (), edges.initial_cell ());
-
- if (filter.wants_variants ()) {
- const_cast (edges).separate_variants (*vars);
- }
-
- }
-
- db::Layout &layout = const_cast (edges.layout ());
-
- std::vector heap;
- std::map > to_commit;
-
- std::auto_ptr res (new OutputContainer (edges.derived ()));
- if (filter.result_must_not_be_merged ()) {
- res->set_merged_semantics (false);
- }
-
- for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
-
- const db::Shapes &s = c->shapes (filter.requires_raw_input () ? edges.layer () : edges.layer ());
-
- if (vars.get ()) {
-
- const std::map &vv = vars->variants (c->cell_index ());
- for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) {
-
- db::Shapes *st;
- if (vv.size () == 1) {
- st = & c->shapes (res->deep_layer ().layer ());
- } else {
- st = & to_commit [c->cell_index ()] [v->first];
- }
-
- delivery delivery (&layout, st);
-
- const db::ICplxTrans &tr = v->first;
- db::ICplxTrans trinv = tr.inverted ();
-
- for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
- heap.clear ();
- filter.process (si->edge ().transformed (tr), heap);
- for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) {
- delivery.put (i->transformed (trinv));
- }
- }
-
- }
-
- } else {
-
- db::Shapes &st = c->shapes (res->deep_layer ().layer ());
- delivery delivery (&layout, &st);
-
- for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
- filter.process (si->edge (), heap);
- for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) {
- delivery.put (*i);
- }
- }
-
- }
-
- }
-
- if (! to_commit.empty () && vars.get ()) {
- res->deep_layer ().commit_shapes (*vars, to_commit);
- }
-
- if (filter.result_is_merged ()) {
- res->set_is_merged (true);
- }
- return res.release ();
+ return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
EdgesDelegate *
DeepEdges::filter_in_place (const EdgeFilterBase &filter)
{
// TODO: implement to be really in-place
- return filtered (filter);
+ *this = *apply_filter (filter);
+ return this;
}
EdgesDelegate *
DeepEdges::filtered (const EdgeFilterBase &filter) const
+{
+ return apply_filter (filter);
+}
+
+DeepEdges *
+DeepEdges::apply_filter (const EdgeFilterBase &filter) const
{
const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
@@ -730,7 +631,7 @@ EdgesDelegate *DeepEdges::merged_in_place ()
ensure_merged_edges_valid ();
// NOTE: this makes both layers share the same resource
- m_deep_layer = m_merged_edges;
+ set_deep_layer (m_merged_edges);
return this;
}
@@ -753,17 +654,17 @@ EdgesDelegate *DeepEdges::merged () const
DeepLayer
DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const
{
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
db::EdgeBoolAndOrNotLocalOperation local_op (op);
- db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
+ db::local_processor proc (const_cast (&deep_layer ().layout ()), const_cast (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
- proc.set_threads (m_deep_layer.store ()->threads ());
- proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
- proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
+ proc.set_threads (deep_layer ().store ()->threads ());
+ proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
+ proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
- proc.run (&local_op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
+ proc.run (&local_op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
@@ -771,17 +672,17 @@ DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const
DeepLayer
DeepEdges::edge_region_op (const DeepRegion *other, bool outside, bool include_borders) const
{
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
db::EdgeToPolygonLocalOperation op (outside, include_borders);
- db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
+ db::local_processor proc (const_cast (&deep_layer ().layout ()), const_cast (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
- proc.set_threads (m_deep_layer.store ()->threads ());
- proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
- proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
+ proc.set_threads (deep_layer ().store ()->threads ());
+ proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
+ proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
- proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
+ proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
@@ -1051,7 +952,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
db::Connectivity conn (db::Connectivity::EdgesConnectByPoints);
conn.connect (edges);
hc.set_base_verbosity (base_verbosity () + 10);
- hc.build (layout, edges.initial_cell (), db::ShapeIterator::Edges, conn);
+ hc.build (layout, edges.initial_cell (), conn);
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
@@ -1278,7 +1179,7 @@ public:
}
}
- for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
scanner.insert1 (&subject, 0);
}
@@ -1295,7 +1196,7 @@ public:
edge_to_region_interaction_filter > filter (interacting);
scanner.process (filter, 1, db::box_convert (), db::box_convert ());
- for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (interacting.find (subject) == interacting.end ()) {
result.insert (subject);
@@ -1374,7 +1275,7 @@ public:
}
}
- for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
scanner.insert1 (&subject, 1);
}
diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h
index 662ac5cd1..7d2eb83ea 100644
--- a/src/db/db/dbDeepEdges.h
+++ b/src/db/db/dbDeepEdges.h
@@ -40,7 +40,7 @@ class DeepRegion;
* @brief Provides hierarchical edges implementation
*/
class DB_PUBLIC DeepEdges
- : public db::AsIfFlatEdges
+ : public db::AsIfFlatEdges, public db::DeepShapeCollectionDelegateBase
{
public:
DeepEdges ();
@@ -144,26 +144,21 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
- const DeepLayer &deep_layer () const
+ virtual DeepShapeCollectionDelegateBase *deep ()
{
- return m_deep_layer;
+ return this;
}
- DeepLayer &deep_layer ()
- {
- return m_deep_layer;
- }
+ void set_is_merged (bool f);
protected:
virtual void merged_semantics_changed ();
- void set_is_merged (bool f);
private:
friend class DeepRegion;
DeepEdges &operator= (const DeepEdges &other);
- DeepLayer m_deep_layer;
mutable DeepLayer m_merged_edges;
mutable bool m_merged_edges_valid;
bool m_is_merged;
@@ -178,6 +173,8 @@ private:
virtual RegionDelegate *pull_generic (const Region ®ion) const;
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const;
+ DeepEdges *apply_filter (const EdgeFilterBase &filter) const;
+
template OutputContainer *processed_impl (const edge_processor &filter) const;
};
diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc
index 078924859..a9ef537dd 100644
--- a/src/db/db/dbDeepRegion.cc
+++ b/src/db/db/dbDeepRegion.cc
@@ -28,6 +28,7 @@
#include "dbRegionUtils.h"
#include "dbDeepEdges.h"
#include "dbDeepEdgePairs.h"
+#include "dbDeepTexts.h"
#include "dbShapeProcessor.h"
#include "dbFlatRegion.h"
#include "dbHierProcessor.h"
@@ -101,14 +102,16 @@ private:
// DeepRegion implementation
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
- : AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons ()
+ : AsIfFlatRegion (), m_merged_polygons ()
{
+ set_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count));
init ();
}
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics, double area_ratio, size_t max_vertex_count)
- : AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count, trans)), m_merged_polygons ()
+ : AsIfFlatRegion (), m_merged_polygons ()
{
+ set_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count, trans));
init ();
set_merged_semantics (merged_semantics);
}
@@ -116,7 +119,7 @@ DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, c
DeepRegion::DeepRegion (const db::Region &other, DeepShapeStore &dss)
: AsIfFlatRegion (), m_merged_polygons ()
{
- m_deep_layer = dss.create_from_flat (other, false);
+ set_deep_layer (dss.create_from_flat (other, false));
init ();
set_merged_semantics (other.merged_semantics ());
@@ -129,8 +132,9 @@ DeepRegion::DeepRegion ()
}
DeepRegion::DeepRegion (const DeepLayer &dl)
- : AsIfFlatRegion (), m_deep_layer (dl)
+ : AsIfFlatRegion ()
{
+ set_deep_layer (dl);
init ();
}
@@ -140,8 +144,7 @@ DeepRegion::~DeepRegion ()
}
DeepRegion::DeepRegion (const DeepRegion &other)
- : AsIfFlatRegion (other),
- m_deep_layer (other.m_deep_layer.copy ()),
+ : AsIfFlatRegion (other), DeepShapeCollectionDelegateBase (other),
m_merged_polygons_valid (other.m_merged_polygons_valid),
m_is_merged (other.m_is_merged)
{
@@ -150,6 +153,25 @@ DeepRegion::DeepRegion (const DeepRegion &other)
}
}
+DeepRegion &
+DeepRegion::operator= (const DeepRegion &other)
+{
+ if (this != &other) {
+
+ AsIfFlatRegion::operator= (other);
+ DeepShapeCollectionDelegateBase::operator= (other);
+
+ m_merged_polygons_valid = other.m_merged_polygons_valid;
+ m_is_merged = other.m_is_merged;
+ if (m_merged_polygons_valid) {
+ m_merged_polygons = other.m_merged_polygons;
+ }
+
+ }
+
+ return *this;
+}
+
void DeepRegion::init ()
{
m_merged_polygons_valid = false;
@@ -192,7 +214,7 @@ DeepRegion::begin_merged () const
std::pair
DeepRegion::begin_iter () const
{
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
@@ -200,7 +222,7 @@ DeepRegion::begin_iter () const
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
- db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
+ db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@@ -273,8 +295,8 @@ bool
DeepRegion::equals (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
- && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
return true;
} else {
return AsIfFlatRegion::equals (other);
@@ -285,8 +307,8 @@ bool
DeepRegion::less (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
- return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
} else {
return AsIfFlatRegion::less (other);
}
@@ -421,27 +443,27 @@ DeepRegion::ensure_merged_polygons_valid () const
if (m_is_merged) {
// NOTE: this will reuse the deep layer reference
- m_merged_polygons = m_deep_layer;
+ m_merged_polygons = deep_layer ();
} else {
- m_merged_polygons = m_deep_layer.derived ();
+ m_merged_polygons = deep_layer ().derived ();
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::Layout &layout = const_cast (deep_layer ().layout ());
db::hier_clusters hc;
db::Connectivity conn;
- conn.connect (m_deep_layer);
+ conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity () + 10);
- hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
+ hc.build (layout, deep_layer ().initial_cell (), conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
- ClusterMerger cm (m_deep_layer.layer (), layout, hc, min_coherence (), report_progress (), progress_desc ());
+ ClusterMerger cm (deep_layer ().layer (), layout, hc, min_coherence (), report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity () + 10);
// TODO: iterate only over the called cells?
@@ -473,7 +495,7 @@ DeepRegion::set_is_merged (bool f)
void
DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
- m_deep_layer.insert_into (layout, into_cell, into_layer);
+ deep_layer ().insert_into (layout, into_cell, into_layer);
}
RegionDelegate *
@@ -523,17 +545,17 @@ DeepRegion::not_with (const Region &other) const
DeepLayer
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
{
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
db::BoolAndOrNotLocalOperation op (and_op);
- db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), m_deep_layer.breakout_cells (), other->deep_layer ().breakout_cells ());
+ db::local_processor proc (const_cast (&deep_layer ().layout ()), const_cast (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
- proc.set_threads (m_deep_layer.store ()->threads ());
- proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
- proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
+ proc.set_threads (deep_layer ().store ()->threads ());
+ proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
+ proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
- proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
+ proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
@@ -648,10 +670,10 @@ DeepRegion::size () const
{
size_t n = 0;
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
- n += cc.weight (*c) * layout.cell (*c).shapes (m_deep_layer.layer ()).size ();
+ n += cc.weight (*c) * layout.cell (*c).shapes (deep_layer ().layer ()).size ();
}
return n;
@@ -726,7 +748,7 @@ DeepRegion::perimeter (const db::Box &box) const
Box
DeepRegion::bbox () const
{
- return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
}
std::string
@@ -933,163 +955,37 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter)
EdgesDelegate *
DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const
{
- return processed_impl (filter);
+ return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
EdgePairsDelegate *
DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const
{
- return processed_impl (filter);
+ return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
RegionDelegate *
DeepRegion::processed (const PolygonProcessorBase &filter) const
{
- return processed_impl (filter);
-}
-
-namespace
-{
-
-template struct delivery;
-
-template <>
-struct delivery
-{
- delivery (db::Layout *layout, db::Shapes *shapes)
- : mp_layout (layout), mp_shapes (shapes)
- { }
-
- void put (const db::Polygon &result)
- {
- tl::MutexLocker locker (&mp_layout->lock ());
- mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
- }
-
-private:
- db::Layout *mp_layout;
- db::Shapes *mp_shapes;
-};
-
-template
-struct delivery
-{
- delivery (db::Layout *, db::Shapes *shapes)
- : mp_shapes (shapes)
- { }
-
- void put (const Result &result)
- {
- mp_shapes->insert (result);
- }
-
-private:
- db::Shapes *mp_shapes;
-};
-
-}
-
-template
-OutputContainer *
-DeepRegion::processed_impl (const polygon_processor &filter) const
-{
- const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
-
- std::auto_ptr vars;
- if (filter.vars ()) {
-
- vars.reset (new db::VariantsCollectorBase (filter.vars ()));
-
- vars->collect (polygons.layout (), polygons.initial_cell ());
-
- if (filter.wants_variants ()) {
- const_cast (polygons).separate_variants (*vars);
- }
-
- }
-
- db::Layout &layout = const_cast (polygons.layout ());
-
- std::vector heap;
- std::map > to_commit;
-
- std::auto_ptr res (new OutputContainer (polygons.derived ()));
- if (filter.result_must_not_be_merged ()) {
- res->set_merged_semantics (false);
- }
-
- for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
-
- const db::Shapes &s = c->shapes (polygons.layer ());
-
- if (vars.get ()) {
-
- const std::map &vv = vars->variants (c->cell_index ());
- for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) {
-
- db::Shapes *st;
- if (vv.size () == 1) {
- st = & c->shapes (res->deep_layer ().layer ());
- } else {
- st = & to_commit [c->cell_index ()] [v->first];
- }
-
- delivery delivery (&layout, st);
-
- const db::ICplxTrans &tr = v->first;
- db::ICplxTrans trinv = tr.inverted ();
-
- for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
- db::Polygon poly;
- si->polygon (poly);
- poly.transform (tr);
- heap.clear ();
- filter.process (poly, heap);
- for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) {
- delivery.put (i->transformed (trinv));
- }
- }
-
- }
-
- } else {
-
- db::Shapes &st = c->shapes (res->deep_layer ().layer ());
- delivery delivery (&layout, &st);
-
- for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
- db::Polygon poly;
- si->polygon (poly);
- heap.clear ();
- filter.process (poly, heap);
- for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) {
- delivery.put (*i);
- }
- }
-
- }
-
- }
-
- if (! to_commit.empty () && vars.get ()) {
- res->deep_layer ().commit_shapes (*vars, to_commit);
- }
-
- if (filter.result_is_merged ()) {
- res->set_is_merged (true);
- }
- return res.release ();
+ return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
RegionDelegate *
DeepRegion::filter_in_place (const PolygonFilterBase &filter)
{
// TODO: implement to be really in-place
- return filtered (filter);
+ *this = *apply_filter (filter);
+ return this;
}
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
+{
+ return apply_filter (filter);
+}
+
+DeepRegion *
+DeepRegion::apply_filter (const PolygonFilterBase &filter) const
{
const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
@@ -1170,7 +1066,7 @@ DeepRegion::merged_in_place ()
ensure_merged_polygons_valid ();
// NOTE: this makes both layers share the same resource
- m_deep_layer = m_merged_polygons;
+ set_deep_layer (m_merged_polygons);
set_is_merged (true);
return this;
@@ -1205,21 +1101,21 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
{
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::Layout &layout = const_cast (deep_layer ().layout ());
db::hier_clusters hc;
db::Connectivity conn;
- conn.connect (m_deep_layer);
+ conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity () + 10);
- hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
+ hc.build (layout, deep_layer ().initial_cell (), conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
- ClusterMerger cm (m_deep_layer.layer (), layout, hc, min_coherence, report_progress (), progress_desc ());
+ ClusterMerger cm (deep_layer ().layer (), layout, hc, min_coherence, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity () + 10);
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
@@ -1289,29 +1185,6 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
return res.release ();
}
-namespace
-{
-
-struct XYAnisotropyAndMagnificationReducer
- : public db::TransformationReducer
-{
- db::ICplxTrans reduce (const db::ICplxTrans &trans) const
- {
- double a = trans.angle ();
- if (a > 180.0 - db::epsilon) {
- a -= 180.0;
- }
- return db::ICplxTrans (trans.mag (), a, false, db::Vector ());
- }
-
- db::Trans reduce (const db::Trans &trans) const
- {
- return db::Trans (trans.angle () % 2, false, db::Vector ());
- }
-};
-
-}
-
RegionDelegate *
DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
{
@@ -1502,7 +1375,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
const_cast (&polygons.initial_cell ()),
other_deep ? &other_deep->deep_layer ().layout () : const_cast (&polygons.layout ()),
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&polygons.initial_cell ()),
- m_deep_layer.breakout_cells (),
+ deep_layer ().breakout_cells (),
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
proc.set_base_verbosity (base_verbosity ());
@@ -1870,6 +1743,143 @@ public:
}
};
+struct TextResultInserter
+{
+ typedef db::TextRef value_type;
+
+ TextResultInserter (std::unordered_set &result)
+ : mp_result (&result)
+ {
+ // .. nothing yet ..
+ }
+
+ void insert (const db::TextRef &e)
+ {
+ (*mp_result).insert (e);
+ }
+
+private:
+ std::unordered_set *mp_result;
+};
+
+class PullWithTextLocalOperation
+ : public local_operation
+{
+public:
+ PullWithTextLocalOperation ()
+ {
+ // .. nothing yet ..
+ }
+
+ virtual db::Coord dist () const
+ {
+ // touching is sufficient
+ return 1;
+ }
+
+ virtual void compute_local (db::Layout *, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
+ {
+ db::box_scanner2 scanner;
+
+ TextResultInserter inserter (result);
+ region_to_text_interaction_filter filter (inserter, false);
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
+ scanner.insert2 (& interactions.intruder_shape (*j), 0);
+ }
+ }
+
+ std::list heap;
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+
+ const db::PolygonRef &subject = interactions.subject_shape (i->first);
+ heap.push_back (subject.obj ().transformed (subject.trans ()));
+
+ scanner.insert1 (&heap.back (), 0);
+
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+ }
+
+ virtual on_empty_intruder_mode on_empty_intruder_hint () const
+ {
+ return Drop;
+ }
+
+ virtual std::string description () const
+ {
+ return tl::to_string (tr ("Pull texts from second by their geometric relation to first"));
+ }
+};
+
+class InteractingWithTextLocalOperation
+ : public local_operation
+{
+public:
+ InteractingWithTextLocalOperation (bool inverse)
+ : m_inverse (inverse)
+ {
+ // .. nothing yet ..
+ }
+
+ virtual db::Coord dist () const
+ {
+ // touching is sufficient
+ return 1;
+ }
+
+ virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
+ {
+ db::box_scanner2 scanner;
+
+ ResultInserter inserter (layout, result);
+ region_to_text_interaction_filter filter (inserter, m_inverse);
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
+ scanner.insert2 (& interactions.intruder_shape (*j), 0);
+ }
+ }
+
+ std::list heap;
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+
+ const db::PolygonRef &subject = interactions.subject_shape (i->first);
+ heap.push_back (subject.obj ().transformed (subject.trans ()));
+
+ scanner.insert1 (&heap.back (), 0);
+ if (m_inverse) {
+ filter.preset (&heap.back ());
+ }
+
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+ if (m_inverse) {
+ filter.fill_output ();
+ }
+ }
+
+ virtual on_empty_intruder_mode on_empty_intruder_hint () const
+ {
+ if (!m_inverse) {
+ return Drop;
+ } else {
+ return Copy;
+ }
+ }
+
+ virtual std::string description () const
+ {
+ return tl::to_string (tr ("Select regions by their geometric relation to texts"));
+ }
+
+private:
+ bool m_inverse;
+};
+
}
RegionDelegate *
@@ -2016,4 +2026,70 @@ DeepRegion::pull_generic (const Edges &other) const
return res;
}
+TextsDelegate *
+DeepRegion::pull_generic (const Texts &other) const
+{
+ std::auto_ptr dr_holder;
+ const db::DeepTexts *other_deep = dynamic_cast (other.delegate ());
+ if (! other_deep) {
+ // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
+ dr_holder.reset (new db::DeepTexts (other, const_cast (*deep_layer ().store ())));
+ other_deep = dr_holder.get ();
+ }
+
+ // in "inside" mode, the first argument needs to be merged too
+ const db::DeepLayer &polygons = deep_layer ();
+ const db::DeepLayer &other_texts = other_deep->deep_layer ();
+
+ DeepLayer dl_out (polygons.derived ());
+
+ db::PullWithTextLocalOperation op;
+
+ db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ());
+ proc.set_base_verbosity (base_verbosity ());
+ proc.set_threads (polygons.store ()->threads ());
+ proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ());
+
+ db::DeepTexts *res = new db::DeepTexts (dl_out);
+ res->set_is_merged (is_merged ());
+ return res;
+}
+
+RegionDelegate *
+DeepRegion::selected_interacting_generic (const Texts &other, bool inverse) const
+{
+ // with these flag set to true, the resulting polygons are broken again.
+ bool split_after = false;
+
+ std::auto_ptr dr_holder;
+ const db::DeepTexts *other_deep = dynamic_cast (other.delegate ());
+ if (! other_deep) {
+ // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
+ dr_holder.reset (new db::DeepTexts (other, const_cast (*deep_layer ().store ())));
+ other_deep = dr_holder.get ();
+ }
+
+ const db::DeepLayer &polygons = merged_deep_layer ();
+
+ DeepLayer dl_out (polygons.derived ());
+
+ db::InteractingWithTextLocalOperation op (inverse);
+
+ db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
+ proc.set_base_verbosity (base_verbosity ());
+ proc.set_threads (polygons.store ()->threads ());
+ if (split_after) {
+ proc.set_area_ratio (polygons.store ()->max_area_ratio ());
+ proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
+ }
+
+ proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
+
+ db::DeepRegion *res = new db::DeepRegion (dl_out);
+ if (! split_after) {
+ res->set_is_merged (merged_semantics () || is_merged ());
+ }
+ return res;
+}
+
}
diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h
index c1665d658..1c672d430 100644
--- a/src/db/db/dbDeepRegion.h
+++ b/src/db/db/dbDeepRegion.h
@@ -35,7 +35,7 @@ namespace db {
* @brief A deep, polygon-set delegate
*/
class DB_PUBLIC DeepRegion
- : public AsIfFlatRegion
+ : public AsIfFlatRegion, public DeepShapeCollectionDelegateBase
{
public:
typedef db::layer polygon_layer_type;
@@ -159,27 +159,23 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
- const DeepLayer &deep_layer () const
+ virtual DeepShapeCollectionDelegateBase *deep ()
{
- return m_deep_layer;
+ return this;
}
- DeepLayer &deep_layer ()
- {
- return m_deep_layer;
- }
+ void set_is_merged (bool f);
protected:
virtual void merged_semantics_changed ();
virtual void min_coherence_changed ();
- void set_is_merged (bool f);
private:
friend class DeepEdges;
+ friend class DeepTexts;
DeepRegion &operator= (const DeepRegion &other);
- DeepLayer m_deep_layer;
mutable DeepLayer m_merged_polygons;
mutable bool m_merged_polygons_valid;
bool m_is_merged;
@@ -192,8 +188,11 @@ private:
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
+ virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
+ virtual TextsDelegate *pull_generic (const Texts &other) const;
+ DeepRegion *apply_filter (const PolygonFilterBase &filter) const;
template OutputContainer *processed_impl (const polygon_processor &filter) const;
};
diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc
index c1fcb9009..a2e11a840 100644
--- a/src/db/db/dbDeepShapeStore.cc
+++ b/src/db/db/dbDeepShapeStore.cc
@@ -25,7 +25,14 @@
#include "dbCellMapping.h"
#include "dbLayoutUtils.h"
#include "dbRegion.h"
+#include "dbEdges.h"
+#include "dbEdgePairs.h"
+#include "dbTexts.h"
#include "dbDeepRegion.h"
+#include "dbDeepEdges.h"
+#include "dbDeepEdgePairs.h"
+#include "dbDeepTexts.h"
+#include "dbShapeCollection.h"
#include "tlTimer.h"
@@ -48,6 +55,30 @@ DeepLayer::DeepLayer (const Region ®ion)
*this = dr->deep_layer ();
}
+DeepLayer::DeepLayer (const Texts &texts)
+ : mp_store (), m_layout (0), m_layer (0)
+{
+ const db::DeepTexts *dr = dynamic_cast (texts.delegate ());
+ tl_assert (dr != 0);
+ *this = dr->deep_layer ();
+}
+
+DeepLayer::DeepLayer (const Edges &edges)
+ : mp_store (), m_layout (0), m_layer (0)
+{
+ const db::DeepEdges *dr = dynamic_cast (edges.delegate ());
+ tl_assert (dr != 0);
+ *this = dr->deep_layer ();
+}
+
+DeepLayer::DeepLayer (const EdgePairs &edge_pairs)
+ : mp_store (), m_layout (0), m_layer (0)
+{
+ const db::DeepEdgePairs *dr = dynamic_cast (edge_pairs.delegate ());
+ tl_assert (dr != 0);
+ *this = dr->deep_layer ();
+}
+
DeepLayer::DeepLayer (const DeepLayer &x)
: mp_store (x.mp_store), m_layout (x.m_layout), m_layer (x.m_layer)
{
@@ -459,9 +490,39 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::IC
return dl;
}
-std::pair DeepShapeStore::layer_for_flat (const db::Region ®ion) const
+DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::ICplxTrans &trans)
{
- return layer_for_flat (tl::id_of (region.delegate ()));
+ // reuse existing layer
+ std::pair lff = layer_for_flat (tl::id_of (texts.delegate ()));
+ if (lff.first) {
+ return lff.second;
+ }
+
+ require_singular ();
+
+ unsigned int layer = layout ().insert_layer ();
+
+ db::Shapes *shapes = &initial_cell ().shapes (layer);
+ db::Box world = db::Box::world ();
+
+ db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ());
+
+ std::pair ii = texts.begin_iter ();
+ db::ICplxTrans ttop = trans * ii.second;
+ while (! ii.first.at_end ()) {
+ tb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
+ ++ii.first;
+ }
+
+ DeepLayer dl (this, 0 /*singular layout index*/, layer);
+ m_layers_for_flat [tl::id_of (texts.delegate ())] = std::make_pair (dl.layout_index (), dl.layer ());
+ m_flat_region_id [std::make_pair (dl.layout_index (), dl.layer ())] = tl::id_of (texts.delegate ());
+ return dl;
+}
+
+std::pair DeepShapeStore::layer_for_flat (const ShapeCollection &coll) const
+{
+ return layer_for_flat (tl::id_of (coll.get_delegate ()));
}
std::pair DeepShapeStore::layer_for_flat (size_t region_id) const
@@ -807,64 +868,23 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans)
{
- unsigned int layout_index = layout_for_iter (si, trans);
-
- db::Layout &layout = m_layouts[layout_index]->layout;
- db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
-
- unsigned int layer_index = init_layer (layout, si);
- builder.set_target_layer (layer_index);
-
- // The chain of operators for producing edges
db::EdgeBuildingHierarchyBuilderShapeReceiver refs (as_edges);
-
- // Build the working hierarchy from the recursive shape iterator
- try {
-
- tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
- db::LayoutLocker ll (&layout, true /*no update*/);
-
- builder.set_shape_receiver (&refs);
- db::RecursiveShapeIterator (si).push (& builder);
- builder.set_shape_receiver (0);
-
- } catch (...) {
- builder.set_shape_receiver (0);
- throw;
- }
-
- return DeepLayer (this, layout_index, layer_index);
+ return create_custom_layer (si, &refs, trans);
}
DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
{
- unsigned int layout_index = layout_for_iter (si, trans);
-
- db::Layout &layout = m_layouts[layout_index]->layout;
- db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
-
- unsigned int layer_index = init_layer (layout, si);
- builder.set_target_layer (layer_index);
-
- // The chain of operators for producing the edge pairs
db::EdgePairBuildingHierarchyBuilderShapeReceiver refs;
+ return create_custom_layer (si, &refs, trans);
+}
- // Build the working hierarchy from the recursive shape iterator
- try {
+DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
+{
+ unsigned int layout_index = layout_for_iter (si, trans);
+ db::Layout &layout = m_layouts[layout_index]->layout;
- tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
- db::LayoutLocker ll (&layout, true /*no update*/);
-
- builder.set_shape_receiver (&refs);
- db::RecursiveShapeIterator (si).push (& builder);
- builder.set_shape_receiver (0);
-
- } catch (...) {
- builder.set_shape_receiver (0);
- throw;
- }
-
- return DeepLayer (this, layout_index, layer_index);
+ db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout);
+ return create_custom_layer (si, &refs, trans);
}
void
@@ -1123,6 +1143,12 @@ DeepShapeStore::insert_as_polygons (const DeepLayer &deep_layer, db::Layout *int
s->polygon (poly);
out.insert (poly);
+ } else if (s->is_text ()) {
+
+ db::Text t;
+ s->text (t);
+ out.insert (db::SimplePolygon (t.box ().enlarged (db::Vector (enl, enl))));
+
}
}
diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h
index 3290d5573..9e6d30dad 100644
--- a/src/db/db/dbDeepShapeStore.h
+++ b/src/db/db/dbDeepShapeStore.h
@@ -43,6 +43,9 @@ class DeepShapeStore;
class DeepShapeStoreState;
class Region;
class Edges;
+class EdgePairs;
+class Texts;
+class ShapeCollection;
/**
* @brief Represents a shape collection from the deep shape store
@@ -75,6 +78,24 @@ public:
*/
DeepLayer (const Region ®ion);
+ /**
+ * @brief Conversion operator from texts collection to DeepLayer
+ * This requires the texts to be a DeepTexts. Otherwise, this constructor will assert
+ */
+ DeepLayer (const Texts ®ion);
+
+ /**
+ * @brief Conversion operator from edges collection to DeepLayer
+ * This requires the edges to be a DeepEdges. Otherwise, this constructor will assert
+ */
+ DeepLayer (const Edges ®ion);
+
+ /**
+ * @brief Conversion operator from edge pairs collection to DeepLayer
+ * This requires the edge pairs to be a DeepEdgePairs. Otherwise, this constructor will assert
+ */
+ DeepLayer (const EdgePairs ®ion);
+
/**
* @brief Copy constructor
*/
@@ -338,15 +359,26 @@ public:
* After a flat layer has been created for a region, it can be retrieved
* from the region later with layer_for_flat (region).
*/
- DeepLayer create_from_flat (const db::Edges ®ion, const db::ICplxTrans &trans = db::ICplxTrans ());
+ DeepLayer create_from_flat (const db::Edges &edges, const db::ICplxTrans &trans = db::ICplxTrans ());
/**
- * @brief Gets the layer for a given flat region.
+ * @brief Creates a new layer from a flat text collection (or the text collection is made flat)
+ *
+ * This method is intended for use with singular-created DSS objects (see
+ * singular constructor).
+ *
+ * After a flat layer has been created for a region, it can be retrieved
+ * from the region later with layer_for_flat (region).
+ */
+ DeepLayer create_from_flat (const db::Texts &texts, const db::ICplxTrans &trans = db::ICplxTrans ());
+
+ /**
+ * @brief Gets the layer for a given flat collection (Region, Edges, Texts, EdgePairs)
*
* If a layer has been created for a flat region with create_from_flat, it can be retrieved with this method.
* The first return value is true in this case.
*/
- std::pair layer_for_flat (const db::Region ®ion) const;
+ std::pair