Merge branch 'master' into wip

This commit is contained in:
Matthias Koefferlein 2026-07-19 15:13:40 +02:00
commit b51187bf7c
17 changed files with 160 additions and 641 deletions

View File

@ -23,7 +23,7 @@ jobs:
outputs: outputs:
code: ${{ steps.filter.outputs.code == 'true' || github.event_name == 'release' }} code: ${{ steps.filter.outputs.code == 'true' || github.event_name == 'release' }}
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
- uses: dorny/paths-filter@v4 - uses: dorny/paths-filter@v4
id: filter id: filter
if: github.event_name != 'release' if: github.event_name != 'release'
@ -78,7 +78,7 @@ jobs:
haskell: true haskell: true
large-packages: true large-packages: true
- uses: hmarr/debug-action@v3 - uses: hmarr/debug-action@v3
- uses: actions/checkout@v6 - uses: actions/checkout@v7
- name: ccache - name: ccache
if: matrix.os != 'ubuntu-24.04-arm' if: matrix.os != 'ubuntu-24.04-arm'
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
@ -95,7 +95,7 @@ jobs:
mkdir -p $HOST_CCACHE_DIR mkdir -p $HOST_CCACHE_DIR
- name: Build wheels (ARM) - name: Build wheels (ARM)
if: matrix.os == 'ubuntu-24.04-arm' if: matrix.os == 'ubuntu-24.04-arm'
uses: pypa/cibuildwheel@v3.4.1 uses: pypa/cibuildwheel@v4.1.0
env: env:
# override the default CentOS “yum install … ccache” and drop ccache # override the default CentOS “yum install … ccache” and drop ccache
CIBW_BEFORE_ALL_LINUX: | CIBW_BEFORE_ALL_LINUX: |
@ -110,7 +110,7 @@ jobs:
- name: Build wheels (all other platforms) - name: Build wheels (all other platforms)
if: matrix.os != 'ubuntu-24.04-arm' if: matrix.os != 'ubuntu-24.04-arm'
uses: pypa/cibuildwheel@v3.4.1 uses: pypa/cibuildwheel@v4.1.0
env: env:
CIBW_BUILD: ${{ matrix.cibuild }} CIBW_BUILD: ${{ matrix.cibuild }}
CIBW_ARCHS_MACOS: ${{ matrix.macos-arch }} CIBW_ARCHS_MACOS: ${{ matrix.macos-arch }}
@ -139,7 +139,7 @@ jobs:
if: needs.changes.outputs.code == 'true' if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
- name: Build SDist - name: Build SDist
run: pipx run build --sdist run: pipx run build --sdist

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v6 uses: actions/checkout@v7
- name: Cleanup - name: Cleanup
run: | run: |

View File

