Merge branch 'pymod' into pymod-msvc

This commit is contained in:
Matthias Köfferlein 2018-09-07 22:56:22 +02:00
commit 28f8a1ee7d
133 changed files with 3487 additions and 806 deletions

View File

@ -1,40 +1,43 @@
matrix: matrix:
include: include:
- os: linux # python 3 osx
dist: trusty # Ubuntu 14.04 - os: osx
sudo: false osx_image: xcode9.4 # macOS 10.13
language: python
python: '2.6'
env: env:
- MATRIX_EVAL="" - MATRIX_EVAL=""
- os: linux - ARCHFLAGS="-std=c++11"
dist: trusty # Ubuntu 14.04 - PIP_UPDATE="1"
sudo: false - os: osx
language: python osx_image: xcode8.3 # macOS 10.12
python: '2.7' 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: env:
- MATRIX_EVAL="" - MATRIX_EVAL=""
- os: linux - ARCHFLAGS="-std=c++11"
dist: trusty # Ubuntu 14.04 - PIP_UPDATE="1"
sudo: false # python 2 osx
language: python - os: osx
python: '3.3' osx_image: xcode9.4 # macOS 10.13
env: env:
- MATRIX_EVAL="" - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
- os: linux - ARCHFLAGS="-std=c++11"
dist: trusty # Ubuntu 14.04 - PIP_UPDATE="1"
sudo: false - os: osx
language: python osx_image: xcode8.3 # macOS 10.12
python: '3.4'
env: env:
- MATRIX_EVAL="" - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
- os: linux - ARCHFLAGS="-std=c++11"
dist: trusty # Ubuntu 14.04 - PIP_UPDATE="1"
sudo: false - os: osx
language: python osx_image: xcode8 # macOS 10.11
python: '3.5'
env: 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 - os: linux
dist: trusty # Ubuntu 14.04 dist: trusty # Ubuntu 14.04
sudo: false sudo: false
@ -42,25 +45,59 @@ matrix:
python: '3.6' python: '3.6'
env: env:
- MATRIX_EVAL="" - MATRIX_EVAL=""
- os: osx - PIP_UPDATE="1"
osx_image: xcode9.3 # macOS 10.13 - os: linux
dist: trusty # Ubuntu 14.04
sudo: false
language: python
python: '2.7'
env: env:
- MATRIX_EVAL="" - MATRIX_EVAL=""
- os: osx - PIP_UPDATE="1"
osx_image: xcode8.3 # macOS 10.12 - os: linux
dist: trusty # Ubuntu 14.04
sudo: false
language: python
python: '2.6'
env: env:
- MATRIX_EVAL="" - MATRIX_EVAL=""
- os: osx - PIP_UPDATE="0" # setuptools installed from last pip has syntax error on py 2.6
osx_image: xcode8 # macOS 10.11 - os: linux
dist: trusty # Ubuntu 14.04
sudo: false
language: python
python: '3.3'
env: env:
- MATRIX_EVAL="" - 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: before_install:
- env - env
- rvm install ruby --latest - rvm install ruby --latest
- gem install dropbox-deployment - 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}" - 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__)" - python -c "import distutils.sysconfig as sysconfig; print(sysconfig.__file__)"
install: install:

View File

@ -1,8 +1,66 @@
0.26 (2018-06-23): 0.26 (xxxx-xx-xx):
* Enhancement: Standalone Python modules provide * Enhancement: Standalone Python modules provided
For details see: For details see:
https://github.com/klayoutmatthias/klayout/wiki/klayout---Standalone-KLayout-Python-Module 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): 0.25.3 (2018-05-03):
* Enhancement: Compile option to use libcurl instead of QtNetwork * Enhancement: Compile option to use libcurl instead of QtNetwork

View File

@ -1,9 +1,9 @@
klayout (0.26-1) unstable; urgency=low klayout (0.25.4-1) unstable; urgency=low
* New features and bugfixes * New features and bugfixes
- See changelog - See changelog
-- Matthias Köfferlein <matthias@koefferlein.de> Sun, 24 Jun 2018 15:43:26 +0200 -- Matthias Köfferlein <matthias@koefferlein.de> Sat, 25 Aug 2018 23:15:23 +0200
klayout (0.25.3-1) unstable; urgency=low klayout (0.25.3-1) unstable; urgency=low

View File

@ -97,6 +97,9 @@ Homebrew's installation of python3 (`brew install python3`) places a `Python.fra
``` ```
# Build step # Build step
./build4mac.py -p B36 -q Qt5Brew ./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 # Deploy step
./build4mac.py -p B36 -q Qt5Brew -y # normal deploy ./build4mac.py -p B36 -q Qt5Brew -y # normal deploy

View File

@ -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

View File

@ -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)

View File

@ -1,4 +1,4 @@
#! /usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#=============================================================================== #===============================================================================
@ -125,7 +125,7 @@ def SetGlobals():
ModulePython = "PythonYosemite" ModulePython = "PythonYosemite"
elif Platform == "ElCapitan": elif Platform == "ElCapitan":
ModuleRuby = "RubyElCapitan" ModuleRuby = "RubyElCapitan"
ModulePytyon = "PythonElCapitan" ModulePython = "PythonElCapitan"
elif Platform == "Sierra": elif Platform == "Sierra":
ModuleRuby = "RubySierra" ModuleRuby = "RubySierra"
ModulePython = "PythonSierra" ModulePython = "PythonSierra"
@ -538,8 +538,8 @@ def DeployBinariesForBundle():
if not DeploymentF and not DeploymentP: if not DeploymentF and not DeploymentP:
return 1 return 1
if DeploymentF and NonOSStdLang: if DeploymentF and NonOSStdLang:
print( "WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr ) 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( " Consider using <-Y|--DEPLOY> instead", file=sys.stderr )
#return 1 #return 1
if not os.path.isfile(MacBuildLog): if not os.path.isfile(MacBuildLog):
print( "!!! Build log file <%s> does not present !!!" % MacBuildLog, file=sys.stderr ) print( "!!! Build log file <%s> does not present !!!" % MacBuildLog, file=sys.stderr )
@ -756,7 +756,6 @@ def DeployBinariesForBundle():
os.chdir(ProjectDir) os.chdir(ProjectDir)
os.chdir(MacPkgDir) os.chdir(MacPkgDir)
command = "%s %s %s" % ( deploytool, app_bundle, options ) command = "%s %s %s" % ( deploytool, app_bundle, options )
print(command)
if subprocess.call( command, shell=True ) != 0: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to deploy applications on OSX !!!" msg = "!!! Failed to deploy applications on OSX !!!"
print( msg, file=sys.stderr ) print( msg, file=sys.stderr )
@ -764,43 +763,111 @@ def DeployBinariesForBundle():
os.chdir(ProjectDir) os.chdir(ProjectDir)
return 1 return 1
deploymentPython = False deploymentPython = True
if deploymentPython: if deploymentPython and NonOSStdLang:
# TODO Code incomplete! To be finished. from build4mac_util import WalkFrameworkPaths, PerformChanges, DetectChanges
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
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 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) depdict = WalkFrameworkPaths(pythonFrameworkPath)
pythonOriginalFrameworkPath = '/usr/local/opt/python/Frameworks/Python.framework'
appPythonFrameworkPath = '@executable_path/../Frameworks/Python.framework/' appPythonFrameworkPath = '@executable_path/../Frameworks/Python.framework/'
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs) PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath, False)], 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)
print(" [2.2] Patching /usr/local/opt/ libs")
usrLocalPath = '/usr/local/opt/' usrLocalPath = '/usr/local/opt/'
appUsrLocalPath = '@executable_path/../Frameworks/' appUsrLocalPath = '@executable_path/../Frameworks/'
depdict = WalkFrameworkPaths(pythonFrameworkPath) replacePairs = [(usrLocalPath, appUsrLocalPath, True)]
PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs) depdict = WalkFrameworkPaths(pythonFrameworkPath, search_path_filter=r'\t+/usr/local/(opt|Cellar)')
PerformChanges(depdict, replacePairs, bundleExecPathAbs)
# usrLocalPath = '/usr/local/lib/' print(" [2.3] Patching openssl, gdbm, readline, sqlite, tcl-tk, xz")
# appUsrLocalPath = '@executable_path/../Frameworks/' usrLocalPath = '/usr/local/opt'
# depdict = WalkFrameworkPaths(pythonFrameworkPath) appUsrLocalPath = '@executable_path/../Frameworks/'
# PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs) 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: else:
print( " [8] Skipped deploying Qt's Frameworks ..." ) print( " [8] Skipped deploying Qt's Frameworks ..." )
@ -925,9 +992,7 @@ def main():
#---------------------------------------------------------- #----------------------------------------------------------
ret = RunMainBuildBash() ret = RunMainBuildBash()
if not DeploymentF and not DeploymentP: if not DeploymentF and not DeploymentP:
if ret == 0: if not ret == 0:
sys.exit(0)
else:
sys.exit(1) sys.exit(1)
else: else:
#---------------------------------------------------------- #----------------------------------------------------------
@ -944,6 +1009,7 @@ def main():
# to make "KLayoutEditor.app" and "KLayoutViewer.app" # to make "KLayoutEditor.app" and "KLayoutViewer.app"
#---------------------------------------------------------- #----------------------------------------------------------
ret2 = DeployScriptBundles() ret2 = DeployScriptBundles()
if not ret2 == 0: if not ret2 == 0:
sys.exit(1) sys.exit(1)
else: else:

View File

