diff --git a/.travis.yml b/.travis.yml
index cec6b84c8..a8a374a71 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,40 +1,43 @@
matrix:
include:
- - os: linux
- dist: trusty # Ubuntu 14.04
- sudo: false
- language: python
- python: '2.6'
+ # python 3 osx
+ - os: osx
+ osx_image: xcode9.4 # macOS 10.13
env:
- MATRIX_EVAL=""
- - os: linux
- dist: trusty # Ubuntu 14.04
- sudo: false
- language: python
- python: '2.7'
+ - ARCHFLAGS="-std=c++11"
+ - PIP_UPDATE="1"
+ - os: osx
+ osx_image: xcode8.3 # macOS 10.12
+ env:
+ - MATRIX_EVAL="brew install python2 || brew link --overwrite python@2" # deficient python2 in travis's xcode8.3 (no ssl)
+ - ARCHFLAGS="-std=c++11"
+ - PIP_UPDATE="1"
+ - os: osx
+ osx_image: xcode8 # macOS 10.11
env:
- MATRIX_EVAL=""
- - os: linux
- dist: trusty # Ubuntu 14.04
- sudo: false
- language: python
- python: '3.3'
+ - ARCHFLAGS="-std=c++11"
+ - PIP_UPDATE="1"
+ # python 2 osx
+ - os: osx
+ osx_image: xcode9.4 # macOS 10.13
env:
- - MATRIX_EVAL=""
- - os: linux
- dist: trusty # Ubuntu 14.04
- sudo: false
- language: python
- python: '3.4'
+ - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
+ - ARCHFLAGS="-std=c++11"
+ - PIP_UPDATE="1"
+ - os: osx
+ osx_image: xcode8.3 # macOS 10.12
env:
- - MATRIX_EVAL=""
- - os: linux
- dist: trusty # Ubuntu 14.04
- sudo: false
- language: python
- python: '3.5'
+ - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
+ - ARCHFLAGS="-std=c++11"
+ - PIP_UPDATE="1"
+ - os: osx
+ osx_image: xcode8 # macOS 10.11
env:
- - MATRIX_EVAL=""
+ - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
+ - ARCHFLAGS="-std=c++11"
+ - PIP_UPDATE="1"
- os: linux
dist: trusty # Ubuntu 14.04
sudo: false
@@ -42,25 +45,59 @@ matrix:
python: '3.6'
env:
- MATRIX_EVAL=""
- - os: osx
- osx_image: xcode9.3 # macOS 10.13
+ - PIP_UPDATE="1"
+ - os: linux
+ dist: trusty # Ubuntu 14.04
+ sudo: false
+ language: python
+ python: '2.7'
env:
- MATRIX_EVAL=""
- - os: osx
- osx_image: xcode8.3 # macOS 10.12
+ - PIP_UPDATE="1"
+ - os: linux
+ dist: trusty # Ubuntu 14.04
+ sudo: false
+ language: python
+ python: '2.6'
env:
- MATRIX_EVAL=""
- - os: osx
- osx_image: xcode8 # macOS 10.11
+ - PIP_UPDATE="0" # setuptools installed from last pip has syntax error on py 2.6
+ - os: linux
+ dist: trusty # Ubuntu 14.04
+ sudo: false
+ language: python
+ python: '3.3'
env:
- MATRIX_EVAL=""
+ - PIP_UPDATE="1"
+ - os: linux
+ dist: trusty # Ubuntu 14.04
+ sudo: false
+ language: python
+ python: '3.4'
+ env:
+ - MATRIX_EVAL=""
+ - PIP_UPDATE="1"
+ - os: linux
+ dist: trusty # Ubuntu 14.04
+ sudo: false
+ language: python
+ python: '3.5'
+ env:
+ - MATRIX_EVAL=""
+ - PIP_UPDATE="1"
before_install:
- env
- rvm install ruby --latest
- gem install dropbox-deployment
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; fi
- eval "${MATRIX_EVAL}"
+ - if [ "${PIP_UPDATE}" == "1" ]; then
+ pip --version;
+ pip install --upgrade pip || sudo pip install --upgrade pip;
+ pip --version;
+ pip install --upgrade setuptools wheel || sudo pip install --upgrade setuptools wheel;
+ fi
- python -c "import distutils.sysconfig as sysconfig; print(sysconfig.__file__)"
install:
diff --git a/Changelog b/Changelog
index bba18b673..2ff284e28 100644
--- a/Changelog
+++ b/Changelog
@@ -1,8 +1,66 @@
-0.26 (2018-06-23):
-* Enhancement: Standalone Python modules provide
+0.26 (xxxx-xx-xx):
+* Enhancement: Standalone Python modules provided
For details see:
https://github.com/klayoutmatthias/klayout/wiki/klayout---Standalone-KLayout-Python-Module
+0.25.5 (xxxx-xx-xx):
+
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/162
+ GDS2 LIBNAME was not maintained on "File/Save".
+
+0.25.4 (2018-08-25):
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/121
+ Issue with multiple reads of GDS2 layouts including PCells
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/134
+ Error in cell.fill_region caused by big polygon with
+ spikes
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/139
+ Libraries have not been reassigned when loading a GDS file
+ from command line (does not happen on File/Open)
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/141
+ Issue with RBA::QHostAddress (ambiguous overload) on Qt5
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/142
+ Issue with RBA::RecursiveShapeIterator#region=
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/144
+ The Salt package descriptions are not shown with Motif
+ style
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/148
+ Wrong font is used
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/152
+ Shapes#size reported a wrong shape count in viewer mode
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/153
+ Application crash when editing guiding shape properties
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/155
+ Program freezes after replacing nothing by something in
+ Macro editor
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/157
+ "Replace cell with ..." rejected cell names with a library
+ prefix
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/158
+ Repaint issue on cell context
+* Bugfix: https://github.com/klayoutmatthias/klayout/issues/159
+ Tech specific macros and DRC scripts were not shown in tech
+ manager
+* Bugfix: 8 bit indexed GIF images can be used for package icons now
+* Enhancement: Provide a way to specify the type of a macro
+ This feature is mainly useful for command line arguments.
+ If you run KLayout with "klayout -b -r myscript"
+ it will not be able to determine the type of macro without
+ a suffix.
+
+ You can now explicitly specify a certain type by
+ giving the suffix implicitly like: "klayout -b -r myscript[rb]"
+ This will read "myscript" but pretend it was "myscript.rb"
+ and execute it as Ruby script.
+
+ This feature is handy if you need to run a file with a
+ specific interpreter but cannot modify the file name.
+* Enhancement: Selection now shows PCell display names
+ Before, the internal name was shown for instances
+* Enhancement: There is an option in the View menu to show or hide markers
+ Markers may hide layout under them. With this feature you can
+ quickly disable all markers and the layout becomes visible.
+
0.25.3 (2018-05-03):
* Enhancement: Compile option to use libcurl instead of QtNetwork
diff --git a/Changelog.Debian b/Changelog.Debian
index 47de11253..979733773 100644
--- a/Changelog.Debian
+++ b/Changelog.Debian
@@ -1,9 +1,9 @@
-klayout (0.26-1) unstable; urgency=low
+klayout (0.25.4-1) unstable; urgency=low
* New features and bugfixes
- See changelog
- -- Matthias Köfferlein Sun, 24 Jun 2018 15:43:26 +0200
+ -- Matthias Köfferlein Sat, 25 Aug 2018 23:15:23 +0200
klayout (0.25.3-1) unstable; urgency=low
diff --git a/macbuild/ReadMe.md b/macbuild/ReadMe.md
index 65be120bf..f03e3ca97 100644
--- a/macbuild/ReadMe.md
+++ b/macbuild/ReadMe.md
@@ -97,6 +97,9 @@ Homebrew's installation of python3 (`brew install python3`) places a `Python.fra
```
# Build step
./build4mac.py -p B36 -q Qt5Brew
+# build with log
+./build4mac.py -p B36 -q Qt5Brew 2>&1 | tee qt5.build.macos-HighSierra-release-version.log
+
# Deploy step
./build4mac.py -p B36 -q Qt5Brew -y # normal deploy
diff --git a/macbuild/Resources/klayout_console b/macbuild/Resources/klayout_console
new file mode 100644
index 000000000..2a4319e34
--- /dev/null
+++ b/macbuild/Resources/klayout_console
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+if [ "$1" != "" ]; then
+/Applications/klayout.app/Contents/MacOS/klayout $1 -r /Applications/klayout.app/Contents/MacOS/start-console.py
+else
+/Applications/klayout.app/Contents/MacOS/klayout -z -r /Applications/klayout.app/Contents/MacOS/start-console.py
+fi
diff --git a/macbuild/Resources/start-console.py b/macbuild/Resources/start-console.py
new file mode 100644
index 000000000..5880e2eed
--- /dev/null
+++ b/macbuild/Resources/start-console.py
@@ -0,0 +1,16 @@
+#!/Applications/klayout.app/Contents/MacOS/klayout -b -r
+import readline
+import code
+import sys
+import os
+pwd = os.getcwd()
+sys.path.append(pwd)
+
+variables = globals().copy()
+variables.update(locals())
+shell = code.InteractiveConsole(variables)
+cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
+banner = "Python %s on %s\n%s\n(%s)" % (sys.version, sys.platform,
+ cprt, "KLayout Python Console")
+exit_msg = 'now exiting %s...' % "KLayout Python Console"
+shell.interact(banner, exit_msg)
diff --git a/macbuild/build4mac.py b/macbuild/build4mac.py
index e9200c88a..907226d2e 100755
--- a/macbuild/build4mac.py
+++ b/macbuild/build4mac.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===============================================================================
@@ -125,7 +125,7 @@ def SetGlobals():
ModulePython = "PythonYosemite"
elif Platform == "ElCapitan":
ModuleRuby = "RubyElCapitan"
- ModulePytyon = "PythonElCapitan"
+ ModulePython = "PythonElCapitan"
elif Platform == "Sierra":
ModuleRuby = "RubySierra"
ModulePython = "PythonSierra"
@@ -538,8 +538,8 @@ def DeployBinariesForBundle():
if not DeploymentF and not DeploymentP:
return 1
if DeploymentF and NonOSStdLang:
- print( "WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
- print( " Use <-Y|--DEPLOY> instead", file=sys.stderr )
+ print( " WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
+ print( " Consider using <-Y|--DEPLOY> instead", file=sys.stderr )
#return 1
if not os.path.isfile(MacBuildLog):
print( "!!! Build log file <%s> does not present !!!" % MacBuildLog, file=sys.stderr )
@@ -756,7 +756,6 @@ def DeployBinariesForBundle():
os.chdir(ProjectDir)
os.chdir(MacPkgDir)
command = "%s %s %s" % ( deploytool, app_bundle, options )
- print(command)
if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to deploy applications on OSX !!!"
print( msg, file=sys.stderr )
@@ -764,43 +763,111 @@ def DeployBinariesForBundle():
os.chdir(ProjectDir)
return 1
- deploymentPython = False
- if deploymentPython:
- # TODO Code incomplete! To be finished.
- from macbuild.build4mac_util import WalkFrameworkPaths, PerformChanges, DetectChanges
-
- bundlePath = 'qt5.pkg.macos-HighSierra-release/klayout.app'
- bundleExecPathAbs = os.getcwd() + '/%s/Contents/MacOS/' % bundlePath
-
- # rsync -a --safe-links /usr/local/opt/python/Frameworks/Python.framework/ qt5.pkg.macos-HighSierra-release/klayout.app/Contents/Frameworks/Python.framework
- # cp -RL /usr/local/opt/python/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages qt5.pkg.macos-HighSierra-release/klayout.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/
- # rm -rf qt5.pkg.macos-HighSierra-release/klayout.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/test
+ deploymentPython = True
+ if deploymentPython and NonOSStdLang:
+ from build4mac_util import WalkFrameworkPaths, PerformChanges, DetectChanges
+ bundlePath = AbsMacPkgDir + '/klayout.app'
+ # bundlePath = os.getcwd() + '/qt5.pkg.macos-HighSierra-release/klayout.app'
+ bundleExecPathAbs = '%s/Contents/MacOS/' % bundlePath
+ pythonOriginalFrameworkPath = '/usr/local/opt/python3/Frameworks/Python.framework'
pythonFrameworkPath = '%s/Contents/Frameworks/Python.framework' % bundlePath
+
+ print(" [8.1] Deploying Python from %s ..." % pythonOriginalFrameworkPath)
+ print(" [1] Copying Python Framework")
+ shell_commands = list()
+ shell_commands.append("rm -rf %s" % pythonFrameworkPath)
+ shell_commands.append("rsync -a --safe-links %s/ %s" % (pythonOriginalFrameworkPath, pythonFrameworkPath))
+ shell_commands.append("mkdir %s/Versions/3.7/lib/python3.7/site-packages/" % pythonFrameworkPath)
+ shell_commands.append("cp -RL %s/Versions/3.7/lib/python3.7/site-packages/{pip*,pkg_resources,setuptools*,wheel*} " % pythonOriginalFrameworkPath +
+ "%s/Versions/3.7/lib/python3.7/site-packages/" % pythonFrameworkPath)
+ shell_commands.append("rm -rf %s/Versions/3.7/lib/python3.7/test" % pythonFrameworkPath)
+ shell_commands.append("rm -rf %s/Versions/3.7/Resources" % pythonFrameworkPath)
+ shell_commands.append("rm -rf %s/Versions/3.7/bin" % pythonFrameworkPath)
+
+ for command in shell_commands:
+ if subprocess.call( command, shell=True ) != 0:
+ msg = "command failed: %s"
+ print( msg % command, file=sys.stderr )
+ exit(1)
+
+ shutil.copy2( sourceDir2 + "/start-console.py", targetDirM )
+ shutil.copy2( sourceDir2 + "/klayout_console", targetDirM )
+ os.chmod( targetDirM + "/klayout_console", 0o0755 )
+
+ print(" [2] Relinking dylib dependencies inside Python.framework")
+ print(" [2.1] Patching Python Framework")
depdict = WalkFrameworkPaths(pythonFrameworkPath)
-
- pythonOriginalFrameworkPath = '/usr/local/opt/python/Frameworks/Python.framework'
appPythonFrameworkPath = '@executable_path/../Frameworks/Python.framework/'
- PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
-
- klayoutPath = bundleExecPathAbs
- depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'klayout$')
- PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
-
- klayoutPath = bundleExecPathAbs + '../Frameworks'
- depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'libklayout')
- PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
-
+ PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
+ print(" [2.2] Patching /usr/local/opt/ libs")
usrLocalPath = '/usr/local/opt/'
appUsrLocalPath = '@executable_path/../Frameworks/'
- depdict = WalkFrameworkPaths(pythonFrameworkPath)
- PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs)
+ replacePairs = [(usrLocalPath, appUsrLocalPath, True)]
+ depdict = WalkFrameworkPaths(pythonFrameworkPath, search_path_filter=r'\t+/usr/local/(opt|Cellar)')
+ PerformChanges(depdict, replacePairs, bundleExecPathAbs)
- # usrLocalPath = '/usr/local/lib/'
- # appUsrLocalPath = '@executable_path/../Frameworks/'
- # depdict = WalkFrameworkPaths(pythonFrameworkPath)
- # PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs)
+ print(" [2.3] Patching openssl, gdbm, readline, sqlite, tcl-tk, xz")
+ usrLocalPath = '/usr/local/opt'
+ appUsrLocalPath = '@executable_path/../Frameworks/'
+ replacePairs = [(usrLocalPath, appUsrLocalPath, True)]
+ replacePairs.extend([(openssl_version, '@executable_path/../Frameworks/openssl', True)
+ for openssl_version in glob.glob('/usr/local/Cellar/openssl/*')])
+ depdict = WalkFrameworkPaths([pythonFrameworkPath + '/../openssl',
+ pythonFrameworkPath + '/../gdbm',
+ pythonFrameworkPath + '/../readline',
+ pythonFrameworkPath + '/../sqlite',
+ pythonFrameworkPath + '/../tcl-tk',
+ pythonFrameworkPath + '/../xz'], search_path_filter=r'\t+/usr/local/(opt|Cellar)')
+
+ PerformChanges(depdict, replacePairs, bundleExecPathAbs)
+
+ print(" [3] Relinking dylib dependencies for klayout")
+ klayoutPath = bundleExecPathAbs
+ depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'klayout$')
+ PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
+
+ libKlayoutPath = bundleExecPathAbs + '../Frameworks'
+ depdict = WalkFrameworkPaths(libKlayoutPath, filter_regex=r'libklayout')
+ PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], bundleExecPathAbs)
+
+ print(" [4] Patching site.py, pip/, and distutils/")
+ site_module = "%s/Versions/3.7/lib/python3.7/site.py" % pythonFrameworkPath
+ with open(site_module, 'r') as site:
+ buf = site.readlines()
+ with open(site_module, 'w') as site:
+ import re
+ for line in buf:
+ # This will fool pip into thinking it's inside a virtual environment
+ # and install new packates to the correct site-packages
+ if re.match("^PREFIXES", line) is not None:
+ line = line + "sys.real_prefix = sys.prefix\n"
+ # do not allow installation in the user folder.
+ if re.match("^ENABLE_USER_SITE", line) is not None:
+ line = "ENABLE_USER_SITE = False\n"
+ site.write(line)
+
+ pip_module = "%s/Versions/3.7/lib/python3.7/site-packages/pip/__init__.py" % pythonFrameworkPath
+ with open(pip_module, 'r') as pip:
+ buf = pip.readlines()
+ with open(pip_module, 'w') as pip:
+ import re
+ for line in buf:
+ # this will reject user's configuration of pip, forcing the isolated mode
+ line = re.sub("return isolated$", "return isolated or True", line)
+ pip.write(line)
+
+ distutilsconfig = "%s/Versions/3.7/lib/python3.7/distutils/distutils.cfg" % pythonFrameworkPath
+ with open(distutilsconfig, 'r') as file:
+ buf = file.readlines()
+ with open(distutilsconfig, 'w') as file:
+ import re
+ for line in buf:
+ # This will cause all packages to be installed to sys.prefix
+ if re.match('prefix=', line) is not None:
+ continue
+ file.write(line)
else:
print( " [8] Skipped deploying Qt's Frameworks ..." )
@@ -925,9 +992,7 @@ def main():
#----------------------------------------------------------
ret = RunMainBuildBash()
if not DeploymentF and not DeploymentP:
- if ret == 0:
- sys.exit(0)
- else:
+ if not ret == 0:
sys.exit(1)
else:
#----------------------------------------------------------
@@ -944,6 +1009,7 @@ def main():
# to make "KLayoutEditor.app" and "KLayoutViewer.app"
#----------------------------------------------------------
ret2 = DeployScriptBundles()
+
if not ret2 == 0:
sys.exit(1)
else:
diff --git a/macbuild/build4mac_util.py b/macbuild/build4mac_util.py
index c9372dd19..17aa26a2c 100755
--- a/macbuild/build4mac_util.py
+++ b/macbuild/build4mac_util.py
@@ -18,14 +18,6 @@ import string
import subprocess
import shutil
-CAN_DEPLOY_PYTHON = False
-try:
- from pathlib import Path
- Path('~').expanduser()
- CAN_DEPLOY_PYTHON = True
-except (ImportError,AttributeError): # python2
- print("Warning: Cannot import pathlib, use python3 if you need python deployment.")
-
#-------------------------------------------------------------------------------
## To import global dictionaries of different modules
#-------------------------------------------------------------------------------
@@ -181,176 +173,167 @@ def SetChangeLibIdentificationName( executable, relativedir ):
# for-lib
return 0
-# TODO: undocumented
-if CAN_DEPLOY_PYTHON:
- def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'):
- NOTHINGTODO = [] # return empty list if nothing to do.
- dylibPath = str(Path(dylibPath))
- cmdNameId = XcodeToolChain['nameID']
- cmdNameChg = XcodeToolChain['nameCH']
- otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex)
- otoolOut = os.popen( otoolCm ).read()
- exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
- keys = exedepdic.keys()
- deplibs = exedepdic[ list(keys)[0] ]
+def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'):
+ NOTHINGTODO = [] # return empty list if nothing to do.
+ cmdNameId = XcodeToolChain['nameID']
+ cmdNameChg = XcodeToolChain['nameCH']
+ otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex)
+ otoolOut = os.popen( otoolCm ).read()
+ exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
+ keys = exedepdic.keys()
+ deplibs = exedepdic[ list(keys)[0] ]
- if depth < 5:
- if len(deplibs) > 0:
- for idx, lib in enumerate(deplibs):
- lib = str(Path(lib))
- if lib != list(keys)[0]:
- deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex)
- else:
- return NOTHINGTODO
- if depth == 0:
- return deplibs
- return exedepdic
+ if depth < 5:
+ if len(deplibs) > 0:
+ for idx, lib in enumerate(deplibs):
+ lib = str(lib)
+ if lib != list(keys)[0]:
+ deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex)
+ if depth == 0:
+ return deplibs
+ return exedepdic
+ else:
+ raise RuntimeError("Exceeded maximum recursion depth.")
+
+def WalkFrameworkPaths(frameworkPaths, filter_regex=r'\.(so|dylib)$', search_path_filter=r'\t+/usr/local/opt'):
+
+ if isinstance(frameworkPaths, str):
+ frameworkPathsIter = [frameworkPaths]
+ else:
+ frameworkPathsIter = frameworkPaths
+
+ dependency_dict = dict()
+
+ for frameworkPath in frameworkPathsIter:
+ # print("Calling:", 'find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex))
+ find_grep_results = os.popen('find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)).read().split('\n')
+ framework_files = filter(lambda x: x != '',
+ map(lambda x: x.strip(),
+ find_grep_results))
+
+ dependency_dict[frameworkPath] = list()
+ for idx, file in enumerate(framework_files):
+ dict_file = {file: WalkLibDependencyTree(file, filter_regex=search_path_filter)}
+ dependency_dict[frameworkPath].append(dict_file)
+ return dependency_dict
+
+def WalkDictTree(dependencyDict, visited_files):
+ libNameChanges = list()
+ for lib, dependencies in dependencyDict.items():
+ if lib in visited_files:
+ continue
+
+ dependency_list = list()
+ if isinstance(dependencies, list):
+ for deplib in dependencies:
+ if isinstance(deplib, str):
+ dependency_list.append(deplib)
+ if deplib not in visited_files:
+ visited_files.append(deplib)
+ elif isinstance(deplib, dict):
+ dependency_list.append(next(iter(deplib)))
+ libNameChanges.extend(WalkDictTree(deplib, visited_files))
+ else:
+ #raise RuntimeError("Unexpected value: %s" % deplib)
+ pass
else:
- raise RuntimeError("Exceeded maximum recursion depth.")
+ raise RuntimeError("Unexpected value: %s" % dependencies)
+ if len(dependency_list) > 0:
+ libNameChanges.append((lib, dependency_list))
+ else:
+ libNameChanges.append((lib, ))
+ visited_files.append(lib)
+ return libNameChanges
- def WalkFrameworkPaths(frameworkPaths, filter_regex=r'\.(so|dylib)$'):
- try:
- frameworkPathsIter = iter(frameworkPaths)
- except TypeError:
- frameworkPathsIter = [frameworkPaths]
- dependency_dict = dict()
+def FindFramework(path, root_path):
+ relPath = os.path.relpath(path, root_path)
+ return os.path.join(root_path, relPath.split(os.sep)[0])
+def ResolveExecutablePath(path, executable_path):
+ """ Transforms @executable_path into executable_path"""
+ p = path.replace("@executable_path", "/%s/" % executable_path)
+ return p
- for frameworkPath in frameworkPaths:
- frameworkPath = str(Path(frameworkPath))
- find_grep_results = os.popen('find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)).read().split('\n')
- framework_files = filter(lambda x: x != '',
- map(lambda x: x.strip(),
- find_grep_results))
+def DetectChanges(frameworkDependencyDict):
+ visited_files = list()
+ libNameChanges = list()
+ for framework, libraries in frameworkDependencyDict.items():
+ for libraryDict in libraries:
+ libNameChanges.extend(WalkDictTree(libraryDict, visited_files))
+ # Changes are stored in libNameChanges in the form of ('lib.dylib', ['dep1.dylib', ...])
- dependency_dict[frameworkPath] = list()
- for idx, file in enumerate(framework_files):
- dict_file = {file: WalkLibDependencyTree(file)}
- dependency_dict[frameworkPath].append(dict_file)
- return dependency_dict
+ return libNameChanges
- def WalkDictTree(dependencyDict, visited_files):
- libNameChanges = list()
- for lib, dependencies in dependencyDict.items():
- if lib in visited_files:
- continue
+def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout"):
+ libNameChanges = DetectChanges(frameworkDependencyDict)
+ cmdNameId = XcodeToolChain['nameID']
+ cmdNameChg = XcodeToolChain['nameCH']
- dependency_list = list()
- if isinstance(dependencies, list):
- for deplib in dependencies:
- if isinstance(deplib, str):
- dependency_list.append(deplib)
- if deplib not in visited_files:
- visited_files.append(deplib)
- elif isinstance(deplib, dict):
- dependency_list.append(str(next(iter(deplib))))
- libNameChanges.extend(WalkDictTree(deplib, visited_files))
+ if replaceFromToPairs is not None:
+ for libNameChange in libNameChanges:
+ libNameChangeIterator = iter(libNameChange)
+ lib = next(libNameChangeIterator)
+ try:
+ dependencies = next(libNameChangeIterator)
+ except StopIteration:
+ dependencies = list()
+ for replaceFrom, replaceTo, libdir in replaceFromToPairs:
+ fileName = ResolveExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
+ if fileName.startswith('/usr'):
+ # print(f'skipping fileName: {fileName}')
+ continue
+
+ if lib.find(replaceFrom) >= 0:
+ if libdir:
+ frameworkPath = FindFramework(lib, replaceFrom)
else:
- #raise RuntimeError("Unexpected value: %s" % deplib)
- pass
- else:
- raise RuntimeError("Unexpected value: %s" % dependencies)
- if len(dependency_list) > 0:
- libNameChanges.append((lib, dependency_list))
- else:
- libNameChanges.append((lib, ))
- visited_files.append(lib)
- return libNameChanges
+ frameworkPath = lib
+ destFrameworkPath = frameworkPath.replace(replaceFrom, replaceTo)
+ destFrameworkPath = ResolveExecutablePath(destFrameworkPath, executable_path)
- def FindFramework(path, root_path):
- path = Path(path)
- root_path = Path(root_path)
- relPath = path.relative_to(root_path)
- return str(root_path / relPath.parts[0])
+ if not os.path.exists(fileName):
+ print (lib.replace(replaceFrom, replaceTo), "DOES NOT EXIST")
+ print ("COPY", frameworkPath, " -> ", destFrameworkPath)
+ shutil.copytree(frameworkPath, destFrameworkPath)
- def ReplaceExecutablePath(path, executable_path):
- executable_path = str(executable_path)
- p = Path(str(path).replace("@executable_path", "/%s/" % executable_path))
- return p
+ nameId = lib.replace(replaceFrom, replaceTo)
+ command = "%s %s %s" % ( cmdNameId, nameId, fileName )
+ if not os.access(fileName, os.W_OK):
+ command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
+ # print("\t%s" % command)
+ if subprocess.call( command, shell=True ) != 0:
+ msg = "!!! Failed to set the new identification name to <%s> !!!"
+ print( msg % fileName, file=sys.stderr )
+ return 1
- def FileExists(file_path, executable_path):
- p = ReplaceExecutablePath(file_path, executable_path)
- return p.exists()
+ for dependency in dependencies:
+ if dependency.find(replaceFrom) >= 0:
+ print("\tIn:", fileName)
+ print("\tRENAME", dependency, " -> ", dependency.replace(replaceFrom, replaceTo))
- def DetectChanges(frameworkDependencyDict):
- visited_files = list()
- libNameChanges = list()
- for framework, libraries in frameworkDependencyDict.items():
- for libraryDict in libraries:
- libNameChanges.extend(WalkDictTree(libraryDict, visited_files))
- # Changes are stored in libNameChanges in the form of ('lib.dylib', ['dep1.dylib', ...])
-
- return libNameChanges
-
- def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout", libdir=False):
- libNameChanges = DetectChanges(frameworkDependencyDict)
- cmdNameId = XcodeToolChain['nameID']
- cmdNameChg = XcodeToolChain['nameCH']
-
- if replaceFromToPairs is not None:
- for libNameChange in libNameChanges:
- libNameChangeIterator = iter(libNameChange)
- lib = next(libNameChangeIterator)
- try:
- dependencies = next(libNameChangeIterator)
- except StopIteration:
- dependencies = list()
- for replaceFrom, replaceTo in replaceFromToPairs:
- replaceFrom = str(Path(replaceFrom))
- replaceTo = str(Path(replaceTo))
-
- if lib.find(replaceFrom) >= 0:
- if libdir:
- frameworkPath = FindFramework(lib, replaceFrom)
- else:
- frameworkPath = lib
- destFrameworkPath = frameworkPath.replace(replaceFrom, replaceTo)
- destFrameworkPath = ReplaceExecutablePath(destFrameworkPath, executable_path)
- if not FileExists(lib.replace(replaceFrom, replaceTo), executable_path):
- print (lib.replace(replaceFrom, replaceTo), "DOES NOT EXIST")
- print ("COPY", frameworkPath, " -> ", destFrameworkPath)
- shutil.copytree(frameworkPath, destFrameworkPath)
-
- fileName = ReplaceExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
- nameId = lib.replace(replaceFrom, replaceTo)
- command = "%s %s %s" % ( cmdNameId, nameId, fileName )
- if not os.access(fileName, os.W_OK):
+ # Try changing id first
+ nameId = dependency.replace(replaceFrom, replaceTo)
+ command = "%s %s %s" % ( cmdNameId, nameId, fileName)
+ if not os.access(str(fileName), os.W_OK):
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
- print("\t%s" % command)
+ # print("\t%s" % command)
if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % fileName, file=sys.stderr )
return 1
- fileName = ReplaceExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path)
- for dependency in dependencies:
- if dependency.find(replaceFrom) >= 0:
- print("In:", fileName)
- print("\tRENAME", dependency, " -> ", dependency.replace(replaceFrom, replaceTo))
+ # Rename dependencies
+ nameOld = dependency
+ nameNew = dependency.replace(replaceFrom, replaceTo)
+ command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, str(fileName) )
+ if not os.access(str(fileName), os.W_OK):
+ command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
- # Try changing id first
- nameId = dependency.replace(replaceFrom, replaceTo)
- command = "%s %s %s" % ( cmdNameId, nameId, fileName )
- if not os.access(fileName, os.W_OK):
- command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
- print("\t%s" % command)
- if subprocess.call( command, shell=True ) != 0:
- msg = "!!! Failed to set the new identification name to <%s> !!!"
- print( msg % fileName, file=sys.stderr )
- return 1
-
- # Rename dependencies
- nameOld = dependency
- nameNew = dependency.replace(replaceFrom, replaceTo)
- command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, fileName )
- if not os.access(fileName, os.W_OK):
- command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName)
-
- print("\t%s" % command)
- if subprocess.call( command, shell=True ) != 0:
- msg = "!!! Failed to set the new identification name to <%s> !!!"
- print( msg % fileName, file=sys.stderr )
- return 1
+ # print("\t%s" % command)
+ if subprocess.call( command, shell=True ) != 0:
+ msg = "!!! Failed to set the new identification name to <%s> !!!"
+ print( msg % fileName, file=sys.stderr )
+ return 1
#------------------------------------------------------------------------------
diff --git a/scripts/makedeb.sh b/scripts/makedeb.sh
index 2ced7ad03..10cda0a29 100755
--- a/scripts/makedeb.sh
+++ b/scripts/makedeb.sh
@@ -89,10 +89,15 @@ cd ..
mkdir -p makedeb-tmp/${sharedir}/doc/klayout
mkdir -p makedeb-tmp/${sharedir}/applications
mkdir -p makedeb-tmp/${sharedir}/pixmaps
+<<<<<<< HEAD
mkdir -p makedeb-tmp/${libdir}/db_plugins
mkdir -p makedeb-tmp/${libdir}/lay_plugins
mkdir -p makedeb-tmp/${pylibdir}
mkdir -p makedeb-tmp/${bindir}
+=======
+mkdir -p makedeb-tmp/${bindir}
+mkdir -p makedeb-tmp/${libdir}
+>>>>>>> master
cp etc/klayout.desktop makedeb-tmp/${sharedir}/applications
cp etc/logo.png makedeb-tmp/${sharedir}/pixmaps
@@ -103,10 +108,13 @@ cp COPYRIGHT makedeb-tmp/${sharedir}/doc/klayout/copyright
cp -pd $bininstdir/strm* makedeb-tmp/${bindir}
cp -pd $bininstdir/klayout makedeb-tmp/${bindir}
cp -pd $bininstdir/lib*so* makedeb-tmp/${libdir}
+<<<<<<< HEAD
cp -pd $bininstdir/db_plugins/lib*so* makedeb-tmp/${libdir}/db_plugins
cp -pd $bininstdir/lay_plugins/lib*so* makedeb-tmp/${libdir}/lay_plugins
cp -pd $bininstdir/pymod/klayout/*so makedeb-tmp/${pylibdir}
cp -pd $bininstdir/pymod/klayout/*py makedeb-tmp/${pylibdir}
+=======
+>>>>>>> master
cd makedeb-tmp
@@ -131,9 +139,12 @@ echo "Modifying control file .."
strip ${bindir}/*
strip ${libdir}/*.so*
+<<<<<<< HEAD
strip ${pylibdir}/*.so
strip ${libdir}/db_plugins/*.so*
strip ${libdir}/lay_plugins/*.so*
+=======
+>>>>>>> master
size=`du -ck usr | grep total | sed "s/ *total//"`
diff --git a/scripts/mkqtdecl5/mkqtdecl.conf b/scripts/mkqtdecl5/mkqtdecl.conf
index 224b69d5f..097ebb151 100644
--- a/scripts/mkqtdecl5/mkqtdecl.conf
+++ b/scripts/mkqtdecl5/mkqtdecl.conf
@@ -864,10 +864,10 @@ no_imports "QAbstractXmlNodeModel" # base class is QSharedData which is not ava
# QtNetwork
drop_method "QUrlInfo", /QUrlInfo::QUrlInfo\(.*permissions/ # too many arguments (13)
-drop_method "QHostAddress", /QHostAddress::QHostAddress\(\s*quint8\s*\*/ # requires char *, a string version is available for IPv6
+drop_method "QHostAddress", /QHostAddress::QHostAddress\(\s*(const\s*)?quint8\s*\*/ # requires char *, a string version is available for IPv6
drop_method "QHostAddress", /QHostAddress::QHostAddress\(\s*const\s+QIPv6Address/ # requires QIPv6Address struct, a string version is available for IPv6
drop_method "QHostAddress", /QHostAddress::QHostAddress\(\s*const\s+sockaddr/ # requires sockaddr struct, a string version is available for IPv6
-drop_method "QHostAddress", /QHostAddress::setAddress\(\s*quint8\s*\*/ # requires char *, a string version is available for IPv6
+drop_method "QHostAddress", /QHostAddress::setAddress\(\s*(const\s*)?quint8\s*\*/ # requires char *, a string version is available for IPv6
drop_method "QHostAddress", /QHostAddress::setAddress\(\s*const\s+QIPv6Address/ # requires QIPv6Address struct, a string version is available for IPv6
drop_method "QHostAddress", /QHostAddress::setAddress\(\s*const\s+sockaddr/ # requires sockaddr struct, a string version is available for IPv6
drop_method "QHostAddress", /QHostAddress::toIPv6Address\(/ # requires QIPv6Address struct
diff --git a/scripts/rpm-data/klayout.spec b/scripts/rpm-data/klayout.spec
index e6c74036a..bf9826b85 100644
--- a/scripts/rpm-data/klayout.spec
+++ b/scripts/rpm-data/klayout.spec
@@ -77,6 +77,14 @@ Requires: libqt4-x11 >= 4.8.7
%define pylib %{python3_sitearch}
%endif
+%if "%{target_system}" == "opensuse15"
+# OpenSuSE Leap 15 requirements
+Requires: ruby >= 2.5
+Requires: python3 >= 3.6
+Requires: libqt4-x11 >= 4.8.7
+%define buildopt -j2
+%endif
+
%description
Mask layout viewer and editor for the chip design engineer.
diff --git a/setup.py b/setup.py
index a9a33b99b..122bfda60 100644
--- a/setup.py
+++ b/setup.py
@@ -59,6 +59,49 @@ import glob
import os
import platform
import distutils.sysconfig as sysconfig
+from distutils.errors import CompileError
+import multiprocessing
+N_cores = multiprocessing.cpu_count()
+
+
+# monkey-patch for parallel compilation
+# from https://stackoverflow.com/questions/11013851/speeding-up-build-process-with-distutils
+def parallelCCompile(self, sources, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None):
+ # those lines are copied from distutils.ccompiler.CCompiler directly
+ macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
+ output_dir, macros, include_dirs, sources, depends, extra_postargs)
+ cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
+ # parallel code
+
+ N = min(N_cores, len(objects) // 2, 8) # number of parallel compilations
+ N = max(N, 1)
+ print("Compiling with", N, "threads.")
+ import multiprocessing.pool
+
+ def _single_compile(obj):
+ try:
+ src, ext = build[obj]
+ except KeyError:
+ return
+ n_tries = 2
+ while n_tries > 0:
+ try:
+ self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
+ except CompileError:
+ n_tries -= 1
+ print("Building", obj, "has failed. Trying again.")
+ else:
+ break
+ # convert to list, imap is evaluated on-demand
+ list(multiprocessing.pool.ThreadPool(N).imap(_single_compile, objects))
+ return objects
+
+
+# only if python version > 2.6, somehow the travis compiler hangs in 2.6
+import sys
+if sys.version_info[0] * 10 + sys.version_info[1] > 26:
+ import distutils.ccompiler
+ distutils.ccompiler.CCompiler.compile = parallelCCompile
# ----------------------------------------------------------------------------------------
@@ -301,6 +344,7 @@ rdb = Extension(config.root + '.rdb',
# Core setup function
if __name__ == '__main__':
+ print("Number of cores", N_cores)
setup(name=config.root,
version=config.version(),
description='KLayout standalone Python package',
diff --git a/src/buddies/unit_tests/bdStrmrunTests.cc b/src/buddies/unit_tests/bdStrmrunTests.cc
index 60187733b..4bf980501 100644
--- a/src/buddies/unit_tests/bdStrmrunTests.cc
+++ b/src/buddies/unit_tests/bdStrmrunTests.cc
@@ -30,7 +30,7 @@ TEST(1)
std::string fp (tl::testsrc ());
fp += "/testdata/bd/strmrun.py";
- std::string path = tl::combine_path (".", "strmrun ") + fp;
+ std::string path = tl::combine_path (tl::get_inst_path (), "strmrun ") + fp;
tl::InputPipe pipe (path);
tl::InputStream is (pipe);
std::string data = is.read_all ();
diff --git a/src/db/db/dbEdge.cc b/src/db/db/dbEdge.cc
index 3237e6582..3af27263f 100644
--- a/src/db/db/dbEdge.cc
+++ b/src/db/db/dbEdge.cc
@@ -22,6 +22,41 @@
#include "dbEdge.h"
+#include "tlLongInt.h"
+
+namespace db
+{
+
+/**
+ * @brief Computes the gcd of two numbers
+ */
+template
+inline C gcd (C a, C b)
+{
+ while (b != 0) {
+ a %= b;
+ std::swap (a, b);
+ }
+ return a;
+}
+
+#if defined(__SIZEOF_INT128__)
+typedef __int128 a2_type;
+#else
+// fallback to long_int in case the __int128 isn't defined
+typedef tl::long_int<4, uint32_t, uint64_t> a2_type;
+#endif
+
+db::Coord div_exact (db::Coord a, db::coord_traits::area_type b, db::coord_traits::area_type d)
+{
+ if (a < 0) {
+ return -db::Coord ((a2_type (-a) * a2_type (b) + a2_type (d / 2)) / a2_type (d));
+ } else {
+ return db::Coord ((a2_type (a) * a2_type (b) + a2_type ((d - 1) / 2)) / a2_type (d));
+ }
+}
+
+}
namespace tl
{
diff --git a/src/db/db/dbEdge.h b/src/db/db/dbEdge.h
index 29b6bd477..15d0cbcdf 100644
--- a/src/db/db/dbEdge.h
+++ b/src/db/db/dbEdge.h
@@ -38,6 +38,25 @@
namespace db {
+/**
+ * @brief A helper function for dividing integers with exact rounding
+ * This function computes (a*b/d) where rounding is exact in the sense of:
+ * a*b/d == N+0.5 => div_exact(a*b/d) = N
+ * b and d needs to be positive.
+ * a can be positive or negative.
+ * The implementation uses the gcd to reduce the ratios. This way we can
+ * represent the numbers with the area type.
+ */
+db::Coord DB_PUBLIC div_exact (db::Coord a, db::coord_traits::area_type b, db::coord_traits::area_type d);
+
+/**
+ * @brief An overload of div_exact for double types
+ */
+inline db::DCoord div_exact (db::DCoord a, db::coord_traits::area_type b, db::coord_traits::area_type d)
+{
+ return db::coord_traits::rounded (double (a) * double (b) / double (d));
+}
+
template class generic_repository;
class ArrayRepository;
@@ -794,10 +813,15 @@ public:
} else if (res) {
- double f = fabs (double (vxa)) / (fabs (double (vxa)) + fabs (double (vxb)));
+ if (vxa < 0) {
+ vxa = -vxa;
+ }
+ if (vxb < 0) {
+ vxb = -vxb;
+ }
- coord_type x = m_p1.x () + coord_traits::rounded (dx () * f);
- coord_type y = m_p1.y () + coord_traits::rounded (dy () * f);
+ coord_type x = m_p1.x () + div_exact (dx (), vxa, vxa + vxb);
+ coord_type y = m_p1.y () + div_exact (dy (), vxa, vxa + vxb);
return std::make_pair (true, db::point (x, y));
@@ -1073,10 +1097,15 @@ public:
if (res) {
- double f = fabs (double (vxa)) / (fabs (double (vxa)) + fabs (double (vxb)));
+ if (vxa < 0) {
+ vxa = -vxa;
+ }
+ if (vxb < 0) {
+ vxb = -vxb;
+ }
- coord_type x = e.p1 ().x () + coord_traits::rounded (e.dx () * f);
- coord_type y = e.p1 ().y () + coord_traits::rounded (e.dy () * f);
+ coord_type x = e.p1 ().x () + div_exact (e.dx (), vxa, vxa + vxb);
+ coord_type y = e.p1 ().y () + div_exact (e.dy (), vxa, vxa + vxb);
return std::make_pair (true, db::point (x, y));
diff --git a/src/db/db/dbEdgeProcessor.cc b/src/db/db/dbEdgeProcessor.cc
index 79640fb53..00025fd8a 100644
--- a/src/db/db/dbEdgeProcessor.cc
+++ b/src/db/db/dbEdgeProcessor.cc
@@ -121,6 +121,26 @@ private:
db::Coord m_y;
};
+inline bool
+is_point_on_exact (const db::Edge &e, const db::Point &pt)
+{
+ if (pt.x () < db::edge_xmin (e) || pt.x () > db::edge_xmax (e) ||
+ pt.y () < db::edge_ymin (e) || pt.y () > db::edge_ymax (e)) {
+
+ return false;
+
+ } else if (e.dy () == 0 || e.dx () == 0) {
+
+ // shortcut for orthogonal edges
+ return true;
+
+ } else {
+
+ return db::vprod_sign (pt - e.p1 (), e.p2 () - e.p1 ()) == 0;
+
+ }
+}
+
inline bool
is_point_on_fuzzy (const db::Edge &e, const db::Point &pt)
{
@@ -141,9 +161,12 @@ is_point_on_fuzzy (const db::Edge &e, const db::Point &pt)
} else {
+ bool with_equal = false;
+
db::Vector offset;
if ((e.dx () < 0 && e.dy () > 0) || (e.dx () > 0 && e.dy () < 0)) {
offset = db::Vector (1, 1);
+ with_equal = true;
} else {
offset = db::Vector (-1, 1);
}
@@ -152,30 +175,16 @@ is_point_on_fuzzy (const db::Edge &e, const db::Point &pt)
typedef db::coord_traits::area_type area_type;
area_type a1 = 2 * db::vprod (pp1, e.d ());
- if (a1 < 0) { a1 = -a1; }
area_type a2 = db::vprod (offset, e.d ());
+
+ if ((a1 < 0) == (a2 < 0)) {
+ with_equal = false;
+ }
+
+ if (a1 < 0) { a1 = -a1; }
if (a2 < 0) { a2 = -a2; }
- return a1 <= a2;
- }
-}
-
-inline bool
-is_point_on_exact (const db::Edge &e, const db::Point &pt)
-{
- if (pt.x () < db::edge_xmin (e) || pt.x () > db::edge_xmax (e) ||
- pt.y () < db::edge_ymin (e) || pt.y () > db::edge_ymax (e)) {
-
- return false;
-
- } else if (e.dy () == 0 || e.dx () == 0) {
-
- // shortcut for orthogonal edges
- return true;
-
- } else {
-
- return db::vprod_sign (pt - e.p1 (), e.p2 () - e.p1 ()) == 0;
+ return a1 < a2 || (a1 == a2 && with_equal);
}
}
@@ -804,7 +813,7 @@ MergeOp::edge (bool north, bool enter, property_type p)
bool inside_after = (*wcv != 0);
m_zeroes += (!inside_after) - (!inside_before);
#ifdef DEBUG_MERGEOP
- printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, p, m_zeroes);
+ printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, int (p), int (m_zeroes));
#endif
tl_assert (long (m_zeroes) >= 0);
@@ -887,7 +896,7 @@ BooleanOp::edge_impl (bool north, bool enter, property_type p, const InsideFunc
bool inside_after = ((p % 2) == 0 ? inside_a (*wcv) : inside_b (*wcv));
m_zeroes += (!inside_after) - (!inside_before);
#ifdef DEBUG_BOOLEAN
- printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, p, m_zeroes);
+ printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, int (p), int (m_zeroes));
#endif
tl_assert (long (m_zeroes) >= 0);
@@ -1345,32 +1354,17 @@ get_intersections_per_band_any (std::vector &cutpoints, std::vector
#endif
// The new cutpoint must be inserted into other edges as well.
- // If the cutpoint is exactly on the edge and there is just one other edge
- // the cutpoint will be a weak attractor - that is an optional cutpoint.
- // In that case we can skip the cutpoint because no related edge will move.
ip_weak.clear ();
- size_t n_off_edge = on_edge1 ? 0 : 1;
for (std::vector ::iterator cc = c; cc != f; ++cc) {
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
ip_weak.push_back (&*cc);
- if (!is_point_on_exact (*cc, cp.second)) {
- ++n_off_edge;
- }
}
}
for (std::vector ::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) {
- if (n_off_edge > 1) {
- (*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
+ (*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
#ifdef DEBUG_EDGE_PROCESSOR
- printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
+ printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
#endif
- } else {
- CutPoints *cpp = (*icc)->make_cutpoints (cutpoints);
- cpp->add_attractor (cp.second, (*icc)->data - 1);
-#ifdef DEBUG_EDGE_PROCESSOR
- printf ("intersection point %s gives weak attractor in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
-#endif
- }
}
}
@@ -1435,38 +1429,17 @@ get_intersections_per_band_any (std::vector &cutpoints, std::vector
#endif
// The new cutpoint must be inserted into other edges as well.
- // If the cutpoint is exactly on the edge and there is just one other edge
- // the cutpoint will be a weak attractor - that is an optional cutpoint.
- // In that case we can skip the cutpoint because no related edge will move.
ip_weak.clear ();
- size_t n_off_edge = 0;
- if (!on_edge1) {
- n_off_edge += 1;
- }
- if (!on_edge2) {
- n_off_edge += 1;
- }
for (std::vector ::iterator cc = c; cc != f; ++cc) {
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
ip_weak.push_back (&*cc);
- if (!is_point_on_exact (*cc, cp.second)) {
- ++n_off_edge;
- }
}
}
for (std::vector ::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) {
- if (n_off_edge > 1) {
- (*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
+ (*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
#ifdef DEBUG_EDGE_PROCESSOR
- printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
+ printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
#endif
- } else {
- CutPoints *cpp = (*icc)->make_cutpoints (cutpoints);
- cpp->add_attractor (cp.second, (*icc)->data - 1);
-#ifdef DEBUG_EDGE_PROCESSOR
- printf ("intersection point %s gives weak attractor in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
-#endif
- }
}
}
@@ -1829,7 +1802,7 @@ EdgeProcessor::process (db::EdgeSink &es, EdgeEvaluatorBase &op)
size_t skip = c->data % skip_unit;
size_t skip_res = c->data / skip_unit;
#ifdef DEBUG_EDGE_PROCESSOR
- printf ("X %ld->%d,%d\n", long(c->data), skip, skip_res);
+ printf ("X %ld->%d,%d\n", long (c->data), int (skip), int (skip_res));
#endif
if (skip != 0 && (c + skip >= future || (c + skip)->data != 0)) {
diff --git a/src/db/db/dbPoint.h b/src/db/db/dbPoint.h
index fade5da34..1392ebdca 100644
--- a/src/db/db/dbPoint.h
+++ b/src/db/db/dbPoint.h
@@ -194,6 +194,20 @@ public:
*/
point &operator*= (long s);
+ /**
+ * @brief Division by some divisor.
+ *
+ * Scaline involves rounding which in our case is simply handled
+ * with the coord_traits scheme.
+ */
+
+ point &operator/= (double s);
+
+ /**
+ * @brief Dividing self by some integer divisor
+ */
+ point &operator/= (long s);
+
/**
* @brief The euclidian distance to another point
*
@@ -452,6 +466,32 @@ operator* (const db::point &p, unsigned int s)
return point (p.x () * s, p.y () * s);
}
+template
+inline point
+operator/ (const db::point &p, Number s)
+{
+ double mult = 1.0 / static_cast(s);
+ return point (p.x () * mult, p.y () * mult);
+}
+
+template
+inline point &
+point::operator/= (double s)
+{
+ double mult = 1.0 / static_cast(s);
+ *this *= mult;
+ return *this;
+}
+
+template
+inline point &
+point::operator/= (long s)
+{
+ double mult = 1.0 / static_cast(s);
+ *this *= mult;
+ return *this;
+}
+
template
inline point &
point::operator*= (double s)
diff --git a/src/db/db/dbPolygonGenerators.cc b/src/db/db/dbPolygonGenerators.cc
index c75b8f24d..dcb9cf274 100644
--- a/src/db/db/dbPolygonGenerators.cc
+++ b/src/db/db/dbPolygonGenerators.cc
@@ -296,7 +296,7 @@ PolygonGenerator::flush ()
{
#ifdef DEBUG_POLYGON_GENERATOR
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
- printf ("%d:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
+ printf ("%ld:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
}
printf ("\n");
#endif
@@ -325,12 +325,12 @@ PolygonGenerator::begin_scanline (db::Coord y)
#ifdef DEBUG_POLYGON_GENERATOR
printf ("m_open=");
for (open_map_type::const_iterator o = m_open.begin (); o != m_open.end (); ++o) {
- printf ("%d:%s ", o->contour, o->point.to_string().c_str());
+ printf ("%ld:%s ", o->contour, o->point.to_string().c_str());
}
printf ("\n");
printf ("contours:\n");
for (size_t j = 0; j < mp_contours->size (); ++j) {
- printf ("c%d%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
+ printf ("c%ld%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
}
@@ -364,7 +364,7 @@ PolygonGenerator::skip_n (size_t n)
{
join_contours (std::numeric_limits::max ());
#ifdef DEBUG_POLYGON_GENERATOR
- printf ("skip(%d)\n", n);
+ printf ("skip(%ld)\n", n);
#endif
while (n-- > 0) {
++m_open_pos;
@@ -375,9 +375,9 @@ void
PolygonGenerator::put (const db::Edge &e)
{
#ifdef DEBUG_POLYGON_GENERATOR
- printf ("put(%s) y=%d m_open(%d)=", e.to_string().c_str(),m_y,std::distance (m_open.begin (), m_open_pos));
+ printf ("put(%s) y=%d m_open(%ld)=", e.to_string().c_str(),m_y,std::distance (m_open.begin (), m_open_pos));
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
- printf ("%d:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
+ printf ("%ld:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
}
printf ("\n");
#endif
@@ -438,7 +438,7 @@ PolygonGenerator::put (const db::Edge &e)
cnew.push_back (e.p2 ());
#ifdef DEBUG_POLYGON_GENERATOR
- printf ("create %s %d\n", hole ? "hole" : "hull", poly_index);
+ printf ("create %s %ld\n", hole ? "hole" : "hull", inew);
#endif
m_open.insert (m_open_pos, PGPoint (hole ? e.p1 () : e.p2 (), inew, true));
m_open.insert (m_open_pos, PGPoint (hole ? e.p2 () : e.p1 (), inew, false));
@@ -449,7 +449,7 @@ PolygonGenerator::put (const db::Edge &e)
#ifdef DEBUG_POLYGON_GENERATOR
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
- printf ("%d:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
+ printf ("%ld:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
}
printf ("\n");
#endif
@@ -552,14 +552,14 @@ PolygonGenerator::join_contours (db::Coord x)
size_t i1 = m_open_pos->contour;
size_t i2 = n->contour;
#ifdef DEBUG_POLYGON_GENERATOR
- printf ("join %d and %d\n", i1, i2);
+ printf ("join %ld and %ld\n", i1, i2);
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
- printf ("%d:%s%c%c%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ', i == n ? '+' : ' ', i == nn ? '#' : ' ');
+ printf ("%ld:%s%c%c%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ', i == n ? '+' : ' ', i == nn ? '#' : ' ');
}
printf ("\n");
printf ("--> input contours:\n");
for (size_t j = 0; j < mp_contours->size (); ++j) {
- printf ("--> c%d%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
+ printf ("--> c%ld%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
}
@@ -705,7 +705,7 @@ PolygonGenerator::join_contours (db::Coord x)
if (! c1.is_hole ()) {
#ifdef DEBUG_POLYGON_GENERATOR
- printf ("finish %d (hull)\n", i1);
+ printf ("finish %ld (hull)\n", i1);
#endif
produce_poly (c1);
@@ -775,7 +775,7 @@ PolygonGenerator::join_contours (db::Coord x)
#ifdef DEBUG_POLYGON_GENERATOR
printf ("--> output contours:\n");
for (size_t j = 0; j < mp_contours->size (); ++j) {
- printf ("--> c%d%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
+ printf ("--> c%ld%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
}
diff --git a/src/db/db/dbVector.h b/src/db/db/dbVector.h
index ad86d4502..f3432c057 100644
--- a/src/db/db/dbVector.h
+++ b/src/db/db/dbVector.h
@@ -266,6 +266,20 @@ public:
*/
vector operator*= (long s);
+ /**
+ * @brief Division by some divisor.
+ *
+ * Scaline involves rounding which in our case is simply handled
+ * with the coord_traits scheme.
+ */
+
+ vector &operator/= (double s);
+
+ /**
+ * @brief Dividing self by some integer divisor
+ */
+ vector &operator/= (long s);
+
/**
* @brief The euclidian length
*/
@@ -450,6 +464,32 @@ vector::operator* (long s) const
return vector (m_x * s, m_y * s);
}
+template
+inline vector
+operator/ (const db::vector &p, Number s)
+{
+ double mult = 1.0 / static_cast(s);
+ return vector (p.x () * mult, p.y () * mult);
+}
+
+template
+inline vector &
+vector::operator/= (double s)
+{
+ double mult = 1.0 / static_cast(s);
+ *this *= mult;
+ return *this;
+}
+
+template
+inline vector &
+vector::operator/= (long s)
+{
+ double mult = 1.0 / static_cast(s);
+ *this *= mult;
+ return *this;
+}
+
template
inline vector
vector::operator*= (double s)
diff --git a/src/db/db/gsiDeclDbPoint.cc b/src/db/db/gsiDeclDbPoint.cc
index 7cf55744b..490b23773 100644
--- a/src/db/db/gsiDeclDbPoint.cc
+++ b/src/db/db/gsiDeclDbPoint.cc
@@ -70,6 +70,23 @@ struct point_defs
return C (*p * s);
}
+ static C divide (const C *p, double s)
+ {
+ return C (*p / s);
+ }
+
+ static C iscale (C *p, double s)
+ {
+ *p *= s;
+ return *p;
+ }
+
+ static C idiv (C *p, double s)
+ {
+ *p /= s;
+ return *p;
+ }
+
static C negate (const C *p)
{
return -*p;
@@ -175,6 +192,30 @@ struct point_defs
"Returns the scaled object. All coordinates are multiplied with the given factor and if "
"necessary rounded."
) +
+ method_ext ("*=", &iscale,
+ "@brief Scaling by some factor\n"
+ "\n"
+ "@args f\n"
+ "\n"
+ "Scales object in place. All coordinates are multiplied with the given factor and if "
+ "necessary rounded."
+ ) +
+ method_ext ("/", ÷,
+ "@brief Division by some divisor\n"
+ "\n"
+ "@args d\n"
+ "\n"
+ "Returns the scaled object. All coordinates are divided with the given divisor and if "
+ "necessary rounded."
+ ) +
+ method_ext ("/=", &idiv,
+ "@brief Division by some divisor\n"
+ "\n"
+ "@args d\n"
+ "\n"
+ "Divides the object in place. All coordinates are divided with the given divisor and if "
+ "necessary rounded."
+ ) +
method ("distance", (double (C::*) (const C &) const) &C::double_distance,
"@brief The Euclidian distance to another point\n"
"\n"
diff --git a/src/db/db/gsiDeclDbRecursiveShapeIterator.cc b/src/db/db/gsiDeclDbRecursiveShapeIterator.cc
index a46081de5..27b6964c1 100644
--- a/src/db/db/gsiDeclDbRecursiveShapeIterator.cc
+++ b/src/db/db/gsiDeclDbRecursiveShapeIterator.cc
@@ -280,7 +280,7 @@ Class decl_RecursiveShapeIterator ("db", "RecursiveS
) +
gsi::method ("region=", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::box_type &)) &db::RecursiveShapeIterator::set_region,
"@brief Sets the rectangular region that is iterator is iterating over\n"
- "@args region\n"
+ "@args box_region\n"
"See \\region for a description of this attribute.\n"
"Setting a simple region will reset the complex region to a rectangle and reset the iterator to "
"the beginning of the sequence."
@@ -298,15 +298,19 @@ Class decl_RecursiveShapeIterator ("db", "RecursiveS
) +
gsi::method ("confine_region", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::box_type &)) &db::RecursiveShapeIterator::confine_region,
"@brief Confines the region that is iterator is iterating over\n"
- "@args region\n"
- "This method is similar to setting the region (see \\region=), but will add to any (complex or simple) region already set. "
+ "@args box_region\n"
+ "This method is similar to setting the region (see \\region=), but will confine any region (complex or simple) already set. "
+ "Essentially it does a logical AND operation between the existing and given region. "
+ "Hence this method can only reduce a region, not extend it.\n"
"\n"
"This method has been introduced in version 0.25.\n"
) +
- gsi::method ("region=", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::region_type &)) &db::RecursiveShapeIterator::confine_region,
+ gsi::method ("confine_region", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::region_type &)) &db::RecursiveShapeIterator::confine_region,
"@brief Confines the region that is iterator is iterating over\n"
- "@args region\n"
- "This method is similar to setting the complex region (see \\region=), but will add to any (complex or simple) region already set."
+ "@args complex_region\n"
+ "This method is similar to setting the region (see \\region=), but will confine any region (complex or simple) already set. "
+ "Essentially it does a logical AND operation between the existing and given region. "
+ "Hence this method can only reduce a region, not extend it.\n"
"\n"
"This method has been introduced in version 0.25.\n"
) +
diff --git a/src/db/db/gsiDeclDbShapes.cc b/src/db/db/gsiDeclDbShapes.cc
index 6ceacab9e..ec8dd1408 100644
--- a/src/db/db/gsiDeclDbShapes.cc
+++ b/src/db/db/gsiDeclDbShapes.cc
@@ -50,6 +50,21 @@ static void dump_mem_statistics (const db::Shapes *shapes, bool detailed)
ms.print ();
}
+static size_t shapes_size (const db::Shapes *shapes)
+{
+ // we may have shape arrays - expand their count to match the shape count with the shapes delivered
+ size_t n = 0;
+ for (db::Shapes::shape_iterator i = shapes->begin (db::ShapeIterator::All); ! i.at_end (); ++i) {
+ if (i.in_array ()) {
+ n += i.array ().array_size ();
+ i.finish_array ();
+ } else {
+ ++n;
+ }
+ }
+ return n;
+}
+
template
static db::Shape insert (db::Shapes *s, const Sh &p)
{
@@ -1088,7 +1103,7 @@ Class decl_Shapes ("db", "Shapes",
"@brief Clears the shape container\n"
"This method has been introduced in version 0.16. It can only be used in editable mode."
) +
- gsi::method ("size", (size_t (db::Shapes::*)() const) &db::Shapes::size,
+ gsi::method_ext ("size", &shapes_size,
"@brief Gets the number of shapes in this container\n"
"This method was introduced in version 0.16\n"
"@return The number of shapes in this container\n"
diff --git a/src/db/db/gsiDeclDbVector.cc b/src/db/db/gsiDeclDbVector.cc
index 29b0b7981..eca3c8f85 100644
--- a/src/db/db/gsiDeclDbVector.cc
+++ b/src/db/db/gsiDeclDbVector.cc
@@ -70,6 +70,23 @@ struct vector_defs
return C (*p * s);
}
+ static C divide (const C *p, double s)
+ {
+ return C (*p / s);
+ }
+
+ static C iscale (C *p, double s)
+ {
+ *p *= s;
+ return *p;
+ }
+
+ static C idiv (C *p, double s)
+ {
+ *p /= s;
+ return *p;
+ }
+
static C negate (const C *p)
{
return -*p;
@@ -202,6 +219,30 @@ struct vector_defs
"Returns the scaled object. All coordinates are multiplied with the given factor and if "
"necessary rounded."
) +
+ method_ext ("*=", &iscale,
+ "@brief Scaling by some factor\n"
+ "\n"
+ "@args f\n"
+ "\n"
+ "Scales object in place. All coordinates are multiplied with the given factor and if "
+ "necessary rounded."
+ ) +
+ method_ext ("/", ÷,
+ "@brief Division by some divisor\n"
+ "\n"
+ "@args d\n"
+ "\n"
+ "Returns the scaled object. All coordinates are divided with the given divisor and if "
+ "necessary rounded."
+ ) +
+ method_ext ("/=", &idiv,
+ "@brief Division by some divisor\n"
+ "\n"
+ "@args d\n"
+ "\n"
+ "Divides the object in place. All coordinates are divided with the given divisor and if "
+ "necessary rounded."
+ ) +
method_ext ("vprod", &vprod,
"@brief Computes the vector product between self and the given vector\n"
"\n"
diff --git a/src/db/unit_tests/dbEdge.cc b/src/db/unit_tests/dbEdge.cc
index 91d5a77b3..32d91641b 100644
--- a/src/db/unit_tests/dbEdge.cc
+++ b/src/db/unit_tests/dbEdge.cc
@@ -514,3 +514,74 @@ TEST(14)
EXPECT_EQ (e.coincident (db::Edge (db::Point (49, 0), db::Point (200, 0))), false);
}
+// exact rounding behaviour
+TEST(15)
+{
+ typedef db::coord_traits::area_type area_type;
+ // div_exact(a, b, d) computes a*b/d with exact rounding behaviour
+ EXPECT_EQ (db::div_exact (area_type (0), area_type (22), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (5), area_type (0), area_type (176)), 0);
+
+ EXPECT_EQ (db::div_exact (area_type (3), area_type (22), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (4), area_type (22), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (5), area_type (22), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (7), area_type (22), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (8), area_type (22), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (12), area_type (22), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (13), area_type (22), area_type (176)), 2);
+
+ EXPECT_EQ (db::div_exact (area_type (3 * 11), area_type (2), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (4 * 11), area_type (2), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (5 * 11), area_type (2), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (7 * 11), area_type (2), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (8 * 11), area_type (2), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (12 * 11), area_type (2), area_type (176)), 1);
+ EXPECT_EQ (db::div_exact (area_type (13 * 11), area_type (2), area_type (176)), 2);
+
+ EXPECT_EQ (db::div_exact (area_type (-3), area_type (22), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (-4), area_type (22), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-5), area_type (22), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-7), area_type (22), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-8), area_type (22), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-12), area_type (22), area_type (176)), -2);
+ EXPECT_EQ (db::div_exact (area_type (-13), area_type (22), area_type (176)), -2);
+
+ EXPECT_EQ (db::div_exact (area_type (-3 * 11), area_type (2), area_type (176)), 0);
+ EXPECT_EQ (db::div_exact (area_type (-4 * 11), area_type (2), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-5 * 11), area_type (2), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-7 * 11), area_type (2), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-8 * 11), area_type (2), area_type (176)), -1);
+ EXPECT_EQ (db::div_exact (area_type (-12 * 11), area_type (2), area_type (176)), -2);
+ EXPECT_EQ (db::div_exact (area_type (-13 * 11), area_type (2), area_type (176)), -2);
+
+ area_type f = 790014345;
+
+ EXPECT_EQ (db::div_exact (area_type (4), area_type (22) * f, area_type (176) * f), 0);
+ EXPECT_EQ (db::div_exact (area_type (5), area_type (22) * f, area_type (176) * f), 1);
+ EXPECT_EQ (db::div_exact (area_type (8), area_type (22) * f, area_type (176) * f), 1);
+
+ EXPECT_EQ (db::div_exact (area_type (-3), area_type (22) * f, area_type (176) * f), 0);
+ EXPECT_EQ (db::div_exact (area_type (-4), area_type (22) * f, area_type (176) * f), -1);
+ EXPECT_EQ (db::div_exact (area_type (-5), area_type (22) * f, area_type (176) * f), -1);
+ EXPECT_EQ (db::div_exact (area_type (-8), area_type (22) * f, area_type (176) * f), -1);
+
+ EXPECT_EQ (db::div_exact (area_type (4) * 100000000, area_type (22) * f, area_type (176) * f), 50000000);
+ EXPECT_EQ (db::div_exact (area_type (5) * 100000000, area_type (22) * f, area_type (176) * f), 62500000);
+ EXPECT_EQ (db::div_exact (area_type (-4) * 100000000, area_type (22) * f, area_type (176) * f), -50000000);
+ EXPECT_EQ (db::div_exact (area_type (-5) * 100000000, area_type (22) * f, area_type (176) * f), -62500000);
+
+ EXPECT_EQ (db::div_exact (1000000004, area_type (22) * f, area_type (176) * f), 125000000);
+ EXPECT_EQ (db::div_exact (1000000005, area_type (22) * f, area_type (176) * f), 125000001);
+ EXPECT_EQ (db::div_exact (-1000000003, area_type (22) * f, area_type (176) * f), -125000000);
+ EXPECT_EQ (db::div_exact (-1000000004, area_type (22) * f, area_type (176) * f), -125000001);
+ EXPECT_EQ (db::div_exact (-1000000005, area_type (22) * f, area_type (176) * f), -125000001);
+
+ db::Edge e1 (db::Point (3, -3), db::Point (-8, -1));
+ db::Edge e2 (db::Point (-4, -2), db::Point (13, -4));
+
+ std::pair ip;
+ ip = e1.intersect_point (e2);
+ EXPECT_EQ (ip.second.to_string ().c_str (), "0,-3");
+ ip = e2.intersect_point (e1);
+ EXPECT_EQ (ip.second.to_string ().c_str (), "0,-3");
+}
diff --git a/src/db/unit_tests/dbEdgeProcessor.cc b/src/db/unit_tests/dbEdgeProcessor.cc
index a7abc8de4..5c019c9be 100644
--- a/src/db/unit_tests/dbEdgeProcessor.cc
+++ b/src/db/unit_tests/dbEdgeProcessor.cc
@@ -25,6 +25,7 @@
#include "dbShapeProcessor.h"
#include "dbPolygon.h"
+#include "dbPolygonGenerators.h"
#include "dbLayout.h"
#include "dbReader.h"
#include "dbCommonReader.h"
@@ -1332,7 +1333,7 @@ TEST(23)
EXPECT_EQ (out.size (), size_t (1));
std::sort (out.begin (), out.end ());
- EXPECT_EQ (out[0].to_string (), "(0,0;0,1;1,0)");
+ EXPECT_EQ (out[0].to_string (), "(0,0;0,1;1,1)");
}
TEST(24)
@@ -1390,15 +1391,29 @@ TEST(24)
in1.back ().assign_hull (p1 + 0, p1 + sizeof (p1) / sizeof (p1[0]));
}
- std::vector out;
+ {
+ std::vector out;
- db::EdgeProcessor ep;
- ep.simple_merge (in1, out, false, false);
+ db::EdgeProcessor ep;
+ ep.simple_merge (in1, out, false, false);
- EXPECT_EQ (out.size (), size_t (2));
- std::sort (out.begin (), out.end ());
- EXPECT_EQ (out[0].to_string (), "(0,-9;0,0;3,0;3,-2;1,0;1,-9)");
- EXPECT_EQ (out[1].to_string (), "(-2,1;-2,3;0,1;0,10;1,10;1,1)");
+ EXPECT_EQ (out.size (), size_t (1));
+ std::sort (out.begin (), out.end ());
+ EXPECT_EQ (out[0].to_string (), "(0,-9;0,0;-2,1;-2,3;0,1;0,10;1,10;1,1;0,0;3,0;3,-2;1,0;1,-9)");
+ }
+
+ {
+ std::vector out;
+
+ db::EdgeProcessor ep;
+ ep.simple_merge (in1, out, false, true);
+
+ EXPECT_EQ (out.size (), size_t (3));
+ std::sort (out.begin (), out.end ());
+ EXPECT_EQ (out[0].to_string (), "(0,-9;0,0;1,0;1,-9)");
+ EXPECT_EQ (out[1].to_string (), "(3,-2;1,0;3,0)");
+ EXPECT_EQ (out[2].to_string (), "(0,0;-2,1;-2,3;0,1;0,10;1,10;1,1)");
+ }
}
TEST(25)
@@ -2247,7 +2262,7 @@ TEST(100)
}
// #74 (GitHub)
-TEST(101)
+std::string run_test101 (tl::TestBase *_this, const db::Trans &t)
{
db::EdgeProcessor ep;
@@ -2260,6 +2275,7 @@ TEST(101)
};
db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
+ p.transform (t);
ep.insert (p, 0);
}
@@ -2272,6 +2288,7 @@ TEST(101)
};
db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
+ p.transform (t);
ep.insert (p, 1);
}
@@ -2284,6 +2301,7 @@ TEST(101)
};
db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
+ p.transform (t);
ep.insert (p, 1);
}
@@ -2295,7 +2313,16 @@ TEST(101)
ep.process (pg, op);
EXPECT_EQ (out.size (), size_t (1));
- EXPECT_EQ (out[0].to_string (), "(0,0;0,9;1,10;10,10;10,0)");
+
+ return out.empty () ? std::string () : out.front ().to_string ();
+}
+
+TEST(101)
+{
+ EXPECT_EQ (run_test101 (_this, db::Trans (db::Trans::r0)), "(0,0;0,9;1,10;10,10;10,0)");
+ EXPECT_EQ (run_test101 (_this, db::Trans (db::Trans::r90)), "(-9,0;-10,1;-10,10;0,10;0,0)");
+ EXPECT_EQ (run_test101 (_this, db::Trans (db::Trans::r180)), "(-10,-10;-10,0;0,0;0,-9;-1,-10)");
+ EXPECT_EQ (run_test101 (_this, db::Trans (db::Trans::r270)), "(0,-10;0,0;9,0;10,-1;10,-10)");
}
TEST(102)
@@ -2348,3 +2375,111 @@ TEST(102)
EXPECT_EQ (out.size (), size_t (1));
EXPECT_EQ (out[0].to_string (), "(0,0;0,200;100,200;100,100;200,100;200,200;500,200;500,100;600,100;600,200;0,200;0,1000;1000,1000;1000,0)");
}
+
+// Bug 134
+TEST(134)
+{
+ const char *pd = "(30,-7957;0,0;56,-4102;30,-7921)";
+
+ db::Coord dx = 0;
+ db::Coord dy = -3999;
+ unsigned int mode = 3;
+
+ db::Polygon p;
+ tl::from_string (pd, p);
+
+ db::EdgeProcessor ep;
+ db::Polygon ps (p.sized (dx, dy, mode));
+ ep.insert (ps);
+
+ db::SimpleMerge op (1 /*wc>0*/);
+ std::vector out;
+ db::PolygonContainer pc (out);
+ db::PolygonGenerator pg (pc);
+ ep.process (pg, op);
+
+ EXPECT_EQ (out.size (), size_t (0));
+}
+
+void run_test135a (tl::TestBase *_this, const db::Trans &t)
+{
+ db::EdgeProcessor ep;
+
+ db::Point pts[] = {
+ db::Point (0, 0),
+ db::Point (19, 19),
+ db::Point (19, 18),
+ db::Point (43, 32),
+ db::Point (37, 27)
+ };
+
+ db::Polygon p;
+ p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
+ p.transform (t);
+ p.size (-2, -2, 2);
+
+ ep.insert (p);
+
+ // this is just supposed to work and not fail with internal error "m_open.empty()"
+ std::vector out;
+ db::PolygonContainer pc (out);
+ db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/);
+ db::SimpleMerge op (1 /*wc>0*/);
+ ep.process (pg2, op);
+
+ EXPECT_EQ (out.size (), size_t (0));
+}
+
+TEST(135a)
+{
+ run_test135a (_this, db::Trans (db::Trans::r0));
+ run_test135a (_this, db::Trans (db::Trans::r90));
+ run_test135a (_this, db::Trans (db::Trans::r180));
+ run_test135a (_this, db::Trans (db::Trans::r270));
+ run_test135a (_this, db::Trans (db::Trans::m0));
+ run_test135a (_this, db::Trans (db::Trans::m45));
+ run_test135a (_this, db::Trans (db::Trans::m90));
+ run_test135a (_this, db::Trans (db::Trans::m135));
+}
+
+std::string run_test135b (tl::TestBase *_this, const db::Trans &t)
+{
+ db::EdgeProcessor ep;
+
+ db::Point pts[] = {
+ db::Point (215, 0),
+ db::Point (145, 11),
+ db::Point (37, 31),
+ db::Point (36, 31),
+ db::Point (0, 43)
+ };
+
+ db::Polygon p;
+ p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
+ p.transform (t);
+ p.size (-2, -2, 2);
+
+ ep.insert (p);
+
+ // this is just supposed to work and not fail with internal error "m_open.empty()"
+ std::vector out;
+ db::PolygonContainer pc (out);
+ db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/);
+ db::SimpleMerge op (1 /*wc>0*/);
+ ep.process (pg2, op);
+
+ EXPECT_EQ (out.size (), size_t (1));
+ return out.empty () ? std::string () : out.front ().to_string ();
+}
+
+TEST(135b)
+{
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r0)), "(36,33;32,34;37,33)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r90)), "(-35,32;-26,77;-33,37;-33,36)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r180)), "(-33,-35;-78,-26;-37,-33;-36,-33)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r270)), "(25,-78;33,-37;33,-36;34,-33)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m0)), "(32,-35;36,-33;37,-33;77,-26)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m45)), "(34,32;33,36;33,37)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m90)), "(-78,25;-33,34;-36,33;-37,33)");
+ EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m135)), "(-26,-78;-35,-33;-33,-36;-33,-37)");
+}
diff --git a/src/db/unit_tests/dbPolygonTools.cc b/src/db/unit_tests/dbPolygonTools.cc
index a690897f3..06224c533 100644
--- a/src/db/unit_tests/dbPolygonTools.cc
+++ b/src/db/unit_tests/dbPolygonTools.cc
@@ -1082,7 +1082,7 @@ TEST(31)
pout = minkowsky_sum (p, db::Edge (db::Point (10, 10), db::Point (210, -90)), true);
- EXPECT_EQ (pout.to_string (), "(210,-190;143,-157;110,-165;-90,-65;10,110;85,73;110,85;310,-15;310,-140)");
+ EXPECT_EQ (pout.to_string (), "(210,-190;143,-157;110,-165;-90,-65;10,110;85,72;110,85;310,-15;310,-140)");
std::vector c;
c.push_back (db::Point (10, 10));
diff --git a/src/db/unit_tests/dbTilingProcessor.cc b/src/db/unit_tests/dbTilingProcessor.cc
index 1a80b94ad..cb67d5aad 100644
--- a/src/db/unit_tests/dbTilingProcessor.cc
+++ b/src/db/unit_tests/dbTilingProcessor.cc
@@ -26,10 +26,13 @@
#include "dbTilingProcessor.h"
#include "dbTextWriter.h"
#include "gsiExpression.h"
+#include "gsiDecl.h"
#include "dbWriter.h"
#include "dbSaveLayoutOptions.h"
#include
+#include
+#include
unsigned int get_rand()
{
@@ -385,3 +388,63 @@ TEST(4)
}
+class MyTilingOutputReceiver
+ : public db::TileOutputReceiver
+{
+public:
+ MyTilingOutputReceiver (double *sum, int *n)
+ : mp_sum (sum), mp_n (n)
+ { }
+
+ MyTilingOutputReceiver ()
+ : mp_sum (0), mp_n (0)
+ { }
+
+ void add (double x) const
+ {
+ static QMutex lock;
+ QMutexLocker locker (&lock);
+ *mp_sum += x;
+ *mp_n += 1;
+ }
+
+private:
+ double *mp_sum;
+ int *mp_n;
+};
+
+namespace gsi
+{
+DB_PUBLIC gsi::Class &dbdecl_TileOutputReceiverBase ();
+}
+
+gsi::Class decl_MyTilingOutputReceiver (gsi::dbdecl_TileOutputReceiverBase (), "db", "MyTileOutputReceiver",
+ gsi::method ("add", &MyTilingOutputReceiver::add)
+);
+
+// Multithreaded, access to _rec()
+// This will mainly test the ability of gsi::Proxy to manage references
+// in a multithreaded case.
+TEST(5)
+{
+ db::Layout ly1;
+ ly1.dbu (0.001);
+ unsigned int l11 = ly1.insert_layer (db::LayerProperties (1, 0));
+ db::cell_index_type top1 = ly1.add_cell ("TOP");
+ ly1.cell (top1).shapes (l11).insert (db::Box (0, 0, 50000, 50000));
+
+ double sum = 0.0;
+ int num = 0;
+ MyTilingOutputReceiver *rec = new MyTilingOutputReceiver (&sum, &num);
+
+ db::TilingProcessor tp;
+ tp.set_threads (4);
+ tp.tile_size (0.11, 0.17);
+ tp.input ("i1", db::RecursiveShapeIterator (ly1, ly1.cell (top1), l11));
+ tp.output ("o1", 0, rec, db::ICplxTrans ());
+ tp.queue ("_rec(o1).add((i1 & _tile).area)");
+ tp.execute ("test");
+
+ EXPECT_EQ (sum, 2500000000);
+ EXPECT_EQ (num, 134225);
+}
diff --git a/src/drc/drc/built-in-macros/drc.lym b/src/drc/drc/built-in-macros/drc.lym
index 65fbd04e7..5bdb3de1b 100644
--- a/src/drc/drc/built-in-macros/drc.lym
+++ b/src/drc/drc/built-in-macros/drc.lym
@@ -896,7 +896,7 @@ CODE
#
# This method produces markers on the corners of the polygons. An angle criterion can be given which
# selects corners based on the angle of the connecting edges. Positive angles indicate a left turn
- # while negative angles indicate a right turn. Since polygons are oriented clockwise, postive angles
+ # while negative angles indicate a right turn. Since polygons are oriented clockwise, positive angles
# indicate concave corners while negative ones indicate convex corners.
#
# The markers generated can be point-like edges or small 2x2 DBU boxes. The latter is the default.
diff --git a/src/edt/edt/edtPropertiesPages.cc b/src/edt/edt/edtPropertiesPages.cc
index 2c9b7dc9e..0ad5dea9f 100644
--- a/src/edt/edt/edtPropertiesPages.cc
+++ b/src/edt/edt/edtPropertiesPages.cc
@@ -251,6 +251,8 @@ ShapePropertiesPage::do_apply (bool current_only)
for (std::vector::const_iterator p = m_selection_ptrs.begin (); p != m_selection_ptrs.end (); ++p) {
+ size_t index = p - m_selection_ptrs.begin ();
+
edt::Service::obj_iterator pos = *p;
// only update objects from the same layout - this is not practical limitation but saves a lot of effort for
@@ -259,6 +261,9 @@ ShapePropertiesPage::do_apply (bool current_only)
continue;
}
+ const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
+ db::Layout &layout = cv->layout ();
+
tl_assert (! pos->is_cell_inst ());
if (pos->shape ().is_array_member ()) {
@@ -271,10 +276,8 @@ ShapePropertiesPage::do_apply (bool current_only)
std::map::const_iterator s = shapes_seen.find (pos->shape ());
if (s == shapes_seen.end ()) {
- const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
-
- db::Shapes &shapes = cv->layout ().cell (pos->cell_index ()).shapes (pos->layer ());
- double dbu = cv->layout ().dbu ();
+ db::Shapes &shapes = layout.cell (pos->cell_index ()).shapes (pos->layer ());
+ double dbu = layout.dbu ();
if (!current_only || pos->shape () == current) {
new_shape = applicator->do_apply (shapes, pos->shape (), dbu, relative_mode);
@@ -288,8 +291,6 @@ ShapePropertiesPage::do_apply (bool current_only)
if (new_shape != pos->shape ()) {
- size_t index = p - m_selection_ptrs.begin ();
-
// change selection to new shape
new_sel[index].set_shape (new_shape);
@@ -298,21 +299,34 @@ ShapePropertiesPage::do_apply (bool current_only)
update_required = true;
- }
+ }
+
+ // handle the case of guiding shape updates
+ std::pair gs = mp_service->handle_guiding_shape_changes (new_sel[index]);
+ if (gs.first) {
+
+ new_sel[index] = gs.second;
+
+ mp_service->select (*pos, lay::Editable::Reset);
+ mp_service->select (new_sel [index], lay::Editable::Add);
+
+ update_required = true;
+
+ }
}
if (update_required) {
+ mp_service->view ()->cellview (cv_index)->layout ().cleanup ();
recompute_selection_ptrs (new_sel);
}
} catch (...) {
+ mp_service->view ()->cellview (cv_index)->layout ().cleanup ();
recompute_selection_ptrs (new_sel);
throw;
}
- mp_service->handle_guiding_shape_changes ();
-
update ();
}
diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc
index 18fd97934..554073692 100644
--- a/src/edt/edt/edtService.cc
+++ b/src/edt/edt/edtService.cc
@@ -1480,30 +1480,23 @@ Service::add_selection (const lay::ObjectInstPath &sel)
selection_to_view ();
}
-bool
-Service::handle_guiding_shape_changes ()
+std::pair
+Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const
{
- // just allow one guiding shape to be selected
- if (m_selection.empty ()) {
- return false;
- }
-
- objects::const_iterator s = m_selection.begin ();
-
- unsigned int cv_index = s->cv_index ();
+ unsigned int cv_index = obj.cv_index ();
lay::CellView cv = view ()->cellview (cv_index);
db::Layout *layout = &cv->layout ();
- if (s->is_cell_inst () || s->layer () != layout->guiding_shape_layer ()) {
- return false;
+ if (obj.is_cell_inst () || obj.layer () != layout->guiding_shape_layer ()) {
+ return std::make_pair (false, lay::ObjectInstPath ());
}
- if (! s->shape ().has_prop_id ()) {
- return false;
+ if (! obj.shape ().has_prop_id ()) {
+ return std::make_pair (false, lay::ObjectInstPath ());
}
- if (! layout->is_pcell_instance (s->cell_index ()).first) {
- return false;
+ if (! layout->is_pcell_instance (obj.cell_index ()).first) {
+ return std::make_pair (false, lay::ObjectInstPath ());
}
db::cell_index_type top_cell = std::numeric_limits::max ();
@@ -1512,37 +1505,38 @@ Service::handle_guiding_shape_changes ()
db::pcell_parameters_type parameters_for_pcell;
// determine parent cell and instance if required
- lay::ObjectInstPath::iterator e = s->end ();
- if (e == s->begin ()) {
- top_cell = s->cell_index ();
+ lay::ObjectInstPath::iterator e = obj.end ();
+ if (e == obj.begin ()) {
+ top_cell = obj.cell_index ();
} else {
--e;
- db::cell_index_type pc = s->topcell ();
- if (e != s->begin ()) {
+ db::cell_index_type pc = obj.topcell ();
+ if (e != obj.begin ()) {
--e;
pc = e->inst_ptr.cell_index ();
}
parent_cell = pc;
- parent_inst = s->back ().inst_ptr;
+ parent_inst = obj.back ().inst_ptr;
}
db::property_names_id_type pn = layout->properties_repository ().prop_name_id ("name");
- const db::PropertiesRepository::properties_set &input_props = layout->properties_repository ().properties (s->shape ().prop_id ());
+ const db::PropertiesRepository::properties_set &input_props = layout->properties_repository ().properties (obj.shape ().prop_id ());
db::PropertiesRepository::properties_set::const_iterator input_pv = input_props.find (pn);
if (input_pv == input_props.end ()) {
- return false;
+ return std::make_pair (false, lay::ObjectInstPath ());
}
std::string shape_name = input_pv->second.to_string ();
// Hint: get_parameters_from_pcell_and_guiding_shapes invalidates the shapes because it resets the changed
// guiding shapes. We must not access s->shape after that.
- if (! get_parameters_from_pcell_and_guiding_shapes (layout, s->cell_index (), parameters_for_pcell)) {
- return false;
+ if (! get_parameters_from_pcell_and_guiding_shapes (layout, obj.cell_index (), parameters_for_pcell)) {
+ return std::make_pair (false, lay::ObjectInstPath ());
}
- std::vector new_sel;
+ bool found = false;
+ lay::ObjectInstPath new_obj = obj;
if (parent_cell != std::numeric_limits ::max ()) {
@@ -1550,21 +1544,20 @@ Service::handle_guiding_shape_changes ()
// try to identify the selected shape in the new shapes and select this one
db::Shapes::shape_iterator sh = layout->cell (new_inst.cell_index ()).shapes (layout->guiding_shape_layer ()).begin (db::ShapeIterator::All);
- while (! sh.at_end ()) {
+ while (! sh.at_end () && !found) {
const db::PropertiesRepository::properties_set &props = layout->properties_repository ().properties (sh->prop_id ());
db::PropertiesRepository::properties_set::const_iterator pv = props.find (pn);
if (pv != props.end ()) {
if (pv->second.to_string () == shape_name) {
- new_sel.push_back (*s);
- new_sel.back ().back ().inst_ptr = new_inst;
- new_sel.back ().back ().array_inst = new_inst.begin ();
- new_sel.back ().set_shape (*sh);
- break;
+ new_obj.back ().inst_ptr = new_inst;
+ new_obj.back ().array_inst = new_inst.begin ();
+ new_obj.set_shape (*sh);
+ found = true;
}
}
++sh;
}
-
+
}
if (top_cell != std::numeric_limits ::max ()) {
@@ -1572,12 +1565,33 @@ Service::handle_guiding_shape_changes ()
// Currently there is not way to create such a configuration ...
}
- // remove superfluous proxies
- layout->cleanup ();
+ return std::make_pair (found, new_obj);
+}
- set_selection (new_sel.begin (), new_sel.end ());
+bool
+Service::handle_guiding_shape_changes ()
+{
+ // just allow one guiding shape to be selected
+ if (m_selection.empty ()) {
+ return false;
+ }
- return true;
+ std::pair gs = handle_guiding_shape_changes (*m_selection.begin ());
+ if (gs.first) {
+
+ // remove superfluous proxies
+ view ()->cellview (gs.second.cv_index ())->layout ().cleanup ();
+
+ // re-set the selection
+ std::vector new_sel;
+ new_sel.push_back (gs.second);
+ set_selection (new_sel.begin (), new_sel.end ());
+
+ return true;
+
+ } else {
+ return false;
+ }
}
diff --git a/src/edt/edt/edtService.h b/src/edt/edt/edtService.h
index 6a02cb6f8..ba0855b08 100644
--- a/src/edt/edt/edtService.h
+++ b/src/edt/edt/edtService.h
@@ -342,9 +342,19 @@ public:
* @brief Handle changes in the guiding shapes, i.e. create PCell variants
*
* @return true, if PCell's have been updated, indicating that our selection is no longer valid
+ *
+ * This version assumes there is only one guiding shape selected and will update the selection.
+ * It will also call layout.cleanup() if required.
*/
bool handle_guiding_shape_changes ();
+ /**
+ * @brief Handle changes in a specific guiding shape, i.e. create new PCell variants if required
+ *
+ * @return A pair of bool (indicating that the object path has changed) and the new guiding shape path
+ */
+ std::pair handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const;
+
protected:
/**
* @brief Update m_markers to reflect the selection
diff --git a/src/gsi/gsi/gsiObject.cc b/src/gsi/gsi/gsiObject.cc
index 7d11f0582..0ed9bc3a4 100644
--- a/src/gsi/gsi/gsiObject.cc
+++ b/src/gsi/gsi/gsiObject.cc
@@ -27,9 +27,13 @@
#include "tlLog.h"
+#include
+
namespace gsi
{
+QMutex Proxy::m_lock;
+
Proxy::Proxy (const gsi::ClassBase *_cls_decl)
: m_cls_decl (_cls_decl),
m_obj (0),
@@ -43,21 +47,34 @@ Proxy::Proxy (const gsi::ClassBase *_cls_decl)
Proxy::~Proxy ()
{
- try {
- set (0, false, false, false);
- } catch (std::exception &ex) {
- tl::warn << "Caught exception in object destructor: " << ex.what ();
- } catch (tl::Exception &ex) {
- tl::warn << "Caught exception in object destructor: " << ex.msg ();
- } catch (...) {
- tl::warn << "Caught unspecified exception in object destructor";
+ void *prev_obj = 0;
+
+ {
+ QMutexLocker locker (&m_lock);
+ try {
+ prev_obj = set_internal (0, false, false, false);
+ } catch (std::exception &ex) {
+ tl::warn << "Caught exception in object destructor: " << ex.what ();
+ } catch (tl::Exception &ex) {
+ tl::warn << "Caught exception in object destructor: " << ex.msg ();
+ } catch (...) {
+ tl::warn << "Caught unspecified exception in object destructor";
+ }
+ m_destroyed = true;
+ }
+
+ // destroy outside the locker because the destructor may raise status
+ // changed events
+ if (prev_obj) {
+ m_cls_decl->destroy (prev_obj);
}
- m_destroyed = true;
}
void
Proxy::destroy ()
{
+ QMutexLocker locker (&m_lock);
+
if (! m_cls_decl) {
m_obj = 0;
return;
@@ -82,7 +99,7 @@ Proxy::destroy ()
if (m_owned || m_can_destroy) {
o = m_obj;
}
- detach ();
+ detach_internal ();
if (o) {
m_cls_decl->destroy (o);
}
@@ -91,28 +108,20 @@ Proxy::destroy ()
void
Proxy::detach ()
{
- if (! m_destroyed && m_cls_decl && m_cls_decl->is_managed ()) {
- gsi::ObjectBase *gsi_object = m_cls_decl->gsi_object (m_obj, false);
- if (gsi_object) {
- gsi_object->status_changed_event ().remove (this, &Proxy::object_status_changed);
- }
- }
-
- m_obj = 0;
- m_destroyed = true;
- m_const_ref = false;
- m_owned = false;
- m_can_destroy = false;
+ QMutexLocker locker (&m_lock);
+ detach_internal ();
}
void
Proxy::release ()
{
+ QMutexLocker locker (&m_lock);
+
// If the object is managed we first reset the ownership of all other clients
// and then make us the owner
const gsi::ClassBase *cls = m_cls_decl;
if (cls && cls->is_managed ()) {
- void *o = obj ();
+ void *o = obj_internal ();
if (o) {
cls->gsi_object (o)->keep ();
}
@@ -125,9 +134,11 @@ Proxy::release ()
void
Proxy::keep ()
{
+ QMutexLocker locker (&m_lock);
+
const gsi::ClassBase *cls = m_cls_decl;
if (cls) {
- void *o = obj ();
+ void *o = obj_internal ();
if (o) {
if (cls->is_managed ()) {
cls->gsi_object (o)->keep ();
@@ -142,12 +153,68 @@ Proxy::keep ()
void
Proxy::set (void *obj, bool owned, bool const_ref, bool can_destroy)
+{
+ void *prev_obj;
+
+ {
+ QMutexLocker locker (&m_lock);
+ prev_obj = set_internal (obj, owned, const_ref, can_destroy);
+ }
+
+ // destroy outside the locker because the destructor may raise status
+ // changed events
+ if (prev_obj) {
+ m_cls_decl->destroy (prev_obj);
+ }
+}
+
+void *
+Proxy::obj ()
+{
+ QMutexLocker locker (&m_lock);
+ return obj_internal ();
+}
+
+void *
+Proxy::obj_internal ()
+{
+ if (! m_obj) {
+ if (m_destroyed) {
+ throw tl::Exception (tl::to_string (QObject::tr ("Object has been destroyed already")));
+ } else {
+ // delayed creation of a detached C++ object ..
+ tl_assert (set_internal (m_cls_decl->create (), true, false, true) == 0);
+ }
+ }
+
+ return m_obj;
+}
+
+void
+Proxy::object_status_changed (gsi::ObjectBase::StatusEventType type)
+{
+ if (type == gsi::ObjectBase::ObjectDestroyed) {
+ QMutexLocker locker (&m_lock);
+ m_destroyed = true; // NOTE: must be set before detach and indicates that the object was destroyed externally.
+ detach_internal ();
+ } else if (type == gsi::ObjectBase::ObjectKeep) {
+ // NOTE: don't lock this as this will cause a deadlock from keep()
+ m_owned = false;
+ } else if (type == gsi::ObjectBase::ObjectRelease) {
+ // NOTE: don't lock this as this will cause a deadlock from release()
+ m_owned = true;
+ }
+}
+
+void *
+Proxy::set_internal (void *obj, bool owned, bool const_ref, bool can_destroy)
{
bool prev_owned = m_owned;
m_owned = owned;
m_can_destroy = can_destroy;
m_const_ref = const_ref;
+ void *prev_object = 0;
const gsi::ClassBase *cls = m_cls_decl;
if (! cls) {
@@ -169,9 +236,8 @@ Proxy::set (void *obj, bool owned, bool const_ref, bool can_destroy)
// Destroy the object if we are owner. We don't destroy the object if it was locked
// (either because we are not owner or from C++ side using keep())
if (prev_owned) {
- void *o = m_obj;
+ prev_object = m_obj;
m_obj = 0;
- cls->destroy (o);
}
}
@@ -196,34 +262,25 @@ Proxy::set (void *obj, bool owned, bool const_ref, bool can_destroy)
// now we have a valid object (or nil) - we can reset "destroyed" state. Note: this has to be done
// here because before detach might be called on *this which resets m_destroyed.
m_destroyed = false;
-}
-void *
-Proxy::obj ()
-{
- if (! m_obj) {
- if (m_destroyed) {
- throw tl::Exception (tl::to_string (tr ("Object has been destroyed already")));
- } else {
- // delayed creation of a detached C++ object ..
- set(m_cls_decl->create (), true, false, true);
- }
- }
-
- return m_obj;
+ return prev_object;
}
void
-Proxy::object_status_changed (gsi::ObjectBase::StatusEventType type)
+Proxy::detach_internal()
{
- if (type == gsi::ObjectBase::ObjectDestroyed) {
- m_destroyed = true; // NOTE: must be set before detach and indicates that the object was destroyed externally.
- detach ();
- } else if (type == gsi::ObjectBase::ObjectKeep) {
- m_owned = false;
- } else if (type == gsi::ObjectBase::ObjectRelease) {
- m_owned = true;
+ if (! m_destroyed && m_cls_decl && m_cls_decl->is_managed ()) {
+ gsi::ObjectBase *gsi_object = m_cls_decl->gsi_object (m_obj, false);
+ if (gsi_object) {
+ gsi_object->status_changed_event ().remove (this, &Proxy::object_status_changed);
+ }
}
+
+ m_obj = 0;
+ m_destroyed = true;
+ m_const_ref = false;
+ m_owned = false;
+ m_can_destroy = false;
}
}
diff --git a/src/gsi/gsi/gsiObject.h b/src/gsi/gsi/gsiObject.h
index cc39f2fb9..223c9f8d2 100644
--- a/src/gsi/gsi/gsiObject.h
+++ b/src/gsi/gsi/gsiObject.h
@@ -29,6 +29,7 @@
#include "gsiCommon.h"
#include
+#include
// For a comprehensive documentation see gsi.h
@@ -191,6 +192,17 @@ private:
*
* Using a proxy object allows having a gsi::ObjectBase that does not derive
* from tl::Object and can derive from any base class (specifically QObject).
+ *
+ * NOTE about MT safety: the model is:
+ *
+ * - the Proxy belongs to a thread
+ * - the original object (the proxy target) belongs to a different thread
+ * - there can be multiple Proxy objects for one target
+ * - the target object itself and the methods by which the proxy acts on
+ * the target object are thread safe
+ *
+ * This implies that all operations related to the manipulation of proxy
+ * to target relation need to be guarded by a lock.
*/
class GSI_PUBLIC Proxy
: public tl::Object
@@ -228,8 +240,12 @@ private:
bool m_const_ref : 1;
bool m_destroyed : 1;
bool m_can_destroy : 1;
+ static QMutex m_lock;
+ void *set_internal (void *obj, bool owned, bool const_ref, bool can_destroy);
void object_status_changed (gsi::ObjectBase::StatusEventType type);
+ void detach_internal ();
+ void *obj_internal ();
};
}
diff --git a/src/gsiqt/qt5/QtNetwork/gsiDeclQHostAddress.cc b/src/gsiqt/qt5/QtNetwork/gsiDeclQHostAddress.cc
index c6346d696..01e967cc1 100644
--- a/src/gsiqt/qt5/QtNetwork/gsiDeclQHostAddress.cc
+++ b/src/gsiqt/qt5/QtNetwork/gsiDeclQHostAddress.cc
@@ -70,25 +70,6 @@ static void _call_ctor_QHostAddress_1098 (const qt_gsi::GenericStaticMethod * /*
}
-// Constructor QHostAddress::QHostAddress(const quint8 *ip6Addr)
-
-
-static void _init_ctor_QHostAddress_1934 (qt_gsi::GenericStaticMethod *decl)
-{
- static gsi::ArgSpecBase argspec_0 ("ip6Addr");
- decl->add_arg (argspec_0);
- decl->set_return_new ();
-}
-
-static void _call_ctor_QHostAddress_1934 (const qt_gsi::GenericStaticMethod * /*decl*/, gsi::SerialArgs &args, gsi::SerialArgs &ret)
-{
- __SUPPRESS_UNUSED_WARNING(args);
- tl::Heap heap;
- const quint8 *arg1 = args.read (heap);
- ret.write (new QHostAddress (arg1));
-}
-
-
// Constructor QHostAddress::QHostAddress(const QString &address)
@@ -397,26 +378,6 @@ static void _call_f_setAddress_1098 (const qt_gsi::GenericMethod * /*decl*/, voi
}
-// void QHostAddress::setAddress(const quint8 *ip6Addr)
-
-
-static void _init_f_setAddress_1934 (qt_gsi::GenericMethod *decl)
-{
- static gsi::ArgSpecBase argspec_0 ("ip6Addr");
- decl->add_arg (argspec_0);
- decl->set_return ();
-}
-
-static void _call_f_setAddress_1934 (const qt_gsi::GenericMethod * /*decl*/, void *cls, gsi::SerialArgs &args, gsi::SerialArgs &ret)
-{
- __SUPPRESS_UNUSED_WARNING(args);
- tl::Heap heap;
- const quint8 *arg1 = args.read (heap);
- __SUPPRESS_UNUSED_WARNING(ret);
- ((QHostAddress *)cls)->setAddress (arg1);
-}
-
-
// bool QHostAddress::setAddress(const QString &address)
@@ -532,7 +493,6 @@ static gsi::Methods methods_QHostAddress () {
gsi::Methods methods;
methods += new qt_gsi::GenericStaticMethod ("new", "@brief Constructor QHostAddress::QHostAddress()\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_0, &_call_ctor_QHostAddress_0);
methods += new qt_gsi::GenericStaticMethod ("new_ip4", "@brief Constructor QHostAddress::QHostAddress(quint32 ip4Addr)\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_1098, &_call_ctor_QHostAddress_1098);
- methods += new qt_gsi::GenericStaticMethod ("new", "@brief Constructor QHostAddress::QHostAddress(const quint8 *ip6Addr)\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_1934, &_call_ctor_QHostAddress_1934);
methods += new qt_gsi::GenericStaticMethod ("new", "@brief Constructor QHostAddress::QHostAddress(const QString &address)\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_2025, &_call_ctor_QHostAddress_2025);
methods += new qt_gsi::GenericStaticMethod ("new", "@brief Constructor QHostAddress::QHostAddress(const QHostAddress ©)\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_2518, &_call_ctor_QHostAddress_2518);
methods += new qt_gsi::GenericStaticMethod ("new_special", "@brief Constructor QHostAddress::QHostAddress(QHostAddress::SpecialAddress address)\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_3172, &_call_ctor_QHostAddress_3172);
@@ -550,7 +510,6 @@ static gsi::Methods methods_QHostAddress () {
methods += new qt_gsi::GenericMethod ("protocol", "@brief Method QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol()\n", true, &_init_f_protocol_c0, &_call_f_protocol_c0);
methods += new qt_gsi::GenericMethod (":scopeId", "@brief Method QString QHostAddress::scopeId()\n", true, &_init_f_scopeId_c0, &_call_f_scopeId_c0);
methods += new qt_gsi::GenericMethod ("setAddress", "@brief Method void QHostAddress::setAddress(quint32 ip4Addr)\n", false, &_init_f_setAddress_1098, &_call_f_setAddress_1098);
- methods += new qt_gsi::GenericMethod ("setAddress", "@brief Method void QHostAddress::setAddress(const quint8 *ip6Addr)\n", false, &_init_f_setAddress_1934, &_call_f_setAddress_1934);
methods += new qt_gsi::GenericMethod ("setAddress", "@brief Method bool QHostAddress::setAddress(const QString &address)\n", false, &_init_f_setAddress_2025, &_call_f_setAddress_2025);
methods += new qt_gsi::GenericMethod ("setScopeId|scopeId=", "@brief Method void QHostAddress::setScopeId(const QString &id)\n", false, &_init_f_setScopeId_2025, &_call_f_setScopeId_2025);
methods += new qt_gsi::GenericMethod ("toIPv4Address", "@brief Method quint32 QHostAddress::toIPv4Address()\n", true, &_init_f_toIPv4Address_c0, &_call_f_toIPv4Address_c0);
diff --git a/src/lay/lay/layFontController.cc b/src/lay/lay/layFontController.cc
index ae4cbbd6b..40f5014dc 100644
--- a/src/lay/lay/layFontController.cc
+++ b/src/lay/lay/layFontController.cc
@@ -112,13 +112,11 @@ FontController::can_exit (lay::PluginRoot * /*root*/) const
void
FontController::sync_dirs ()
{
- if (! m_file_watcher) {
- return;
+ if (m_file_watcher) {
+ m_file_watcher->clear ();
+ m_file_watcher->enable (false);
}
- m_file_watcher->clear ();
- m_file_watcher->enable (false);
-
std::vector paths = lay::ApplicationBase::instance ()->klayout_path ();
// add the salt grains as potential sources for library definitions
@@ -137,14 +135,18 @@ FontController::sync_dirs ()
for (std::vector ::const_iterator p = paths.begin (); p != paths.end (); ++p) {
QDir fp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("fonts"));
if (fp.exists ()) {
- m_file_watcher->add_file (tl::to_string (fp.absolutePath ()));
+ if (m_file_watcher) {
+ m_file_watcher->add_file (tl::to_string (fp.absolutePath ()));
+ }
font_paths.push_back (tl::to_string (fp.absolutePath ()));
}
}
db::TextGenerator::set_font_paths (font_paths);
- m_file_watcher->enable (true);
+ if (m_file_watcher) {
+ m_file_watcher->enable (true);
+ }
}
void
diff --git a/src/lay/lay/layLibraryController.cc b/src/lay/lay/layLibraryController.cc
index d2db3c047..065c24b61 100644
--- a/src/lay/lay/layLibraryController.cc
+++ b/src/lay/lay/layLibraryController.cc
@@ -117,13 +117,11 @@ LibraryController::can_exit (lay::PluginRoot * /*root*/) const
void
LibraryController::sync_files ()
{
- if (! m_file_watcher) {
- return;
+ if (m_file_watcher) {
+ m_file_watcher->clear ();
+ m_file_watcher->enable (false);
}
- m_file_watcher->clear ();
- m_file_watcher->enable (false);
-
std::map > new_lib_files;
// build a list of paths vs. technology
@@ -158,7 +156,9 @@ LibraryController::sync_files ()
QDir lp = QDir (tl::to_qstring (p->first)).filePath (tl::to_qstring ("libraries"));
if (lp.exists ()) {
- m_file_watcher->add_file (tl::to_string (lp.absolutePath ()));
+ if (m_file_watcher) {
+ m_file_watcher->add_file (tl::to_string (lp.absolutePath ()));
+ }
QStringList name_filters;
name_filters << QString::fromUtf8 ("*");
@@ -222,7 +222,9 @@ LibraryController::sync_files ()
}
- m_file_watcher->enable (true);
+ if (m_file_watcher) {
+ m_file_watcher->enable (true);
+ }
// remove libraries which are no longer present
diff --git a/src/lay/lay/layMacroController.cc b/src/lay/lay/layMacroController.cc
index c0a7d7ba3..7bc3d8ca6 100644
--- a/src/lay/lay/layMacroController.cc
+++ b/src/lay/lay/layMacroController.cc
@@ -146,7 +146,10 @@ MacroController::finish ()
if (! m_no_implicit_macros) {
for (std::vector ::const_iterator p = m_external_paths.begin (); p != m_external_paths.end (); ++p) {
- lym::MacroCollection::root ().add_folder (p->description, p->path, p->cat, p->readonly);
+ lym::MacroCollection *mc = lym::MacroCollection::root ().add_folder (p->description, p->path, p->cat, p->readonly);
+ if (mc) {
+ mc->set_virtual_mode (p->type);
+ }
}
}
diff --git a/src/lay/lay/layMacroEditorPage.cc b/src/lay/lay/layMacroEditorPage.cc
index 55d80cacf..b55753fb0 100644
--- a/src/lay/lay/layMacroEditorPage.cc
+++ b/src/lay/lay/layMacroEditorPage.cc
@@ -1004,6 +1004,8 @@ MacroEditorPage::replace_all (const QString &replace)
int i = m_current_search.indexIn (b.text (), o);
if (i < 0) {
break;
+ } else if (m_current_search.matchedLength () == 0) {
+ break; // avoid an infinite loop
}
QString r = interpolate_string (replace, m_current_search);
diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc
index 469583247..94d3941c3 100644
--- a/src/lay/lay/layMainWindow.cc
+++ b/src/lay/lay/layMainWindow.cc
@@ -842,6 +842,7 @@ MainWindow::init_menu ()
MenuLayoutEntry ("show_grid", tl::to_string (QObject::tr ("Show Grid")), std::make_pair (cfg_grid_visible, "?")),
MenuLayoutEntry ("default_grid:default_grids_group", tl::to_string (QObject::tr ("Grid")), empty_menu),
MenuLayoutEntry::separator ("layout_group"),
+ MenuLayoutEntry ("show_markers", tl::to_string (QObject::tr ("Show Markers")), std::make_pair (cfg_markers_visible, "?")),
MenuLayoutEntry ("show_texts", tl::to_string (QObject::tr ("Show Texts")), std::make_pair (cfg_text_visible, "?")),
MenuLayoutEntry ("show_cell_boxes", tl::to_string (QObject::tr ("Show Cell Frames")), std::make_pair (cfg_cell_box_visible, "?")),
MenuLayoutEntry ("no_stipples", tl::to_string (QObject::tr ("Show Layers Without Fill")), std::make_pair (cfg_no_stipple, "?")),
@@ -1312,6 +1313,18 @@ MainWindow::about_to_exec ()
}
}
+ f = false;
+ config_get (cfg_markers_visible, f);
+ if (! f) {
+ TipDialog td (this,
+ tl::to_string (QObject::tr ("Markers are not visible because they have been turned off.\nYou may not see markers when using the marker browser feature.\n\nTo turn markers on, check \"Show Markers\" in the \"View\" menu.")),
+ "show-markers");
+ if (td.exec_dialog ()) {
+ // Don't bother the user with more dialogs.
+ return;
+ }
+ }
+
f = false;
config_get (cfg_hide_empty_layers, f);
if (f) {
@@ -3162,6 +3175,8 @@ MainWindow::do_save (bool as)
options.set_dbu (cv->layout ().dbu ());
options.set_format_from_filename (fn);
+ cv->update_save_options (options);
+
tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto;
if (as && ! mp_layout_save_as_options->get_options (current_view (), cv_index, fn, om, options)) {
diff --git a/src/lay/lay/laySaltDownloadManager.cc b/src/lay/lay/laySaltDownloadManager.cc
index e8c0024fe..b2ca7633c 100644
--- a/src/lay/lay/laySaltDownloadManager.cc
+++ b/src/lay/lay/laySaltDownloadManager.cc
@@ -68,7 +68,7 @@ ConfirmationDialog::add_info (const std::string &name, bool update, const std::s
item->setText (3, tl::to_qstring (url));
for (int column = 0; column < list->colorCount (); ++column) {
- item->setData (column, Qt::ForegroundRole, QVariant (QBrush (update ? Qt::blue : Qt::black)));
+ item->setData (column, Qt::ForegroundRole, QVariant (QBrush (update ? QColor (Qt::blue) : QColor (Qt::black))));
}
}
diff --git a/src/lay/lay/laySaltModel.cc b/src/lay/lay/laySaltModel.cc
index db9139800..3cce6c3a9 100644
--- a/src/lay/lay/laySaltModel.cc
+++ b/src/lay/lay/laySaltModel.cc
@@ -47,8 +47,15 @@ SaltItemDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option,
{
QStyleOptionViewItemV4 optionV4 = option;
initStyleOption (&optionV4, index);
+ // let the text take all the available space (fixes #144)
+ optionV4.showDecorationSelected = true;
bool is_enabled = (optionV4.state & QStyle::State_Enabled);
+ if ((index.flags () & 0x10000) != 0) {
+ // the item wants to be drawn "disabled"
+ is_enabled = false;
+ }
+
optionV4.state |= QStyle::State_Enabled;
QStyle *style = optionV4.widget ? optionV4.widget->style () : QApplication::style ();
@@ -121,6 +128,11 @@ SaltModel::flags (const QModelIndex &index) const
f &= ~Qt::ItemIsEnabled;
}
+ if (g && (! is_enabled (g->name ()) || g->is_hidden ())) {
+ // We use a custom flag to indicate "disabled" display without actually disabling the item
+ f |= Qt::ItemFlags (0x10000);
+ }
+
return f;
}
@@ -134,15 +146,9 @@ SaltModel::data (const QModelIndex &index, int role) const
return QVariant (tr ("There are no items to show in this list
%1
").arg (m_empty_explanation));
}
- bool en = is_enabled (g->name ());
bool hidden = g->is_hidden ();
std::string text = "";
- if (! en || hidden) {
- text += "";
- } else {
- text += "";
- }
if (hidden) {
text += "";
}
@@ -179,7 +185,6 @@ SaltModel::data (const QModelIndex &index, int role) const
text += tl::to_string (tr ("This package is an auxiliary package for use with other packages."));
text += "
";
}
- text += "";
text += "";
return tl::to_qstring (text);
diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc
index eb77cd48f..ae70b30e1 100644
--- a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc
+++ b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc
@@ -197,13 +197,13 @@ static unsigned int create_rdb (lay::LayoutView *view, const std::string &name)
}
// this binding returns a const pointer which is not converted into a copy by RBA
-static const lay::LayerPropertiesNode *insert_layer1 (lay::LayoutView *view, const lay::LayerPropertiesConstIterator &iter, const lay::LayerProperties &props)
+static lay::LayerPropertiesNodeRef insert_layer1 (lay::LayoutView *view, const lay::LayerPropertiesConstIterator &iter, const lay::LayerProperties &props)
{
const lay::LayerPropertiesNode *lp = dynamic_cast (&props);
if (lp) {
- return &view->insert_layer (iter, *lp);
+ return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (iter, *lp)));
} else {
- return &view->insert_layer (iter, props);
+ return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (iter, props)));
}
}
@@ -227,13 +227,13 @@ static void replace_layer_node1 (lay::LayoutView *view, const lay::LayerProperti
}
}
-static const lay::LayerPropertiesNode *insert_layer2 (lay::LayoutView *view, unsigned int index, const lay::LayerPropertiesConstIterator &iter, const lay::LayerProperties &props)
+static lay::LayerPropertiesNodeRef insert_layer2 (lay::LayoutView *view, unsigned int index, const lay::LayerPropertiesConstIterator &iter, const lay::LayerProperties &props)
{
const lay::LayerPropertiesNode *lp = dynamic_cast (&props);
if (lp) {
- return &view->insert_layer (index, iter, *lp);
+ return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (index, iter, *lp)));
} else {
- return &view->insert_layer (index, iter, props);
+ return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (index, iter, props)));
}
}
@@ -396,10 +396,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"layout or the cell views and the LayoutView configuration. This is usually done automatically. "
"For rare cases, where this is not the case, this method is provided.\n"
) +
- gsi::method ("title=|#set_title", &lay::LayoutView::set_title,
+ gsi::method ("title=|#set_title", &lay::LayoutView::set_title, gsi::arg ("title"),
"@brief Sets the title of the view\n"
"\n"
- "@args title\n"
"@param title The title string to use\n"
"\n"
"Override the standard title of the view indicating the file names loaded by "
@@ -419,25 +418,21 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"The title string is either a string composed of the file names loaded (in some "
"\"readable\" manner) or a customized title string set by \\set_title."
) +
- gsi::method ("save_layer_props", &lay::LayoutView::save_layer_props,
+ gsi::method ("save_layer_props", &lay::LayoutView::save_layer_props, gsi::arg ("fn"),
"@brief Saves the layer properties\n"
"\n"
- "@args fn\n"
- "\n"
"Save the layer properties to the file given in \"fn\""
) +
- gsi::method ("load_layer_props", (void (lay::LayoutView::*)(const std::string &)) &lay::LayoutView::load_layer_props,
+ gsi::method ("load_layer_props", (void (lay::LayoutView::*)(const std::string &)) &lay::LayoutView::load_layer_props, gsi::arg ("fn"),
"@brief Loads the layer properties\n"
"\n"
- "@args fn\n"
"@param fn The file name of the .lyp file to load\n"
"\n"
"Load the layer properties from the file given in \"fn\""
) +
- gsi::method ("load_layer_props", (void (lay::LayoutView::*)(const std::string &, bool)) &lay::LayoutView::load_layer_props,
+ gsi::method ("load_layer_props", (void (lay::LayoutView::*)(const std::string &, bool)) &lay::LayoutView::load_layer_props, gsi::arg ("fn"), gsi::arg ("add_default"),
"@brief Loads the layer properties with options\n"
"\n"
- "@args fn, add_default\n"
"@param fn The file name of the .lyp file to load\n"
"@param add_default If true, default layers will be added for each other layer in the layout\n"
"\n"
@@ -447,10 +442,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This variant has been added on version 0.21."
) +
- gsi::method ("load_layer_props", (void (lay::LayoutView::*)(const std::string &, int, bool)) &lay::LayoutView::load_layer_props,
+ gsi::method ("load_layer_props", (void (lay::LayoutView::*)(const std::string &, int, bool)) &lay::LayoutView::load_layer_props, gsi::arg ("fn"), gsi::arg ("cv_index"), gsi::arg ("add_default"),
"@brief Loads the layer properties with options\n"
"\n"
- "@args fn, cv_index, add_default\n"
"@param fn The file name of the .lyp file to load\n"
"@param cv_index See description text\n"
"@param add_default If true, default layers will be added for each other layer in the layout\n"
@@ -466,10 +460,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This variant has been added on version 0.21."
) +
- gsi::method ("min_hier_levels=", &lay::LayoutView::set_min_hier_levels,
+ gsi::method ("min_hier_levels=", &lay::LayoutView::set_min_hier_levels, gsi::arg ("level"),
"@brief Sets the minimum hierarchy level at which to display geometries\n"
"\n"
- "@args level\n"
"@param level The minimum level above which to display something\n"
"\n"
"This methods allows to set the minimum hierarchy level above which to display geometries."
@@ -480,10 +473,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"@return The minimum level at which to display geometries"
) +
- gsi::method ("max_hier_levels=", &lay::LayoutView::set_max_hier_levels,
+ gsi::method ("max_hier_levels=", &lay::LayoutView::set_max_hier_levels, gsi::arg ("level"),
"@brief Sets the maximum hierarchy level up to which to display geometries\n"
"\n"
- "@args level\n"
"@param level The maximum level below which to display something\n"
"\n"
"This methods allows to set the maximum hierarchy below which to display geometries."
@@ -494,10 +486,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"@return The maximum level up to which to display geometries"
) +
- gsi::method ("enable_edits", &lay::LayoutView::enable_edits,
+ gsi::method ("enable_edits", &lay::LayoutView::enable_edits, gsi::arg ("enable"),
"@brief Enables or disables edits\n"
"\n"
- "@args enable\n"
"@param enable Enable edits if set to true\n"
"\n"
"This method allows putting the view into read-only mode by disabling all edit "
@@ -508,18 +499,14 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"In 0.25, this method has been moved from MainWindow to LayoutView.\n"
) +
- gsi::method ("reload_layout", &lay::LayoutView::reload_layout,
+ gsi::method ("reload_layout", &lay::LayoutView::reload_layout, gsi::arg ("cv"),
"@brief Reloads the given cellview\n"
"\n"
- "@args cv\n"
- "\n"
"@param cv The index of the cellview to reload"
) +
- gsi::method ("create_layout", (unsigned int (lay::LayoutView::*) (bool)) &lay::LayoutView::create_layout,
+ gsi::method ("create_layout", (unsigned int (lay::LayoutView::*) (bool)) &lay::LayoutView::create_layout, gsi::arg ("add_cellview"),
"@brief Creates a new, empty layout\n"
"\n"
- "@args add_cellview\n"
- "\n"
"The add_cellview parameter controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n"
"\n"
@@ -527,11 +514,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"@return The index of the cellview created.\n"
) +
- gsi::method ("create_layout", (unsigned int (lay::LayoutView::*) (const std::string &, bool)) &lay::LayoutView::create_layout,
+ gsi::method ("create_layout", (unsigned int (lay::LayoutView::*) (const std::string &, bool)) &lay::LayoutView::create_layout, gsi::arg ("tech"), gsi::arg ("add_cellview"),
"@brief Create a new, empty layout and associate it with the given technology\n"
"\n"
- "@args tech,add_cellview\n"
- "\n"
"The add_cellview parameter controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n"
"\n"
@@ -539,11 +524,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This variant has been introduced in version 0.22.\n"
) +
- gsi::method ("create_layout", (unsigned int (lay::LayoutView::*) (const std::string &, bool, bool)) &lay::LayoutView::create_layout,
+ gsi::method ("create_layout", (unsigned int (lay::LayoutView::*) (const std::string &, bool, bool)) &lay::LayoutView::create_layout, gsi::arg ("tech"), gsi::arg ("add_cellview"), gsi::arg ("init_layers"),
"@brief Create a new, empty layout and associate it with the given technology\n"
"\n"
- "@args tech,add_cellview,init_layers\n"
- "\n"
"The add_cellview parameter controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false). This variant also allows to control whether the layer properties are\n"
"initialized (init_layers = true) or not (init_layers = false).\n"
@@ -552,9 +535,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This variant has been introduced in version 0.22.\n"
) +
- gsi::method_ext ("show_layout", &show_layout1,
+ gsi::method_ext ("show_layout", &show_layout1, gsi::arg ("layout"), gsi::arg ("add_cellview"),
"@brief Shows an existing layout in the view\n"
- "@args layout, add_cellview\n"
"\n"
"Shows the given layout in the view. If add_cellview is true, the new layout is added to the list of "
"cellviews in the view.\n"
@@ -566,9 +548,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.22.\n"
) +
- gsi::method_ext ("show_layout", &show_layout2,
+ gsi::method_ext ("show_layout", &show_layout2, gsi::arg ("layout"), gsi::arg ("tech"), gsi::arg ("add_cellview"),
"@brief Shows an existing layout in the view\n"
- "@args layout, tech, add_cellview\n"
"\n"
"Shows the given layout in the view. If add_cellview is true, the new layout is added to the list of "
"cellviews in the view.\n"
@@ -583,9 +564,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.22.\n"
) +
- gsi::method_ext ("show_layout", &show_layout3,
+ gsi::method_ext ("show_layout", &show_layout3, gsi::arg ("layout"), gsi::arg ("tech"), gsi::arg ("add_cellview"), gsi::arg ("init_layers"),
"@brief Shows an existing layout in the view\n"
- "@args layout, tech, add_cellview, init_layers\n"
"\n"
"Shows the given layout in the view. If add_cellview is true, the new layout is added to the list of "
"cellviews in the view.\n"
@@ -602,28 +582,22 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.22.\n"
) +
- gsi::method ("erase_cellview", &lay::LayoutView::erase_cellview,
+ gsi::method ("erase_cellview", &lay::LayoutView::erase_cellview, gsi::arg ("index"),
"@brief Erases the cellview with the given index\n"
"\n"
- "@args index\n"
- "\n"
"This closes the given cellview and unloads the layout associated with it, unless referred to by another cellview."
) +
- gsi::method ("rename_cellview", &lay::LayoutView::rename_cellview,
+ gsi::method ("rename_cellview", &lay::LayoutView::rename_cellview, gsi::arg ("name"), gsi::arg ("index"),
"@brief Renames the cellview with the given index\n"
"\n"
- "@args name, index\n"
- "\n"
"If the name is not unique, a unique name will be constructed from the name given.\n"
"The name may be different from the filename but is associated with the layout object.\n"
"If a layout is shared between multiple cellviews (which may happen due to a clone of the layout view\n"
"for example), all cellviews are renamed.\n"
) +
- gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &, const db::LoadLayoutOptions &, const std::string &, bool)) &lay::LayoutView::load_layout,
+ gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &, const db::LoadLayoutOptions &, const std::string &, bool)) &lay::LayoutView::load_layout, gsi::arg ("filename"), gsi::arg ("options"), gsi::arg ("technology"), gsi::arg ("add_cellview"),
"@brief Loads a (new) file into the layout view with the given technology\n"
"\n"
- "@args filename, options, technology, add_cellview\n"
- "\n"
"Loads the file given by the \"filename\" parameter and associates it with the given technology.\n"
"The options specify various options for reading the file.\n"
"The add_cellview param controls whether to create a new cellview (true)\n"
@@ -633,11 +607,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This version has been introduced in version 0.22.\n"
) +
- gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &, const db::LoadLayoutOptions &, bool)) &lay::LayoutView::load_layout,
+ gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &, const db::LoadLayoutOptions &, bool)) &lay::LayoutView::load_layout, gsi::arg ("filename"), gsi::arg ("options"), gsi::arg ("add_cellview"),
"@brief Loads a (new) file into the layout view\n"
"\n"
- "@args filename, options, add_cellview\n"
- "\n"
"Loads the file given by the \"filename\" parameter.\n"
"The options specify various options for reading the file.\n"
"The add_cellview param controls whether to create a new cellview (true)\n"
@@ -647,11 +619,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.18.\n"
) +
- gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &, const std::string &, bool)) &lay::LayoutView::load_layout,
+ gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &, const std::string &, bool)) &lay::LayoutView::load_layout, gsi::arg ("filename"), gsi::arg ("technology"), gsi::arg ("add_cellview"),
"@brief Loads a (new) file into the layout view with the given technology\n"
"\n"
- "@args filename, technology, add_cellview\n"
- "\n"
"Loads the file given by the \"filename\" parameter and associates it with the given technology.\n"
"The add_cellview param controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n"
@@ -660,11 +630,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This version has been introduced in version 0.22.\n"
) +
- gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &filename, bool add_cellview)) &lay::LayoutView::load_layout,
+ gsi::method ("load_layout", (unsigned int (lay::LayoutView::*) (const std::string &filename, bool add_cellview)) &lay::LayoutView::load_layout, gsi::arg ("filename"), gsi::arg ("add_cellview"),
"@brief Loads a (new) file into the layout view\n"
"\n"
- "@args filename, add_cellview\n"
- "\n"
"Loads the file given by the \"filename\" parameter.\n"
"The add_cellview param controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n"
@@ -683,19 +651,16 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("active_cellview_index", &lay::LayoutView::active_cellview_index,
"@brief Gets the index of the active cellview (shown in hierarchy browser)\n"
) +
- gsi::method ("active_setview_index=|#set_active_cellview_index", &lay::LayoutView::set_active_cellview_index,
+ gsi::method ("active_setview_index=|#set_active_cellview_index", &lay::LayoutView::set_active_cellview_index, gsi::arg ("index"),
"@brief Makes the cellview with the given index the active one (shown in hierarchy browser)\n"
- "@args index\n"
"See \\active_cellview_index.\n"
"\n"
"This method has been renamed from set_active_cellview_index to active_cellview_index= in version 0.25. "
"The original name is still available, but is deprecated."
) +
- gsi::method_ext ("selected_cells_paths", &selected_cells_paths,
+ gsi::method_ext ("selected_cells_paths", &selected_cells_paths, gsi::arg ("cv_index"),
"@brief Gets the paths of the selected cells\n"
"\n"
- "@args cv_index\n"
- "\n"
"Gets a list of cell paths to the cells selected in the cellview given by \\cv_index. "
"The \"selected cells\" are the ones selected in the cell list or cell tree. This is not the \"current cell\" "
"which is the one that is shown in the layout window.\n"
@@ -704,11 +669,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has be introduced in version 0.25.\n"
) +
- gsi::method ("#get_current_cell_path", &lay::LayoutView::get_current_cell_path,
+ gsi::method ("#get_current_cell_path", &lay::LayoutView::get_current_cell_path, gsi::arg ("cv_index"),
"@brief Gets the cell path of the current cell\n"
"\n"
- "@args cv_index\n"
- "\n"
"The current cell is the one highlighted in the browser with the focus rectangle. The \n"
"current path is returned for the cellview given by cv_index.\n"
"The cell path is a list of cell indices from the top cell to the current cell.\n"
@@ -717,11 +680,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method is was deprecated in version 0.25 since from then, the \\CellView object can be used to obtain an manipulate the selected cell."
) +
- gsi::method ("#set_current_cell_path", (void (lay::LayoutView::*) (int, const lay::LayoutView::cell_path_type &)) &lay::LayoutView::set_current_cell_path,
+ gsi::method ("#set_current_cell_path", (void (lay::LayoutView::*) (int, const lay::LayoutView::cell_path_type &)) &lay::LayoutView::set_current_cell_path, gsi::arg ("cv_index"), gsi::arg ("cell_path"),
"@brief Sets the path to the current cell\n"
"\n"
- "@args cv_index\n"
- "\n"
"The current cell is the one highlighted in the browser with the focus rectangle. The\n"
"cell given by the path is hightlighted and scrolled into view.\n"
"To select the cell to be drawn, use the \\select_cell or \\select_cell_path method.\n"
@@ -734,11 +695,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("cellviews", &lay::LayoutView::cellviews,
"@brief Gets the number of cellviews\n"
) +
- gsi::method ("cellview", &lay::LayoutView::cellview_ref,
+ gsi::method ("cellview", &lay::LayoutView::cellview_ref, gsi::arg ("cv_index"),
"@brief Gets the cellview object for a given index\n"
"\n"
- "@args cv_index\n"
- "\n"
"@param cv_index The cellview index for which to get the object for\n"
"\n"
"Starting with version 0.25, this method returns a \\CellView object that can be manipulated to directly reflect "
@@ -752,10 +711,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.25.\n"
) +
- gsi::method ("zoom_box", &lay::LayoutView::zoom_box,
+ gsi::method ("zoom_box", &lay::LayoutView::zoom_box, gsi::arg ("box"),
"@brief Sets the viewport to the given box\n"
"\n"
- "@args box\n"
"@param box The box to which to set the view in micron coordinates\n"
) +
gsi::method ("zoom_in", &lay::LayoutView::zoom_in,
@@ -776,11 +734,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("pan_right", &lay::LayoutView::pan_right,
"@brief Pans to the right"
) +
- gsi::method ("pan_center", &lay::LayoutView::pan_center,
+ gsi::method ("pan_center", &lay::LayoutView::pan_center, gsi::arg ("p"),
"@brief Pans to the given point\n"
"\n"
- "@args p\n"
- "\n"
"The window is positioned such that \"p\" becomes the new center"
) +
gsi::method ("box", &lay::LayoutView::box,
@@ -801,11 +757,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Return the viewport height in pixels\n"
"This method was introduced in version 0.18.\n"
) +
- gsi::method ("bookmark_view", &lay::LayoutView::bookmark_view,
+ gsi::method ("bookmark_view", &lay::LayoutView::bookmark_view, gsi::arg ("name"),
"@brief Bookmarks the current view under the given name\n"
"\n"
- "@args name\n"
- "\n"
"@param name The name under which to bookmark the current state"
) +
gsi::method ("add_missing_layers", &lay::LayoutView::add_missing_layers,
@@ -816,9 +770,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Removes unused layers from layer list\n"
"This method was introduced in version 0.19.\n"
) +
- gsi::method ("init_layer_properties", (void (lay::LayoutView::*) (lay::LayerProperties &) const) &lay::LayoutView::init_layer_properties,
+ gsi::method ("init_layer_properties", (void (lay::LayoutView::*) (lay::LayerProperties &) const) &lay::LayoutView::init_layer_properties, gsi::arg ("props"),
"@brief Fills the layer properties for a new layer\n"
- "@args props\n"
"\n"
"This method initializes a layer properties object's color and stipples according to "
"the defaults for the given layer source specification. The layer's source must be set already "
@@ -839,11 +792,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Stops redraw thread and close any browsers\n"
"This method usually does not need to be called explicitly. The redraw thread is stopped automatically."
) +
- gsi::method ("#select_cell_path", (void (lay::LayoutView::*) (const lay::LayoutView::cell_path_type &, int)) &lay::LayoutView::select_cell,
+ gsi::method ("#select_cell_path", (void (lay::LayoutView::*) (const lay::LayoutView::cell_path_type &, int)) &lay::LayoutView::select_cell, gsi::arg ("cell_index"), gsi::arg ("cv_index"),
"@brief Selects a cell by cell index for a certain cell view\n"
"\n"
- "@args cell_index, cv_index\n"
- "\n"
"Select the current (top) cell by specifying a cell indexand the cellview index for which this cell should become the currently shown one. The path to the cell is constructed by "
"selecting one that leads to a top cell.\n"
"This method selects the cell to be drawn. In constrast, the \\set_current_cell_path method selects "
@@ -851,11 +802,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method is was deprecated in version 0.25 since from then, the \\CellView object can be used to obtain an manipulate the selected cell."
) +
- gsi::method ("#select_cell", (void (lay::LayoutView::*) (lay::LayoutView::cell_index_type, int)) &lay::LayoutView::select_cell,
+ gsi::method ("#select_cell", (void (lay::LayoutView::*) (lay::LayoutView::cell_index_type, int)) &lay::LayoutView::select_cell, gsi::arg ("cell_index"), gsi::arg ("cv_index"),
"@brief Selects a cell by index for a certain cell view\n"
"\n"
- "@args cell_index, cv_index\n"
- "\n"
"Select the current (top) cell by specifying a path (a list of cell indices from top to "
"the actual cell) and the cellview index for which this cell should become the currently "
"shown one.\n"
@@ -864,9 +813,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method is was deprecated in version 0.25 since from then, the \\CellView object can be used to obtain an manipulate the selected cell."
) +
- gsi::method ("descend", &lay::LayoutView::descend,
+ gsi::method ("descend", &lay::LayoutView::descend, gsi::arg ("path"), gsi::arg ("index"),
"@brief Descends further into the hierarchy.\n"
- "@args path, index\n"
+ "\n"
"Adds the given path (given as an array of InstElement objects) to the specific path of the "
"cellview with the given index. In effect, the cell addressed by the terminal of the new path "
"components can be shown in the context of the upper cells, if the minimum hierarchy level is "
@@ -874,28 +823,22 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"The path is assumed to originate from the current cell and contain specific instances sorted from "
"top to bottom."
) +
- gsi::method ("ascend", &lay::LayoutView::ascend,
+ gsi::method ("ascend", &lay::LayoutView::ascend, gsi::arg ("index"),
"@brief Ascends upwards in the hierarchy.\n"
- "@args index\n"
+ "\n"
"Removes one element from the specific path of the cellview with the given index. Returns the element "
"removed."
) +
- gsi::method ("is_cell_hidden?", &lay::LayoutView::is_cell_hidden,
+ gsi::method ("is_cell_hidden?", &lay::LayoutView::is_cell_hidden, gsi::arg ("cell_index"), gsi::arg ("cv_index"),
"@brief Returns true, if the cell is hidden\n"
"\n"
- "@args cell_index, cv_index\n"
- "\n"
"@return True, if the cell with \"cell_index\" is hidden for the cellview \"cv_index\""
) +
- gsi::method ("hide_cell", &lay::LayoutView::hide_cell,
+ gsi::method ("hide_cell", &lay::LayoutView::hide_cell, gsi::arg ("cell_index"), gsi::arg ("cv_index"),
"@brief Hides the given cell for the given cellview\n"
- "\n"
- "@args cell_index, cv_index\n"
) +
- gsi::method ("show_cell", &lay::LayoutView::show_cell,
+ gsi::method ("show_cell", &lay::LayoutView::show_cell, gsi::arg ("cell_index"), gsi::arg ("cv_index"),
"@brief Shows the given cell for the given cellview (cancel effect of \\hide_cell)\n"
- "\n"
- "@args cell_index, cv_index\n"
) +
gsi::method ("show_all_cells", (void (lay::LayoutView::*) ()) &lay::LayoutView::show_all_cells,
"@brief Makes all cells shown (cancel effects of \\hide_cell)"
@@ -929,20 +872,18 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"for the application to guarantee this condition. The image will have the size of the viewport "
"showing the current layout."
) +
- gsi::method ("get_image", &lay::LayoutView::get_image,
+ gsi::method ("get_image", &lay::LayoutView::get_image, gsi::arg ("width"), gsi::arg ("height"),
"@brief Gets the layout image as a \\QImage\n"
"\n"
- "@args width, height\n"
"@param width The width of the image to render in pixel.\n"
"@param height The height of the image to render in pixel.\n"
"\n"
"The image contains the current scene (layout, annotations etc.).\n"
"The image is drawn synchroneously with the given width and height. Drawing may take some time. "
) +
- gsi::method_ext ("get_image_with_options", &get_image_with_options,
+ gsi::method_ext ("get_image_with_options", &get_image_with_options, gsi::arg ("width"), gsi::arg ("height"), gsi::arg ("linewidth"), gsi::arg ("oversampling"), gsi::arg ("resolution"), gsi::arg ("target"), gsi::arg ("monochrome"),
"@brief Gets the layout image as a \\QImage (with options)\n"
"\n"
- "@args width, height, linewidth, oversampling, resolution, target, monochrome\n"
"@param width The width of the image to render in pixel.\n"
"@param height The height of the image to render in pixel.\n"
"@param linewidth The width of a line in pixels (usually 1) or 0 for default.\n"
@@ -959,10 +900,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"This method has been introduced in 0.23.10.\n"
) +
#endif
- gsi::method ("save_screenshot", &lay::LayoutView::save_screenshot,
+ gsi::method ("save_screenshot", &lay::LayoutView::save_screenshot, gsi::arg ("filename"),
"@brief Saves a screenshot to the given file\n"
"\n"
- "@args filename\n"
"@param filename The file to which to write the screenshot to.\n"
"\n"
"The screenshot is written as a PNG file to the given file. "
@@ -970,10 +910,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"for the application to guarantee this condition. The image will have the size of the viewport "
"showing the current layout."
) +
- gsi::method ("save_image", &lay::LayoutView::save_image,
+ gsi::method ("save_image", &lay::LayoutView::save_image, gsi::arg ("filename"), gsi::arg ("width"), gsi::arg ("height"),
"@brief Saves the layout as an image to the given file\n"
"\n"
- "@args filename, width, height\n"
"@param filename The file to which to write the screenshot to.\n"
"@param width The width of the image to render in pixel.\n"
"@param height The height of the image to render in pixel.\n"
@@ -982,10 +921,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"The image is written as a PNG file to the given file. "
"The image is drawn synchroneously with the given width and height. Drawing may take some time. "
) +
- gsi::method_ext ("save_image_with_options", &save_image_with_options,
+ gsi::method_ext ("save_image_with_options", &save_image_with_options, gsi::arg ("filename"), gsi::arg ("width"), gsi::arg ("height"), gsi::arg ("linewidth"), gsi::arg ("oversampling"), gsi::arg ("resolution"), gsi::arg ("target"), gsi::arg ("monochrome"),
"@brief Saves the layout as an image to the given file (with options)\n"
"\n"
- "@args filename, width, height, linewidth, oversampling, resolution, target, monochrome\n"
"@param filename The file to which to write the screenshot to.\n"
"@param width The width of the image to render in pixel.\n"
"@param height The height of the image to render in pixel.\n"
@@ -1002,10 +940,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in 0.23.10.\n"
) +
- gsi::method_ext ("#save_as", &save_as2,
+ gsi::method_ext ("#save_as", &save_as2, gsi::arg ("index"), gsi::arg ("filename"), gsi::arg ("gzip"), gsi::arg ("options"),
"@brief Saves a layout to the given stream file\n"
"\n"
- "@args index, filename, gzip, options\n"
"@param index The cellview index of the layout to save.\n"
"@param filename The file to write.\n"
"@param gzip Ignored.\n"
@@ -1019,10 +956,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"This method is deprecated starting from version 0.23. The compression mode is "
"determined from the file name automatically and the \\gzip parameter is ignored.\n"
) +
- gsi::method_ext ("save_as", &save_as1,
+ gsi::method_ext ("save_as", &save_as1, gsi::arg ("index"), gsi::arg ("filename"), gsi::arg ("options"),
"@brief Saves a layout to the given stream file\n"
"\n"
- "@args index, filename, options\n"
"@param index The cellview index of the layout to save.\n"
"@param filename The file to write.\n"
"@param options Writer options.\n"
@@ -1035,16 +971,14 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"If the file name ends with a suffix \".gz\" or \".gzip\", the file is compressed with the zlib "
"algorithm.\n"
) +
- gsi::method ("set_layer_properties", (void (lay::LayoutView::*) (const lay::LayerPropertiesConstIterator &, const lay::LayerProperties &)) &lay::LayoutView::set_properties,
+ gsi::method ("set_layer_properties", (void (lay::LayoutView::*) (const lay::LayerPropertiesConstIterator &, const lay::LayerProperties &)) &lay::LayoutView::set_properties, gsi::arg ("iter"), gsi::arg ("props"),
"@brief Sets the layer properties of the layer pointed to by the iterator\n"
- "@args iter, props\n"
"\n"
"This method replaces the layer properties of the element pointed to by \"iter\" by the properties "
"given by \"props\". It will not change the hierarchy but just the properties of the given node."
) +
- gsi::method ("set_layer_properties", (void (lay::LayoutView::*) (unsigned int index, const lay::LayerPropertiesConstIterator &, const lay::LayerProperties &)) &lay::LayoutView::set_properties,
+ gsi::method ("set_layer_properties", (void (lay::LayoutView::*) (unsigned int index, const lay::LayerPropertiesConstIterator &, const lay::LayerProperties &)) &lay::LayoutView::set_properties, gsi::arg ("index"), gsi::arg ("iter"), gsi::arg ("props"),
"@brief Sets the layer properties of the layer pointed to by the iterator\n"
- "@args index, iter, props\n"
"\n"
"This method replaces the layer properties of the element pointed to by \"iter\" by the properties "
"given by \"props\" in the tab given by \"index\". It will not change the hierarchy but just the properties of the given node."
@@ -1059,34 +993,30 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method was introduced in version 0.21.\n"
) +
- gsi::method ("expand_layer_properties", (void (lay::LayoutView::*) (unsigned int)) &lay::LayoutView::expand_properties,
+ gsi::method ("expand_layer_properties", (void (lay::LayoutView::*) (unsigned int)) &lay::LayoutView::expand_properties, gsi::arg ("index"),
"@brief Expands the layer properties for the given tab\n"
- "@args index\n"
"\n"
"This method will expand all wildcard specifications in the layer properties by iterating over the specified objects (i.e. layers, cellviews) and "
"by replacing default colors and stipples by the ones specified with the palettes.\n"
"\n"
"This method was introduced in version 0.21.\n"
) +
- gsi::method_ext ("replace_layer_node", &replace_layer_node1,
+ gsi::method_ext ("replace_layer_node", &replace_layer_node1, gsi::arg ("iter"), gsi::arg ("node"),
"@brief Replaces the layer node at the position given by \"iter\" with a new one\n"
- "@args iter, node\n"
"\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode "
"object can contain a hierarchy of further nodes."
) +
- gsi::method_ext ("replace_layer_node", &replace_layer_node2,
+ gsi::method_ext ("replace_layer_node", &replace_layer_node2, gsi::arg ("index"), gsi::arg ("iter"), gsi::arg ("node"),
"@brief Replaces the layer node at the position given by \"iter\" with a new one\n"
- "@args index, iter, node\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"\n"
"This method has been introduced in version 0.21.\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode "
"object can contain a hierarchy of further nodes."
) +
- gsi::method_ext ("insert_layer", &insert_layer1,
+ gsi::method_ext ("insert_layer", &insert_layer1, gsi::arg ("iter"), gsi::arg ("node", lay::LayerProperties (), "LayerProperties()"),
"@brief Inserts the given layer properties node into the list before the given position\n"
- "@args iter, node\n"
"\n"
"This method inserts the new properties node before the position given by \"iter\" and returns "
"a const reference to the element created. The iterator that specified the position will remain valid "
@@ -1094,11 +1024,12 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"To add children to the node inserted, use iter.last_child as insertion point for the next insert operations.\n"
"\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode "
- "object can contain a hierarchy of further nodes."
+ "object can contain a hierarchy of further nodes.\n"
+ "Since version 0.26 the node parameter is optional and the "
+ "reference returned by this method can be used to set the properties of the new node."
) +
- gsi::method_ext ("insert_layer", &insert_layer2,
+ gsi::method_ext ("insert_layer", &insert_layer2, gsi::arg ("index"), gsi::arg ("iter"), gsi::arg ("node", lay::LayerProperties (), "LayerProperties()"),
"@brief Inserts the given layer properties node into the list before the given position\n"
- "@args index, iter, node\n"
"\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"This method inserts the new properties node before the position given by \"iter\" and returns "
@@ -1107,9 +1038,11 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.21.\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode "
- "object can contain a hierarchy of further nodes."
+ "object can contain a hierarchy of further nodes.\n"
+ "Since version 0.26 the node parameter is optional and the "
+ "reference returned by this method can be used to set the properties of the new node."
) +
- gsi::method_ext ("delete_layers", &delete_layers1,
+ gsi::method_ext ("delete_layers", &delete_layers1, gsi::arg ("iterators"),
"@brief Deletes the layer properties nodes specified by the iterator\n"
"@args iterators\n"
"\n"
@@ -1118,25 +1051,22 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been added in version 0.22.\n"
) +
- gsi::method_ext ("delete_layers", &delete_layers2,
+ gsi::method_ext ("delete_layers", &delete_layers2, gsi::arg ("index"), gsi::arg ("iterators"),
"@brief Deletes the layer properties nodes specified by the iterator\n"
- "@args index, iterators\n"
"\n"
"This method deletes the nodes specifies by the iterators. This method is the most convenient way to "
"delete multiple entries.\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"This method has been introduced in version 0.22.\n"
) +
- gsi::method ("delete_layer", (void (lay::LayoutView::*) (lay::LayerPropertiesConstIterator &iter)) &lay::LayoutView::delete_layer,
+ gsi::method ("delete_layer", (void (lay::LayoutView::*) (lay::LayerPropertiesConstIterator &iter)) &lay::LayoutView::delete_layer, gsi::arg ("iter"),
"@brief Deletes the layer properties node specified by the iterator\n"
- "@args iter\n"
"\n"
"This method deletes the object that the iterator points to and invalidates\n"
"the iterator since the object that the iterator points to is no longer valid.\n"
) +
- gsi::method ("delete_layer", (void (lay::LayoutView::*) (unsigned int index, lay::LayerPropertiesConstIterator &iter)) &lay::LayoutView::delete_layer,
+ gsi::method ("delete_layer", (void (lay::LayoutView::*) (unsigned int index, lay::LayerPropertiesConstIterator &iter)) &lay::LayoutView::delete_layer, gsi::arg ("index"), gsi::arg ("iter"),
"@brief Deletes the layer properties node specified by the iterator\n"
- "@args index, iter\n"
"\n"
"This method deletes the object that the iterator points to and invalidates\n"
"the iterator since the object that the iterator points to is no longer valid.\n"
@@ -1183,9 +1113,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief End iterator for the layers\n"
"See \\begin_layers for a description about this iterator\n"
) +
- gsi::method ("begin_layers", (lay::LayerPropertiesConstIterator (lay::LayoutView::*) (unsigned int index) const) &lay::LayoutView::begin_layers,
+ gsi::method ("begin_layers", (lay::LayerPropertiesConstIterator (lay::LayoutView::*) (unsigned int index) const) &lay::LayoutView::begin_layers, gsi::arg ("index"),
"@brief Begin iterator for the layers\n"
- "@args index\n"
"\n"
"This iterator delivers the layers of this view, either in a recursive or non-recursive\n"
"fashion, depending which iterator increment methods are used.\n"
@@ -1194,9 +1123,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"This method has been introduced in version 0.21.\n"
) +
- gsi::method ("end_layers", (lay::LayerPropertiesConstIterator (lay::LayoutView::*) (unsigned int index) const) &lay::LayoutView::end_layers,
+ gsi::method ("end_layers", (lay::LayerPropertiesConstIterator (lay::LayoutView::*) (unsigned int index) const) &lay::LayoutView::end_layers, gsi::arg ("index"),
"@brief End iterator for the layers\n"
- "@args index\n"
"See \\begin_layers for a description about this iterator\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"This method has been introduced in version 0.21.\n"
@@ -1204,21 +1132,18 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("clear_layers", (void (lay::LayoutView::*) ()) &lay::LayoutView::clear_layers,
"@brief Clears all layers\n"
) +
- gsi::method ("clear_layers", (void (lay::LayoutView::*) (unsigned int index)) &lay::LayoutView::clear_layers,
+ gsi::method ("clear_layers", (void (lay::LayoutView::*) (unsigned int index)) &lay::LayoutView::clear_layers, gsi::arg ("index"),
"@brief Clears all layers for the given layer properties list\n"
- "@args index\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"This method has been introduced in version 0.21.\n"
) +
- gsi::method ("delete_layer_list", (void (lay::LayoutView::*) (unsigned int index)) &lay::LayoutView::delete_layer_list,
+ gsi::method ("delete_layer_list", (void (lay::LayoutView::*) (unsigned int index)) &lay::LayoutView::delete_layer_list, gsi::arg ("index"),
"@brief Deletes the given properties list\n"
- "@args index\n"
"At least one layer properties list must remain. This method may change the current properties list.\n"
"This method has been introduced in version 0.21.\n"
) +
- gsi::method ("insert_layer_list", (void (lay::LayoutView::*) (unsigned int index)) &lay::LayoutView::insert_layer_list,
+ gsi::method ("insert_layer_list", (void (lay::LayoutView::*) (unsigned int index)) &lay::LayoutView::insert_layer_list, gsi::arg ("index"),
"@brief Inserts a new layer properties list at the given index\n"
- "@args index\n"
"This method inserts a new tab at the given position. The current layer properties list will be changed to "
"the new list.\n"
"This method has been introduced in version 0.21.\n"
@@ -1231,19 +1156,16 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Gets the index of the currently selected layer properties tab\n"
"This method has been introduced in version 0.21.\n"
) +
- gsi::method ("current_layer_list=|#set_current_layer_list", &lay::LayoutView::set_current_layer_list,
+ gsi::method ("current_layer_list=|#set_current_layer_list", &lay::LayoutView::set_current_layer_list, gsi::arg ("index"),
"@brief Sets the index of the currently selected layer properties tab\n"
- "@args index\n"
"This method has been introduced in version 0.21.\n"
) +
- gsi::method ("rename_layer_list", &lay::LayoutView::rename_properties,
+ gsi::method ("rename_layer_list", &lay::LayoutView::rename_properties, gsi::arg ("index"), gsi::arg ("name"),
"@brief Sets the title of the given layer properties tab\n"
- "@args index, name\n"
"This method has been introduced in version 0.21.\n"
) +
- gsi::method_ext ("remove_stipple", &remove_stipple,
+ gsi::method_ext ("remove_stipple", &remove_stipple, gsi::arg ("index"),
"@brief Removes the stipple pattern with the given index\n"
- "@args index\n"
"The pattern with an index less than the first custom pattern cannot be removed. "
"If a stipple pattern is removed that is still used, the results are undefined. "
) +
@@ -1286,9 +1208,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.25."
) +
- gsi::method_ext ("remove_line_style", &remove_line_style,
+ gsi::method_ext ("remove_line_style", &remove_line_style, gsi::arg ("index"),
"@brief Removes the line style with the given index\n"
- "@args index\n"
"The line styles with an index less than the first custom style. "
"If a style is removed that is still used, the results are undefined.\n"
"\n"
@@ -1335,9 +1256,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"Returns the \\LayerPropertiesIterator pointing to the current layer view (the one that has the focus). "
"If no layer view is active currently, a null iterator is returned.\n"
) +
- gsi::method ("current_layer=", (void (lay::LayoutView::*) (const lay::LayerPropertiesConstIterator &l)) &lay::LayoutView::set_current_layer,
+ gsi::method ("current_layer=", (void (lay::LayoutView::*) (const lay::LayerPropertiesConstIterator &l)) &lay::LayoutView::set_current_layer, gsi::arg ("iter"),
"@brief Sets the current layer view\n"
- "@args iter\n"
"\n"
"Specifies an \\LayerPropertiesIterator pointing to the new current layer view.\n"
"\n"
@@ -1367,9 +1287,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"Before version 0.25 this event was based on the observer pattern obsolete now. The corresponding methods "
"(add_cellview_list_observer/remove_cellview_list_observer) have been removed in 0.25.\n"
) +
- gsi::event ("on_cellview_changed", &lay::LayoutView::cellview_changed_event,
+ gsi::event ("on_cellview_changed", &lay::LayoutView::cellview_changed_event, gsi::arg ("cellview_index"),
"@brief An event indicating that a cellview has changed\n"
- "@args cellview_index\n"
"\n"
"If a cellview is modified, this event is triggered.\n"
"When this event is triggered, the cellview have already been changed.\n"
@@ -1414,9 +1333,8 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"Before version 0.25 this event was based on the observer pattern obsolete now. The corresponding methods "
"(add_viewport_changed_observer/remove_viewport_changed_observer) have been removed in 0.25.\n"
) +
- gsi::event ("on_layer_list_changed", &lay::LayoutView::layer_list_changed_event,
+ gsi::event ("on_layer_list_changed", &lay::LayoutView::layer_list_changed_event, gsi::arg ("flags"),
"@brief An event indicating that the layer list has changed\n"
- "@args flags\n"
"\n"
"This event is triggered after the layer list has changed it's configuration.\n"
"The integer argument gives a hint about the nature of the changed:\n"
@@ -1426,27 +1344,24 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"Before version 0.25 this event was based on the observer pattern obsolete now. The corresponding methods "
"(add_layer_list_observer/remove_layer_list_observer) have been removed in 0.25.\n"
) +
- gsi::event ("on_layer_list_inserted", &lay::LayoutView::layer_list_inserted_event,
+ gsi::event ("on_layer_list_inserted", &lay::LayoutView::layer_list_inserted_event, gsi::arg ("index"),
"@brief An event indicating that a layer list (a tab) has been inserted\n"
- "@args index\n"
"@param index The index of the layer list that was inserted\n"
"\n"
"This event is triggered after the layer list has been inserted - i.e. a new tab was created.\n"
"\n"
"This event was introduced in version 0.25.\n"
) +
- gsi::event ("on_layer_list_deleted", &lay::LayoutView::layer_list_deleted_event,
+ gsi::event ("on_layer_list_deleted", &lay::LayoutView::layer_list_deleted_event, gsi::arg ("index"),
"@brief An event indicating that a layer list (a tab) has been removed\n"
- "@args index\n"
"@param index The index of the layer list that was removed\n"
"\n"
"This event is triggered after the layer list has been removed - i.e. a tab was deleted.\n"
"\n"
"This event was introduced in version 0.25.\n"
) +
- gsi::event ("on_current_layer_list_changed", &lay::LayoutView::current_layer_list_changed_event,
+ gsi::event ("on_current_layer_list_changed", &lay::LayoutView::current_layer_list_changed_event, gsi::arg ("index"),
"@brief An event indicating the current layer list (the selected tab) has changed\n"
- "@args index\n"
"@param index The index of the new current layer list\n"
"\n"
"This event is triggered after the current layer list was changed - i.e. a new tab was selected.\n"
@@ -1491,28 +1406,24 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Gets the number of report databases loaded into this view\n"
"@return The number of \\ReportDatabase objects present in this view\n"
) +
- gsi::method ("remove_rdb", &lay::LayoutView::remove_rdb,
+ gsi::method ("remove_rdb", &lay::LayoutView::remove_rdb, gsi::arg ("index"),
"@brief Removes a report database with the given index\n"
- "@args index\n"
"@param The index of the report database to remove from this view"
) +
- gsi::method ("rdb", (rdb::Database *(lay::LayoutView::*) (int index)) &lay::LayoutView::get_rdb,
+ gsi::method ("rdb", (rdb::Database *(lay::LayoutView::*) (int index)) &lay::LayoutView::get_rdb, gsi::arg ("index"),
"@brief Gets the report database with the given index\n"
- "@args index\n"
"@return The \\ReportDatabase object or nil if the index is not valid"
) +
- gsi::method_ext ("create_rdb", &create_rdb,
+ gsi::method_ext ("create_rdb", &create_rdb, gsi::arg ("name"),
"@brief Creates a new report database and returns the index of the new database\n"
- "@args name\n"
"@param name The name of the new report database\n"
"@return The index of the new database\n"
"This method returns an index of the new report database. Use \\rdb to get the actual object. "
"If a report database with the given name already exists, a unique name will be created.\n"
"The name will be replaced by the file name when a file is loaded into the report database.\n"
) +
- gsi::method ("show_rdb", &lay::LayoutView::open_rdb_browser,
+ gsi::method ("show_rdb", &lay::LayoutView::open_rdb_browser, gsi::arg ("rdb_index"), gsi::arg ("cv_index"),
"@brief Shows a report database in the marker browser on a certain layout\n"
- "@args rdb_index, cv_index\n"
"The marker browser is opened showing the report database with the index given by \"rdb_index\".\n"
"It will be attached (i.e. navigate to) the layout with the given cellview index in \"cv_index\".\n"
) +
@@ -1542,10 +1453,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
// TODO: this method belongs to the Plugin interface and should be located there.
// Change this once there is a mixin concept available and the Plugin interface can
// be mixed into LayoutView.
- gsi::method ("get_config", (std::string (lay::LayoutView::*)(const std::string &name) const) &lay::LayoutView::config_get,
+ gsi::method ("get_config", (std::string (lay::LayoutView::*)(const std::string &name) const) &lay::LayoutView::config_get, gsi::arg ("name"),
"@brief Gets the value of a local configuration parameter\n"
"\n"
- "@args name\n"
"@param name The name of the configuration parameter whose value shall be obtained (a string)\n"
"\n"
"@return The value of the parameter\n"
@@ -1555,10 +1465,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
// TODO: this method belongs to the Plugin interface and should be located there.
// Change this once there is a mixin concept available and the Plugin interface can
// be mixed into LayoutView.
- gsi::method ("set_config", (void (lay::LayoutView::*)(const std::string &name, const std::string &value)) &lay::LayoutView::config_set,
+ gsi::method ("set_config", (void (lay::LayoutView::*)(const std::string &name, const std::string &value)) &lay::LayoutView::config_set, gsi::arg ("name"), gsi::arg ("value"),
"@brief Sets a local configuration parameter with the given name to the given value\n"
"\n"
- "@args name, value\n"
"@param name The name of the configuration parameter to set\n"
"@param value The value to which to set the configuration parameter\n"
"\n"
@@ -1580,10 +1489,9 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n"
"This method has been introduced in version 0.25.\n"
) +
- gsi::method_ext ("transaction", &gsi::transaction,
+ gsi::method_ext ("transaction", &gsi::transaction, gsi::arg ("description"),
"@brief Begins a transaction\n"
"\n"
- "@args description\n"
"@param description A text that appears in the 'undo' description\n"
"\n"
"A transaction brackets a sequence of database modifications that appear as a single "
diff --git a/src/laybasic/laybasic/gsiDeclLayMarker.cc b/src/laybasic/laybasic/gsiDeclLayMarker.cc
index 15dab23ed..0b78ce91d 100644
--- a/src/laybasic/laybasic/gsiDeclLayMarker.cc
+++ b/src/laybasic/laybasic/gsiDeclLayMarker.cc
@@ -164,6 +164,18 @@ Class decl_Marker ("lay", "Marker",
"@brief Returns a value indicating whether the marker has a specific frame color\n"
"The set method has been added in version 0.20.\n"
) +
+ gsi::method ("dismissable=", &lay::DMarker::set_dismissable,
+ "@brief Sets a value indicating whether the marker can be hidden\n"
+ "@args flag\n"
+ "Dismissable markers can be hidden setting \"View/Show Markers\" to \"off\". "
+ "The default setting is \"false\" meaning the marker can't be hidden.\n"
+ "\n"
+ "This attribute has been introduced in version 0.25.4."
+ ) +
+ gsi::method ("dismissable?", &lay::DMarker::get_dismissable,
+ "@brief Gets a value indicating whether the marker can be hidden\n"
+ "See \\dismissable= for a description of this predicate."
+ ) +
gsi::method ("line_width=", &lay::DMarker::set_line_width,
"@brief Sets the line width of the marker\n"
"@args width\n"
diff --git a/src/laybasic/laybasic/layCellView.cc b/src/laybasic/laybasic/layCellView.cc
index d8e3eb877..b21627566 100644
--- a/src/laybasic/laybasic/layCellView.cc
+++ b/src/laybasic/laybasic/layCellView.cc
@@ -258,6 +258,31 @@ LayoutHandle::set_save_options (const db::SaveLayoutOptions &options, bool valid
m_save_options_valid = valid;
}
+void
+LayoutHandle::update_save_options (db::SaveLayoutOptions &options)
+{
+ for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) {
+
+ const lay::StreamWriterPluginDeclaration *decl = dynamic_cast (&*cls);
+ if (! decl) {
+ continue;
+ }
+
+ std::auto_ptr specific_options;
+ if (options.get_options (decl->format_name ())) {
+ specific_options.reset (options.get_options (decl->format_name ())->clone ());
+ } else {
+ specific_options.reset (decl->create_specific_options ());
+ }
+
+ if (specific_options.get ()) {
+ decl->initialize_options_from_layout_handle (specific_options.get (), *this);
+ options.set_options (specific_options.release ());
+ }
+
+ }
+}
+
void
LayoutHandle::save_as (const std::string &fn, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update)
{
diff --git a/src/laybasic/laybasic/layCellView.h b/src/laybasic/laybasic/layCellView.h
index 2f5d9e436..998b798da 100644
--- a/src/laybasic/laybasic/layCellView.h
+++ b/src/laybasic/laybasic/layCellView.h
@@ -234,6 +234,15 @@ public:
return m_save_options;
}
+ /**
+ * @brief Updates the given save options with attributes from this cell view
+ *
+ * Some formats will initialize attributes from the cell view and the layout's
+ * metadata (example: libname of GDS2). This method will update the options
+ * if the layout provides attributes for initializing the latter.
+ */
+ void update_save_options (db::SaveLayoutOptions &options);
+
/**
* @brief Gets a flag indicating whether the save options are valid
*
diff --git a/src/laybasic/laybasic/layDialogs.cc b/src/laybasic/laybasic/layDialogs.cc
index 73df4ae4f..31fb50d10 100644
--- a/src/laybasic/laybasic/layDialogs.cc
+++ b/src/laybasic/laybasic/layDialogs.cc
@@ -625,6 +625,18 @@ ReplaceCellOptionsDialog::~ReplaceCellOptionsDialog ()
mp_ui = 0;
}
+static std::pair
+find_cell_by_display_name (const db::Layout &layout, const std::string &cn)
+{
+ for (db::Layout::const_iterator c = layout.begin (); c != layout.end (); ++c) {
+ if (layout.display_name (c->cell_index ()) == cn) {
+ return std::make_pair (true, c->cell_index ());
+ }
+ }
+
+ return std::make_pair (false, 0);
+}
+
bool
ReplaceCellOptionsDialog::exec_dialog (const lay::CellView &cv, int &replace_mode, db::cell_index_type &cell_index)
{
@@ -647,7 +659,7 @@ ReplaceCellOptionsDialog::exec_dialog (const lay::CellView &cv, int &replace_mod
}
std::string cn = tl::to_string (mp_ui->cell_selection_cbx->lineEdit ()->text ());
- std::pair cc = cv->layout ().cell_by_name (cn.c_str ());
+ std::pair cc = find_cell_by_display_name (cv->layout (), cn.c_str ());
cell_index = cc.second;
return cc.first;
@@ -665,7 +677,7 @@ BEGIN_PROTECTED;
lay::CellTreeModel *model = dynamic_cast (mp_ui->cell_selection_cbx->model ());
if (model) {
std::string cn = tl::to_string (mp_ui->cell_selection_cbx->lineEdit ()->text ());
- std::pair cc = model->layout ()->cell_by_name (cn.c_str ());
+ std::pair cc = find_cell_by_display_name (*model->layout (), cn.c_str ());
if (! cc.first) {
throw tl::Exception (tl::to_string (QObject::tr ("Not a valid cell name: ")) + cn);
}
diff --git a/src/laybasic/laybasic/layDitherPattern.cc b/src/laybasic/laybasic/layDitherPattern.cc
index 8ee1823e1..ad95f8ea4 100644
--- a/src/laybasic/laybasic/layDitherPattern.cc
+++ b/src/laybasic/laybasic/layDitherPattern.cc
@@ -555,6 +555,7 @@ DitherPatternInfo::operator< (const DitherPatternInfo &d) const
return m_order_index < d.m_order_index;
}
+// TODO including a scaling algorithm in this formula, or give more resolution to the dither
QBitmap
DitherPatternInfo::get_bitmap (int width, int height) const
{
diff --git a/src/laybasic/laybasic/layLayerToolbox.cc b/src/laybasic/laybasic/layLayerToolbox.cc
index 583478775..b1e303714 100644
--- a/src/laybasic/laybasic/layLayerToolbox.cc
+++ b/src/laybasic/laybasic/layLayerToolbox.cc
@@ -200,16 +200,29 @@ LCPDitherPalette::create_pixmap_for (LCPActiveLabel *b, int n)
const unsigned int h = 24;
const unsigned int w = 24;
- QImage image (w, h, QImage::Format_RGB32);
- image.fill (color0.rgb ());
+#if QT_VERSION > 0x050000
+ unsigned int dpr = devicePixelRatio ();
+#else
+ unsigned int dpr = 1;
+#endif
- QBitmap bitmap = pattern.pattern (n).get_bitmap (w, h);
+ QImage image (w * dpr, h * dpr, QImage::Format_RGB32);
+ image.fill (color0.rgb ());
+#if QT_VERSION > 0x050000
+ image.setDevicePixelRatio (dpr);
+#endif
+
+ // TODO include a scaling algorithm in get_bitmap, because it looks small in highDPI screens
+ QBitmap bitmap = pattern.pattern (n).get_bitmap (w * dpr, h * dpr);
QPainter painter (&image);
painter.setPen (QPen (color1));
painter.setBackgroundMode (Qt::TransparentMode);
- painter.drawPixmap (0, 0, bitmap);
+ painter.drawPixmap (0, 0, w, h, bitmap);
QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
+#if QT_VERSION > 0x050000
+ pixmap.setDevicePixelRatio (dpr);
+#endif
b->setPixmap (pixmap);
}
@@ -629,16 +642,28 @@ LCPStylePalette::create_pixmap_for_line_style (LCPActiveLabel *b, int n)
const unsigned int h = 14;
const unsigned int w = 24;
- QImage image (w, h, QImage::Format_RGB32);
- image.fill (color0.rgb ());
+#if QT_VERSION > 0x050000
+ unsigned int dpr = devicePixelRatio ();
+#else
+ unsigned int dpr = 1;
+#endif
- QBitmap bitmap = styles.style (n).get_bitmap (w, h);
+ QImage image (dpr * w, dpr * h, QImage::Format_RGB32);
+ image.fill (color0.rgb ());
+#if QT_VERSION > 0x050000
+ image.setDevicePixelRatio (dpr);
+#endif
+
+ QBitmap bitmap = styles.style (n).get_bitmap (dpr * w, dpr * h);
QPainter painter (&image);
painter.setPen (QPen (color1));
painter.setBackgroundMode (Qt::TransparentMode);
- painter.drawPixmap (0, 0, bitmap);
+ painter.drawPixmap (0, 0, w, h, bitmap);
QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
+#if QT_VERSION > 0x050000
+ pixmap.setDevicePixelRatio (dpr);
+#endif
b->setPixmap (pixmap);
}
diff --git a/src/laybasic/laybasic/layLayoutCanvas.cc b/src/laybasic/laybasic/layLayoutCanvas.cc
index ce8293b35..ae6fa4379 100644
--- a/src/laybasic/laybasic/layLayoutCanvas.cc
+++ b/src/laybasic/laybasic/layLayoutCanvas.cc
@@ -291,8 +291,6 @@ LayoutCanvas::LayoutCanvas (QWidget *parent, lay::LayoutView *view, const char *
{
#if QT_VERSION > 0x050000
m_dpr = devicePixelRatio ();
-#else
- m_dpr = 1;
#endif
// The gamma value used for subsampling: something between 1.8 and 2.2.
diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc
index 543553d41..02d98642f 100644
--- a/src/laybasic/laybasic/layLayoutView.cc
+++ b/src/laybasic/laybasic/layLayoutView.cc
@@ -384,6 +384,7 @@ LayoutView::init (db::Manager *mgr, lay::PluginRoot *root, QWidget * /*parent*/)
m_apply_text_trans = true;
m_default_text_size = 0.1;
m_text_font = 0;
+ m_show_markers = true;
m_no_stipples = false;
m_stipple_offset = true;
m_fit_new_cell = true;
@@ -1155,6 +1156,13 @@ LayoutView::configure (const std::string &name, const std::string &value)
apply_text_trans (flag);
return true;
+ } else if (name == cfg_markers_visible) {
+
+ bool flag;
+ tl::from_string (value, flag);
+ mp_canvas->set_dismiss_view_objects (! flag);
+ return true;
+
} else if (name == cfg_no_stipple) {
bool flag;
@@ -4923,7 +4931,16 @@ LayoutView::no_stipples (bool f)
}
}
-void
+void
+LayoutView::show_markers (bool f)
+{
+ if (m_show_markers != f) {
+ m_show_markers = f;
+ mp_canvas->update_image ();
+ }
+}
+
+void
LayoutView::text_color (QColor c)
{
if (m_text_color != c) {
diff --git a/src/laybasic/laybasic/layLayoutView.h b/src/laybasic/laybasic/layLayoutView.h
index 5d5d2e4c3..a9e3ff5aa 100644
--- a/src/laybasic/laybasic/layLayoutView.h
+++ b/src/laybasic/laybasic/layLayoutView.h
@@ -1062,6 +1062,19 @@ public:
return m_default_text_size;
}
+ /**
+ * @brief Show or hide markers
+ */
+ void show_markers (bool f);
+
+ /**
+ * @brief "show_markers" property getter
+ */
+ bool show_markers () const
+ {
+ return m_show_markers;
+ }
+
/**
* @brief Don't show stipples
*/
@@ -2671,6 +2684,7 @@ private:
bool m_apply_text_trans;
double m_default_text_size;
unsigned int m_text_font;
+ bool m_show_markers;
bool m_no_stipples;
bool m_stipple_offset;
diff --git a/src/laybasic/laybasic/layLayoutViewConfigPages.cc b/src/laybasic/laybasic/layLayoutViewConfigPages.cc
index 9cfb81595..dd31d6856 100644
--- a/src/laybasic/laybasic/layLayoutViewConfigPages.cc
+++ b/src/laybasic/laybasic/layLayoutViewConfigPages.cc
@@ -819,9 +819,22 @@ LayoutViewConfigPage4::update ()
}
}
+#if QT_VERSION > 0x050000
+ unsigned int dpr = 1; //devicePixelRatio ();
+#else
+ unsigned int dpr = 1;
+#endif
+
QFontMetrics fm (font (), this);
QRect rt (fm.boundingRect (QString::fromUtf8 ("AA")));
- QPixmap pxmp (rt.width () + 10, rt.height () + 10);
+
+ const unsigned int h = rt.height () + 10;
+ const unsigned int w = rt.width () + 10;
+
+ QPixmap pxmp (w * dpr, h * dpr);
+#if QT_VERSION > 0x050000
+ pxmp.setDevicePixelRatio (dpr);
+#endif
QPainter pxpainter (&pxmp);
pxpainter.setPen (QPen (palette ().color (QPalette::Active, QPalette::Text)));
@@ -1159,29 +1172,29 @@ LayoutViewConfigPage6::update ()
const unsigned int h = rt.height () + 10;
const unsigned int w = rt.width () + 10;
- unsigned int color0 = palette ().color (QPalette::Active, QPalette::Button).rgb();
- unsigned int color1 = palette ().color (QPalette::Active, QPalette::Dark).rgb();
+ QColor color0 = palette ().color (QPalette::Active, QPalette::Button);
+ QColor color1 = palette ().color (QPalette::Active, QPalette::Dark);
- QImage image (w, h, QImage::Format_RGB32);
- if (s >= 0) {
- const uint32_t * const *dp = m_pattern.pattern ((unsigned int) s).pattern ();
- for (unsigned int l = 0; l < h; ++l, ++dp) {
- uint32_t m = **dp;
- if (l == 0 || l == h - 1) {
- m |= ((1 << w) - 1);
- } else {
- m |= ((1 << (w - 1)) | 1);
- }
- color_t *pt = (color_t *) image.scanLine (h - 1 - l);
- for (unsigned int b = 0; b < w; ++b) {
- *pt++ = (m & 1) ? color1 : color0;
- m >>= 1;
- }
- }
- }
+#if QT_VERSION > 0x050000
+ unsigned int dpr = 1; //devicePixelRatio ();
+#else
+ unsigned int dpr = 1;
+#endif
+
+ QImage image (w * dpr, h * dpr, QImage::Format_RGB32);
+#if QT_VERSION > 0x050000
+ image.setDevicePixelRatio (dpr);
+#endif
+ image.fill (color0.rgb ());
+
+ // copying code from layLayerToolbox.cc
+ QBitmap bitmap = m_pattern.pattern ((unsigned int) s).get_bitmap (w * dpr, h * dpr);
+ QPainter painter (&image);
+ painter.setPen (QPen (color1));
+ painter.setBackgroundMode (Qt::TransparentMode);
+ painter.drawPixmap (0, 0, w, h, bitmap);
QPixmap pxmp = QPixmap::fromImage (image); // Qt 4.6.0 workaround
-
QPainter pxpainter (&pxmp);
pxpainter.setPen (QPen (palette ().color (QPalette::Active, QPalette::Text)));
QRect r (0, 0, pxmp.width () - 1, pxmp.height () - 1);
@@ -1189,6 +1202,10 @@ LayoutViewConfigPage6::update ()
pxpainter.setFont (font ());
pxpainter.drawText (r, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, text);
+#if QT_VERSION > 0x050000
+ pxmp.setDevicePixelRatio (dpr);
+#endif
+
(mp_ui->*(cfg6_buttons [i]))->setIconSize (pxmp.size ());
(mp_ui->*(cfg6_buttons [i]))->setIcon (QIcon (pxmp));
@@ -1366,16 +1383,28 @@ LayoutViewConfigPage6a::update ()
const unsigned int h = 26;
const unsigned int w = 26;
- QImage image (w, h, QImage::Format_RGB32);
- image.fill (color0.rgb ());
+#if QT_VERSION > 0x050000
+ unsigned int dpr = 1; //devicePixelRatio ();
+#else
+ unsigned int dpr = 1;
+#endif
- QBitmap bitmap = m_style.style (s).get_bitmap (w, h);
+ QImage image (w * dpr, h * dpr, QImage::Format_RGB32);
+ image.fill (color0.rgb ());
+#if QT_VERSION > 0x050000
+ image.setDevicePixelRatio (dpr);
+#endif
+
+ QBitmap bitmap = m_style.style (s).get_bitmap (w * dpr, h * dpr);
QPainter painter (&image);
painter.setPen (QPen (color1));
painter.setBackgroundMode (Qt::TransparentMode);
- painter.drawPixmap (0, 0, bitmap);
+ painter.drawPixmap (0, 0, w, h, bitmap);
QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
+#if QT_VERSION > 0x050000
+ pixmap.setDevicePixelRatio (dpr);
+#endif
b->setIconSize (pixmap.size ());
b->setIcon (QIcon (pixmap));
@@ -1510,6 +1539,7 @@ public:
options.push_back (std::pair (cfg_stipple_offset, "true"));
options.push_back (std::pair (cfg_line_style_palette, lay::LineStylePalette ().to_string ()));
options.push_back (std::pair (cfg_no_stipple, "false"));
+ options.push_back (std::pair (cfg_markers_visible, "true"));
}
virtual std::vector > config_pages (QWidget *parent) const
diff --git a/src/laybasic/laybasic/layMarker.cc b/src/laybasic/laybasic/layMarker.cc
index 80bd67f96..45a3d1554 100644
--- a/src/laybasic/laybasic/layMarker.cc
+++ b/src/laybasic/laybasic/layMarker.cc
@@ -270,7 +270,7 @@ MarkerBase::set_line_style (int line_style)
}
}
-void
+void
MarkerBase::get_bitmaps (const Viewport & /*vp*/, ViewObjectCanvas &canvas, lay::CanvasPlane *&fill, lay::CanvasPlane *&contour, lay::CanvasPlane *&vertex, lay::CanvasPlane *&text)
{
double resolution = canvas.resolution ();
diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.cc b/src/laybasic/laybasic/layRedrawThreadWorker.cc
index 5f485e208..a7d84268a 100644
--- a/src/laybasic/laybasic/layRedrawThreadWorker.cc
+++ b/src/laybasic/laybasic/layRedrawThreadWorker.cc
@@ -665,13 +665,11 @@ need_draw_box (const db::Layout *layout, const db::Cell &cell,
return int (cell.hierarchy_levels ()) + level >= to_level;
}
-void
-RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level)
+void
+RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level)
{
- lay::Renderer &r = *mp_renderer;
-
// do not draw, if there is nothing to draw
- if (mp_layout->cells () <= ci || vp.empty ()) {
+ if (mp_layout->cells () <= ci || redraw_regions.empty ()) {
return;
}
@@ -685,6 +683,17 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
return;
}
+ for (std::vector::const_iterator b = redraw_regions.begin (); b != redraw_regions.end (); ++b) {
+ draw_boxes (drawing_context, ci, trans, *b, level);
+ }
+}
+
+void
+RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level)
+{
+ lay::Renderer &r = *mp_renderer;
+ const db::Cell &cell = mp_layout->cell (ci);
+
// For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox ();
@@ -714,19 +723,19 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
} else {
db::box_convert bc (*mp_layout);
-
+
// create a set of boxes to look into
db::Coord aw = db::coord_traits::rounded (m_abstract_mode_width / mp_layout->dbu ());
std::vector vv;
if (level == 1 && m_abstract_mode_width > 0 && bbox.width () > db::Box::distance_type (aw * 2) && bbox.height () > db::Box::distance_type (aw * 2)) {
vv.reserve (4);
- vv.push_back (vp & db::Box (bbox.left (), bbox.bottom (), bbox.left () + aw, bbox.top ()));
- vv.push_back (vp & db::Box (bbox.right () - aw, bbox.bottom (), bbox.right (), bbox.top ()));
- vv.push_back (vp & db::Box (bbox.left () + aw, bbox.bottom (), bbox.right () - aw, bbox.bottom () + aw));
- vv.push_back (vp & db::Box (bbox.left () + aw, bbox.top () - aw, bbox.right () - aw, bbox.top ()));
+ vv.push_back (redraw_box & db::Box (bbox.left (), bbox.bottom (), bbox.left () + aw, bbox.top ()));
+ vv.push_back (redraw_box & db::Box (bbox.right () - aw, bbox.bottom (), bbox.right (), bbox.top ()));
+ vv.push_back (redraw_box & db::Box (bbox.left () + aw, bbox.bottom (), bbox.right () - aw, bbox.bottom () + aw));
+ vv.push_back (redraw_box & db::Box (bbox.left () + aw, bbox.top () - aw, bbox.right () - aw, bbox.top ()));
} else {
vv.reserve (1);
- vv.push_back (vp);
+ vv.push_back (redraw_box);
}
// dive down into the hierarchy ..
@@ -737,7 +746,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
bool anything = false;
db::cell_index_type last_ci = std::numeric_limits::max ();
- db::Cell::touching_iterator inst = cell.begin_touching (*v);
+ db::Cell::touching_iterator inst = cell.begin_touching (*v);
while (! inst.at_end ()) {
const db::CellInstArray &cell_inst = inst->cell_inst ();
@@ -746,7 +755,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
db::Box new_cell_box = mp_layout->cell (new_ci).bbox ();
if (last_ci != new_ci) {
- // Hint: don't use any_cell_box on partially visible cells because that will degrade performance
+ // Hint: don't use any_cell_box on partially visible cells because that will degrade performance
if (new_cell_box.inside (*v)) {
last_ci = new_ci;
anything = any_cell_box (new_ci, m_to_level - (level + 1));
@@ -758,7 +767,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
if (anything) {
db::Vector a, b;
- unsigned long amax, bmax;
+ unsigned long amax, bmax;
bool simplify = false;
if (cell_inst.is_regular_array (a, b, amax, bmax)) {
@@ -768,8 +777,8 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
} else {
inst_box = trans * new_cell_box;
}
- if (((a.x () == 0 && b.y () == 0) || (a.y () == 0 && b.x () == 0)) &&
- inst_box.width () < 1.5 && inst_box.height () < 1.5 &&
+ if (((a.x () == 0 && b.y () == 0) || (a.y () == 0 && b.x () == 0)) &&
+ inst_box.width () < 1.5 && inst_box.height () < 1.5 &&
(amax <= 1 || trans.ctrans (a.length ()) < 1.5) &&
(bmax <= 1 || trans.ctrans (b.length ()) < 1.5)) {
simplify = true;
@@ -781,7 +790,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
// The array can be simplified if there are levels below to draw
if (need_draw_box (mp_layout, mp_layout->cell (new_ci), level + 1, m_to_level, m_hidden_cells, m_cv_index)) {
-
+
db::box_convert bc (*mp_layout);
unsigned int plane_group = 2;
@@ -801,8 +810,8 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
// The array (or single instance) must be iterated instance
// by instance
for (db::CellInstArray::iterator p = cell_inst.begin_touching (*v, bc); ! p.at_end (); ++p) {
-
- test_snapshot (0);
+
+ test_snapshot (0);
db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v);
draw_boxes (drawing_context, new_ci, trans * t, new_vp, level + 1);
@@ -814,7 +823,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
}
++inst;
-
+
}
}
@@ -828,7 +837,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
}
void
-RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level)
+RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vp, int level)
{
if (! m_text_visible) {
return;
@@ -838,7 +847,7 @@ RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_ty
}
void
-RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level, db::properties_id_type prop_id)
+RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vp, int level, db::properties_id_type prop_id)
{
// do not draw, if there is nothing to draw
if (mp_layout->cells () <= ci || vp.empty ()) {
@@ -855,6 +864,16 @@ RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_ty
return;
}
+ for (std::vector::const_iterator b = vp.begin (); b != vp.end (); ++b) {
+ draw_box_properties (drawing_context, ci, trans, *b, level, prop_id);
+ }
+}
+
+void
+RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level, db::properties_id_type prop_id)
+{
+ const db::Cell &cell = mp_layout->cell (ci);
+
// For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox ();
@@ -1193,14 +1212,12 @@ RedrawThreadWorker::search_regions (const db::Box &cell_bbox, const db::Box &vp,
}
void
-RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level)
+RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vp, int level)
{
if (! m_text_visible) {
return;
}
- lay::Renderer &r = *mp_renderer;
-
unsigned int plane_group = 2;
if (drawing_context) {
plane_group = 0;
@@ -1214,8 +1231,6 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + plane_group * (planes_per_layer / 3)];
- test_snapshot (0);
-
// do not draw, if there is nothing to draw
if (mp_layout->cells () <= ci || vp.empty ()) {
return;
@@ -1224,7 +1239,18 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
return;
}
+ for (std::vector::const_iterator b = vp.begin (); b != vp.end (); ++b) {
+ draw_text_layer (drawing_context, ci, trans, *b, level, fill, frame, vertex, text);
+ }
+}
+
+void
+RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level, CanvasPlane *fill, CanvasPlane *frame, CanvasPlane *vertex, CanvasPlane *text)
+{
+ test_snapshot (0);
+
const db::Cell &cell = mp_layout->cell (ci);
+ lay::Renderer &r = *mp_renderer;
// For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox (m_layer);
@@ -1422,7 +1448,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
db::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v);
- draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1);
+ draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text);
}
@@ -1751,11 +1777,9 @@ private:
};
void
-RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level,
+RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vp, int level,
lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot)
{
- test_snapshot (update_snapshot);
-
// do not draw, if there is nothing to draw
if (mp_layout->cells () <= ci || vp.empty ()) {
return;
@@ -1764,6 +1788,17 @@ RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_typ
return;
}
+ for (std::vector::const_iterator b = vp.begin (); b != vp.end (); ++b) {
+ draw_layer (from_level, to_level, ci, trans, *b, level, fill, frame, vertex, text, update_snapshot);
+ }
+}
+
+void
+RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level,
+ lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot)
+{
+ test_snapshot (update_snapshot);
+
const db::Cell &cell = mp_layout->cell (ci);
db::Box bbox = cell.bbox (m_layer);
db::Box cell_bbox = cell.bbox ();
@@ -1891,7 +1926,7 @@ RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_typ
}
void
-RedrawThreadWorker::draw_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level)
+RedrawThreadWorker::draw_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level)
{
if (drawing_context) {
@@ -1904,7 +1939,7 @@ RedrawThreadWorker::draw_layer (bool drawing_context, db::cell_index_type ci, co
text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + plane_group * (planes_per_layer / 3)];
- draw_layer (m_from_level, m_to_level, ci, trans, vp, level, fill, frame, vertex, text, 0);
+ draw_layer (m_from_level, m_to_level, ci, trans, redraw_regions, level, fill, frame, vertex, text, 0);
}
@@ -1919,7 +1954,7 @@ RedrawThreadWorker::draw_layer (bool drawing_context, db::cell_index_type ci, co
text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + plane_group * (planes_per_layer / 3)];
- draw_layer (m_from_level, m_to_level, ci, trans, vp, level, fill, frame, vertex, text, 0);
+ draw_layer (m_from_level, m_to_level, ci, trans, redraw_regions, level, fill, frame, vertex, text, 0);
}
@@ -1934,7 +1969,7 @@ RedrawThreadWorker::draw_layer (bool drawing_context, db::cell_index_type ci, co
text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + plane_group * (planes_per_layer / 3)];
- draw_layer (m_from_level, 1, ci, trans, vp, level, fill, frame, vertex, text, 0);
+ draw_layer (m_from_level, 1, ci, trans, redraw_regions, level, fill, frame, vertex, text, 0);
}
@@ -1947,7 +1982,7 @@ RedrawThreadWorker::draw_layer (bool drawing_context, db::cell_index_type ci, co
text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + plane_group * (planes_per_layer / 3)];
- draw_layer (1, m_to_level, ci, trans, vp, level, fill, frame, vertex, text, 0);
+ draw_layer (1, m_to_level, ci, trans, redraw_regions, level, fill, frame, vertex, text, 0);
}
@@ -1990,7 +2025,7 @@ RedrawThreadWorker::cell_var_cached (db::cell_index_type ci, const db::CplxTrans
}
void
-RedrawThreadWorker::iterate_variants (const std::vector &redraw_regions, db::cell_index_type ci, db::CplxTrans trans, void (RedrawThreadWorker::*what) (bool, db::cell_index_type, const db::CplxTrans &, const db::Box &, int))
+RedrawThreadWorker::iterate_variants (const std::vector &redraw_regions, db::cell_index_type ci, db::CplxTrans trans, void (RedrawThreadWorker::*what) (bool, db::cell_index_type, const db::CplxTrans &, const std::vector &, int))
{
// save current state
int from_level = m_from_level;
@@ -2050,7 +2085,7 @@ RedrawThreadWorker::iterate_variants (const std::vector &redraw_region
}
void
-RedrawThreadWorker::iterate_variants_rec (const std::vector &redraw_regions, db::cell_index_type ci, const db::CplxTrans &trans, int level, void (RedrawThreadWorker::*what) (bool, db::cell_index_type, const db::CplxTrans &, const db::Box &, int), bool drawing_context)
+RedrawThreadWorker::iterate_variants_rec (const std::vector &redraw_regions, db::cell_index_type ci, const db::CplxTrans &trans, int level, void (RedrawThreadWorker::*what) (bool, db::cell_index_type, const db::CplxTrans &, const std::vector &, int), bool drawing_context)
{
db::Cell::parent_inst_iterator p = mp_layout->cell (ci).begin_parent_insts ();
int context_path_length = int (m_cellviews [m_cv_index].specific_path ().size ());
@@ -2092,19 +2127,25 @@ RedrawThreadWorker::iterate_variants_rec (const std::vector &redraw_re
} else {
+ std::vector actual_regions;
+ actual_regions.reserve (redraw_regions.size ());
+
for (std::vector::const_iterator rr = redraw_regions.begin (); rr != redraw_regions.end (); ++rr) {
db::Coord lim = std::numeric_limits::max ();
db::DBox world (trans * db::Box (db::Point (-lim, -lim), db::Point (lim, lim)));
db::Box vp = db::Box (trans.inverted () * (world & db::DBox (*rr)));
vp &= mp_layout->cell (ci).bbox (); // this avoids problems when accessing designs through very large viewports
-
if (! vp.empty ()) {
- (this->*what) (drawing_context, ci, trans, vp, level);
+ actual_regions.push_back (vp);
}
}
+ if (! actual_regions.empty ()) {
+ (this->*what) (drawing_context, ci, trans, actual_regions, level);
+ }
+
}
}
diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.h b/src/laybasic/laybasic/layRedrawThreadWorker.h
index 9f0e5b5c9..0b49a44d3 100644
--- a/src/laybasic/laybasic/layRedrawThreadWorker.h
+++ b/src/laybasic/laybasic/layRedrawThreadWorker.h
@@ -175,20 +175,24 @@ protected:
void perform_task (tl::Task *task);
private:
- void draw_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level);
- void draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot);
+ void draw_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level);
+ void draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot);
+ void draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot);
void draw_layer_wo_cache (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vv, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot);
- void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &box, int level);
- void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &box, int level);
- void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &box, int level);
- void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &box, int level, db::properties_id_type prop_id);
+ void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level);
+ void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text);
+ void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level);
+ void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level);
+ void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level);
+ void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level, db::properties_id_type prop_id);
+ void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, db::properties_id_type prop_id);
void draw_cell (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, const std::string &txt);
void draw_cell_properties (bool drawing_context, int level, const db::CplxTrans &trans, const db::Box &box, db::properties_id_type prop_id);
void draw_cell_shapes (const db::CplxTrans &trans, const db::Cell &cell, const db::Box &vp, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text);
void test_snapshot (const UpdateSnapshotCallback *update_snapshot);
void transfer ();
- void iterate_variants (const std::vector &redraw_regions, db::cell_index_type ci, db::CplxTrans trans, void (RedrawThreadWorker::*what) (bool, db::cell_index_type ci, const db::CplxTrans &, const db::Box &, int level));
- void iterate_variants_rec (const std::vector &redraw_regions, db::cell_index_type ci, const db::CplxTrans &trans, int level, void (RedrawThreadWorker::*what) (bool, db::cell_index_type ci, const db::CplxTrans &, const db::Box &, int level), bool spread);
+ void iterate_variants (const std::vector &redraw_regions, db::cell_index_type ci, db::CplxTrans trans, void (RedrawThreadWorker::*what) (bool, db::cell_index_type ci, const db::CplxTrans &, const std::vector &, int level));
+ void iterate_variants_rec (const std::vector &redraw_regions, db::cell_index_type ci, const db::CplxTrans &trans, int level, void (RedrawThreadWorker::*what) (bool, db::cell_index_type ci, const db::CplxTrans &, const std::vector &, int level), bool spread);
bool cell_var_cached (db::cell_index_type ci, const db::CplxTrans &trans);
bool drop_cell (const db::Cell &cell, const db::CplxTrans &trans);
std::vector search_regions (const db::Box &cell_bbox, const db::Box &vp, int level);
diff --git a/src/laybasic/laybasic/layViewObject.cc b/src/laybasic/laybasic/layViewObject.cc
index 3b93eeb51..9e52c8acb 100644
--- a/src/laybasic/laybasic/layViewObject.cc
+++ b/src/laybasic/laybasic/layViewObject.cc
@@ -165,7 +165,7 @@ BackgroundViewObject::z_order (int z)
// ViewObject implementation
ViewObject::ViewObject (ViewObjectWidget *widget, bool _static)
- : mp_widget (widget), m_static (_static), m_visible (true)
+ : mp_widget (widget), m_static (_static), m_visible (true), m_dismissable (false)
{
if (widget) {
widget->m_objects.push_back (this);
@@ -178,6 +178,15 @@ ViewObject::~ViewObject ()
redraw ();
}
+void
+ViewObject::set_dismissable (bool dismissable)
+{
+ if (m_dismissable != dismissable) {
+ m_dismissable = dismissable;
+ redraw ();
+ }
+}
+
void
ViewObject::visible (bool vis)
{
@@ -251,6 +260,7 @@ ViewService::set_cursor (lay::Cursor::cursor_shape cursor)
ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name)
: QWidget (parent),
+ m_view_objects_dismissed (false),
m_needs_update_static (false),
m_needs_update_bg (false),
mp_active_service (0),
@@ -888,7 +898,7 @@ ViewObjectWidget::do_render (const lay::Viewport &vp, lay::ViewObjectCanvas &can
}
for (object_iterator obj = begin_objects (); obj != end_objects (); ++obj) {
- if (obj->m_static == st && obj->is_visible ()) {
+ if (obj->m_static == st && obj->is_visible () && (! m_view_objects_dismissed || ! obj->get_dismissable ())) {
BEGIN_PROTECTED_SILENT
obj->render (vp, canvas);
END_PROTECTED_SILENT
@@ -963,6 +973,16 @@ ViewObjectWidget::touch_bg ()
}
}
+void
+ViewObjectWidget::set_dismiss_view_objects (bool dismiss)
+{
+ if (dismiss != m_view_objects_dismissed) {
+ m_view_objects_dismissed = dismiss;
+ touch ();
+ update ();
+ }
+}
+
void
ViewObjectWidget::objects_changed ()
{
diff --git a/src/laybasic/laybasic/layViewObject.h b/src/laybasic/laybasic/layViewObject.h
index 2d4087919..6a274aab8 100644
--- a/src/laybasic/laybasic/layViewObject.h
+++ b/src/laybasic/laybasic/layViewObject.h
@@ -513,6 +513,23 @@ public:
return const_cast (mp_widget.get());
}
+ /**
+ * @brief Gets a value indicating whether the marker can be dismissed (made invisible)
+ *
+ * Markers with this flag set to true can be hidden by using ViewObjectCanvas::show_markers.
+ */
+ bool get_dismissable () const
+ {
+ return m_dismissable;
+ }
+
+ /**
+ * @brief Sets a value indicating whether the marker can be dismissed (made invisible)
+ *
+ * See \\get_dismissable for details.
+ */
+ void set_dismissable (bool f);
+
/**
* @brief Set the visibility state of the view object
*
@@ -561,6 +578,7 @@ private:
tl::weak_ptr mp_widget;
bool m_static;
bool m_visible;
+ bool m_dismissable;
};
/**
@@ -905,6 +923,21 @@ public:
*/
void set_default_cursor (lay::Cursor::cursor_shape cursor);
+ /**
+ * @brief Sets a value indicating whether dismissable view objects shall be drawn or not
+ *
+ * Markers with dismissable = false are always drawn. The default value is "false".
+ */
+ void set_dismiss_view_objects (bool dismissed);
+
+ /**
+ * @brief Gets a value indicating whether dismissable markers shall be drawn or not
+ */
+ bool dismiss_view_objects () const
+ {
+ return m_view_objects_dismissed;
+ }
+
protected:
/**
* @brief Qt focus event handler
@@ -985,6 +1018,7 @@ private:
tl::weak_collection m_background_objects;
std::list m_services;
std::list m_grabbed;
+ bool m_view_objects_dismissed;
bool m_needs_update_static;
bool m_needs_update_bg;
lay::ViewService *mp_active_service;
diff --git a/src/laybasic/laybasic/laybasicConfig.h b/src/laybasic/laybasic/laybasicConfig.h
index 4926e8ca3..6f8aafaed 100644
--- a/src/laybasic/laybasic/laybasicConfig.h
+++ b/src/laybasic/laybasic/laybasicConfig.h
@@ -70,6 +70,8 @@ static const std::string cfg_sel_line_style ("sel-line-style");
static const std::string cfg_sel_transient_mode ("sel-transient-mode");
static const std::string cfg_sel_inside_pcells_mode ("sel-inside-pcells-mode");
+static const std::string cfg_markers_visible ("markers-visible");
+
static const std::string cfg_min_inst_label_size ("min-inst-label-size");
static const std::string cfg_cell_box_text_font ("inst-label-font");
static const std::string cfg_cell_box_text_transform ("inst-label-transform");
diff --git a/src/laybasic/laybasic/rdbMarkerBrowserPage.cc b/src/laybasic/laybasic/rdbMarkerBrowserPage.cc
index db54294e0..303455ee7 100644
--- a/src/laybasic/laybasic/rdbMarkerBrowserPage.cc
+++ b/src/laybasic/laybasic/rdbMarkerBrowserPage.cc
@@ -2177,36 +2177,42 @@ MarkerBrowserPage::do_update_markers ()
mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * polygon_value->value ());
+ mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * polygon_value->value ().box ();
} else if (edge_pair_value) {
mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * edge_pair_value->value ());
+ mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * db::DBox (edge_pair_value->value ().bbox ());
} else if (edge_value) {
mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * edge_value->value ());
+ mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * db::DBox (edge_value->value ().bbox ());
} else if (box_value) {
mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * box_value->value ());
+ mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * box_value->value ();
} else if (text_value) {
mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * text_value->value ());
+ mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * text_value->value ().box ();
} else if (path_value) {
mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * path_value->value ());
+ mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * path_value->value ().box ();
}
diff --git a/src/lym/lym/lymMacro.cc b/src/lym/lym/lymMacro.cc
index 02d370f7c..b6fd483b4 100644
--- a/src/lym/lym/lymMacro.cc
+++ b/src/lym/lym/lymMacro.cc
@@ -32,6 +32,7 @@
#include "tlClassRegistry.h"
#include "tlLog.h"
#include "tlXMLParser.h"
+#include "tlGlobPattern.h"
#include "rba.h"
#include "pya.h"
@@ -213,15 +214,18 @@ void Macro::save_to (const std::string &path)
}
}
-void Macro::load_from (const std::string &path)
+void Macro::load_from (const std::string &fn)
{
m_format = NoFormat;
- if (tl::verbosity () >= 20) {
- tl::log << "Loading macro from " << path;
- }
+ std::pair f = format_from_filename (fn, m_interpreter, m_dsl_interpreter, m_autorun_default, m_format);
+ if (f.first) {
- if (format_from_suffix (path, m_interpreter, m_dsl_interpreter, m_autorun_default, m_format)) {
+ const std::string &path = f.second;
+
+ if (tl::verbosity () >= 20) {
+ tl::log << "Loading macro from " << path;
+ }
m_autorun = m_autorun_default;
@@ -242,7 +246,7 @@ void Macro::load_from (const std::string &path)
}
} else {
- throw tl::Exception (tl::to_string (QObject::tr ("Unable to determine format for file from suffix ")) + path);
+ throw tl::Exception (tl::to_string (QObject::tr ("Unable to determine format for file from suffix or format spec ")) + fn);
}
m_modified = true;
@@ -297,7 +301,24 @@ bool
Macro::format_from_suffix (const std::string &fn, Macro::Interpreter &interpreter, std::string &dsl_name, bool &autorun_pref, Macro::Format &format)
{
std::string suffix = tl::to_string (QFileInfo (tl::to_qstring (fn)).suffix ());
+ return format_from_suffix_string (suffix, interpreter, dsl_name, autorun_pref, format);
+}
+std::pair
+Macro::format_from_filename (const std::string &fn, Macro::Interpreter &interpreter, std::string &dsl_name, bool &autorun_pref, Macro::Format &format)
+{
+ tl::GlobPattern pat ("(*)\\[(*)\\]");
+ std::vector pat_parts;
+ if (pat.match (fn, pat_parts) && pat_parts.size () == 2) {
+ return std::make_pair (format_from_suffix_string (pat_parts[1], interpreter, dsl_name, autorun_pref, format), pat_parts[0]);
+ } else {
+ return std::make_pair (format_from_suffix (fn, interpreter, dsl_name, autorun_pref, format), fn);
+ }
+}
+
+bool
+Macro::format_from_suffix_string (const std::string &suffix, Macro::Interpreter &interpreter, std::string &dsl_name, bool &autorun_pref, Macro::Format &format)
+{
interpreter = None;
dsl_name = std::string ();
format = NoFormat;
diff --git a/src/lym/lym/lymMacro.h b/src/lym/lym/lymMacro.h
index 734921c81..46e813294 100644
--- a/src/lym/lym/lymMacro.h
+++ b/src/lym/lym/lymMacro.h
@@ -602,6 +602,8 @@ private:
void on_menu_needs_update ();
void on_changed ();
void save_to (const std::string &path);
+ static bool format_from_suffix_string (const std::string &suffix, Macro::Interpreter &interpreter, std::string &dsl_name, bool &autorun_pref, Macro::Format &format);
+ static std::pair format_from_filename (const std::string &fn, Macro::Interpreter &interpreter, std::string &dsl_name, bool &autorun_pref, Macro::Format &format);
void set_autorun_default (bool f)
{
diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc
index 219e49721..893e88b0c 100644
--- a/src/pya/pya/pyaModule.cc
+++ b/src/pya/pya/pyaModule.cc
@@ -493,7 +493,11 @@ static std::string extract_python_name (const std::string &name)
} else if (name == "-@") {
return "__neg__";
} else if (name == "/") {
+ #if PY_MAJOR_VERSION < 3
return "__div__";
+ #else
+ return "__truediv__";
+ #endif
} else if (name == "*") {
return "__mul__";
} else if (name == "%") {
@@ -515,7 +519,11 @@ static std::string extract_python_name (const std::string &name)
} else if (name == "-=") {
return "__isub__";
} else if (name == "/=") {
+ #if PY_MAJOR_VERSION < 3
return "__idiv__";
+ #else
+ return "__itruediv__";
+ #endif
} else if (name == "*=") {
return "__imul__";
} else if (name == "%=") {
@@ -2698,6 +2706,11 @@ PythonModule::make_classes (const char *mod_name)
add_python_doc (*c, mt, int (mid), tl::to_string (tr ("This method enables iteration of the object")));
alt_names.push_back ("__iter__");
+ } else if (name == "__mul__") {
+ // Adding right multiplication
+ // Rationale: if pyaObj * x works, so should x * pyaObj
+ add_python_doc (*c, mt, mid, tl::to_string (tr ("This method is also available as '__mul__'")));
+ alt_names.push_back ("__rmul__");
}
for (std::vector ::const_iterator an = alt_names.begin (); an != alt_names.end (); ++an) {
diff --git a/src/tl/tl/tl.pro b/src/tl/tl/tl.pro
index 8d57c1b34..d5c002aea 100644
--- a/src/tl/tl/tl.pro
+++ b/src/tl/tl/tl.pro
@@ -40,7 +40,8 @@ SOURCES = \
tlThreadedWorkers.cc \
tlThreads.cc \
tlDeferredExecution.cc \
- tlUri.cc
+ tlUri.cc \
+ tlLongInt.cc
HEADERS = \
tlAlgorithm.h \
@@ -84,14 +85,14 @@ HEADERS = \
tlCommandLineParser.h \
tlUnitTest.h \
tlInt128Support.h \
- tlHttpStreamCurl.h \
tlDefs.h \
tlXMLParser.h \
tlXMLWriter.h \
tlThreadedWorkers.h \
tlThreads.h \
tlDeferredExecution.h \
- tlUri.h
+ tlUri.h \
+ tlLongInt.h
equals(HAVE_CURL, "1") {
diff --git a/src/tl/tl/tlLongInt.cc b/src/tl/tl/tlLongInt.cc
new file mode 100644
index 000000000..ac0f4bbe7
--- /dev/null
+++ b/src/tl/tl/tlLongInt.cc
@@ -0,0 +1,29 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2018 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 "tlLongInt.h"
+
+namespace tl
+{
+ // .. nothing yet ..
+}
diff --git a/src/tl/tl/tlLongInt.h b/src/tl/tl/tlLongInt.h
new file mode 100644
index 000000000..7a56bd927
--- /dev/null
+++ b/src/tl/tl/tlLongInt.h
@@ -0,0 +1,1277 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2018 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_tlLongInt
+#define HDR_tlLongInt
+
+#include "tlCommon.h"
+
+#include
+
+namespace tl
+{
+
+/**
+ * @brief A universal long unsigned int
+ *
+ * The long unsigned int is composed of N chunks of B type.
+ * B can be any unsigned int type. BI is the working type
+ * which must be twice the size of B.
+ *
+ * Specifically, this universal int is intended to emulate
+ * __uint128 by using:
+ *
+ * typedef long_uint<4, uint32_t, uint64_t> __uint128;
+ */
+template
+class long_uint
+{
+public:
+ enum { bits = sizeof (B) * 8 };
+
+ typedef B basic_type;
+
+ /**
+ * @brief Default constructor
+ * This will initialize the value to 0.
+ */
+ long_uint ()
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ b[i] = 0;
+ }
+ }
+
+ /**
+ * @brief Initialize the universal unsigned int with a POD type
+ * If T is a signed type, the upper bit won't be sign-extended.
+ */
+ template
+ long_uint (T t)
+ {
+ unsigned int i = 0;
+ unsigned int tbits = sizeof (T) * 8;
+
+ while (tbits > 0) {
+ b[i] = B (t);
+ if (tbits > bits) {
+ t >>= bits;
+ }
+ tbits -= bits;
+ ++i;
+ }
+ for ( ; i < N; ++i) {
+ b[i] = 0;
+ }
+ }
+
+ /**
+ * @brief Convert the universal long int to the given type
+ * Casting will potentially reduce the number of significant
+ * bits of the value.
+ */
+ template
+ operator T () const
+ {
+ unsigned int tbits = sizeof (T) * 8;
+ T t = 0;
+
+ if (tbits <= bits) {
+ t = T (b[0]);
+ } else {
+ unsigned int i = sizeof (T) / sizeof (B);
+ for ( ; i > 0 && tbits > 0; ) {
+ --i;
+ t <<= bits;
+ t |= b[i];
+ tbits -= bits;
+ }
+ }
+
+ return t;
+ }
+
+ /**
+ * @brief Initialize the universal unsigned int from another one with a different width
+ */
+ template
+ long_uint (const long_uint &o)
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ b[i] = i < N2 ? o.b[i] : 0;
+ }
+ }
+
+ /**
+ * @brief zero predicate
+ * This method returns true, if the value is 0.
+ */
+ bool is_zero () const
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ if (b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @brief Equality
+ */
+ bool operator== (const long_uint &o) const
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ if (b[i] != o.b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @brief Inequality
+ */
+ bool operator!= (const long_uint &b) const
+ {
+ return !operator== (b);
+ }
+
+ /**
+ * @brief Less operator
+ */
+ bool operator< (const long_uint &o) const
+ {
+ for (unsigned int i = N; i > 0; ) {
+ --i;
+ if (b[i] != o.b[i]) {
+ return b[i] < o.b[i];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @brief Greater or equal
+ */
+ bool operator>= (const long_uint &b) const
+ {
+ return !operator< (b);
+ }
+
+ /**
+ * @brief Less or equal
+ */
+ bool operator<= (const long_uint &b) const
+ {
+ return b >= *this;
+ }
+
+ /**
+ * @brief Greater
+ */
+ bool operator> (const long_uint &b) const
+ {
+ return b < *this;
+ }
+
+ /**
+ * @brief Multiplication
+ */
+ template
+ long_uint operator* (const long_uint &o) const
+ {
+ long_uint res;
+
+ for (unsigned int i = 0; i < N; ++i) {
+ for (unsigned int j = 0; j < N2; ++j) {
+ BI p = BI (b[i]) * BI (o.b[j]);
+ unsigned int n = i + j;
+ while (p > 0) {
+ B &r = res.b[n];
+ B rold = r;
+ r += B (p);
+ p >>= bits;
+ if (r < rold) {
+ p += 1;
+ }
+ ++n;
+ }
+ }
+ }
+
+ return long_uint (res);
+ }
+
+ /**
+ * @brief In-place multiplication
+ */
+ template
+ long_uint &operator*= (const long_uint &o)
+ {
+ *this = *this * o;
+ return *this;
+ }
+
+ /**
+ * @brief Bitwise inversion
+ */
+ long_uint operator~ () const
+ {
+ long_uint res = *this;
+ for (unsigned int i = 0; i < N; ++i) {
+ res.b[i] = ~res.b[i];
+ }
+ return res;
+ }
+
+ /**
+ * @brief Boolean and operator
+ */
+ long_uint operator& (const long_uint &o) const
+ {
+ long_uint res = *this;
+ res &= o;
+ return res;
+ }
+
+ /**
+ * @brief In-place boolean and operator
+ */
+ long_uint &operator&= (const long_uint &o)
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ b[i] &= o.b[i];
+ }
+ return *this;
+ }
+
+ /**
+ * @brief Boolean xor operator
+ */
+ long_uint operator^ (const long_uint &o) const
+ {
+ long_uint res = *this;
+ res ^= o;
+ return res;
+ }
+
+ /**
+ * @brief In-place boolean xor operator
+ */
+ long_uint &operator^= (const long_uint &o)
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ b[i] ^= o.b[i];
+ }
+ return *this;
+ }
+
+ /**
+ * @brief Boolean or operator
+ */
+ long_uint operator| (const long_uint &o) const
+ {
+ long_uint res = *this;
+ res |= o;
+ return res;
+ }
+
+ /**
+ * @brief In-place boolean or operator
+ */
+ long_uint &operator|= (const long_uint &o)
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ b[i] |= o.b[i];
+ }
+ return *this;
+ }
+
+ /**
+ * @brief Left-shift operator
+ */
+ long_uint operator<< (unsigned int n) const
+ {
+ long_uint res = *this;
+ res.lshift (n);
+ return res;
+ }
+
+ /**
+ * @brief In-place left-shift operator
+ */
+ long_uint &operator<<= (unsigned int n)
+ {
+ lshift (n);
+ return *this;
+ }
+
+ /**
+ * @brief Bitwise left-shift
+ * This method will left-shift the value by the given number of bits
+ */
+ void lshift (unsigned int n)
+ {
+ unsigned int w = n / bits;
+ if (w > 0) {
+ n -= w * bits;
+ for (unsigned int i = N - w; i > 0; ) {
+ --i;
+ b[i + w] = b[i];
+ }
+ for (unsigned int i = 0; i < w; ++i) {
+ b[i] = 0;
+ }
+ }
+
+ B carry = 0;
+ for (unsigned int i = 0; i < N; ++i) {
+ BI p = b[i];
+ p <<= n;
+ p |= carry;
+ carry = B (p >> bits);
+ b[i] = B (p);
+ }
+ }
+
+ /**
+ * @brief right-shift operator
+ */
+ long_uint operator>> (unsigned int n) const
+ {
+ long_uint res = *this;
+ res.rshift (n);
+ return res;
+ }
+
+ /**
+ * @brief In-place right-shift operator
+ */
+ long_uint &operator>>= (unsigned int n)
+ {
+ rshift (n);
+ return *this;
+ }
+
+ /**
+ * @brief Bitwise right-shift
+ * This method will right-shift the value by the given number of bits.
+ * The sign flag will be used to fill the upper bits.
+ */
+ void rshift (unsigned int n, bool sign = false)
+ {
+ unsigned int w = n / bits;
+ if (w > 0) {
+ n -= w * bits;
+ for (unsigned int i = 0; i < N - w; ++i) {
+ b[i] = b[i + w];
+ }
+ for (unsigned int i = N - w; i < N; ++i) {
+ b[i] = sign ? ~B (0) : B (0);
+ }
+ }
+
+ if (n > 0) {
+ B carry = sign ? (~B (0) << (bits - n)) : 0;
+ for (unsigned int i = N; i > 0; ) {
+ --i;
+ BI p = BI (b[i]) << bits;
+ p >>= n;
+ p |= (BI (carry) << bits);
+ carry = B (p);
+ b[i] = B (p >> bits);
+ }
+ }
+ }
+
+ /**
+ * @brief Sets the given bit in the universal long int
+ * Bit 0 is the rightmost (LSB) one.
+ */
+ void set_bit (unsigned int n)
+ {
+ unsigned int i = n / bits;
+ n -= i * bits;
+ if (i < N) {
+ b[i] |= (1 << n);
+ }
+ }
+
+ /**
+ * @brief Gets the number of zero bits counted from the MSB to the right
+ */
+ unsigned int zero_bits_from_msb () const
+ {
+ unsigned int zb = 0;
+ for (unsigned int i = N; i > 0; ) {
+ --i;
+ if (!b[i]) {
+ zb += bits;
+ } else {
+ B m = 1 << (bits - 1);
+ B n = b[i];
+ while (! (n & m)) {
+ ++zb;
+ n <<= 1;
+ }
+ break;
+ }
+ }
+ return zb;
+ }
+
+ /**
+ * @brief Division and modulo operation
+ * This method returns the division of *this and d (the divider) in the first
+ * element of the returned pair and the modulo value (remainder) in the second.
+ */
+ std::pair, long_uint > divmod (const long_uint &d) const
+ {
+ long_uint rem = *this;
+ long_uint div;
+
+ if (d.is_zero ()) {
+ // should assert?
+ return std::make_pair (div, rem);
+ }
+
+ unsigned int bd = d.zero_bits_from_msb ();
+
+ while (rem >= d) {
+
+ unsigned int brem = rem.zero_bits_from_msb ();
+ unsigned int shift = bd - brem;
+
+ if (shift == 0) {
+ rem -= d;
+ div.set_bit (0);
+ } else {
+ long_uint sub = d;
+ sub.lshift (shift);
+ if (sub > rem) {
+ shift -= 1;
+ sub.rshift (1);
+ }
+ div.set_bit (shift);
+ rem -= sub;
+ }
+
+ }
+
+ return std::make_pair (div, rem);
+ }
+
+ /**
+ * @brief Division operator
+ */
+ long_uint operator/ (const long_uint &b) const
+ {
+ return divmod (b).first;
+ }
+
+ /**
+ * @brief In-place division operator
+ */
+ long_uint &operator/= (const long_uint &b)
+ {
+ *this = divmod (b).first;
+ return *this;
+ }
+
+ /**
+ * @brief Modulo operator
+ */
+ long_uint operator% (const long_uint &b) const
+ {
+ return divmod (b).second;
+ }
+
+ /**
+ * @brief In-place modulo operator
+ */
+ long_uint &operator%= (const long_uint &b)
+ {
+ *this = divmod (b).second;
+ return *this;
+ }
+
+ /**
+ * @brief Addition with the basic type
+ */
+ long_uint operator+ (B o) const
+ {
+ long_uint res;
+
+ B carry = o;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = res.b[i];
+ r = b[i];
+ B rold = r;
+ r += carry;
+ carry = 0;
+ if (r < rold) {
+ carry = 1;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * @brief In-place addition with the basic type
+ */
+ long_uint &operator+= (B o)
+ {
+ B carry = o;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = b[i];
+ B rold = r;
+ r += carry;
+ carry = 0;
+ if (r < rold) {
+ carry = 1;
+ }
+ }
+
+ return *this;
+ }
+
+ /**
+ * @brief Addition
+ */
+ long_uint operator+ (const long_uint &o) const
+ {
+ long_uint res;
+
+ B carry = 0;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = res.b[i];
+ r = b[i];
+ B rold = r;
+ r += carry;
+ carry = 0;
+ if (r < rold) {
+ carry = 1;
+ }
+ rold = r;
+ r += o.b[i];
+ if (r < rold) {
+ carry = 1;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * @brief In-place addition
+ */
+ long_uint &operator+= (const long_uint &o)
+ {
+ B carry = 0;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = b[i];
+ B rold = r;
+ r += carry;
+ carry = 0;
+ if (r < rold) {
+ carry = 1;
+ }
+ rold = r;
+ r += o.b[i];
+ if (r < rold) {
+ carry = 1;
+ }
+ }
+
+ return *this;
+ }
+
+ /**
+ * @brief Subtraction
+ */
+ long_uint operator- (const long_uint &o) const
+ {
+ long_uint res;
+
+ B carry = 0;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = res.b[i];
+ r = b[i];
+ B rold = r;
+ r -= carry;
+ carry = 0;
+ if (r > rold) {
+ carry = 1;
+ }
+ rold = r;
+ r -= o.b[i];
+ if (r > rold) {
+ carry = 1;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * @brief In-place subtraction
+ */
+ long_uint &operator-= (const long_uint &o)
+ {
+ B carry = 0;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = b[i];
+ B rold = r;
+ r -= carry;
+ carry = 0;
+ if (r > rold) {
+ carry = 1;
+ }
+ rold = r;
+ r -= o.b[i];
+ if (r > rold) {
+ carry = 1;
+ }
+ }
+
+ return *this;
+ }
+
+ /**
+ * @brief Subtraction with the basic type
+ */
+ long_uint operator- (B o) const
+ {
+ long_uint res;
+
+ B carry = o;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = res.b[i];
+ r = b[i];
+ B rold = r;
+ r -= carry;
+ carry = 0;
+ if (r > rold) {
+ carry = 1;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * @brief In-place subtraction with the basic type
+ */
+ long_uint &operator-= (B o)
+ {
+ B carry = o;
+ for (unsigned int i = 0; i < N; ++i) {
+ B &r = b[i];
+ B rold = r;
+ r -= carry;
+ carry = 0;
+ if (r > rold) {
+ carry = 1;
+ }
+ }
+
+ return *this;
+ }
+
+ B b[N];
+};
+
+/**
+ * @brief A universal long signed int
+ *
+ * The long unsigned int is composed of N chunks of B type.
+ * B can be any unsigned int type. BI is the working type
+ * which must be twice the size of B.
+ *
+ * B and BI must be unsigned types.
+ *
+ * Specifically, this universal int is intended to emulate
+ * __int128 by using:
+ *
+ * typedef long_int<4, uint32_t, uint64_t> __int128;
+ */
+template
+class long_int
+ : public long_uint
+{
+public:
+ /**
+ * @brief Default constructor
+ * This will initialize the value to 0.
+ */
+ long_int ()
+ : long_uint ()
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief Initialize the universal int with a POD type
+ * If T is a signed type, the upper bit will be sign-extended.
+ */
+ template
+ long_int (T t)
+ {
+ unsigned int tbits = sizeof (T) * 8;
+
+ for (unsigned int i = 0; i < N; ++i) {
+ long_uint::b[i] = B (t);
+ if (tbits <= long_uint::bits) {
+ t = (t < 0 ? ~B (0) : 0);
+ } else {
+ t >>= long_uint::bits;
+ }
+ }
+ }
+
+ /**
+ * @brief Convert the universal long int to the given type
+ * Casting will potentially reduce the number of significant
+ * bits of the value.
+ */
+ template
+ operator T () const
+ {
+ unsigned int tbits = sizeof (T) * 8;
+ T t = 0;
+
+ if (tbits <= long_uint::bits) {
+ t = T (long_uint::b[0]);
+ } else {
+ unsigned int i = sizeof (T) / sizeof (B);
+ for ( ; i > 0 && tbits > 0; ) {
+ --i;
+ t <<= long_uint::bits;
+ t |= long_uint::b[i];
+ tbits -= long_uint::bits;
+ }
+ }
+
+ return t;
+ }
+
+ /**
+ * @brief Initialize the universal unsigned int from an unsigned one with a different width
+ * Sign inversion will happen, if the unsigned int is bigger than the maximum value
+ * representable by our type.
+ */
+ template
+ long_int (const long_uint &o)
+ : long_uint (o)
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief Initialize the universal int from another one with a different width
+ */
+ template
+ long_int (const long_int &o)
+ : long_uint (o)
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief negative predicate
+ * This method returns true, if the value is negative.
+ */
+ bool is_neg () const
+ {
+ return (long_uint::b[N - 1] & (1 << (long_uint::bits - 1))) != 0;
+ }
+
+ /**
+ * @brief zero predicate
+ * This method returns true, if the value is 0.
+ */
+ bool is_zero () const
+ {
+ for (unsigned int i = 0; i < N; ++i) {
+ if (long_uint::b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @brief Less operator
+ */
+ bool operator< (const long_uint &o) const
+ {
+ // we cast both arguments to unsigned as C++ does
+ return long_uint::operator< (o);
+ }
+
+ /**
+ * @brief Less operator
+ */
+ bool operator< (const long_int &o) const
+ {
+ if (is_neg () != o.is_neg ()) {
+ return is_neg () > o.is_neg ();
+ } else {
+ return long_uint::operator< (o);
+ }
+ }
+
+ /**
+ * @brief Greater or equal
+ */
+ bool operator>= (const long_uint &b) const
+ {
+ return !operator< (b);
+ }
+
+ /**
+ * @brief Greater or equal
+ */
+ bool operator>= (const long_int &b) const
+ {
+ return !operator< (b);
+ }
+
+ /**
+ * @brief Less or equal
+ */
+ bool operator<= (const long_uint &b) const
+ {
+ return b >= *this;
+ }
+
+ /**
+ * @brief Less or equal
+ */
+ bool operator<= (const long_int &b) const
+ {
+ return b >= *this;
+ }
+
+ /**
+ * @brief Greater
+ */
+ bool operator> (const long_uint &b) const
+ {
+ return b < *this;
+ }
+
+ /**
+ * @brief Greater
+ */
+ bool operator> (const long_int &b) const
+ {
+ return b < *this;
+ }
+
+ /**
+ * @brief Sign inversion (two's complement)
+ */
+ long_int operator- () const
+ {
+ long_uint res = ~*this;
+ res += B (1);
+ return long_int (res);
+ }
+
+ /**
+ * @brief Multiplication with unsigned
+ */
+ template
+ long_uint operator* (const long_uint &o) const
+ {
+ return long_uint::operator* (o);
+ }
+
+ /**
+ * @brief Multiplication with signed
+ */
+ template
+ long_int operator* (const long_int &o) const
+ {
+ if (is_neg () && ! o.is_neg ()) {
+ return -long_int ((-*this).long_uint::operator* (o));
+ } else if (! is_neg () && o.is_neg ()) {
+ return -long_int (long_uint::operator* (-o));
+ } else if (is_neg () && o.is_neg ()) {
+ return long_int ((-*this).long_uint::operator* (-o));
+ } else {
+ return long_int (long_uint::operator* (o));
+ }
+ }
+
+ /**
+ * @brief In-place multiplication with unsigned
+ */
+ template
+ long_int &operator*= (const long_uint &o)
+ {
+ long_uint::operator= (*this * o);
+ return *this;
+ }
+
+ /**
+ * @brief In-place multiplication with signed
+ */
+ template
+ long_int &operator*= (const long_int &o)
+ {
+ *this = *this * o;
+ return *this;
+ }
+
+ /**
+ * @brief Left-shift operator
+ */
+ long_int operator<< (unsigned int n) const
+ {
+ long_int res = *this;
+ res.lshift (n);
+ return res;
+ }
+
+ /**
+ * @brief In-place left-shift operator
+ */
+ long_int