diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01b41cd1e..f9dd98312 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: outputs: code: ${{ steps.filter.outputs.code == 'true' || github.event_name == 'release' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: dorny/paths-filter@v4 id: filter if: github.event_name != 'release' @@ -78,7 +78,7 @@ jobs: haskell: true large-packages: true - uses: hmarr/debug-action@v3 - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: ccache if: matrix.os != 'ubuntu-24.04-arm' uses: hendrikmuhs/ccache-action@v1.2 @@ -95,7 +95,7 @@ jobs: mkdir -p $HOST_CCACHE_DIR - name: Build wheels (ARM) if: matrix.os == 'ubuntu-24.04-arm' - uses: pypa/cibuildwheel@v3.4.1 + uses: pypa/cibuildwheel@v4.1.0 env: # override the default CentOS “yum install … ccache” and drop ccache CIBW_BEFORE_ALL_LINUX: | @@ -110,7 +110,7 @@ jobs: - name: Build wheels (all other platforms) if: matrix.os != 'ubuntu-24.04-arm' - uses: pypa/cibuildwheel@v3.4.1 + uses: pypa/cibuildwheel@v4.1.0 env: CIBW_BUILD: ${{ matrix.cibuild }} CIBW_ARCHS_MACOS: ${{ matrix.macos-arch }} @@ -139,7 +139,7 @@ jobs: if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Build SDist run: pipx run build --sdist diff --git a/.github/workflows/cache-maintenance.yml b/.github/workflows/cache-maintenance.yml index f57190c28..8208d0e97 100644 --- a/.github/workflows/cache-maintenance.yml +++ b/.github/workflows/cache-maintenance.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Cleanup run: | diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1d653e497..000000000 --- a/.travis.yml +++ /dev/null @@ -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 diff --git a/dropbox-deployment.yml b/dropbox-deployment.yml deleted file mode 100644 index f9ee0f21b..000000000 --- a/dropbox-deployment.yml +++ /dev/null @@ -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 diff --git a/scripts/makedeb.sh b/scripts/makedeb.sh index 3932b43ee..690ecac45 100755 --- a/scripts/makedeb.sh +++ b/scripts/makedeb.sh @@ -41,6 +41,9 @@ ubuntu22) 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)" ;; +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)" exit 1 diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index dc9953582..cd4ea75a9 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -1682,13 +1682,9 @@ CompoundRegionCheckOperationNode::computed_dist () const void CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &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 bool is_merged = true; - db::check_local_operation op (check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); + db::check_local_operation op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); tl_assert (results.size () == 1); if (results.front ().empty ()) { @@ -1704,13 +1700,9 @@ CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache void CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > &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 bool is_merged = true; - db::check_local_operation op (check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); + db::check_local_operation op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); tl_assert (results.size () == 1); if (results.front ().empty ()) { diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 2d6db90f1..40fcf0376 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -2113,3 +2113,13 @@ TEST(148_sparse_array_limit) 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); +} diff --git a/src/gsi/gsi/gsiDeclTlPixelBuffer.cc b/src/gsi/gsi/gsiDeclTlPixelBuffer.cc index c78cd1b1d..56b45a655 100644 --- a/src/gsi/gsi/gsiDeclTlPixelBuffer.cc +++ b/src/gsi/gsi/gsiDeclTlPixelBuffer.cc @@ -126,6 +126,40 @@ static std::vector pixel_buffer_to_png (const tl::PixelBuffer *pb) #endif } +// Returns an 8-byte header (width, height as uint32) followed by the raw ARGB32 pixel data +static std::vector 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 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 &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 decl_PixelBuffer ("lay", "PixelBuffer", gsi::constructor ("new", &create_pixel_buffer, gsi::arg ("width"), gsi::arg ("height"), @@ -188,6 +222,24 @@ Class decl_PixelBuffer ("lay", "PixelBuffer", "\n" "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"), "@brief Patches another pixel buffer into this one\n" "\n" diff --git a/src/laybasic/laybasic/layLayoutCanvas.cc b/src/laybasic/laybasic/layLayoutCanvas.cc index 2d93485f0..6ddd22956 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.cc +++ b/src/laybasic/laybasic/layLayoutCanvas.cc @@ -855,7 +855,9 @@ LayoutCanvas::image_with_options (unsigned int width, unsigned int height, int l lay::RedrawThread redraw_thread (&rd_canvas, mp_view); // 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 // paint the background objects. It uses "img" to paint on. diff --git a/testdata/drc/drcSimpleTests_149.drc b/testdata/drc/drcSimpleTests_149.drc new file mode 100644 index 000000000..d08836713 --- /dev/null +++ b/testdata/drc/drcSimpleTests_149.drc @@ -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) + diff --git a/testdata/drc/drcSimpleTests_149.gds b/testdata/drc/drcSimpleTests_149.gds new file mode 100644 index 000000000..a1d4e0d45 Binary files /dev/null and b/testdata/drc/drcSimpleTests_149.gds differ diff --git a/testdata/drc/drcSimpleTests_au149.gds b/testdata/drc/drcSimpleTests_au149.gds new file mode 100644 index 000000000..e376ef0bb Binary files /dev/null and b/testdata/drc/drcSimpleTests_au149.gds differ diff --git a/testdata/drc/drcSimpleTests_au149d.gds b/testdata/drc/drcSimpleTests_au149d.gds new file mode 100644 index 000000000..0bc742300 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au149d.gds differ diff --git a/testdata/python/dbShapesTest.py b/testdata/python/dbShapesTest.py index 2be2b5c49..47622e442 100644 --- a/testdata/python/dbShapesTest.py +++ b/testdata/python/dbShapesTest.py @@ -53,13 +53,18 @@ class DBShapesTest(unittest.TestCase): # Issue #2012 (reference count) def test_2(self): + # an empty dict provides the normal reference count + obj = {} + rc = sys.getrefcount(obj) + ly = pya.Layout() + self.assertEqual(sys.getrefcount(ly), rc) top = ly.create_cell("TOP") l1 = ly.layer(1, 0) top.shapes(l1).insert(pya.Box(0, 0, 100, 200)) 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 # for setter diff --git a/testdata/python/layPixelBuffer.py b/testdata/python/layPixelBuffer.py index 8a91ea189..f04ebfde1 100644 --- a/testdata/python/layPixelBuffer.py +++ b/testdata/python/layPixelBuffer.py @@ -57,6 +57,31 @@ class LAYPixelBufferTests(unittest.TestCase): pb_copy = pya.PixelBuffer.read_png(tmp) 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 if __name__ == '__main__': diff --git a/testdata/ruby/layPixelBuffer.rb b/testdata/ruby/layPixelBuffer.rb index abcb3254b..d6054c453 100644 --- a/testdata/ruby/layPixelBuffer.rb +++ b/testdata/ruby/layPixelBuffer.rb @@ -152,6 +152,41 @@ class LAYPixelBuffer_TestClass < TestBase 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 pb = RBA::BitmapBuffer::new diff --git a/travis-build.sh b/travis-build.sh deleted file mode 100755 index 9d5acabc3..000000000 --- a/travis-build.sh +++ /dev/null @@ -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