@ -18,14 +18,6 @@ import string
import subprocess import subprocess
import shutil 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 ## To import global dictionaries of different modules
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@ -181,176 +173,167 @@ def SetChangeLibIdentificationName( executable, relativedir ):
# for-lib # for-lib
return 0 return 0
# TODO: undocumented def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'):
if CAN_DEPLOY_PYTHON: NOTHINGTODO = [] # return empty list if nothing to do.
def WalkLibDependencyTree( dylibPath, depth=0, filter_regex=r'\t+/usr/local/opt'): cmdNameId = XcodeToolChain['nameID']
NOTHINGTODO = [] # return empty list if nothing to do. cmdNameChg = XcodeToolChain['nameCH']
dylibPath = str(Path(dylibPath)) otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex)
cmdNameId = XcodeToolChain['nameID'] otoolOut = os.popen( otoolCm ).read()
cmdNameChg = XcodeToolChain['nameCH'] exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
otoolCm = 'otool -L %s | grep -E "%s"' % (dylibPath, filter_regex) keys = exedepdic.keys()
otoolOut = os.popen( otoolCm ).read() deplibs = exedepdic[ list(keys)[0] ]
exedepdic = DecomposeLibraryDependency( dylibPath + ":\n" + otoolOut )
keys = exedepdic.keys()
deplibs = exedepdic[ list(keys)[0] ]
if depth < 5: if depth < 5:
if len(deplibs) > 0: if len(deplibs) > 0:
for idx, lib in enumerate(deplibs): for idx, lib in enumerate(deplibs):
lib = str(Path(lib)) lib = str(lib)
if lib != list(keys)[0]: if lib != list(keys)[0]:
deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex) deplibs[idx] = WalkLibDependencyTree(lib, depth+1, filter_regex)
else: if depth == 0:
return NOTHINGTODO return deplibs
if depth == 0: return exedepdic
return deplibs else:
return exedepdic 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: 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: def DetectChanges(frameworkDependencyDict):
frameworkPath = str(Path(frameworkPath)) visited_files = list()
find_grep_results = os.popen('find %s -type f | grep -E "%s"' % (frameworkPath, filter_regex)).read().split('\n') libNameChanges = list()
framework_files = filter(lambda x: x != '', for framework, libraries in frameworkDependencyDict.items():
map(lambda x: x.strip(), for libraryDict in libraries:
find_grep_results)) libNameChanges.extend(WalkDictTree(libraryDict, visited_files))
# Changes are stored in libNameChanges in the form of ('lib.dylib', ['dep1.dylib', ...])
dependency_dict[frameworkPath] = list() return libNameChanges
for idx, file in enumerate(framework_files):
dict_file = {file: WalkLibDependencyTree(file)}
dependency_dict[frameworkPath].append(dict_file)
return dependency_dict
def WalkDictTree(dependencyDict, visited_files): def PerformChanges(frameworkDependencyDict, replaceFromToPairs=None, executable_path="/tmp/klayout"):
libNameChanges = list() libNameChanges = DetectChanges(frameworkDependencyDict)
for lib, dependencies in dependencyDict.items(): cmdNameId = XcodeToolChain['nameID']
if lib in visited_files: cmdNameChg = XcodeToolChain['nameCH']
continue
dependency_list = list() if replaceFromToPairs is not None:
if isinstance(dependencies, list): for libNameChange in libNameChanges:
for deplib in dependencies: libNameChangeIterator = iter(libNameChange)
if isinstance(deplib, str): lib = next(libNameChangeIterator)
dependency_list.append(deplib) try:
if deplib not in visited_files: dependencies = next(libNameChangeIterator)
visited_files.append(deplib) except StopIteration:
elif isinstance(deplib, dict): dependencies = list()
dependency_list.append(str(next(iter(deplib)))) for replaceFrom, replaceTo, libdir in replaceFromToPairs:
libNameChanges.extend(WalkDictTree(deplib, visited_files)) 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: else:
#raise RuntimeError("Unexpected value: %s" % deplib) frameworkPath = lib
pass destFrameworkPath = frameworkPath.replace(replaceFrom, replaceTo)
else: destFrameworkPath = ResolveExecutablePath(destFrameworkPath, executable_path)
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 FindFramework(path, root_path): if not os.path.exists(fileName):
path = Path(path) print (lib.replace(replaceFrom, replaceTo), "DOES NOT EXIST")
root_path = Path(root_path) print ("COPY", frameworkPath, " -> ", destFrameworkPath)
relPath = path.relative_to(root_path) shutil.copytree(frameworkPath, destFrameworkPath)
return str(root_path / relPath.parts[0])
def ReplaceExecutablePath(path, executable_path): nameId = lib.replace(replaceFrom, replaceTo)
executable_path = str(executable_path) command = "%s %s %s" % ( cmdNameId, nameId, fileName )
p = Path(str(path).replace("@executable_path", "/%s/" % executable_path)) if not os.access(fileName, os.W_OK):
return p 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): for dependency in dependencies:
p = ReplaceExecutablePath(file_path, executable_path) if dependency.find(replaceFrom) >= 0:
return p.exists() print("\tIn:", fileName)
print("\tRENAME", dependency, " -> ", dependency.replace(replaceFrom, replaceTo))
def DetectChanges(frameworkDependencyDict): # Try changing id first
visited_files = list() nameId = dependency.replace(replaceFrom, replaceTo)
libNameChanges = list() command = "%s %s %s" % ( cmdNameId, nameId, fileName)
for framework, libraries in frameworkDependencyDict.items(): if not os.access(str(fileName), os.W_OK):
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):
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName) 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: if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to set the new identification name to <%s> !!!" msg = "!!! Failed to set the new identification name to <%s> !!!"
print( msg % fileName, file=sys.stderr ) print( msg % fileName, file=sys.stderr )
return 1 return 1
fileName = ReplaceExecutablePath(lib.replace(replaceFrom, replaceTo), executable_path) # Rename dependencies
for dependency in dependencies: nameOld = dependency
if dependency.find(replaceFrom) >= 0: nameNew = dependency.replace(replaceFrom, replaceTo)
print("In:", fileName) command = "%s %s %s %s" % ( cmdNameChg, nameOld, nameNew, str(fileName) )
print("\tRENAME", dependency, " -> ", dependency.replace(replaceFrom, replaceTo)) 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 # print("\t%s" % command)
nameId = dependency.replace(replaceFrom, replaceTo) if subprocess.call( command, shell=True ) != 0:
command = "%s %s %s" % ( cmdNameId, nameId, fileName ) msg = "!!! Failed to set the new identification name to <%s> !!!"
if not os.access(fileName, os.W_OK): print( msg % fileName, file=sys.stderr )
command = "chmod u+w %s; %s; chmod u-w %s" % (fileName, command, fileName) 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
# 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
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -89,10 +89,15 @@ cd ..
mkdir -p makedeb-tmp/${sharedir}/doc/klayout mkdir -p makedeb-tmp/${sharedir}/doc/klayout
mkdir -p makedeb-tmp/${sharedir}/applications mkdir -p makedeb-tmp/${sharedir}/applications
mkdir -p makedeb-tmp/${sharedir}/pixmaps mkdir -p makedeb-tmp/${sharedir}/pixmaps
<<<<<<< HEAD
mkdir -p makedeb-tmp/${libdir}/db_plugins mkdir -p makedeb-tmp/${libdir}/db_plugins
mkdir -p makedeb-tmp/${libdir}/lay_plugins mkdir -p makedeb-tmp/${libdir}/lay_plugins
mkdir -p makedeb-tmp/${pylibdir} mkdir -p makedeb-tmp/${pylibdir}
mkdir -p makedeb-tmp/${bindir} 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/klayout.desktop makedeb-tmp/${sharedir}/applications
cp etc/logo.png makedeb-tmp/${sharedir}/pixmaps 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/strm* makedeb-tmp/${bindir}
cp -pd $bininstdir/klayout makedeb-tmp/${bindir} cp -pd $bininstdir/klayout makedeb-tmp/${bindir}
cp -pd $bininstdir/lib*so* makedeb-tmp/${libdir} cp -pd $bininstdir/lib*so* makedeb-tmp/${libdir}
<<<<<<< HEAD
cp -pd $bininstdir/db_plugins/lib*so* makedeb-tmp/${libdir}/db_plugins 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/lay_plugins/lib*so* makedeb-tmp/${libdir}/lay_plugins
cp -pd $bininstdir/pymod/klayout/*so makedeb-tmp/${pylibdir} cp -pd $bininstdir/pymod/klayout/*so makedeb-tmp/${pylibdir}
cp -pd $bininstdir/pymod/klayout/*py makedeb-tmp/${pylibdir} cp -pd $bininstdir/pymod/klayout/*py makedeb-tmp/${pylibdir}
=======
>>>>>>> master
cd makedeb-tmp cd makedeb-tmp
@ -131,9 +139,12 @@ echo "Modifying control file .."
strip ${bindir}/* strip ${bindir}/*
strip ${libdir}/*.so* strip ${libdir}/*.so*
<<<<<<< HEAD
strip ${pylibdir}/*.so strip ${pylibdir}/*.so
strip ${libdir}/db_plugins/*.so* strip ${libdir}/db_plugins/*.so*
strip ${libdir}/lay_plugins/*.so* strip ${libdir}/lay_plugins/*.so*
=======
>>>>>>> master
size=`du -ck usr | grep total | sed "s/ *total//"` size=`du -ck usr | grep total | sed "s/ *total//"`

View File

@ -864,10 +864,10 @@ no_imports "QAbstractXmlNodeModel" # base class is QSharedData which is not ava
# QtNetwork # QtNetwork
drop_method "QUrlInfo", /QUrlInfo::QUrlInfo\(.*permissions/ # too many arguments (13) 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+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::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+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::setAddress\(\s*const\s+sockaddr/ # requires sockaddr struct, a string version is available for IPv6
drop_method "QHostAddress", /QHostAddress::toIPv6Address\(/ # requires QIPv6Address struct drop_method "QHostAddress", /QHostAddress::toIPv6Address\(/ # requires QIPv6Address struct

View File

@ -77,6 +77,14 @@ Requires: libqt4-x11 >= 4.8.7
%define pylib %{python3_sitearch} %define pylib %{python3_sitearch}
%endif %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 %description
Mask layout viewer and editor for the chip design engineer. Mask layout viewer and editor for the chip design engineer.

View File

@ -59,6 +59,49 @@ import glob
import os import os
import platform import platform
import distutils.sysconfig as sysconfig 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 # Core setup function
if __name__ == '__main__': if __name__ == '__main__':
print("Number of cores", N_cores)
setup(name=config.root, setup(name=config.root,
version=config.version(), version=config.version(),
description='KLayout standalone Python package', description='KLayout standalone Python package',

View File

@ -30,7 +30,7 @@ TEST(1)
std::string fp (tl::testsrc ()); std::string fp (tl::testsrc ());
fp += "/testdata/bd/strmrun.py"; 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::InputPipe pipe (path);
tl::InputStream is (pipe); tl::InputStream is (pipe);
std::string data = is.read_all (); std::string data = is.read_all ();

View File

@ -22,6 +22,41 @@
#include "dbEdge.h" #include "dbEdge.h"
#include "tlLongInt.h"
namespace db
{
/**
* @brief Computes the gcd of two numbers
*/
template <class C>
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<db::Coord>::area_type b, db::coord_traits<db::Coord>::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 namespace tl
{ {

View File

@ -38,6 +38,25 @@
namespace db { 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<db::Coord>::area_type b, db::coord_traits<db::Coord>::area_type d);
/**
* @brief An overload of div_exact for double types
*/
inline db::DCoord div_exact (db::DCoord a, db::coord_traits<db::DCoord>::area_type b, db::coord_traits<db::DCoord>::area_type d)
{
return db::coord_traits<db::DCoord>::rounded (double (a) * double (b) / double (d));
}
template <class C> class generic_repository; template <class C> class generic_repository;
class ArrayRepository; class ArrayRepository;
@ -794,10 +813,15 @@ public:
} else if (res) { } 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 x = m_p1.x () + div_exact (dx (), vxa, vxa + vxb);
coord_type y = m_p1.y () + coord_traits::rounded (dy () * f); coord_type y = m_p1.y () + div_exact (dy (), vxa, vxa + vxb);
return std::make_pair (true, db::point<C> (x, y)); return std::make_pair (true, db::point<C> (x, y));
@ -1073,10 +1097,15 @@ public:
if (res) { 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 x = e.p1 ().x () + div_exact (e.dx (), vxa, vxa + vxb);
coord_type y = e.p1 ().y () + coord_traits::rounded (e.dy () * f); coord_type y = e.p1 ().y () + div_exact (e.dy (), vxa, vxa + vxb);
return std::make_pair (true, db::point<C> (x, y)); return std::make_pair (true, db::point<C> (x, y));

View File

@ -121,6 +121,26 @@ private:
db::Coord m_y; 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 inline bool
is_point_on_fuzzy (const db::Edge &e, const db::Point &pt) 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 { } else {
bool with_equal = false;
db::Vector offset; db::Vector offset;
if ((e.dx () < 0 && e.dy () > 0) || (e.dx () > 0 && e.dy () < 0)) { if ((e.dx () < 0 && e.dy () > 0) || (e.dx () > 0 && e.dy () < 0)) {
offset = db::Vector (1, 1); offset = db::Vector (1, 1);
with_equal = true;
} else { } else {
offset = db::Vector (-1, 1); 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<db::Point::coord_type>::area_type area_type; typedef db::coord_traits<db::Point::coord_type>::area_type area_type;
area_type a1 = 2 * db::vprod (pp1, e.d ()); area_type a1 = 2 * db::vprod (pp1, e.d ());
if (a1 < 0) { a1 = -a1; }
area_type a2 = db::vprod (offset, e.d ()); 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; } if (a2 < 0) { a2 = -a2; }
return a1 <= a2;
} return a1 < a2 || (a1 == a2 && with_equal);
}
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;
} }
} }
@ -804,7 +813,7 @@ MergeOp::edge (bool north, bool enter, property_type p)
bool inside_after = (*wcv != 0); bool inside_after = (*wcv != 0);
m_zeroes += (!inside_after) - (!inside_before); m_zeroes += (!inside_after) - (!inside_before);
#ifdef DEBUG_MERGEOP #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 #endif
tl_assert (long (m_zeroes) >= 0); 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)); bool inside_after = ((p % 2) == 0 ? inside_a (*wcv) : inside_b (*wcv));
m_zeroes += (!inside_after) - (!inside_before); m_zeroes += (!inside_after) - (!inside_before);
#ifdef DEBUG_BOOLEAN #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 #endif
tl_assert (long (m_zeroes) >= 0); tl_assert (long (m_zeroes) >= 0);
@ -1345,32 +1354,17 @@ get_intersections_per_band_any (std::vector <CutPoints> &cutpoints, std::vector
#endif #endif
// The new cutpoint must be inserted into other edges as well. // 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 (); ip_weak.clear ();
size_t n_off_edge = on_edge1 ? 0 : 1;
for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) { for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) {
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) { if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
ip_weak.push_back (&*cc); ip_weak.push_back (&*cc);
if (!is_point_on_exact (*cc, cp.second)) {
++n_off_edge;
}
} }
} }
for (std::vector <WorkEdge *>::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) { for (std::vector <WorkEdge *>::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 #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 #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> &cutpoints, std::vector
#endif #endif
// The new cutpoint must be inserted into other edges as well. // 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 (); 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 <WorkEdge>::iterator cc = c; cc != f; ++cc) { for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) {
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) { if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
ip_weak.push_back (&*cc); ip_weak.push_back (&*cc);
if (!is_point_on_exact (*cc, cp.second)) {
++n_off_edge;
}
} }
} }
for (std::vector <WorkEdge *>::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) { for (std::vector <WorkEdge *>::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 #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 #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 = c->data % skip_unit;
size_t skip_res = c->data / skip_unit; size_t skip_res = c->data / skip_unit;
#ifdef DEBUG_EDGE_PROCESSOR #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 #endif
if (skip != 0 && (c + skip >= future || (c + skip)->data != 0)) { if (skip != 0 && (c + skip >= future || (c + skip)->data != 0)) {

View File

@ -194,6 +194,20 @@ public:
*/ */
point<C> &operator*= (long s); point<C> &operator*= (long s);
/**
* @brief Division by some divisor.
*
* Scaline involves rounding which in our case is simply handled
* with the coord_traits scheme.
*/
point<C> &operator/= (double s);
/**
* @brief Dividing self by some integer divisor
*/
point<C> &operator/= (long s);
/** /**
* @brief The euclidian distance to another point * @brief The euclidian distance to another point
* *
@ -452,6 +466,32 @@ operator* (const db::point<C> &p, unsigned int s)
return point<C> (p.x () * s, p.y () * s); return point<C> (p.x () * s, p.y () * s);
} }
template <class C, typename Number>
inline point<C>
operator/ (const db::point<C> &p, Number s)
{
double mult = 1.0 / static_cast<double>(s);
return point<C> (p.x () * mult, p.y () * mult);
}
template <class C>
inline point<C> &
point<C>::operator/= (double s)
{
double mult = 1.0 / static_cast<double>(s);
*this *= mult;
return *this;
}
template <class C>
inline point<C> &
point<C>::operator/= (long s)
{
double mult = 1.0 / static_cast<double>(s);
*this *= mult;
return *this;
}
template <class C> template <class C>
inline point<C> & inline point<C> &
point<C>::operator*= (double s) point<C>::operator*= (double s)

View File

@ -296,7 +296,7 @@ PolygonGenerator::flush ()
{ {
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) { 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"); printf ("\n");
#endif #endif
@ -325,12 +325,12 @@ PolygonGenerator::begin_scanline (db::Coord y)
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
printf ("m_open="); printf ("m_open=");
for (open_map_type::const_iterator o = m_open.begin (); o != m_open.end (); ++o) { 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 ("\n");
printf ("contours:\n"); printf ("contours:\n");
for (size_t j = 0; j < mp_contours->size (); ++j) { 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) { for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ()); 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<db::Coord>::max ()); join_contours (std::numeric_limits<db::Coord>::max ());
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
printf ("skip(%d)\n", n); printf ("skip(%ld)\n", n);
#endif #endif
while (n-- > 0) { while (n-- > 0) {
++m_open_pos; ++m_open_pos;
@ -375,9 +375,9 @@ void
PolygonGenerator::put (const db::Edge &e) PolygonGenerator::put (const db::Edge &e)
{ {
#ifdef DEBUG_POLYGON_GENERATOR #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) { 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"); printf ("\n");
#endif #endif
@ -438,7 +438,7 @@ PolygonGenerator::put (const db::Edge &e)
cnew.push_back (e.p2 ()); cnew.push_back (e.p2 ());
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
printf ("create %s %d\n", hole ? "hole" : "hull", poly_index); printf ("create %s %ld\n", hole ? "hole" : "hull", inew);
#endif #endif
m_open.insert (m_open_pos, PGPoint (hole ? e.p1 () : e.p2 (), inew, true)); 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)); 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 #ifdef DEBUG_POLYGON_GENERATOR
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) { 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"); printf ("\n");
#endif #endif
@ -552,14 +552,14 @@ PolygonGenerator::join_contours (db::Coord x)
size_t i1 = m_open_pos->contour; size_t i1 = m_open_pos->contour;
size_t i2 = n->contour; size_t i2 = n->contour;
#ifdef DEBUG_POLYGON_GENERATOR #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) { 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 ("\n");
printf ("--> input contours:\n"); printf ("--> input contours:\n");
for (size_t j = 0; j < mp_contours->size (); ++j) { 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) { for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ()); 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 ()) { if (! c1.is_hole ()) {
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
printf ("finish %d (hull)\n", i1); printf ("finish %ld (hull)\n", i1);
#endif #endif
produce_poly (c1); produce_poly (c1);
@ -775,7 +775,7 @@ PolygonGenerator::join_contours (db::Coord x)
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
printf ("--> output contours:\n"); printf ("--> output contours:\n");
for (size_t j = 0; j < mp_contours->size (); ++j) { 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) { for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ()); printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
} }

View File

@ -266,6 +266,20 @@ public:
*/ */
vector<C> operator*= (long s); vector<C> operator*= (long s);
/**
* @brief Division by some divisor.
*
* Scaline involves rounding which in our case is simply handled
* with the coord_traits scheme.
*/
vector<C> &operator/= (double s);
/**
* @brief Dividing self by some integer divisor
*/
vector<C> &operator/= (long s);
/** /**
* @brief The euclidian length * @brief The euclidian length
*/ */
@ -450,6 +464,32 @@ vector<C>::operator* (long s) const
return vector<C> (m_x * s, m_y * s); return vector<C> (m_x * s, m_y * s);
} }
template <class C, typename Number>
inline vector<C>
operator/ (const db::vector<C> &p, Number s)
{
double mult = 1.0 / static_cast<double>(s);
return vector<C> (p.x () * mult, p.y () * mult);
}
template <class C>
inline vector<C> &
vector<C>::operator/= (double s)
{
double mult = 1.0 / static_cast<double>(s);
*this *= mult;
return *this;
}
template <class C>
inline vector<C> &
vector<C>::operator/= (long s)
{
double mult = 1.0 / static_cast<double>(s);
*this *= mult;
return *this;
}
template <class C> template <class C>
inline vector<C> inline vector<C>
vector<C>::operator*= (double s) vector<C>::operator*= (double s)

View File

@ -70,6 +70,23 @@ struct point_defs
return C (*p * s); 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) static C negate (const C *p)
{ {
return -*p; return -*p;
@ -175,6 +192,30 @@ struct point_defs
"Returns the scaled object. All coordinates are multiplied with the given factor and if " "Returns the scaled object. All coordinates are multiplied with the given factor and if "
"necessary rounded." "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 ("/", &divide,
"@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, method ("distance", (double (C::*) (const C &) const) &C::double_distance,
"@brief The Euclidian distance to another point\n" "@brief The Euclidian distance to another point\n"
"\n" "\n"

View File

@ -280,7 +280,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
) + ) +
gsi::method ("region=", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::box_type &)) &db::RecursiveShapeIterator::set_region, 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" "@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" "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 " "Setting a simple region will reset the complex region to a rectangle and reset the iterator to "
"the beginning of the sequence." "the beginning of the sequence."
@ -298,15 +298,19 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
) + ) +
gsi::method ("confine_region", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::box_type &)) &db::RecursiveShapeIterator::confine_region, 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" "@brief Confines the region that is iterator is iterating over\n"
"@args region\n" "@args box_region\n"
"This method is similar to setting the region (see \\region=), but will add to any (complex or simple) region already set. " "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" "\n"
"This method has been introduced in version 0.25.\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" "@brief Confines the region that is iterator is iterating over\n"
"@args region\n" "@args complex_region\n"
"This method is similar to setting the complex region (see \\region=), but will add to any (complex or simple) region already set." "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" "\n"
"This method has been introduced in version 0.25.\n" "This method has been introduced in version 0.25.\n"
) + ) +