@ -1,582 +0,0 @@
branches:
only:
- /v\d+\.\d+(\.\d+)?(\S*)?$/ # tag format: *v0.25(.8)(dev14)
- staging
- master
matrix:
include:
# python manylinux packages
- name: "cp39-cp39m-manylinux2014_x86_64.whl"
os: linux
sudo: true
language: python
python: '3.9'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux2014_x86_64"
- PY_VERSION="cp39-cp39"
- DOCKER_BUILD=true
- TEST_IN_HOST=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp38-cp38m-manylinux2014_x86_64.whl"
os: linux
sudo: true
language: python
python: '3.8'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux2014_x86_64"
- PY_VERSION="cp38-cp38"
- DOCKER_BUILD=true
- TEST_IN_HOST=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp37-cp37m-manylinux2014_x86_64.whl"
os: linux
sudo: true
language: python
python: '3.7-dev'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux2014_x86_64"
- PY_VERSION="cp37-cp37m"
- DOCKER_BUILD=true
- TEST_IN_HOST=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp36-cp36m-manylinux2014_x86_64.whl"
os: linux
sudo: true
language: python
python: '3.6'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux2014_x86_64"
- PY_VERSION="cp36-cp36m"
- DOCKER_BUILD=true
- TEST_IN_HOST=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp35-cp35m-manylinux2014_x86_64.whl"
os: linux
sudo: true
language: python
python: '3.5'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux2014_x86_64"
- PY_VERSION="cp35-cp35m"
- DOCKER_BUILD=true
- TEST_IN_HOST=true
- MATRIX_EVAL=""
cache:
directories:
- ccache
- name: "cp27-cp27m-manylinux2014_x86_64.whl"
os: linux
sudo: true
language: python
python: '2.7'
services:
- docker
env:
- DOCKER_IMAGE="quay.io/pypa/manylinux2014_x86_64"
- PY_VERSION="cp27-cp27m"
- DOCKER_BUILD=true
- TEST_IN_HOST=false # travis's python 2.7 uses ucs4 (mu), so this test fails.
- MATRIX_EVAL=""
cache:
directories:
- ccache
# python 3 osx
# MacOS 10.15
# MacOS 10.15, Python 3.9
- name: "cp39-cp39m-macosx_10_15_x86_64.whl"
os: osx
osx_image: xcode12 # macOS 10.15
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.9
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.9/bin/python3'; alias pip='/usr/local/opt/python@3.9/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.15, Python 3.8
- name: "cp38-cp38m-macosx_10_15_x86_64.whl"
os: osx
osx_image: xcode12 # macOS 10.15
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.8
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.8/bin/python3'; alias pip='/usr/local/opt/python@3.8/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.15, Python 3.7
- name: "cp37-cp37m-macosx_10_15_x86_64.whl"
os: osx
osx_image: xcode12 # macOS 10.15
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.7
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.7/bin/python3'; alias pip='/usr/local/opt/python@3.7/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.14
# MacOS 10.14, Python 3.9
- name: "cp39-cp39m-macosx_10_14_x86_64.whl"
os: osx
osx_image: xcode11 # macOS 10.14
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.9
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.9/bin/python3'; alias pip='/usr/local/opt/python@3.9/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.14, Python 3.8
- name: "cp38-cp38m-macosx_10_14_x86_64.whl"
os: osx
osx_image: xcode11 # macOS 10.14
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.8
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.8/bin/python3'; alias pip='/usr/local/opt/python@3.8/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.14, Python 3.7
- name: "cp37-cp37m-macosx_10_14_x86_64.whl"
os: osx
osx_image: xcode11 # macOS 10.14
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.7
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.7/bin/python3'; alias pip='/usr/local/opt/python@3.7/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.13
# MacOS 10.13, Python 3.9
- name: "cp39-cp39m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode10.1 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.9
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.9/bin/python3'; alias pip='/usr/local/opt/python@3.9/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.13, Python 3.8
- name: "cp38-cp38m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode10.1 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.8
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.8/bin/python3'; alias pip='/usr/local/opt/python@3.8/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.13, Python 3.7
- name: "cp37-cp37m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode10.1 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python@3.7
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='/usr/local/opt/python@3.7/bin/python3'; alias pip='/usr/local/opt/python@3.7/bin/pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# MacOS 10.12, Python 3.7
# - name: "klayout python3 osx10.12"
- name: "cp37-cp37m-macosx_10_12_x86_64.whl"
os: osx
osx_image: xcode9.2 # macOS 10.12
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- ccache
update: true
env:
- MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
exclude:
# No XCode 8.2.1 for Mac OS 10.11
# - name: "klayout python3 osx10.11"
- name: "cp37-cp37m-macosx_10_11_x86_64.whl"
os: osx
osx_image: xcode8 # macOS 10.11
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew config; brew upgrade python; brew postinstall python; ls -l /usr/local/opt/python/libexec/bin/; shopt -s expand_aliases; alias python='/usr/local/opt/python/libexec/bin/python'; alias pip='/usr/local/opt/python/libexec/bin/pip';"
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# Python 2 is EOL
# python 2 osx
# - name: "klayout python2 osx10.13"
- name: "cp27-cp27m-macosx_10_13_x86_64.whl"
os: osx
osx_image: xcode9.4 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL=""
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# - name: "klayout python2 osx10.12"
- name: "cp27-cp27m-macosx_10_12_x86_64.whl"
os: osx
osx_image: xcode8.3 # macOS 10.12
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
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"
- PYTHON_BUILD=true
# - name: "klayout python2 osx10.11"
- name: "cp27-cp27m-macosx_10_11_x86_64.whl"
os: osx
osx_image: xcode8 # macOS 10.11
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL=""
- ARCHFLAGS="-std=c++11"
- PIP_UPDATE="1"
- PYTHON_BUILD=true
# KLayout builds not enabled for now on MacOS
# KLayout builds for mac
# Python 3
- name: "KLayout macOS 10.13 with py3.7"
os: osx
osx_image: xcode9.4 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- qt
- ccache
update: true
env:
- MATRIX_EVAL=""
- PYTHON_VERSION=B37
- MACOS_VERSION=HighSierra
- KLAYOUT_BUILD=true
- name: "KLayout macOS 10.12 with py3.7"
os: osx
osx_image: xcode8.3 # macOS 10.12
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- qt
- ccache
update: true
env:
- MATRIX_EVAL=""
- PYTHON_VERSION=B37
- MACOS_VERSION=Sierra
- KLAYOUT_BUILD=true
- name: "KLayout macOS 10.11 with py3.7"
os: osx
osx_image: xcode8 # macOS 10.11
cache:
directories:
- ccache
addons:
homebrew:
packages:
- python3
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew config; brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/56c500b569c724b049be7ab9e12d9693f85522f9/Formula/qt.rb" # Qt 5.11.2
- PYTHON_VERSION=B37
- MACOS_VERSION=ElCapitan
- KLAYOUT_BUILD=true
# Python 2
- name: "KLayout macOS 10.13 with py2.7"
os: osx
osx_image: xcode9.4 # macOS 10.13
cache:
directories:
- ccache
addons:
homebrew:
packages:
- qt
- ccache
update: true
env:
- MATRIX_EVAL=""
- PYTHON_VERSION=Sys
- MACOS_VERSION=HighSierra
- KLAYOUT_BUILD=true
- name: "KLayout macOS 10.12 with py2.7"
os: osx
osx_image: xcode8.3 # macOS 10.12
cache:
directories:
- ccache
addons:
homebrew:
packages:
- qt
- ccache
update: true
env:
- MATRIX_EVAL=""
- PYTHON_VERSION=Sys
- MACOS_VERSION=Sierra
- KLAYOUT_BUILD=true
- name: "KLayout macOS 10.11 with py2.7"
os: osx
osx_image: xcode8 # macOS 10.11
cache:
directories:
- ccache
addons:
homebrew:
packages:
- ccache
update: true
env:
- MATRIX_EVAL="brew update; brew config; brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/56c500b569c724b049be7ab9e12d9693f85522f9/Formula/qt.rb" # Qt 5.11.2
- PYTHON_VERSION=Sys
- MACOS_VERSION=ElCapitan
- KLAYOUT_BUILD=true
before_install:
- env
- gem install dropbox-deployment
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
export PATH="/usr/local/opt/ccache/libexec:$PATH";
mkdir -p ccache;
export CCACHE_DIR="`pwd`/ccache";
ccache -s;
fi
- eval "${MATRIX_EVAL}"
- if [ "${PIP_UPDATE}" == "1" ]; then
pip --version;
pip install --upgrade pip || sudo pip install --upgrade pip;
pip --version;
pip install --upgrade setuptools wheel || sudo pip install --upgrade setuptools wheel;
fi
- python -c "import distutils.sysconfig as sysconfig; print(sysconfig.__file__)"
install:
- if [ "$DOCKER_BUILD" = true ]; then
docker pull $DOCKER_IMAGE;
fi
script:
- if [ "$DOCKER_BUILD" = true ]; then
mkdir -p ccache;
mkdir -p wheelhouse;
docker run --rm -e DOCKER_IMAGE -e PY_VERSION -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD "/io/ci-scripts/docker/docker_build.sh";
klayout_version=$(python -c 'import setup; print(setup.Config().version())');
mkdir -p deploy/dist-pymod/$klayout_version;
cp -a wheelhouse/{klayout-*manylinux2014*.whl,*.zip} deploy/dist-pymod/$klayout_version;
if [ "$TEST_IN_HOST" = true ]; then
pip install klayout --no-index -f ./wheelhouse;
python testdata/pymod/import_db.py;
python testdata/pymod/import_rdb.py;
python testdata/pymod/import_tl.py;
python testdata/pymod/import_lib.py;
python testdata/pymod/pya_tests.py;
fi
fi
- if [ "$PYTHON_BUILD" = true ]; then
python setup.py build;
python setup.py bdist_wheel;
python setup.py install;
python setup.py sdist --formats=zip;
python testdata/pymod/import_db.py;
python testdata/pymod/import_rdb.py;
python testdata/pymod/import_tl.py;
python testdata/pymod/import_lib.py;
python testdata/pymod/pya_tests.py;
klayout_version=$(python -c 'import setup; print(setup.Config().version())');
mkdir -p deploy/dist-pymod/$klayout_version;
cp -a dist/{*.whl,*.zip} deploy/dist-pymod/$klayout_version;
python -c 'import klayout.db as db; print(dir(db))';
python -c 'import klayout.rdb as rdb; print(dir(rdb))';
python -c 'import klayout.tl as tl; print(dir(tl))';
fi
- if [ "$KLAYOUT_BUILD" = true ]; then
./travis-build.sh;
fi
before_cache:
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
ccache -s;
fi
after_success:
# upload to dropbox
# need DROPBOX_OAUTH_BEARER environment variable
- dropbox-deployment
# uploading to pypi using twine
# need TWINE_USERNAME, TWINE_PASSWORD and TWINE_REPOSITORY_URL env variable
- if [ ! -z "$TRAVIS_TAG" ] && [ ! -z "$TWINE_PASSWORD" ] && [[ "$PYTHON_BUILD" = true || "$DOCKER_BUILD" = true ]]; then
pip install -U twine || sudo pip install -U twine;
twine upload --skip-existing deploy/dist-pymod/$klayout_version/*;
fi

View File

@ -1,4 +0,0 @@
deploy:
dropbox_path: /Builds/klayout # The path to the folder on Dropbox where the files will go
artifacts_path: deploy # can be a single file, or a path
debug: true # if you want to see more logs

View File

@ -41,6 +41,9 @@ ubuntu22)
ubuntu24) ubuntu24)
depends="libqt5core5t64 (>= 5.15.13), libqt5designer5 (>= 5.15.13), libqt5gui5t64 (>= 5.15.13), libqt5multimedia5 (>= 5.15.13), libqt5multimediawidgets5 (>= 5.15.13), libqt5network5t64 (>= 5.15.13), libqt5opengl5t64 (>= 5.15.13), libqt5printsupport5t64 (>= 5.15.13), libqt5sql5t64 (>= 5.15.13), libqt5svg5 (>= 5.15.13), libqt5widgets5t64 (>= 5.15.13), libqt5xml5t64 (>= 5.15.13), libqt5xmlpatterns5 (>= 5.15.13), zlib1g (>= 1.3), libgit2-1.7 (>= 1.7.2), libruby3.2 (>= 3.2.3), python3 (>= 3.12.3), libpython3.12 (>= 3.12.3), libstdc++6 (>=14), libc6 (>= 2.39)" depends="libqt5core5t64 (>= 5.15.13), libqt5designer5 (>= 5.15.13), libqt5gui5t64 (>= 5.15.13), libqt5multimedia5 (>= 5.15.13), libqt5multimediawidgets5 (>= 5.15.13), libqt5network5t64 (>= 5.15.13), libqt5opengl5t64 (>= 5.15.13), libqt5printsupport5t64 (>= 5.15.13), libqt5sql5t64 (>= 5.15.13), libqt5svg5 (>= 5.15.13), libqt5widgets5t64 (>= 5.15.13), libqt5xml5t64 (>= 5.15.13), libqt5xmlpatterns5 (>= 5.15.13), zlib1g (>= 1.3), libgit2-1.7 (>= 1.7.2), libruby3.2 (>= 3.2.3), python3 (>= 3.12.3), libpython3.12 (>= 3.12.3), libstdc++6 (>=14), libc6 (>= 2.39)"
;; ;;
ubuntu26)
depends="libqt5core5t64 (>= 5.15.18), libqt5designer5 (>= 5.15.18), libqt5gui5t64 (>= 5.15.18), libqt5multimedia5 (>= 5.15.18), libqt5multimediawidgets5 (>= 5.15.18), libqt5network5t64 (>= 5.15.18), libqt5opengl5t64 (>= 5.15.18), libqt5printsupport5t64 (>= 5.15.18), libqt5sql5t64 (>= 5.15.18), libqt5svg5 (>= 5.15.18), libqt5widgets5t64 (>= 5.15.18), libqt5xml5t64 (>= 5.15.18), libqt5xmlpatterns5 (>= 5.15.18), zlib1g (>= 1.3), libgit2-1.9 (>= 1.9.1), libruby3.3 (>= 3.3.8), python3 (>= 3.14.3), libpython3.14 (>= 3.14.3), libstdc++6 (>=16), libc6 (>= 2.43)"
;;
*) *)
echo "Unknown target '$target' (given as first argument)" echo "Unknown target '$target' (given as first argument)"
exit 1 exit 1

View File

@ -1682,13 +1682,9 @@ CompoundRegionCheckOperationNode::computed_dist () const
void void
CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonWithProperties, db::PolygonWithProperties> &interactions, std::vector<std::unordered_set<db::EdgePairWithProperties> > &results, const db::LocalProcessorBase *proc) const CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonWithProperties, db::PolygonWithProperties> &interactions, std::vector<std::unordered_set<db::EdgePairWithProperties> > &results, const db::LocalProcessorBase *proc) const
{ {
// consider magnification variants
db::EdgeRelationFilter check = m_check;
check.set_distance (proc->dist_for_cell (cell, check.distance ()));
// TODO: needs a concept to deal with merged/non-merged inputs // TODO: needs a concept to deal with merged/non-merged inputs
bool is_merged = true; bool is_merged = true;
db::check_local_operation<db::PolygonWithProperties, db::PolygonWithProperties> op (check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); db::check_local_operation<db::PolygonWithProperties, db::PolygonWithProperties> op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options);
tl_assert (results.size () == 1); tl_assert (results.size () == 1);
if (results.front ().empty ()) { if (results.front ().empty ()) {
@ -1704,13 +1700,9 @@ CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache
void void
CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::EdgePairWithProperties> > &results, const db::LocalProcessorBase *proc) const CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::EdgePairWithProperties> > &results, const db::LocalProcessorBase *proc) const
{ {
// consider magnification variants
db::EdgeRelationFilter check = m_check;
check.set_distance (proc->dist_for_cell (cell, check.distance ()));
// TODO: needs a concept to deal with merged/non-merged inputs // TODO: needs a concept to deal with merged/non-merged inputs
bool is_merged = true; bool is_merged = true;
db::check_local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties> op (check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); db::check_local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties> op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options);
tl_assert (results.size () == 1); tl_assert (results.size () == 1);
if (results.front ().empty ()) { if (results.front ().empty ()) {

View File

@ -2113,3 +2113,13 @@ TEST(148_sparse_array_limit)
run_test (_this, "148", true); run_test (_this, "148", true);
} }
// issue 2384
TEST(149_compound_drc_with_mag)
{
run_test (_this, "149", false);
}
TEST(149d_compound_drc_with_mag)
{
run_test (_this, "149", true);
}

View File

@ -126,6 +126,40 @@ static std::vector<char> pixel_buffer_to_png (const tl::PixelBuffer *pb)
#endif #endif
} }
// Returns an 8-byte header (width, height as uint32) followed by the raw ARGB32 pixel data
static std::vector<char> pixel_buffer_to_bytes (const tl::PixelBuffer *pb)
{
uint32_t w = pb->width (), h = pb->height ();
size_t n = (size_t) w * (size_t) h * 4;
std::vector<char> data (8 + n);
memcpy (data.data (), &w, 4);
memcpy (data.data () + 4, &h, 4);
memcpy (data.data () + 8, pb->data (), n);
return data;
}
// Inverse of to_bytes: reads width/height from the header and checks the length
static tl::PixelBuffer pixel_buffer_from_bytes (const std::vector<char> &data)
{
uint32_t w = 0, h = 0;
if (data.size () >= 8) {
memcpy (&w, data.data (), 4);
memcpy (&h, data.data () + 4, 4);
}
// sanity guard against malformed headers: reader caps dimensions at 64k x 64k
// (generous for finely-resolved drawings), writer stays full 32-bit
const uint32_t max_dim = 65536;
if (w > max_dim || h > max_dim) {
throw tl::Exception (tl::to_string (tr ("Invalid PixelBuffer byte stream: width or height exceeds the 65536 x 65536 limit")));
}
if (data.size () != 8 + (size_t) w * (size_t) h * 4) {
throw tl::Exception (tl::to_string (tr ("Invalid PixelBuffer byte stream: length does not match the width and height in the header")));
}
tl::PixelBuffer pb (w, h, (const tl::color_t *) (data.data () + 8));
pb.set_transparent (true);
return pb;
}
Class<tl::PixelBuffer> decl_PixelBuffer ("lay", "PixelBuffer", Class<tl::PixelBuffer> decl_PixelBuffer ("lay", "PixelBuffer",
gsi::constructor ("new", &create_pixel_buffer, gsi::arg ("width"), gsi::arg ("height"), gsi::constructor ("new", &create_pixel_buffer, gsi::arg ("width"), gsi::arg ("height"),
@ -188,6 +222,24 @@ Class<tl::PixelBuffer> decl_PixelBuffer ("lay", "PixelBuffer",
"\n" "\n"
"This method may not be available if PNG support is not compiled into KLayout." "This method may not be available if PNG support is not compiled into KLayout."
) + ) +
gsi::method_ext ("to_bytes", &pixel_buffer_to_bytes,
"@brief Converts the pixel buffer to a raw byte stream\n"
"\n"
"The stream starts with an 8-byte header (width and height as 32-bit unsigned integers) "
"followed by the raw ARGB32 pixel data with 4 bytes per pixel in row-major order, "
"top to bottom. Unlike \\to_png_data this method has zero encoding overhead. "
"Use \\from_bytes to reconstruct the pixel buffer.\n"
"\n"
"This method has been added in version 0.30.10."
) +
gsi::method ("from_bytes", &pixel_buffer_from_bytes, gsi::arg ("data"),
"@brief Reconstructs a pixel buffer from a byte stream produced by \\to_bytes\n"
"\n"
"The width and height are taken from the header and the stream length is checked against them. "
"The dimensions are capped at 65536 x 65536; a header exceeding this limit raises an error.\n"
"\n"
"This method has been added in version 0.30.10."
) +
gsi::method ("patch", &tl::PixelBuffer::patch, gsi::arg ("other"), gsi::method ("patch", &tl::PixelBuffer::patch, gsi::arg ("other"),
"@brief Patches another pixel buffer into this one\n" "@brief Patches another pixel buffer into this one\n"
"\n" "\n"

View File

@ -855,7 +855,9 @@ LayoutCanvas::image_with_options (unsigned int width, unsigned int height, int l
lay::RedrawThread redraw_thread (&rd_canvas, mp_view); lay::RedrawThread redraw_thread (&rd_canvas, mp_view);
// render the layout // render the layout
redraw_thread.start (0 /*synchronous*/, m_layers, vp, resolution, font_resolution, true); int workers = mp_view->synchronous () ? 0 : mp_view->drawing_workers ();
redraw_thread.start (workers, m_layers, vp, resolution, font_resolution, true);
redraw_thread.wait ();
redraw_thread.stop (); // safety redraw_thread.stop (); // safety
// paint the background objects. It uses "img" to paint on. // paint the background objects. It uses "img" to paint on.