View File

@ -50,6 +50,21 @@ static void dump_mem_statistics (const db::Shapes *shapes, bool detailed)
ms.print (); 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<class Sh> template<class Sh>
static db::Shape insert (db::Shapes *s, const Sh &p) static db::Shape insert (db::Shapes *s, const Sh &p)
{ {
@ -1088,7 +1103,7 @@ Class<db::Shapes> decl_Shapes ("db", "Shapes",
"@brief Clears the shape container\n" "@brief Clears the shape container\n"
"This method has been introduced in version 0.16. It can only be used in editable mode." "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" "@brief Gets the number of shapes in this container\n"
"This method was introduced in version 0.16\n" "This method was introduced in version 0.16\n"
"@return The number of shapes in this container\n" "@return The number of shapes in this container\n"

View File

@ -70,6 +70,23 @@ struct vector_defs
return C (*p * s); 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) static C negate (const C *p)
{ {
return -*p; return -*p;
@ -202,6 +219,30 @@ struct vector_defs
"Returns the scaled object. All coordinates are multiplied with the given factor and if " "Returns the scaled object. All coordinates are multiplied with the given factor and if "
"necessary rounded." "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 ("/", &divide,
"@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, method_ext ("vprod", &vprod,
"@brief Computes the vector product between self and the given vector\n" "@brief Computes the vector product between self and the given vector\n"
"\n" "\n"

View File

@ -514,3 +514,74 @@ TEST(14)
EXPECT_EQ (e.coincident (db::Edge (db::Point (49, 0), db::Point (200, 0))), false); EXPECT_EQ (e.coincident (db::Edge (db::Point (49, 0), db::Point (200, 0))), false);
} }
// exact rounding behaviour
TEST(15)
{
typedef db::coord_traits<db::Coord>::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<bool, db::Point> 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");
}

View File

@ -25,6 +25,7 @@
#include "dbShapeProcessor.h" #include "dbShapeProcessor.h"
#include "dbPolygon.h" #include "dbPolygon.h"
#include "dbPolygonGenerators.h"
#include "dbLayout.h" #include "dbLayout.h"
#include "dbReader.h" #include "dbReader.h"
#include "dbCommonReader.h" #include "dbCommonReader.h"
@ -1332,7 +1333,7 @@ TEST(23)
EXPECT_EQ (out.size (), size_t (1)); EXPECT_EQ (out.size (), size_t (1));
std::sort (out.begin (), out.end ()); 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) TEST(24)
@ -1390,15 +1391,29 @@ TEST(24)
in1.back ().assign_hull (p1 + 0, p1 + sizeof (p1) / sizeof (p1[0])); in1.back ().assign_hull (p1 + 0, p1 + sizeof (p1) / sizeof (p1[0]));
} }
std::vector<db::Polygon> out; {
std::vector<db::Polygon> out;
db::EdgeProcessor ep; db::EdgeProcessor ep;
ep.simple_merge (in1, out, false, false); ep.simple_merge (in1, out, false, false);
EXPECT_EQ (out.size (), size_t (2)); EXPECT_EQ (out.size (), size_t (1));
std::sort (out.begin (), out.end ()); 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[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)");
EXPECT_EQ (out[1].to_string (), "(-2,1;-2,3;0,1;0,10;1,10;1,1)"); }
{
std::vector<db::Polygon> 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) TEST(25)
@ -2247,7 +2262,7 @@ TEST(100)
} }
// #74 (GitHub) // #74 (GitHub)
TEST(101) std::string run_test101 (tl::TestBase *_this, const db::Trans &t)
{ {
db::EdgeProcessor ep; db::EdgeProcessor ep;
@ -2260,6 +2275,7 @@ TEST(101)
}; };
db::Polygon p; db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]); p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
p.transform (t);
ep.insert (p, 0); ep.insert (p, 0);
} }
@ -2272,6 +2288,7 @@ TEST(101)
}; };
db::Polygon p; db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]); p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
p.transform (t);
ep.insert (p, 1); ep.insert (p, 1);
} }
@ -2284,6 +2301,7 @@ TEST(101)
}; };
db::Polygon p; db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]); p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
p.transform (t);
ep.insert (p, 1); ep.insert (p, 1);
} }
@ -2295,7 +2313,16 @@ TEST(101)
ep.process (pg, op); ep.process (pg, op);
EXPECT_EQ (out.size (), size_t (1)); 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) TEST(102)
@ -2348,3 +2375,111 @@ TEST(102)
EXPECT_EQ (out.size (), size_t (1)); 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)"); 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<db::Polygon> 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<db::Polygon> 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<db::Polygon> 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)");
}

View File

@ -1082,7 +1082,7 @@ TEST(31)
pout = minkowsky_sum (p, db::Edge (db::Point (10, 10), db::Point (210, -90)), true); 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 <db::Point> c; std::vector <db::Point> c;
c.push_back (db::Point (10, 10)); c.push_back (db::Point (10, 10));

View File

@ -26,10 +26,13 @@
#include "dbTilingProcessor.h" #include "dbTilingProcessor.h"
#include "dbTextWriter.h" #include "dbTextWriter.h"
#include "gsiExpression.h" #include "gsiExpression.h"
#include "gsiDecl.h"
#include "dbWriter.h" #include "dbWriter.h"
#include "dbSaveLayoutOptions.h" #include "dbSaveLayoutOptions.h"
#include <cstdlib> #include <cstdlib>
#include <QMutex>
#include <QMutexLocker>
unsigned int get_rand() 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<db::TileOutputReceiver> &dbdecl_TileOutputReceiverBase ();
}
gsi::Class<MyTilingOutputReceiver> 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);
}

View File

@ -896,7 +896,7 @@ CODE
# #
# This method produces markers on the corners of the polygons. An angle criterion can be given which # 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 # 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. # 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. # The markers generated can be point-like edges or small 2x2 DBU boxes. The latter is the default.

View File

@ -251,6 +251,8 @@ ShapePropertiesPage::do_apply (bool current_only)
for (std::vector<edt::Service::obj_iterator>::const_iterator p = m_selection_ptrs.begin (); p != m_selection_ptrs.end (); ++p) { for (std::vector<edt::Service::obj_iterator>::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; 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 // 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; continue;
} }
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
db::Layout &layout = cv->layout ();
tl_assert (! pos->is_cell_inst ()); tl_assert (! pos->is_cell_inst ());
if (pos->shape ().is_array_member ()) { if (pos->shape ().is_array_member ()) {
@ -271,10 +276,8 @@ ShapePropertiesPage::do_apply (bool current_only)
std::map<db::Shape, db::Shape>::const_iterator s = shapes_seen.find (pos->shape ()); std::map<db::Shape, db::Shape>::const_iterator s = shapes_seen.find (pos->shape ());
if (s == shapes_seen.end ()) { if (s == shapes_seen.end ()) {
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ()); db::Shapes &shapes = layout.cell (pos->cell_index ()).shapes (pos->layer ());
double dbu = layout.dbu ();
db::Shapes &shapes = cv->layout ().cell (pos->cell_index ()).shapes (pos->layer ());
double dbu = cv->layout ().dbu ();
if (!current_only || pos->shape () == current) { if (!current_only || pos->shape () == current) {
new_shape = applicator->do_apply (shapes, pos->shape (), dbu, relative_mode); 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 ()) { if (new_shape != pos->shape ()) {
size_t index = p - m_selection_ptrs.begin ();
// change selection to new shape // change selection to new shape
new_sel[index].set_shape (new_shape); new_sel[index].set_shape (new_shape);
@ -298,21 +299,34 @@ ShapePropertiesPage::do_apply (bool current_only)
update_required = true; update_required = true;
} }
// handle the case of guiding shape updates
std::pair<bool, lay::ObjectInstPath> 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) { if (update_required) {
mp_service->view ()->cellview (cv_index)->layout ().cleanup ();
recompute_selection_ptrs (new_sel); recompute_selection_ptrs (new_sel);
} }
} catch (...) { } catch (...) {
mp_service->view ()->cellview (cv_index)->layout ().cleanup ();
recompute_selection_ptrs (new_sel); recompute_selection_ptrs (new_sel);
throw; throw;
} }
mp_service->handle_guiding_shape_changes ();
update (); update ();
} }

View File

@ -1480,30 +1480,23 @@ Service::add_selection (const lay::ObjectInstPath &sel)
selection_to_view (); selection_to_view ();
} }
bool std::pair<bool, lay::ObjectInstPath>
Service::handle_guiding_shape_changes () Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const
{ {
// just allow one guiding shape to be selected unsigned int cv_index = obj.cv_index ();
if (m_selection.empty ()) {
return false;
}
objects::const_iterator s = m_selection.begin ();
unsigned int cv_index = s->cv_index ();
lay::CellView cv = view ()->cellview (cv_index); lay::CellView cv = view ()->cellview (cv_index);
db::Layout *layout = &cv->layout (); db::Layout *layout = &cv->layout ();
if (s->is_cell_inst () || s->layer () != layout->guiding_shape_layer ()) { if (obj.is_cell_inst () || obj.layer () != layout->guiding_shape_layer ()) {
return false; return std::make_pair (false, lay::ObjectInstPath ());
} }
if (! s->shape ().has_prop_id ()) { if (! obj.shape ().has_prop_id ()) {
return false; return std::make_pair (false, lay::ObjectInstPath ());
} }
if (! layout->is_pcell_instance (s->cell_index ()).first) { if (! layout->is_pcell_instance (obj.cell_index ()).first) {
return false; return std::make_pair (false, lay::ObjectInstPath ());
} }
db::cell_index_type top_cell = std::numeric_limits<db::cell_index_type>::max (); db::cell_index_type top_cell = std::numeric_limits<db::cell_index_type>::max ();
@ -1512,37 +1505,38 @@ Service::handle_guiding_shape_changes ()
db::pcell_parameters_type parameters_for_pcell; db::pcell_parameters_type parameters_for_pcell;
// determine parent cell and instance if required // determine parent cell and instance if required
lay::ObjectInstPath::iterator e = s->end (); lay::ObjectInstPath::iterator e = obj.end ();
if (e == s->begin ()) { if (e == obj.begin ()) {
top_cell = s->cell_index (); top_cell = obj.cell_index ();
} else { } else {
--e; --e;
db::cell_index_type pc = s->topcell (); db::cell_index_type pc = obj.topcell ();
if (e != s->begin ()) { if (e != obj.begin ()) {
--e; --e;
pc = e->inst_ptr.cell_index (); pc = e->inst_ptr.cell_index ();
} }
parent_cell = pc; 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"); 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); db::PropertiesRepository::properties_set::const_iterator input_pv = input_props.find (pn);
if (input_pv == input_props.end ()) { if (input_pv == input_props.end ()) {
return false; return std::make_pair (false, lay::ObjectInstPath ());
} }
std::string shape_name = input_pv->second.to_string (); 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 // 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. // 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)) { if (! get_parameters_from_pcell_and_guiding_shapes (layout, obj.cell_index (), parameters_for_pcell)) {
return false; return std::make_pair (false, lay::ObjectInstPath ());
} }
std::vector<lay::ObjectInstPath> new_sel; bool found = false;
lay::ObjectInstPath new_obj = obj;
if (parent_cell != std::numeric_limits <db::cell_index_type>::max ()) { if (parent_cell != std::numeric_limits <db::cell_index_type>::max ()) {
@ -1550,21 +1544,20 @@ Service::handle_guiding_shape_changes ()
// try to identify the selected shape in the new shapes and select this one // 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); 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 ()); const db::PropertiesRepository::properties_set &props = layout->properties_repository ().properties (sh->prop_id ());
db::PropertiesRepository::properties_set::const_iterator pv = props.find (pn); db::PropertiesRepository::properties_set::const_iterator pv = props.find (pn);
if (pv != props.end ()) { if (pv != props.end ()) {
if (pv->second.to_string () == shape_name) { if (pv->second.to_string () == shape_name) {
new_sel.push_back (*s); new_obj.back ().inst_ptr = new_inst;
new_sel.back ().back ().inst_ptr = new_inst; new_obj.back ().array_inst = new_inst.begin ();
new_sel.back ().back ().array_inst = new_inst.begin (); new_obj.set_shape (*sh);
new_sel.back ().set_shape (*sh); found = true;
break;
} }
} }
++sh; ++sh;
} }
} }
if (top_cell != std::numeric_limits <db::cell_index_type>::max ()) { if (top_cell != std::numeric_limits <db::cell_index_type>::max ()) {
@ -1572,12 +1565,33 @@ Service::handle_guiding_shape_changes ()
// Currently there is not way to create such a configuration ... // Currently there is not way to create such a configuration ...
} }
// remove superfluous proxies return std::make_pair (found, new_obj);
layout->cleanup (); }
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<bool, lay::ObjectInstPath> 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<lay::ObjectInstPath> new_sel;
new_sel.push_back (gs.second);
set_selection (new_sel.begin (), new_sel.end ());
return true;
} else {
return false;
}
} }

View File

@ -342,9 +342,19 @@ public:
* @brief Handle changes in the guiding shapes, i.e. create PCell variants * @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 * @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 (); 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<bool, lay::ObjectInstPath> handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const;
protected: protected:
/** /**
* @brief Update m_markers to reflect the selection * @brief Update m_markers to reflect the selection

View File

@ -27,9 +27,13 @@
#include "tlLog.h" #include "tlLog.h"
#include <QMutexLocker>
namespace gsi namespace gsi
{ {
QMutex Proxy::m_lock;
Proxy::Proxy (const gsi::ClassBase *_cls_decl) Proxy::Proxy (const gsi::ClassBase *_cls_decl)
: m_cls_decl (_cls_decl), : m_cls_decl (_cls_decl),
m_obj (0), m_obj (0),
@ -43,21 +47,34 @@ Proxy::Proxy (const gsi::ClassBase *_cls_decl)
Proxy::~Proxy () Proxy::~Proxy ()
{ {
try { void *prev_obj = 0;
set (0, false, false, false);
} catch (std::exception &ex) { {
tl::warn << "Caught exception in object destructor: " << ex.what (); QMutexLocker locker (&m_lock);
} catch (tl::Exception &ex) { try {
tl::warn << "Caught exception in object destructor: " << ex.msg (); prev_obj = set_internal (0, false, false, false);
} catch (...) { } catch (std::exception &ex) {
tl::warn << "Caught unspecified exception in object destructor"; 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 void
Proxy::destroy () Proxy::destroy ()
{ {
QMutexLocker locker (&m_lock);
if (! m_cls_decl) { if (! m_cls_decl) {
m_obj = 0; m_obj = 0;
return; return;
@ -82,7 +99,7 @@ Proxy::destroy ()
if (m_owned || m_can_destroy) { if (m_owned || m_can_destroy) {
o = m_obj; o = m_obj;
} }
detach (); detach_internal ();
if (o) { if (o) {
m_cls_decl->destroy (o); m_cls_decl->destroy (o);
} }
@ -91,28 +108,20 @@ Proxy::destroy ()
void void
Proxy::detach () Proxy::detach ()
{ {
if (! m_destroyed && m_cls_decl && m_cls_decl->is_managed ()) { QMutexLocker locker (&m_lock);
gsi::ObjectBase *gsi_object = m_cls_decl->gsi_object (m_obj, false); detach_internal ();
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;
} }
void void
Proxy::release () Proxy::release ()
{ {
QMutexLocker locker (&m_lock);
// If the object is managed we first reset the ownership of all other clients // If the object is managed we first reset the ownership of all other clients
// and then make us the owner // and then make us the owner
const gsi::ClassBase *cls = m_cls_decl; const gsi::ClassBase *cls = m_cls_decl;
if (cls && cls->is_managed ()) { if (cls && cls->is_managed ()) {
void *o = obj (); void *o = obj_internal ();
if (o) { if (o) {
cls->gsi_object (o)->keep (); cls->gsi_object (o)->keep ();
} }
@ -125,9 +134,11 @@ Proxy::release ()
void void
Proxy::keep () Proxy::keep ()
{ {
QMutexLocker locker (&m_lock);
const gsi::ClassBase *cls = m_cls_decl; const gsi::ClassBase *cls = m_cls_decl;
if (cls) { if (cls) {
void *o = obj (); void *o = obj_internal ();
if (o) { if (o) {
if (cls->is_managed ()) { if (cls->is_managed ()) {
cls->gsi_object (o)->keep (); cls->gsi_object (o)->keep ();
@ -142,12 +153,68 @@ Proxy::keep ()
void void
Proxy::set (void *obj, bool owned, bool const_ref, bool can_destroy) 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; bool prev_owned = m_owned;
m_owned = owned; m_owned = owned;
m_can_destroy = can_destroy; m_can_destroy = can_destroy;
m_const_ref = const_ref; m_const_ref = const_ref;
void *prev_object = 0;
const gsi::ClassBase *cls = m_cls_decl; const gsi::ClassBase *cls = m_cls_decl;
if (! cls) { 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 // 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()) // (either because we are not owner or from C++ side using keep())
if (prev_owned) { if (prev_owned) {
void *o = m_obj; prev_object = m_obj;
m_obj = 0; 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 // 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. // here because before detach might be called on *this which resets m_destroyed.
m_destroyed = false; m_destroyed = false;
}
void * return prev_object;
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;
} }
void void
Proxy::object_status_changed (gsi::ObjectBase::StatusEventType type) Proxy::detach_internal()
{ {
if (type == gsi::ObjectBase::ObjectDestroyed) { if (! m_destroyed && m_cls_decl && m_cls_decl->is_managed ()) {
m_destroyed = true; // NOTE: must be set before detach and indicates that the object was destroyed externally. gsi::ObjectBase *gsi_object = m_cls_decl->gsi_object (m_obj, false);
detach (); if (gsi_object) {
} else if (type == gsi::ObjectBase::ObjectKeep) { gsi_object->status_changed_event ().remove (this, &Proxy::object_status_changed);
m_owned = false; }
} else if (type == gsi::ObjectBase::ObjectRelease) {
m_owned = true;
} }
m_obj = 0;
m_destroyed = true;
m_const_ref = false;
m_owned = false;
m_can_destroy = false;
} }
} }

View File

@ -29,6 +29,7 @@
#include "gsiCommon.h" #include "gsiCommon.h"
#include <memory> #include <memory>
#include <QMutex>
// For a comprehensive documentation see gsi.h // 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 * 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). * 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 class GSI_PUBLIC Proxy
: public tl::Object : public tl::Object
@ -228,8 +240,12 @@ private:
bool m_const_ref : 1; bool m_const_ref : 1;
bool m_destroyed : 1; bool m_destroyed : 1;
bool m_can_destroy : 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 object_status_changed (gsi::ObjectBase::StatusEventType type);
void detach_internal ();
void *obj_internal ();
}; };
} }

View File

@ -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<const quint8 * > (argspec_0);
decl->set_return_new<QHostAddress> ();
}
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<const quint8 * > (heap);
ret.write<QHostAddress *> (new QHostAddress (arg1));
}
// Constructor QHostAddress::QHostAddress(const QString &address) // 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<const quint8 * > (argspec_0);
decl->set_return<void > ();
}
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<const quint8 * > (heap);
__SUPPRESS_UNUSED_WARNING(ret);
((QHostAddress *)cls)->setAddress (arg1);
}
// bool QHostAddress::setAddress(const QString &address) // bool QHostAddress::setAddress(const QString &address)
@ -532,7 +493,6 @@ static gsi::Methods methods_QHostAddress () {
gsi::Methods methods; 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", "@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_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 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 &copy)\nThis method creates an object of class QHostAddress.", &_init_ctor_QHostAddress_2518, &_call_ctor_QHostAddress_2518); methods += new qt_gsi::GenericStaticMethod ("new", "@brief Constructor QHostAddress::QHostAddress(const QHostAddress &copy)\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); 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 ("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 (":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(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 ("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 ("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); methods += new qt_gsi::GenericMethod ("toIPv4Address", "@brief Method quint32 QHostAddress::toIPv4Address()\n", true, &_init_f_toIPv4Address_c0, &_call_f_toIPv4Address_c0);

View File

@ -112,13 +112,11 @@ FontController::can_exit (lay::PluginRoot * /*root*/) const
void void
FontController::sync_dirs () FontController::sync_dirs ()
{ {
if (! m_file_watcher) { if (m_file_watcher) {
return; m_file_watcher->clear ();
m_file_watcher->enable (false);
} }
m_file_watcher->clear ();
m_file_watcher->enable (false);
std::vector<std::string> paths = lay::ApplicationBase::instance ()->klayout_path (); std::vector<std::string> paths = lay::ApplicationBase::instance ()->klayout_path ();
// add the salt grains as potential sources for library definitions // add the salt grains as potential sources for library definitions
@ -137,14 +135,18 @@ FontController::sync_dirs ()
for (std::vector <std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) { for (std::vector <std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
QDir fp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("fonts")); QDir fp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("fonts"));
if (fp.exists ()) { 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 ())); font_paths.push_back (tl::to_string (fp.absolutePath ()));
} }
} }
db::TextGenerator::set_font_paths (font_paths); db::TextGenerator::set_font_paths (font_paths);
m_file_watcher->enable (true); if (m_file_watcher) {
m_file_watcher->enable (true);
}
} }
void void

View File

@ -117,13 +117,11 @@ LibraryController::can_exit (lay::PluginRoot * /*root*/) const
void void
LibraryController::sync_files () LibraryController::sync_files ()
{ {
if (! m_file_watcher) { if (m_file_watcher) {
return; m_file_watcher->clear ();
m_file_watcher->enable (false);
} }
m_file_watcher->clear ();
m_file_watcher->enable (false);
std::map<std::string, std::pair<std::string, QDateTime> > new_lib_files; std::map<std::string, std::pair<std::string, QDateTime> > new_lib_files;
// build a list of paths vs. technology // 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")); QDir lp = QDir (tl::to_qstring (p->first)).filePath (tl::to_qstring ("libraries"));
if (lp.exists ()) { 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; QStringList name_filters;
name_filters << QString::fromUtf8 ("*"); 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 // remove libraries which are no longer present

View File

@ -146,7 +146,10 @@ MacroController::finish ()
if (! m_no_implicit_macros) { if (! m_no_implicit_macros) {
for (std::vector <ExternalPathDescriptor>::const_iterator p = m_external_paths.begin (); p != m_external_paths.end (); ++p) { for (std::vector <ExternalPathDescriptor>::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);
}
} }
} }

View File

@ -1004,6 +1004,8 @@ MacroEditorPage::replace_all (const QString &replace)
int i = m_current_search.indexIn (b.text (), o); int i = m_current_search.indexIn (b.text (), o);
if (i < 0) { if (i < 0) {
break; break;
} else if (m_current_search.matchedLength () == 0) {
break; // avoid an infinite loop
} }
QString r = interpolate_string (replace, m_current_search); QString r = interpolate_string (replace, m_current_search);

View File

@ -842,6 +842,7 @@ MainWindow::init_menu ()
MenuLayoutEntry ("show_grid", tl::to_string (QObject::tr ("Show Grid")), std::make_pair (cfg_grid_visible, "?")), 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 ("default_grid:default_grids_group", tl::to_string (QObject::tr ("Grid")), empty_menu),
MenuLayoutEntry::separator ("layout_group"), 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_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 ("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, "?")), 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; f = false;
config_get (cfg_hide_empty_layers, f); config_get (cfg_hide_empty_layers, f);
if (f) { if (f) {
@ -3162,6 +3175,8 @@ MainWindow::do_save (bool as)
options.set_dbu (cv->layout ().dbu ()); options.set_dbu (cv->layout ().dbu ());
options.set_format_from_filename (fn); options.set_format_from_filename (fn);
cv->update_save_options (options);
tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto; tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto;
if (as && ! mp_layout_save_as_options->get_options (current_view (), cv_index, fn, om, options)) { if (as && ! mp_layout_save_as_options->get_options (current_view (), cv_index, fn, om, options)) {

View File

@ -68,7 +68,7 @@ ConfirmationDialog::add_info (const std::string &name, bool update, const std::s
item->setText (3, tl::to_qstring (url)); item->setText (3, tl::to_qstring (url));
for (int column = 0; column < list->colorCount (); ++column) { 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))));
} }
} }

View File

@ -47,8 +47,15 @@ SaltItemDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option,
{ {
QStyleOptionViewItemV4 optionV4 = option; QStyleOptionViewItemV4 optionV4 = option;
initStyleOption (&optionV4, index); initStyleOption (&optionV4, index);
// let the text take all the available space (fixes #144)
optionV4.showDecorationSelected = true;
bool is_enabled = (optionV4.state & QStyle::State_Enabled); 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; optionV4.state |= QStyle::State_Enabled;
QStyle *style = optionV4.widget ? optionV4.widget->style () : QApplication::style (); QStyle *style = optionV4.widget ? optionV4.widget->style () : QApplication::style ();
@ -121,6 +128,11 @@ SaltModel::flags (const QModelIndex &index) const
f &= ~Qt::ItemIsEnabled; 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; return f;
} }
@ -134,15 +146,9 @@ SaltModel::data (const QModelIndex &index, int role) const
return QVariant (tr ("<html><body><h4>There are no items to show in this list</h4><p>%1</p></body></html>").arg (m_empty_explanation)); return QVariant (tr ("<html><body><h4>There are no items to show in this list</h4><p>%1</p></body></html>").arg (m_empty_explanation));
} }
bool en = is_enabled (g->name ());
bool hidden = g->is_hidden (); bool hidden = g->is_hidden ();
std::string text = "<html><body>"; std::string text = "<html><body>";
if (! en || hidden) {
text += "<font color=\"#c0c0c0\">";
} else {
text += "<font color=\"#303030\">";
}
if (hidden) { if (hidden) {
text += "<i>"; text += "<i>";
} }
@ -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 += tl::to_string (tr ("This package is an auxiliary package for use with other packages."));
text += "</p></i>"; text += "</p></i>";
} }
text += "</font>";
text += "</body></html>"; text += "</body></html>";
return tl::to_qstring (text); return tl::to_qstring (text);

View File