18
testdata/drc/drcSimpleTests_149.drc vendored Normal file
View File

@ -0,0 +1,18 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
deep
metal2_drawn = polygons(36, 0)
metal2_slot = polygons(36, 3)
metal2_drawn.output(36, 0)
metal2_slot.output(36, 3)
violations_enclosed = metal2_slot.drc(enclosed(metal2_drawn) < 10.um)
violations_enclosed.output(100, 0)

BIN
testdata/drc/drcSimpleTests_149.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au149.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au149d.gds vendored Normal file

Binary file not shown.

View File

@ -53,13 +53,18 @@ class DBShapesTest(unittest.TestCase):
# Issue #2012 (reference count) # Issue #2012 (reference count)
def test_2(self): def test_2(self):
# an empty dict provides the normal reference count
obj = {}
rc = sys.getrefcount(obj)
ly = pya.Layout() ly = pya.Layout()
self.assertEqual(sys.getrefcount(ly), rc)
top = ly.create_cell("TOP") top = ly.create_cell("TOP")
l1 = ly.layer(1, 0) l1 = ly.layer(1, 0)
top.shapes(l1).insert(pya.Box(0, 0, 100, 200)) top.shapes(l1).insert(pya.Box(0, 0, 100, 200))
shapes = top.shapes(l1) shapes = top.shapes(l1)
self.assertEqual(sys.getrefcount(shapes), 2) self.assertEqual(sys.getrefcount(shapes), rc)
# Tests the ability to take PolygonWithProperties instead of base class # Tests the ability to take PolygonWithProperties instead of base class
# for setter # for setter