@ -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 // 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<const lay::LayerPropertiesNode *> (&props); const lay::LayerPropertiesNode *lp = dynamic_cast<const lay::LayerPropertiesNode *> (&props);
if (lp) { if (lp) {
return &view->insert_layer (iter, *lp); return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (iter, *lp)));
} else { } 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<const lay::LayerPropertiesNode *> (&props); const lay::LayerPropertiesNode *lp = dynamic_cast<const lay::LayerPropertiesNode *> (&props);
if (lp) { if (lp) {
return &view->insert_layer (index, iter, *lp); return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (index, iter, *lp)));
} else { } else {
return &view->insert_layer (index, iter, props); return lay::LayerPropertiesNodeRef (lay::LayerPropertiesConstIterator (&view->insert_layer (index, iter, props)));
} }
} }
@ -396,10 +396,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"layout or the cell views and the LayoutView configuration. This is usually done automatically. " "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" "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" "@brief Sets the title of the view\n"
"\n" "\n"
"@args title\n"
"@param title The title string to use\n" "@param title The title string to use\n"
"\n" "\n"
"Override the standard title of the view indicating the file names loaded by " "Override the standard title of the view indicating the file names loaded by "
@ -419,25 +418,21 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"The title string is either a string composed of the file names loaded (in some " "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." "\"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" "@brief Saves the layer properties\n"
"\n" "\n"
"@args fn\n"
"\n"
"Save the layer properties to the file given in \"fn\"" "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" "@brief Loads the layer properties\n"
"\n" "\n"
"@args fn\n"
"@param fn The file name of the .lyp file to load\n" "@param fn The file name of the .lyp file to load\n"
"\n" "\n"
"Load the layer properties from the file given in \"fn\"" "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" "@brief Loads the layer properties with options\n"
"\n" "\n"
"@args fn, add_default\n"
"@param fn The file name of the .lyp file to load\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" "@param add_default If true, default layers will be added for each other layer in the layout\n"
"\n" "\n"
@ -447,10 +442,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This variant has been added on version 0.21." "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" "@brief Loads the layer properties with options\n"
"\n" "\n"
"@args fn, cv_index, add_default\n"
"@param fn The file name of the .lyp file to load\n" "@param fn The file name of the .lyp file to load\n"
"@param cv_index See description text\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" "@param add_default If true, default layers will be added for each other layer in the layout\n"
@ -466,10 +460,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This variant has been added on version 0.21." "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" "@brief Sets the minimum hierarchy level at which to display geometries\n"
"\n" "\n"
"@args level\n"
"@param level The minimum level above which to display something\n" "@param level The minimum level above which to display something\n"
"\n" "\n"
"This methods allows to set the minimum hierarchy level above which to display geometries." "This methods allows to set the minimum hierarchy level above which to display geometries."
@ -480,10 +473,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"@return The minimum level at which to display geometries" "@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" "@brief Sets the maximum hierarchy level up to which to display geometries\n"
"\n" "\n"
"@args level\n"
"@param level The maximum level below which to display something\n" "@param level The maximum level below which to display something\n"
"\n" "\n"
"This methods allows to set the maximum hierarchy below which to display geometries." "This methods allows to set the maximum hierarchy below which to display geometries."
@ -494,10 +486,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"@return The maximum level up to which to display geometries" "@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" "@brief Enables or disables edits\n"
"\n" "\n"
"@args enable\n"
"@param enable Enable edits if set to true\n" "@param enable Enable edits if set to true\n"
"\n" "\n"
"This method allows putting the view into read-only mode by disabling all edit " "This method allows putting the view into read-only mode by disabling all edit "
@ -508,18 +499,14 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"In 0.25, this method has been moved from MainWindow to LayoutView.\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" "@brief Reloads the given cellview\n"
"\n" "\n"
"@args cv\n"
"\n"
"@param cv The index of the cellview to reload" "@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" "@brief Creates a new, empty layout\n"
"\n" "\n"
"@args add_cellview\n"
"\n"
"The add_cellview parameter controls whether to create a new cellview (true)\n" "The add_cellview parameter controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n" "or clear all cellviews before (false).\n"
"\n" "\n"
@ -527,11 +514,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"@return The index of the cellview created.\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" "@brief Create a new, empty layout and associate it with the given technology\n"
"\n" "\n"
"@args tech,add_cellview\n"
"\n"
"The add_cellview parameter controls whether to create a new cellview (true)\n" "The add_cellview parameter controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n" "or clear all cellviews before (false).\n"
"\n" "\n"
@ -539,11 +524,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This variant has been introduced in version 0.22.\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" "@brief Create a new, empty layout and associate it with the given technology\n"
"\n" "\n"
"@args tech,add_cellview,init_layers\n"
"\n"
"The add_cellview parameter controls whether to create a new cellview (true)\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" "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" "initialized (init_layers = true) or not (init_layers = false).\n"
@ -552,9 +535,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This variant has been introduced in version 0.22.\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" "@brief Shows an existing layout in the view\n"
"@args layout, add_cellview\n"
"\n" "\n"
"Shows the given layout in the view. If add_cellview is true, the new layout is added to the list of " "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" "cellviews in the view.\n"
@ -566,9 +548,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.22.\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" "@brief Shows an existing layout in the view\n"
"@args layout, tech, add_cellview\n"
"\n" "\n"
"Shows the given layout in the view. If add_cellview is true, the new layout is added to the list of " "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" "cellviews in the view.\n"
@ -583,9 +564,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.22.\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" "@brief Shows an existing layout in the view\n"
"@args layout, tech, add_cellview, init_layers\n"
"\n" "\n"
"Shows the given layout in the view. If add_cellview is true, the new layout is added to the list of " "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" "cellviews in the view.\n"
@ -602,28 +582,22 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.22.\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" "@brief Erases the cellview with the given index\n"
"\n" "\n"
"@args index\n"
"\n"
"This closes the given cellview and unloads the layout associated with it, unless referred to by another cellview." "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" "@brief Renames the cellview with the given index\n"
"\n" "\n"
"@args name, index\n"
"\n"
"If the name is not unique, a unique name will be constructed from the name given.\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" "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" "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" "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" "@brief Loads a (new) file into the layout view with the given technology\n"
"\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" "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 options specify various options for reading the file.\n"
"The add_cellview param controls whether to create a new cellview (true)\n" "The add_cellview param controls whether to create a new cellview (true)\n"
@ -633,11 +607,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This version has been introduced in version 0.22.\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" "@brief Loads a (new) file into the layout view\n"
"\n" "\n"
"@args filename, options, add_cellview\n"
"\n"
"Loads the file given by the \"filename\" parameter.\n" "Loads the file given by the \"filename\" parameter.\n"
"The options specify various options for reading the file.\n" "The options specify various options for reading the file.\n"
"The add_cellview param controls whether to create a new cellview (true)\n" "The add_cellview param controls whether to create a new cellview (true)\n"
@ -647,11 +619,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.18.\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" "@brief Loads a (new) file into the layout view with the given technology\n"
"\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" "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" "The add_cellview param controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n" "or clear all cellviews before (false).\n"
@ -660,11 +630,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This version has been introduced in version 0.22.\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" "@brief Loads a (new) file into the layout view\n"
"\n" "\n"
"@args filename, add_cellview\n"
"\n"
"Loads the file given by the \"filename\" parameter.\n" "Loads the file given by the \"filename\" parameter.\n"
"The add_cellview param controls whether to create a new cellview (true)\n" "The add_cellview param controls whether to create a new cellview (true)\n"
"or clear all cellviews before (false).\n" "or clear all cellviews before (false).\n"
@ -683,19 +651,16 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("active_cellview_index", &lay::LayoutView::active_cellview_index, gsi::method ("active_cellview_index", &lay::LayoutView::active_cellview_index,
"@brief Gets the index of the active cellview (shown in hierarchy browser)\n" "@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" "@brief Makes the cellview with the given index the active one (shown in hierarchy browser)\n"
"@args index\n"
"See \\active_cellview_index.\n" "See \\active_cellview_index.\n"
"\n" "\n"
"This method has been renamed from set_active_cellview_index to active_cellview_index= in version 0.25. " "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." "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" "@brief Gets the paths of the selected cells\n"
"\n" "\n"
"@args cv_index\n"
"\n"
"Gets a list of cell paths to the cells selected in the cellview given by \\cv_index. " "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\" " "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" "which is the one that is shown in the layout window.\n"
@ -704,11 +669,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has be introduced in version 0.25.\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" "@brief Gets the cell path of the current cell\n"
"\n" "\n"
"@args cv_index\n"
"\n"
"The current cell is the one highlighted in the browser with the focus rectangle. The \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" "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" "The cell path is a list of cell indices from the top cell to the current cell.\n"
@ -717,11 +680,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\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." "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" "@brief Sets the path to the current cell\n"
"\n" "\n"
"@args cv_index\n"
"\n"
"The current cell is the one highlighted in the browser with the focus rectangle. The\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" "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" "To select the cell to be drawn, use the \\select_cell or \\select_cell_path method.\n"
@ -734,11 +695,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("cellviews", &lay::LayoutView::cellviews, gsi::method ("cellviews", &lay::LayoutView::cellviews,
"@brief Gets the number of cellviews\n" "@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" "@brief Gets the cellview object for a given index\n"
"\n" "\n"
"@args cv_index\n"
"\n"
"@param cv_index The cellview index for which to get the object for\n" "@param cv_index The cellview index for which to get the object for\n"
"\n" "\n"
"Starting with version 0.25, this method returns a \\CellView object that can be manipulated to directly reflect " "Starting with version 0.25, this method returns a \\CellView object that can be manipulated to directly reflect "
@ -752,10 +711,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.25.\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" "@brief Sets the viewport to the given box\n"
"\n" "\n"
"@args box\n"
"@param box The box to which to set the view in micron coordinates\n" "@param box The box to which to set the view in micron coordinates\n"
) + ) +
gsi::method ("zoom_in", &lay::LayoutView::zoom_in, gsi::method ("zoom_in", &lay::LayoutView::zoom_in,
@ -776,11 +734,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("pan_right", &lay::LayoutView::pan_right, gsi::method ("pan_right", &lay::LayoutView::pan_right,
"@brief Pans to the 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" "@brief Pans to the given point\n"
"\n" "\n"
"@args p\n"
"\n"
"The window is positioned such that \"p\" becomes the new center" "The window is positioned such that \"p\" becomes the new center"
) + ) +
gsi::method ("box", &lay::LayoutView::box, gsi::method ("box", &lay::LayoutView::box,
@ -801,11 +757,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Return the viewport height in pixels\n" "@brief Return the viewport height in pixels\n"
"This method was introduced in version 0.18.\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" "@brief Bookmarks the current view under the given name\n"
"\n" "\n"
"@args name\n"
"\n"
"@param name The name under which to bookmark the current state" "@param name The name under which to bookmark the current state"
) + ) +
gsi::method ("add_missing_layers", &lay::LayoutView::add_missing_layers, gsi::method ("add_missing_layers", &lay::LayoutView::add_missing_layers,
@ -816,9 +770,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Removes unused layers from layer list\n" "@brief Removes unused layers from layer list\n"
"This method was introduced in version 0.19.\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" "@brief Fills the layer properties for a new layer\n"
"@args props\n"
"\n" "\n"
"This method initializes a layer properties object's color and stipples according to " "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 " "the defaults for the given layer source specification. The layer's source must be set already "
@ -839,11 +792,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Stops redraw thread and close any browsers\n" "@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." "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" "@brief Selects a cell by cell index for a certain cell view\n"
"\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 " "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" "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 " "This method selects the cell to be drawn. In constrast, the \\set_current_cell_path method selects "
@ -851,11 +802,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\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." "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" "@brief Selects a cell by index for a certain cell view\n"
"\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 " "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 " "the actual cell) and the cellview index for which this cell should become the currently "
"shown one.\n" "shown one.\n"
@ -864,9 +813,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\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." "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" "@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 " "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 " "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 " "components can be shown in the context of the upper cells, if the minimum hierarchy level is "
@ -874,28 +823,22 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"The path is assumed to originate from the current cell and contain specific instances sorted from " "The path is assumed to originate from the current cell and contain specific instances sorted from "
"top to bottom." "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" "@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 " "Removes one element from the specific path of the cellview with the given index. Returns the element "
"removed." "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" "@brief Returns true, if the cell is hidden\n"
"\n" "\n"
"@args cell_index, cv_index\n"
"\n"
"@return True, if the cell with \"cell_index\" is hidden for the cellview \"cv_index\"" "@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" "@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" "@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, gsi::method ("show_all_cells", (void (lay::LayoutView::*) ()) &lay::LayoutView::show_all_cells,
"@brief Makes all cells shown (cancel effects of \\hide_cell)" "@brief Makes all cells shown (cancel effects of \\hide_cell)"
@ -929,20 +872,18 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"for the application to guarantee this condition. The image will have the size of the viewport " "for the application to guarantee this condition. The image will have the size of the viewport "
"showing the current layout." "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" "@brief Gets the layout image as a \\QImage\n"
"\n" "\n"
"@args width, height\n"
"@param width The width of the image to render in pixel.\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 height The height of the image to render in pixel.\n"
"\n" "\n"
"The image contains the current scene (layout, annotations etc.).\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. " "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" "@brief Gets the layout image as a \\QImage (with options)\n"
"\n" "\n"
"@args width, height, linewidth, oversampling, resolution, target, monochrome\n"
"@param width The width of the image to render in pixel.\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 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" "@param linewidth The width of a line in pixels (usually 1) or 0 for default.\n"
@ -959,10 +900,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"This method has been introduced in 0.23.10.\n" "This method has been introduced in 0.23.10.\n"
) + ) +
#endif #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" "@brief Saves a screenshot to the given file\n"
"\n" "\n"
"@args filename\n"
"@param filename The file to which to write the screenshot to.\n" "@param filename The file to which to write the screenshot to.\n"
"\n" "\n"
"The screenshot is written as a PNG file to the given file. " "The screenshot is written as a PNG file to the given file. "
@ -970,10 +910,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"for the application to guarantee this condition. The image will have the size of the viewport " "for the application to guarantee this condition. The image will have the size of the viewport "
"showing the current layout." "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" "@brief Saves the layout as an image to the given file\n"
"\n" "\n"
"@args filename, width, height\n"
"@param filename The file to which to write the screenshot to.\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 width The width of the image to render in pixel.\n"
"@param height The height 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<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"The image is written as a PNG file to the given file. " "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. " "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" "@brief Saves the layout as an image to the given file (with options)\n"
"\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 filename The file to which to write the screenshot to.\n"
"@param width The width of the image to render in pixel.\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 height The height of the image to render in pixel.\n"
@ -1002,10 +940,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in 0.23.10.\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" "@brief Saves a layout to the given stream file\n"
"\n" "\n"
"@args index, filename, gzip, options\n"
"@param index The cellview index of the layout to save.\n" "@param index The cellview index of the layout to save.\n"
"@param filename The file to write.\n" "@param filename The file to write.\n"
"@param gzip Ignored.\n" "@param gzip Ignored.\n"
@ -1019,10 +956,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"This method is deprecated starting from version 0.23. The compression mode is " "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" "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" "@brief Saves a layout to the given stream file\n"
"\n" "\n"
"@args index, filename, options\n"
"@param index The cellview index of the layout to save.\n" "@param index The cellview index of the layout to save.\n"
"@param filename The file to write.\n" "@param filename The file to write.\n"
"@param options Writer options.\n" "@param options Writer options.\n"
@ -1035,16 +971,14 @@ Class<lay::LayoutView> 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 " "If the file name ends with a suffix \".gz\" or \".gzip\", the file is compressed with the zlib "
"algorithm.\n" "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" "@brief Sets the layer properties of the layer pointed to by the iterator\n"
"@args iter, props\n"
"\n" "\n"
"This method replaces the layer properties of the element pointed to by \"iter\" by the properties " "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." "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" "@brief Sets the layer properties of the layer pointed to by the iterator\n"
"@args index, iter, props\n"
"\n" "\n"
"This method replaces the layer properties of the element pointed to by \"iter\" by the properties " "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." "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<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method was introduced in version 0.21.\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" "@brief Expands the layer properties for the given tab\n"
"@args index\n"
"\n" "\n"
"This method will expand all wildcard specifications in the layer properties by iterating over the specified objects (i.e. layers, cellviews) and " "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" "by replacing default colors and stipples by the ones specified with the palettes.\n"
"\n" "\n"
"This method was introduced in version 0.21.\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" "@brief Replaces the layer node at the position given by \"iter\" with a new one\n"
"@args iter, node\n"
"\n" "\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode " "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."
) + ) +
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" "@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. " "This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. "
"\n" "\n"
"This method has been introduced in version 0.21.\n" "This method has been introduced in version 0.21.\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode " "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."
) + ) +
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" "@brief Inserts the given layer properties node into the list before the given position\n"
"@args iter, node\n"
"\n" "\n"
"This method inserts the new properties node before the position given by \"iter\" and returns " "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 " "a const reference to the element created. The iterator that specified the position will remain valid "
@ -1094,11 +1024,12 @@ Class<lay::LayoutView> 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" "To add children to the node inserted, use iter.last_child as insertion point for the next insert operations.\n"
"\n" "\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode " "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" "@brief Inserts the given layer properties node into the list before the given position\n"
"@args index, iter, node\n"
"\n" "\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. " "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 " "This method inserts the new properties node before the position given by \"iter\" and returns "
@ -1107,9 +1038,11 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.21.\n" "This method has been introduced in version 0.21.\n"
"Since version 0.22, this method accepts LayerProperties and LayerPropertiesNode objects. A LayerPropertiesNode " "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" "@brief Deletes the layer properties nodes specified by the iterator\n"
"@args iterators\n" "@args iterators\n"
"\n" "\n"
@ -1118,25 +1051,22 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been added in version 0.22.\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" "@brief Deletes the layer properties nodes specified by the iterator\n"
"@args index, iterators\n"
"\n" "\n"
"This method deletes the nodes specifies by the iterators. This method is the most convenient way to " "This method deletes the nodes specifies by the iterators. This method is the most convenient way to "
"delete multiple entries.\n" "delete multiple entries.\n"
"This version addresses a specific list in a multi-tab layer properties arrangement with the \"index\" parameter. " "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" "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" "@brief Deletes the layer properties node specified by the iterator\n"
"@args iter\n"
"\n" "\n"
"This method deletes the object that the iterator points to and invalidates\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" "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" "@brief Deletes the layer properties node specified by the iterator\n"
"@args index, iter\n"
"\n" "\n"
"This method deletes the object that the iterator points to and invalidates\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" "the iterator since the object that the iterator points to is no longer valid.\n"
@ -1183,9 +1113,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief End iterator for the layers\n" "@brief End iterator for the layers\n"
"See \\begin_layers for a description about this iterator\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" "@brief Begin iterator for the layers\n"
"@args index\n"
"\n" "\n"
"This iterator delivers the layers of this view, either in a recursive or non-recursive\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" "fashion, depending which iterator increment methods are used.\n"
@ -1194,9 +1123,8 @@ Class<lay::LayoutView> 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 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" "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" "@brief End iterator for the layers\n"
"@args index\n"
"See \\begin_layers for a description about this iterator\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 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" "This method has been introduced in version 0.21.\n"
@ -1204,21 +1132,18 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
gsi::method ("clear_layers", (void (lay::LayoutView::*) ()) &lay::LayoutView::clear_layers, gsi::method ("clear_layers", (void (lay::LayoutView::*) ()) &lay::LayoutView::clear_layers,
"@brief Clears all layers\n" "@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" "@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 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" "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" "@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" "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" "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" "@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 " "This method inserts a new tab at the given position. The current layer properties list will be changed to "
"the new list.\n" "the new list.\n"
"This method has been introduced in version 0.21.\n" "This method has been introduced in version 0.21.\n"
@ -1231,19 +1156,16 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Gets the index of the currently selected layer properties tab\n" "@brief Gets the index of the currently selected layer properties tab\n"
"This method has been introduced in version 0.21.\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" "@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" "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" "@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" "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" "@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. " "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. " "If a stipple pattern is removed that is still used, the results are undefined. "
) + ) +
@ -1286,9 +1208,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.25." "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" "@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. " "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" "If a style is removed that is still used, the results are undefined.\n"
"\n" "\n"
@ -1335,9 +1256,8 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"Returns the \\LayerPropertiesIterator pointing to the current layer view (the one that has the focus). " "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" "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" "@brief Sets the current layer view\n"
"@args iter\n"
"\n" "\n"
"Specifies an \\LayerPropertiesIterator pointing to the new current layer view.\n" "Specifies an \\LayerPropertiesIterator pointing to the new current layer view.\n"
"\n" "\n"
@ -1367,9 +1287,8 @@ Class<lay::LayoutView> 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 " "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" "(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" "@brief An event indicating that a cellview has changed\n"
"@args cellview_index\n"
"\n" "\n"
"If a cellview is modified, this event is triggered.\n" "If a cellview is modified, this event is triggered.\n"
"When this event is triggered, the cellview have already been changed.\n" "When this event is triggered, the cellview have already been changed.\n"
@ -1414,9 +1333,8 @@ Class<lay::LayoutView> 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 " "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" "(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" "@brief An event indicating that the layer list has changed\n"
"@args flags\n"
"\n" "\n"
"This event is triggered after the layer list has changed it's configuration.\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" "The integer argument gives a hint about the nature of the changed:\n"
@ -1426,27 +1344,24 @@ Class<lay::LayoutView> 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 " "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" "(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" "@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" "@param index The index of the layer list that was inserted\n"
"\n" "\n"
"This event is triggered after the layer list has been inserted - i.e. a new tab was created.\n" "This event is triggered after the layer list has been inserted - i.e. a new tab was created.\n"
"\n" "\n"
"This event was introduced in version 0.25.\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" "@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" "@param index The index of the layer list that was removed\n"
"\n" "\n"
"This event is triggered after the layer list has been removed - i.e. a tab was deleted.\n" "This event is triggered after the layer list has been removed - i.e. a tab was deleted.\n"
"\n" "\n"
"This event was introduced in version 0.25.\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" "@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" "@param index The index of the new current layer list\n"
"\n" "\n"
"This event is triggered after the current layer list was changed - i.e. a new tab was selected.\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<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"@brief Gets the number of report databases loaded into this view\n" "@brief Gets the number of report databases loaded into this view\n"
"@return The number of \\ReportDatabase objects present in 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" "@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" "@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" "@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" "@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" "@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" "@param name The name of the new report database\n"
"@return The index of the new 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. " "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" "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" "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" "@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" "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" "It will be attached (i.e. navigate to) the layout with the given cellview index in \"cv_index\".\n"
) + ) +
@ -1542,10 +1453,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
// TODO: this method belongs to the Plugin interface and should be located there. // 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 // Change this once there is a mixin concept available and the Plugin interface can
// be mixed into LayoutView. // 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" "@brief Gets the value of a local configuration parameter\n"
"\n" "\n"
"@args name\n"
"@param name The name of the configuration parameter whose value shall be obtained (a string)\n" "@param name The name of the configuration parameter whose value shall be obtained (a string)\n"
"\n" "\n"
"@return The value of the parameter\n" "@return The value of the parameter\n"
@ -1555,10 +1465,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
// TODO: this method belongs to the Plugin interface and should be located there. // 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 // Change this once there is a mixin concept available and the Plugin interface can
// be mixed into LayoutView. // 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" "@brief Sets a local configuration parameter with the given name to the given value\n"
"\n" "\n"
"@args name, value\n"
"@param name The name of the configuration parameter to set\n" "@param name The name of the configuration parameter to set\n"
"@param value The value to which to set the configuration parameter\n" "@param value The value to which to set the configuration parameter\n"
"\n" "\n"
@ -1580,10 +1489,9 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"\n" "\n"
"This method has been introduced in version 0.25.\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" "@brief Begins a transaction\n"
"\n" "\n"
"@args description\n"
"@param description A text that appears in the 'undo' description\n" "@param description A text that appears in the 'undo' description\n"
"\n" "\n"
"A transaction brackets a sequence of database modifications that appear as a single " "A transaction brackets a sequence of database modifications that appear as a single "

View File

@ -164,6 +164,18 @@ Class<lay::DMarker> decl_Marker ("lay", "Marker",
"@brief Returns a value indicating whether the marker has a specific frame color\n" "@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" "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, gsi::method ("line_width=", &lay::DMarker::set_line_width,
"@brief Sets the line width of the marker\n" "@brief Sets the line width of the marker\n"
"@args width\n" "@args width\n"

View File

@ -258,6 +258,31 @@ LayoutHandle::set_save_options (const db::SaveLayoutOptions &options, bool valid
m_save_options_valid = valid; m_save_options_valid = valid;
} }
void
LayoutHandle::update_save_options (db::SaveLayoutOptions &options)
{
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
const lay::StreamWriterPluginDeclaration *decl = dynamic_cast <const lay::StreamWriterPluginDeclaration *> (&*cls);
if (! decl) {
continue;
}
std::auto_ptr<db::FormatSpecificWriterOptions> 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 void
LayoutHandle::save_as (const std::string &fn, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update) LayoutHandle::save_as (const std::string &fn, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update)
{ {

View File

@ -234,6 +234,15 @@ public:
return m_save_options; 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 * @brief Gets a flag indicating whether the save options are valid
* *

View File

@ -625,6 +625,18 @@ ReplaceCellOptionsDialog::~ReplaceCellOptionsDialog ()
mp_ui = 0; mp_ui = 0;
} }
static std::pair<bool, db::cell_index_type>
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 bool
ReplaceCellOptionsDialog::exec_dialog (const lay::CellView &cv, int &replace_mode, db::cell_index_type &cell_index) 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::string cn = tl::to_string (mp_ui->cell_selection_cbx->lineEdit ()->text ());
std::pair<bool, db::cell_index_type> cc = cv->layout ().cell_by_name (cn.c_str ()); std::pair<bool, db::cell_index_type> cc = find_cell_by_display_name (cv->layout (), cn.c_str ());
cell_index = cc.second; cell_index = cc.second;
return cc.first; return cc.first;
@ -665,7 +677,7 @@ BEGIN_PROTECTED;
lay::CellTreeModel *model = dynamic_cast<lay::CellTreeModel *> (mp_ui->cell_selection_cbx->model ()); lay::CellTreeModel *model = dynamic_cast<lay::CellTreeModel *> (mp_ui->cell_selection_cbx->model ());
if (model) { if (model) {
std::string cn = tl::to_string (mp_ui->cell_selection_cbx->lineEdit ()->text ()); std::string cn = tl::to_string (mp_ui->cell_selection_cbx->lineEdit ()->text ());
std::pair<bool, db::cell_index_type> cc = model->layout ()->cell_by_name (cn.c_str ()); std::pair<bool, db::cell_index_type> cc = find_cell_by_display_name (*model->layout (), cn.c_str ());
if (! cc.first) { if (! cc.first) {
throw tl::Exception (tl::to_string (QObject::tr ("Not a valid cell name: ")) + cn); throw tl::Exception (tl::to_string (QObject::tr ("Not a valid cell name: ")) + cn);
} }

View File

@ -555,6 +555,7 @@ DitherPatternInfo::operator< (const DitherPatternInfo &d) const
return m_order_index < d.m_order_index; return m_order_index < d.m_order_index;
} }
// TODO including a scaling algorithm in this formula, or give more resolution to the dither
QBitmap QBitmap
DitherPatternInfo::get_bitmap (int width, int height) const DitherPatternInfo::get_bitmap (int width, int height) const
{ {

View File

@ -200,16 +200,29 @@ LCPDitherPalette::create_pixmap_for (LCPActiveLabel *b, int n)
const unsigned int h = 24; const unsigned int h = 24;
const unsigned int w = 24; const unsigned int w = 24;
QImage image (w, h, QImage::Format_RGB32); #if QT_VERSION > 0x050000
image.fill (color0.rgb ()); 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); QPainter painter (&image);
painter.setPen (QPen (color1)); painter.setPen (QPen (color1));
painter.setBackgroundMode (Qt::TransparentMode); 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 QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
#if QT_VERSION > 0x050000
pixmap.setDevicePixelRatio (dpr);
#endif
b->setPixmap (pixmap); 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 h = 14;
const unsigned int w = 24; const unsigned int w = 24;
QImage image (w, h, QImage::Format_RGB32); #if QT_VERSION > 0x050000
image.fill (color0.rgb ()); 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); QPainter painter (&image);
painter.setPen (QPen (color1)); painter.setPen (QPen (color1));
painter.setBackgroundMode (Qt::TransparentMode); 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 QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
#if QT_VERSION > 0x050000
pixmap.setDevicePixelRatio (dpr);
#endif
b->setPixmap (pixmap); b->setPixmap (pixmap);
} }

View File

@ -291,8 +291,6 @@ LayoutCanvas::LayoutCanvas (QWidget *parent, lay::LayoutView *view, const char *
{ {
#if QT_VERSION > 0x050000 #if QT_VERSION > 0x050000
m_dpr = devicePixelRatio (); m_dpr = devicePixelRatio ();
#else
m_dpr = 1;
#endif #endif
// The gamma value used for subsampling: something between 1.8 and 2.2. // The gamma value used for subsampling: something between 1.8 and 2.2.

View File

@ -384,6 +384,7 @@ LayoutView::init (db::Manager *mgr, lay::PluginRoot *root, QWidget * /*parent*/)
m_apply_text_trans = true; m_apply_text_trans = true;
m_default_text_size = 0.1; m_default_text_size = 0.1;
m_text_font = 0; m_text_font = 0;
m_show_markers = true;
m_no_stipples = false; m_no_stipples = false;
m_stipple_offset = true; m_stipple_offset = true;
m_fit_new_cell = true; m_fit_new_cell = true;
@ -1155,6 +1156,13 @@ LayoutView::configure (const std::string &name, const std::string &value)
apply_text_trans (flag); apply_text_trans (flag);
return true; 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) { } else if (name == cfg_no_stipple) {
bool flag; 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) LayoutView::text_color (QColor c)
{ {
if (m_text_color != c) { if (m_text_color != c) {

View File

@ -1062,6 +1062,19 @@ public:
return m_default_text_size; 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 * @brief Don't show stipples
*/ */
@ -2671,6 +2684,7 @@ private:
bool m_apply_text_trans; bool m_apply_text_trans;
double m_default_text_size; double m_default_text_size;
unsigned int m_text_font; unsigned int m_text_font;
bool m_show_markers;
bool m_no_stipples; bool m_no_stipples;
bool m_stipple_offset; bool m_stipple_offset;

View File

@ -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); QFontMetrics fm (font (), this);
QRect rt (fm.boundingRect (QString::fromUtf8 ("AA"))); 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); QPainter pxpainter (&pxmp);
pxpainter.setPen (QPen (palette ().color (QPalette::Active, QPalette::Text))); 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 h = rt.height () + 10;
const unsigned int w = rt.width () + 10; const unsigned int w = rt.width () + 10;
unsigned int color0 = palette ().color (QPalette::Active, QPalette::Button).rgb(); QColor color0 = palette ().color (QPalette::Active, QPalette::Button);
unsigned int color1 = palette ().color (QPalette::Active, QPalette::Dark).rgb(); QColor color1 = palette ().color (QPalette::Active, QPalette::Dark);
QImage image (w, h, QImage::Format_RGB32); #if QT_VERSION > 0x050000
if (s >= 0) { unsigned int dpr = 1; //devicePixelRatio ();
const uint32_t * const *dp = m_pattern.pattern ((unsigned int) s).pattern (); #else
for (unsigned int l = 0; l < h; ++l, ++dp) { unsigned int dpr = 1;
uint32_t m = **dp; #endif
if (l == 0 || l == h - 1) {
m |= ((1 << w) - 1); QImage image (w * dpr, h * dpr, QImage::Format_RGB32);
} else { #if QT_VERSION > 0x050000
m |= ((1 << (w - 1)) | 1); image.setDevicePixelRatio (dpr);
} #endif
color_t *pt = (color_t *) image.scanLine (h - 1 - l); image.fill (color0.rgb ());
for (unsigned int b = 0; b < w; ++b) {
*pt++ = (m & 1) ? color1 : color0; // copying code from layLayerToolbox.cc
m >>= 1; 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 QPixmap pxmp = QPixmap::fromImage (image); // Qt 4.6.0 workaround
QPainter pxpainter (&pxmp); QPainter pxpainter (&pxmp);
pxpainter.setPen (QPen (palette ().color (QPalette::Active, QPalette::Text))); pxpainter.setPen (QPen (palette ().color (QPalette::Active, QPalette::Text)));
QRect r (0, 0, pxmp.width () - 1, pxmp.height () - 1); QRect r (0, 0, pxmp.width () - 1, pxmp.height () - 1);
@ -1189,6 +1202,10 @@ LayoutViewConfigPage6::update ()
pxpainter.setFont (font ()); pxpainter.setFont (font ());
pxpainter.drawText (r, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, text); 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]))->setIconSize (pxmp.size ());
(mp_ui->*(cfg6_buttons [i]))->setIcon (QIcon (pxmp)); (mp_ui->*(cfg6_buttons [i]))->setIcon (QIcon (pxmp));
@ -1366,16 +1383,28 @@ LayoutViewConfigPage6a::update ()
const unsigned int h = 26; const unsigned int h = 26;
const unsigned int w = 26; const unsigned int w = 26;
QImage image (w, h, QImage::Format_RGB32); #if QT_VERSION > 0x050000
image.fill (color0.rgb ()); 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); QPainter painter (&image);
painter.setPen (QPen (color1)); painter.setPen (QPen (color1));
painter.setBackgroundMode (Qt::TransparentMode); 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 QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
#if QT_VERSION > 0x050000
pixmap.setDevicePixelRatio (dpr);
#endif
b->setIconSize (pixmap.size ()); b->setIconSize (pixmap.size ());
b->setIcon (QIcon (pixmap)); b->setIcon (QIcon (pixmap));
@ -1510,6 +1539,7 @@ public:
options.push_back (std::pair<std::string, std::string> (cfg_stipple_offset, "true")); options.push_back (std::pair<std::string, std::string> (cfg_stipple_offset, "true"));
options.push_back (std::pair<std::string, std::string> (cfg_line_style_palette, lay::LineStylePalette ().to_string ())); options.push_back (std::pair<std::string, std::string> (cfg_line_style_palette, lay::LineStylePalette ().to_string ()));
options.push_back (std::pair<std::string, std::string> (cfg_no_stipple, "false")); options.push_back (std::pair<std::string, std::string> (cfg_no_stipple, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_markers_visible, "true"));
} }
virtual std::vector<std::pair <std::string, ConfigPage *> > config_pages (QWidget *parent) const virtual std::vector<std::pair <std::string, ConfigPage *> > config_pages (QWidget *parent) const

View File

@ -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) MarkerBase::get_bitmaps (const Viewport & /*vp*/, ViewObjectCanvas &canvas, lay::CanvasPlane *&fill, lay::CanvasPlane *&contour, lay::CanvasPlane *&vertex, lay::CanvasPlane *&text)
{ {
double resolution = canvas.resolution (); double resolution = canvas.resolution ();

View File

@ -665,13 +665,11 @@ need_draw_box (const db::Layout *layout, const db::Cell &cell,
return int (cell.hierarchy_levels ()) + level >= to_level; return int (cell.hierarchy_levels ()) + level >= to_level;
} }
void void
RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &vp, int level) RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector<db::Box> &redraw_regions, int level)
{ {
lay::Renderer &r = *mp_renderer;
// do not draw, if there is nothing to draw // 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; return;
} }
@ -685,6 +683,17 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
return; return;
} }
for (std::vector<db::Box>::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 .. // For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox (); db::Box bbox = cell.bbox ();
@ -714,19 +723,19 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
} else { } else {
db::box_convert <db::CellInst> bc (*mp_layout); db::box_convert <db::CellInst> bc (*mp_layout);
// create a set of boxes to look into // create a set of boxes to look into
db::Coord aw = db::coord_traits<db::Coord>::rounded (m_abstract_mode_width / mp_layout->dbu ()); db::Coord aw = db::coord_traits<db::Coord>::rounded (m_abstract_mode_width / mp_layout->dbu ());
std::vector<db::Box> vv; std::vector<db::Box> 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)) { 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.reserve (4);
vv.push_back (vp & db::Box (bbox.left (), bbox.bottom (), bbox.left () + aw, bbox.top ())); vv.push_back (redraw_box & 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 (redraw_box & 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 (redraw_box & 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 () + aw, bbox.top () - aw, bbox.right () - aw, bbox.top ()));
} else { } else {
vv.reserve (1); vv.reserve (1);
vv.push_back (vp); vv.push_back (redraw_box);
} }
// dive down into the hierarchy .. // dive down into the hierarchy ..
@ -737,7 +746,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
bool anything = false; bool anything = false;
db::cell_index_type last_ci = std::numeric_limits<db::cell_index_type>::max (); db::cell_index_type last_ci = std::numeric_limits<db::cell_index_type>::max ();
db::Cell::touching_iterator inst = cell.begin_touching (*v); db::Cell::touching_iterator inst = cell.begin_touching (*v);
while (! inst.at_end ()) { while (! inst.at_end ()) {
const db::CellInstArray &cell_inst = inst->cell_inst (); 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 (); db::Box new_cell_box = mp_layout->cell (new_ci).bbox ();
if (last_ci != new_ci) { 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)) { if (new_cell_box.inside (*v)) {
last_ci = new_ci; last_ci = new_ci;
anything = any_cell_box (new_ci, m_to_level - (level + 1)); 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) { if (anything) {
db::Vector a, b; db::Vector a, b;
unsigned long amax, bmax; unsigned long amax, bmax;
bool simplify = false; bool simplify = false;
if (cell_inst.is_regular_array (a, b, amax, bmax)) { 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 { } else {
inst_box = trans * new_cell_box; inst_box = trans * new_cell_box;
} }
if (((a.x () == 0 && b.y () == 0) || (a.y () == 0 && b.x () == 0)) && if (((a.x () == 0 && b.y () == 0) || (a.y () == 0 && b.x () == 0)) &&
inst_box.width () < 1.5 && inst_box.height () < 1.5 && inst_box.width () < 1.5 && inst_box.height () < 1.5 &&
(amax <= 1 || trans.ctrans (a.length ()) < 1.5) && (amax <= 1 || trans.ctrans (a.length ()) < 1.5) &&
(bmax <= 1 || trans.ctrans (b.length ()) < 1.5)) { (bmax <= 1 || trans.ctrans (b.length ()) < 1.5)) {
simplify = true; 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 // 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)) { 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 <db::CellInst> bc (*mp_layout); db::box_convert <db::CellInst> bc (*mp_layout);
unsigned int plane_group = 2; 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 // The array (or single instance) must be iterated instance
// by instance // by instance
for (db::CellInstArray::iterator p = cell_inst.begin_touching (*v, bc); ! p.at_end (); ++p) { 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::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v); db::Box new_vp = db::Box (t.inverted () * *v);
draw_boxes (drawing_context, new_ci, trans * t, new_vp, level + 1); 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; ++inst;
} }
} }
@ -828,7 +837,7 @@ RedrawThreadWorker::draw_boxes (bool drawing_context, db::cell_index_type ci, co
} }
void 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<db::Box> &vp, int level)
{ {
if (! m_text_visible) { if (! m_text_visible) {
return; return;
@ -838,7 +847,7 @@ RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_ty
} }
void 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<db::Box> &vp, int level, db::properties_id_type prop_id)
{ {
// do not draw, if there is nothing to draw // do not draw, if there is nothing to draw
if (mp_layout->cells () <= ci || vp.empty ()) { if (mp_layout->cells () <= ci || vp.empty ()) {
@ -855,6 +864,16 @@ RedrawThreadWorker::draw_box_properties (bool drawing_context, db::cell_index_ty
return; return;
} }
for (std::vector<db::Box>::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 .. // For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox (); db::Box bbox = cell.bbox ();
@ -1193,14 +1212,12 @@ RedrawThreadWorker::search_regions (const db::Box &cell_bbox, const db::Box &vp,
} }
void 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<db::Box> &vp, int level)
{ {
if (! m_text_visible) { if (! m_text_visible) {
return; return;
} }
lay::Renderer &r = *mp_renderer;
unsigned int plane_group = 2; unsigned int plane_group = 2;
if (drawing_context) { if (drawing_context) {
plane_group = 0; 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)]; text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + 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 // do not draw, if there is nothing to draw
if (mp_layout->cells () <= ci || vp.empty ()) { if (mp_layout->cells () <= ci || vp.empty ()) {
return; return;
@ -1224,7 +1239,18 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c
return; return;
} }
for (std::vector<db::Box>::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); const db::Cell &cell = mp_layout->cell (ci);
lay::Renderer &r = *mp_renderer;
// For small bboxes, the cell outline can be reduced .. // For small bboxes, the cell outline can be reduced ..
db::Box bbox = cell.bbox (m_layer); 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::ICplxTrans t (cell_inst.complex_trans (*p));
db::Box new_vp = db::Box (t.inverted () * *v); 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 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<db::Box> &vp, int level,
lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot) 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 // do not draw, if there is nothing to draw
if (mp_layout->cells () <= ci || vp.empty ()) { if (mp_layout->cells () <= ci || vp.empty ()) {
return; return;
@ -1764,6 +1788,17 @@ RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_typ
return; return;
} }
for (std::vector<db::Box>::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); const db::Cell &cell = mp_layout->cell (ci);
db::Box bbox = cell.bbox (m_layer); db::Box bbox = cell.bbox (m_layer);
db::Box cell_bbox = cell.bbox (); db::Box cell_bbox = cell.bbox ();
@ -1891,7 +1926,7 @@ RedrawThreadWorker::draw_layer (int from_level, int to_level, db::cell_index_typ
} }
void 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<db::Box> &redraw_regions, int level)
{ {
if (drawing_context) { 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)]; text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + 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)]; text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + 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)]; text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + 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)]; text = m_planes[2 + plane_group * (planes_per_layer / 3)];
vertex = m_planes[3 + 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 void
RedrawThreadWorker::iterate_variants (const std::vector <db::Box> &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 <db::Box> &redraw_regions, db::cell_index_type ci, db::CplxTrans trans, void (RedrawThreadWorker::*what) (bool, db::cell_index_type, const db::CplxTrans &, const std::vector<db::Box> &, int))
{ {
// save current state // save current state
int from_level = m_from_level; int from_level = m_from_level;
@ -2050,7 +2085,7 @@ RedrawThreadWorker::iterate_variants (const std::vector <db::Box> &redraw_region
} }
void void
RedrawThreadWorker::iterate_variants_rec (const std::vector <db::Box> &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 <db::Box> &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<db::Box> &, int), bool drawing_context)
{ {
db::Cell::parent_inst_iterator p = mp_layout->cell (ci).begin_parent_insts (); 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 ()); int context_path_length = int (m_cellviews [m_cv_index].specific_path ().size ());
@ -2092,19 +2127,25 @@ RedrawThreadWorker::iterate_variants_rec (const std::vector <db::Box> &redraw_re
} else { } else {
std::vector<db::Box> actual_regions;
actual_regions.reserve (redraw_regions.size ());
for (std::vector<db::Box>::const_iterator rr = redraw_regions.begin (); rr != redraw_regions.end (); ++rr) { for (std::vector<db::Box>::const_iterator rr = redraw_regions.begin (); rr != redraw_regions.end (); ++rr) {
db::Coord lim = std::numeric_limits<db::Coord>::max (); db::Coord lim = std::numeric_limits<db::Coord>::max ();
db::DBox world (trans * db::Box (db::Point (-lim, -lim), db::Point (lim, lim))); 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))); 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 vp &= mp_layout->cell (ci).bbox (); // this avoids problems when accessing designs through very large viewports
if (! vp.empty ()) { 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);
}
} }
} }