View File

@ -57,6 +57,31 @@ class LAYPixelBufferTests(unittest.TestCase):
pb_copy = pya.PixelBuffer.read_png(tmp) pb_copy = pya.PixelBuffer.read_png(tmp)
self.assertEqual(compare(pb, pb_copy), True) self.assertEqual(compare(pb, pb_copy), True)
def test_2(self):
# to_bytes / from_bytes round-trip
import struct
pb = pya.PixelBuffer(10, 20)
pb.transparent = True
pb.fill(0xf0010203)
pb.set_pixel(1, 2, 0x80102030)
data = bytes(pb.to_bytes())
self.assertEqual(len(data), 8 + 10 * 20 * 4)
self.assertEqual(struct.unpack("=II", data[0:8]), (10, 20)) # width, height header
self.assertEqual(pb == pya.PixelBuffer.from_bytes(data), True)
# a mismatched stream is rejected
with self.assertRaises(Exception):
pya.PixelBuffer.from_bytes(data[:-4])
# a header beyond the 64k x 64k limit is rejected
with self.assertRaises(Exception):
pya.PixelBuffer.from_bytes(struct.pack("=II", 65537, 1))
# run unit tests # run unit tests
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -152,6 +152,41 @@ class LAYPixelBuffer_TestClass < TestBase
end end
def test_5
# to_bytes / from_bytes round-trip
pb = RBA::PixelBuffer::new(10, 20)
pb.transparent = true
pb.fill(0xf0010203)
pb.set_pixel(1, 2, 0x80102030)
bytes = pb.to_bytes
assert_equal(bytes.size, 8 + 10 * 20 * 4)
assert_equal(bytes[0, 8].unpack("VV"), [ 10, 20 ]) # width, height header
assert_equal(pb == RBA::PixelBuffer.from_bytes(bytes), true)
# a mismatched stream is rejected
error = false
begin
RBA::PixelBuffer.from_bytes(bytes[0, bytes.size - 4])
rescue
error = true
end
assert_equal(error, true)
# a header beyond the 64k x 64k limit is rejected
error = false
begin
RBA::PixelBuffer.from_bytes([ 65537, 1 ].pack("VV"))
rescue
error = true
end
assert_equal(error, true)
end
def test_11 def test_11
pb = RBA::BitmapBuffer::new pb = RBA::BitmapBuffer::new

View File

@ -1,37 +0,0 @@
#!/bin/bash
set -e
export PING_SLEEP=30s
bash -c "while true; do find qt* | wc -l; sleep $PING_SLEEP; done" &
PING_LOOP_PID=$!
touch build.txt
# Configure ccache
mkdir -p ccache;
export CCACHE_DIR="`pwd`/ccache"
export QMAKE_CCACHE=1
# Show ccache stats
echo "Cache stats:"
ccache -s
echo "build"
make build >> build.txt 2>&1 || tail -500 build.txt
echo "deploy"
make deploy >> build.txt 2>&1 || tail -500 build.txt
echo "test"
make test >> build.txt 2>&1 || tail -500 build.txt
echo "dropbox-deploy"
make dropbox-deploy
# Show ccache stats
echo "Cache stats:"
ccache -s
echo "build finished"
kill $PING_LOOP_PID
exit 0