View File

@ -175,20 +175,24 @@ protected:
void perform_task (tl::Task *task); void perform_task (tl::Task *task);
private: 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 (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, 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 (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &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<db::Box> &vv, 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<db::Box> &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_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &redraw_regions, 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_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_box_properties (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 std::vector <db::Box> &redraw_regions, 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_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 <db::Box> &redraw_regions, int level);
void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector <db::Box> &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 (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_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 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 test_snapshot (const UpdateSnapshotCallback *update_snapshot);
void transfer (); void transfer ();
void iterate_variants (const std::vector <db::Box> &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 (const std::vector <db::Box> &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 <db::Box> &, int level));
void iterate_variants_rec (const std::vector <db::Box> &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_rec (const std::vector <db::Box> &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 <db::Box> &, int level), bool spread);
bool cell_var_cached (db::cell_index_type ci, const db::CplxTrans &trans); bool cell_var_cached (db::cell_index_type ci, const db::CplxTrans &trans);
bool drop_cell (const db::Cell &cell, const db::CplxTrans &trans); bool drop_cell (const db::Cell &cell, const db::CplxTrans &trans);
std::vector<db::Box> search_regions (const db::Box &cell_bbox, const db::Box &vp, int level); std::vector<db::Box> search_regions (const db::Box &cell_bbox, const db::Box &vp, int level);

View File

@ -165,7 +165,7 @@ BackgroundViewObject::z_order (int z)
// ViewObject implementation // ViewObject implementation
ViewObject::ViewObject (ViewObjectWidget *widget, bool _static) 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) { if (widget) {
widget->m_objects.push_back (this); widget->m_objects.push_back (this);
@ -178,6 +178,15 @@ ViewObject::~ViewObject ()
redraw (); redraw ();
} }
void
ViewObject::set_dismissable (bool dismissable)
{
if (m_dismissable != dismissable) {
m_dismissable = dismissable;
redraw ();
}
}
void void
ViewObject::visible (bool vis) ViewObject::visible (bool vis)
{ {
@ -251,6 +260,7 @@ ViewService::set_cursor (lay::Cursor::cursor_shape cursor)
ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name) ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name)
: QWidget (parent), : QWidget (parent),
m_view_objects_dismissed (false),
m_needs_update_static (false), m_needs_update_static (false),
m_needs_update_bg (false), m_needs_update_bg (false),
mp_active_service (0), 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) { 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 BEGIN_PROTECTED_SILENT
obj->render (vp, canvas); obj->render (vp, canvas);
END_PROTECTED_SILENT 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 void
ViewObjectWidget::objects_changed () ViewObjectWidget::objects_changed ()
{ {

View File

@ -513,6 +513,23 @@ public:
return const_cast<ViewObjectWidget *> (mp_widget.get()); return const_cast<ViewObjectWidget *> (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 * @brief Set the visibility state of the view object
* *
@ -561,6 +578,7 @@ private:
tl::weak_ptr<ViewObjectWidget> mp_widget; tl::weak_ptr<ViewObjectWidget> mp_widget;
bool m_static; bool m_static;
bool m_visible; bool m_visible;
bool m_dismissable;
}; };
/** /**
@ -905,6 +923,21 @@ public:
*/ */
void set_default_cursor (lay::Cursor::cursor_shape cursor); 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: protected:
/** /**
* @brief Qt focus event handler * @brief Qt focus event handler
@ -985,6 +1018,7 @@ private:
tl::weak_collection<lay::BackgroundViewObject> m_background_objects; tl::weak_collection<lay::BackgroundViewObject> m_background_objects;
std::list<lay::ViewService *> m_services; std::list<lay::ViewService *> m_services;
std::list<ViewService *> m_grabbed; std::list<ViewService *> m_grabbed;
bool m_view_objects_dismissed;
bool m_needs_update_static; bool m_needs_update_static;
bool m_needs_update_bg; bool m_needs_update_bg;
lay::ViewService *mp_active_service; lay::ViewService *mp_active_service;

View File

@ -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_transient_mode ("sel-transient-mode");
static const std::string cfg_sel_inside_pcells_mode ("sel-inside-pcells-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_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_font ("inst-label-font");
static const std::string cfg_cell_box_text_transform ("inst-label-transform"); static const std::string cfg_cell_box_text_transform ("inst-label-transform");

View File

@ -2177,36 +2177,42 @@ MarkerBrowserPage::do_update_markers ()
mp_markers.push_back (new lay::DMarker (mp_view)); mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * polygon_value->value ()); mp_markers.back ()->set (trans * polygon_value->value ());
mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * polygon_value->value ().box (); m_markers_bbox += trans * polygon_value->value ().box ();
} else if (edge_pair_value) { } else if (edge_pair_value) {
mp_markers.push_back (new lay::DMarker (mp_view)); mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * edge_pair_value->value ()); 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 ()); m_markers_bbox += trans * db::DBox (edge_pair_value->value ().bbox ());
} else if (edge_value) { } else if (edge_value) {
mp_markers.push_back (new lay::DMarker (mp_view)); mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * edge_value->value ()); mp_markers.back ()->set (trans * edge_value->value ());
mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * db::DBox (edge_value->value ().bbox ()); m_markers_bbox += trans * db::DBox (edge_value->value ().bbox ());
} else if (box_value) { } else if (box_value) {
mp_markers.push_back (new lay::DMarker (mp_view)); mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * box_value->value ()); mp_markers.back ()->set (trans * box_value->value ());
mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * box_value->value (); m_markers_bbox += trans * box_value->value ();
} else if (text_value) { } else if (text_value) {
mp_markers.push_back (new lay::DMarker (mp_view)); mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * text_value->value ()); mp_markers.back ()->set (trans * text_value->value ());
mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * text_value->value ().box (); m_markers_bbox += trans * text_value->value ().box ();
} else if (path_value) { } else if (path_value) {
mp_markers.push_back (new lay::DMarker (mp_view)); mp_markers.push_back (new lay::DMarker (mp_view));
mp_markers.back ()->set (trans * path_value->value ()); mp_markers.back ()->set (trans * path_value->value ());
mp_markers.back ()->set_dismissable (true);
m_markers_bbox += trans * path_value->value ().box (); m_markers_bbox += trans * path_value->value ().box ();
} }

View File

@ -32,6 +32,7 @@
#include "tlClassRegistry.h" #include "tlClassRegistry.h"
#include "tlLog.h" #include "tlLog.h"
#include "tlXMLParser.h" #include "tlXMLParser.h"
#include "tlGlobPattern.h"
#include "rba.h" #include "rba.h"
#include "pya.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; m_format = NoFormat;
if (tl::verbosity () >= 20) { std::pair<bool, std::string> f = format_from_filename (fn, m_interpreter, m_dsl_interpreter, m_autorun_default, m_format);
tl::log << "Loading macro from " << path; 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; m_autorun = m_autorun_default;
@ -242,7 +246,7 @@ void Macro::load_from (const std::string &path)
} }
} else { } 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; 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) 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 ()); 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<bool, std::string>
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<std::string> 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; interpreter = None;
dsl_name = std::string (); dsl_name = std::string ();
format = NoFormat; format = NoFormat;

View File

@ -602,6 +602,8 @@ private:
void on_menu_needs_update (); void on_menu_needs_update ();
void on_changed (); void on_changed ();
void save_to (const std::string &path); 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<bool, std::string> 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) void set_autorun_default (bool f)
{ {

View File

@ -493,7 +493,11 @@ static std::string extract_python_name (const std::string &name)
} else if (name == "-@") { } else if (name == "-@") {
return "__neg__"; return "__neg__";
} else if (name == "/") { } else if (name == "/") {
#if PY_MAJOR_VERSION < 3
return "__div__"; return "__div__";
#else
return "__truediv__";
#endif
} else if (name == "*") { } else if (name == "*") {
return "__mul__"; return "__mul__";
} else if (name == "%") { } else if (name == "%") {
@ -515,7 +519,11 @@ static std::string extract_python_name (const std::string &name)
} else if (name == "-=") { } else if (name == "-=") {
return "__isub__"; return "__isub__";
} else if (name == "/=") { } else if (name == "/=") {
#if PY_MAJOR_VERSION < 3
return "__idiv__"; return "__idiv__";
#else
return "__itruediv__";
#endif
} else if (name == "*=") { } else if (name == "*=") {
return "__imul__"; return "__imul__";
} else if (name == "%=") { } 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"))); add_python_doc (*c, mt, int (mid), tl::to_string (tr ("This method enables iteration of the object")));
alt_names.push_back ("__iter__"); 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 <std::string>::const_iterator an = alt_names.begin (); an != alt_names.end (); ++an) { for (std::vector <std::string>::const_iterator an = alt_names.begin (); an != alt_names.end (); ++an) {

View File

@ -40,7 +40,8 @@ SOURCES = \
tlThreadedWorkers.cc \ tlThreadedWorkers.cc \
tlThreads.cc \ tlThreads.cc \
tlDeferredExecution.cc \ tlDeferredExecution.cc \
tlUri.cc tlUri.cc \
tlLongInt.cc
HEADERS = \ HEADERS = \
tlAlgorithm.h \ tlAlgorithm.h \
@ -84,14 +85,14 @@ HEADERS = \
tlCommandLineParser.h \ tlCommandLineParser.h \
tlUnitTest.h \ tlUnitTest.h \
tlInt128Support.h \ tlInt128Support.h \
tlHttpStreamCurl.h \
tlDefs.h \ tlDefs.h \
tlXMLParser.h \ tlXMLParser.h \
tlXMLWriter.h \ tlXMLWriter.h \
tlThreadedWorkers.h \ tlThreadedWorkers.h \
tlThreads.h \ tlThreads.h \
tlDeferredExecution.h \ tlDeferredExecution.h \
tlUri.h tlUri.h \
tlLongInt.h
equals(HAVE_CURL, "1") { equals(HAVE_CURL, "1") {

29
src/tl/tl/tlLongInt.cc Normal file
View File

@ -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 ..
}

1277
src/tl/tl/tlLongInt.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@
#include "tlThreads.h" #include "tlThreads.h"
#include "tlUtils.h" #include "tlUtils.h"
#include "tlTimer.h"
#include "tlLog.h" #include "tlLog.h"
#include "tlInternational.h" #include "tlInternational.h"

View File

@ -22,7 +22,6 @@
#include "tlTimer.h" #include "tlTimer.h"
#include "tlUtils.h"
#include "tlLog.h" #include "tlLog.h"
#include "tlString.h" #include "tlString.h"

View File

@ -0,0 +1,178 @@
/*
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 <algorithm>
#include <stdint.h>
#include <cstdio>
#include "tlLongInt.h"
#include "tlUnitTest.h"
typedef tl::long_int<4, uint8_t, uint16_t> li_type;
typedef int32_t i_type;
typedef tl::long_uint<4, uint8_t, uint16_t> lui_type;
typedef uint32_t ui_type;
i_type to_i (li_type x)
{
return i_type (x);
}
ui_type to_i (lui_type x)
{
return ui_type (x);
}
li_type to_e (i_type x)
{
return li_type (x);
}
lui_type to_e (ui_type x)
{
return lui_type (x);
}
template <class I1, class LI1, class I2, class LI2>
static void run_test_int (tl::TestBase *_this, I1 a, I2 b)
{
typedef typename LI1::basic_type basic_type;
if (tl::verbose ()) {
printf("Long int test with pair (%ld,%ld)\n", long (a), long (b));
}
LI1 ae = to_e (a);
LI2 be = to_e (b);
LI1 r;
EXPECT_EQ (to_i (ae), a);
EXPECT_EQ (to_i (be), b);
EXPECT_EQ (to_i (ae + be), a + b);
r = ae;
r += be;
EXPECT_EQ (to_i (r), a + b);
EXPECT_EQ (to_i (ae + basic_type (2)), a + basic_type (2));
r = ae;
r += basic_type (2);
EXPECT_EQ (to_i (r), a + basic_type (2));
EXPECT_EQ (to_i (ae - be), a - b);
r = ae;
r -= be;
EXPECT_EQ (to_i (r), a - b);
EXPECT_EQ (to_i (ae - basic_type (2)), a - basic_type (2));
r = ae;
r -= basic_type (2);
EXPECT_EQ (to_i (r), a - basic_type (2));
EXPECT_EQ (ae == be, a == b);
EXPECT_EQ (ae != be, a != b);
EXPECT_EQ (ae < be, a < b);
EXPECT_EQ (ae <= be, a <= b);
EXPECT_EQ (ae > be, a > b);
EXPECT_EQ (ae >= be, a >= b);
EXPECT_EQ (ae.is_zero (), a == 0);
EXPECT_EQ (to_i (ae * be), a * b);
r = ae;
r *= be;
EXPECT_EQ (to_i (r), a * b);
if (b != 0) {
EXPECT_EQ (to_i (ae / be), a / b);
r = ae;
r /= be;
EXPECT_EQ (to_i (r), a / b);
EXPECT_EQ (to_i (ae % be), a % b);
r = ae;
r %= be;
EXPECT_EQ (to_i (r), a % b);
}
}
template <class I1, class LI1, class I2, class LI2>
static void run_test (tl::TestBase *_this, I1 a, I2 b)
{
run_test_int<I1, LI1, I2, LI2> (_this, a, b);
run_test_int<I1, LI1, I2, LI2> (_this, a, a);
run_test_int<I1, LI1, I2, LI2> (_this, b, b);
run_test_int<I1, LI1, I2, LI2> (_this, b, a);
}
TEST(1)
{
run_test<i_type, li_type, i_type, li_type> (_this, 0, 1);
run_test<i_type, li_type, i_type, li_type> (_this, 256, 257);
run_test<i_type, li_type, i_type, li_type> (_this, 256, 2);
run_test<i_type, li_type, i_type, li_type> (_this, 65535, 65536);
run_test<i_type, li_type, i_type, li_type> (_this, 65535, 2);
run_test<i_type, li_type, i_type, li_type> (_this, 0xfffffffe, 0xffffffff);
run_test<i_type, li_type, i_type, li_type> (_this, 0xfffffffe, 2);
for (unsigned int i = 0; i < 100000; ++i) {
run_test<i_type, li_type, i_type, li_type> (_this, rand () * rand (), rand () * rand ());
}
}
TEST(2)
{
run_test<ui_type, lui_type, i_type, li_type> (_this, 0, 1);
run_test<ui_type, lui_type, i_type, li_type> (_this, 256, 257);
run_test<ui_type, lui_type, i_type, li_type> (_this, 256, 2);
run_test<ui_type, lui_type, i_type, li_type> (_this, 65535, 65536);
run_test<ui_type, lui_type, i_type, li_type> (_this, 65535, 2);
run_test<ui_type, lui_type, i_type, li_type> (_this, 0xfffffffe, 0xffffffff);
run_test<ui_type, lui_type, i_type, li_type> (_this, 0xfffffffe, 2);
for (unsigned int i = 0; i < 100000; ++i) {
run_test<ui_type, lui_type, i_type, li_type> (_this, rand () * rand (), rand () * rand ());
}
}
TEST(3)
{
run_test<i_type, li_type, ui_type, lui_type> (_this, 0, 1);
run_test<i_type, li_type, ui_type, lui_type> (_this, 256, 257);
run_test<i_type, li_type, ui_type, lui_type> (_this, 256, 2);
run_test<i_type, li_type, ui_type, lui_type> (_this, 65535, 65536);
run_test<i_type, li_type, ui_type, lui_type> (_this, 65535, 2);
run_test<i_type, li_type, ui_type, lui_type> (_this, 0xfffffffe, 0xffffffff);
run_test<i_type, li_type, ui_type, lui_type> (_this, 0xfffffffe, 2);
for (unsigned int i = 0; i < 100000; ++i) {
run_test<i_type, li_type, ui_type, lui_type> (_this, rand () * rand (), rand () * rand ());
}
}
TEST(4)
{
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 0, 1);
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 256, 257);
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 256, 2);
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 65535, 65536);
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 65535, 2);
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 0xfffffffe, 0xffffffff);
run_test<ui_type, lui_type, ui_type, lui_type> (_this, 0xfffffffe, 2);
for (unsigned int i = 0; i < 100000; ++i) {
run_test<ui_type, lui_type, ui_type, lui_type> (_this, rand () * rand (), rand () * rand ());
}
}

View File

@ -357,7 +357,7 @@ void run_thread_tests (tl::TestBase *_this, int wait)
s_sum[3].reset (); s_sum[3].reset ();
for (int i = 0; i < 10000; ++i) { for (int i = 0; i < 10000; ++i) {
job.schedule (new MyTask (10000)); job.schedule (new MyTask (100000));
} }
job.start (); job.start ();

View File

@ -28,11 +28,12 @@ SOURCES = \
tlThreads.cc \ tlThreads.cc \
tlUtils.cc \ tlUtils.cc \
tlVariant.cc \ tlVariant.cc \
tlInt128Support.cc \
tlXMLParser.cc \ tlXMLParser.cc \
tlUri.cc \ tlUri.cc \
tlWebDAV.cc \ tlWebDAV.cc \
tlHttpStream.cc \ tlHttpStream.cc \
tlInt128Support.cc \
tlLongInt.cc \
!equals(HAVE_QT, "0") { !equals(HAVE_QT, "0") {

98
test-pydeploy.py Normal file
View File

@ -0,0 +1,98 @@
import os, subprocess
import sys
from macbuild.build4mac_util import WalkFrameworkPaths, PerformChanges, DetectChanges
from pathlib import Path
# bundlePath = AbsMacPkgDir
bundlePath = os.getcwd() + '/qt5.pkg.macos-HighSierra-release/klayout.app'
bundleExecPathAbs = '%s/Contents/MacOS/' % bundlePath
pythonOriginalFrameworkPath = '/usr/local/opt/python/Frameworks/Python.framework'
pythonFrameworkPath = '%s/Contents/Frameworks/Python.framework' % bundlePath
print("[1] Copying Python Framework")
shell_commands = list()
shell_commands.append(f"rm -rf {pythonFrameworkPath}")
shell_commands.append(f"rsync -a --safe-links {pythonOriginalFrameworkPath}/ {pythonFrameworkPath}")
shell_commands.append(f"mkdir {pythonFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/")
shell_commands.append(f"cp -RL {pythonOriginalFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/{{pip*,pkg_resources,setuptools*,wheel*}} " +
f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/")
shell_commands.append(f"rm -rf {pythonFrameworkPath}/Versions/3.6/lib/python3.6/test")
shell_commands.append(f"rm -rf {pythonFrameworkPath}/Versions/3.6/Resources")
shell_commands.append(f"rm -rf {pythonFrameworkPath}/Versions/3.6/bin")
for command in shell_commands:
if subprocess.call( command, shell=True ) != 0:
msg = "command failed: %s"
print( msg % command, file=sys.stderr )
exit(1)
print("[2] Relinking dylib dependencies inside Python.framework")
depdict = WalkFrameworkPaths(pythonFrameworkPath)
appPythonFrameworkPath = '@executable_path/../Frameworks/Python.framework/'
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
usrLocalPath = '/usr/local/opt/'
appUsrLocalPath = '@executable_path/../Frameworks/'
depdict = WalkFrameworkPaths(pythonFrameworkPath)
PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs, libdir=True)
print("[3] Relinking dylib dependencies for klayout")
klayoutPath = bundleExecPathAbs
depdict = WalkFrameworkPaths(klayoutPath, filter_regex=r'klayout$')
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
libKlayoutPath = bundleExecPathAbs + '../Frameworks'
depdict = WalkFrameworkPaths(libKlayoutPath, filter_regex=r'libklayout')
PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath)], bundleExecPathAbs)
print("[4] Patching site.py, pip/, and distutils/")
site_module = f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/site.py"
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 = f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/site-packages/pip/__init__.py"
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 = f"{pythonFrameworkPath}/Versions/3.6/lib/python3.6/distutils/distutils.cfg"
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)
# pythonPath = bundleExecPathAbs + '../Frameworks/Python.framework/Versions/3.6/bin/'
# # pythonOriginalPrefixPath = '/usr/local/opt/python/Frameworks/Python.framework/Versions/3.6'
# # appPythonBinPath = '@executable_path/../'
# depdict = WalkFrameworkPaths(pythonPath, filter_regex=r'python')
# print(depdict)
# PerformChanges(depdict, [(pythonOriginalFrameworkPath, appPythonFrameworkPath),
# (Path(pythonOriginalFrameworkPath).resolve(), appPythonFrameworkPath)], bundleExecPathAbs)
# usrLocalPath = '/usr/local/lib/'
# appUsrLocalPath = '@executable_path/../Frameworks/'
# depdict = WalkFrameworkPaths(pythonFrameworkPath)
# PerformChanges(depdict, [(usrLocalPath, appUsrLocalPath)], bundleExecPathAbs)

29
test-pylib-script.py Normal file
View File

@ -0,0 +1,29 @@
import site; print(site.getsitepackages())
import pip
installed_packages = pip.get_installed_distributions()
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
for i in installed_packages])
print(installed_packages_list)
print("-------------")
if pip.main(['install', '--upgrade', 'numpy']) > 0:
exit(1)
print("-------------")
print("Importing numpy")
import numpy
print("-------------")
import sys;
print("Executing from: ", sys.executable)
print("-------------")
import os
print("Environment variables:")
for variable, value in os.environ.items():
print(variable, ":", value)

BIN
testdata/bool/and5.oas vendored

Binary file not shown.

Binary file not shown.

BIN
testdata/bool/and6.oas vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/bool/or5.oas vendored

Binary file not shown.

BIN
testdata/bool/or6.oas vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/bool/xor5.oas vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/bool/xor6.oas vendored

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More