diff --git a/.travis.yml b/.travis.yml index a8a374a71..42f0d13f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,44 +1,71 @@ matrix: include: - # python 3 osx - - os: osx + # python 2 osx + + - name: "klayout python2 osx10.13" + os: osx osx_image: xcode9.4 # macOS 10.13 env: - MATRIX_EVAL="" - ARCHFLAGS="-std=c++11" - PIP_UPDATE="1" - - os: osx + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python2 osx10.12" + os: osx osx_image: xcode8.3 # macOS 10.12 env: - MATRIX_EVAL="brew install python2 || brew link --overwrite python@2" # deficient python2 in travis's xcode8.3 (no ssl) - ARCHFLAGS="-std=c++11" - PIP_UPDATE="1" - - os: osx + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python2 osx10.11" + os: osx osx_image: xcode8 # macOS 10.11 env: - MATRIX_EVAL="" - ARCHFLAGS="-std=c++11" - PIP_UPDATE="1" - # python 2 osx - - os: osx + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + # python 3 osx + + - name: "klayout python3 osx10.13" + os: osx osx_image: xcode9.4 # macOS 10.13 env: - - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';" + - MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';" - ARCHFLAGS="-std=c++11" - PIP_UPDATE="1" - - os: osx + - PYTHON_BUILD=true + - BREW_BUNDLE=true + + - name: "klayout python3 osx10.12" + os: osx osx_image: xcode8.3 # macOS 10.12 env: - - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';" + - MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';" - ARCHFLAGS="-std=c++11" - PIP_UPDATE="1" - - os: osx + - PYTHON_BUILD=true + - BREW_BUNDLE=true + + - name: "klayout python3 osx10.11" + os: osx osx_image: xcode8 # macOS 10.11 env: - - MATRIX_EVAL="brew update; brew bundle; shopt -s expand_aliases; alias python='python3'; alias pip='pip3';" + - MATRIX_EVAL="shopt -s expand_aliases; alias python='python3'; alias pip='pip3';" - ARCHFLAGS="-std=c++11" - PIP_UPDATE="1" - - os: linux + - PYTHON_BUILD=true + - BREW_BUNDLE=true + + - name: "klayout python3.6 package" + os: linux dist: trusty # Ubuntu 14.04 sudo: false language: python @@ -46,7 +73,11 @@ matrix: env: - MATRIX_EVAL="" - PIP_UPDATE="1" - - os: linux + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python2.7 package" + os: linux dist: trusty # Ubuntu 14.04 sudo: false language: python @@ -54,7 +85,11 @@ matrix: env: - MATRIX_EVAL="" - PIP_UPDATE="1" - - os: linux + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python2.6 package" + os: linux dist: trusty # Ubuntu 14.04 sudo: false language: python @@ -62,7 +97,11 @@ matrix: env: - MATRIX_EVAL="" - PIP_UPDATE="0" # setuptools installed from last pip has syntax error on py 2.6 - - os: linux + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python3.3 package" + os: linux dist: trusty # Ubuntu 14.04 sudo: false language: python @@ -70,7 +109,11 @@ matrix: env: - MATRIX_EVAL="" - PIP_UPDATE="1" - - os: linux + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python3.4 package" + os: linux dist: trusty # Ubuntu 14.04 sudo: false language: python @@ -78,7 +121,11 @@ matrix: env: - MATRIX_EVAL="" - PIP_UPDATE="1" - - os: linux + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + - name: "klayout python3.5 package" + os: linux dist: trusty # Ubuntu 14.04 sudo: false language: python @@ -86,12 +133,82 @@ matrix: env: - MATRIX_EVAL="" - PIP_UPDATE="1" + - PYTHON_BUILD=true + - BREW_BUNDLE=false + + # KLayout builds for mac + # Python 3 + - name: "KLayout macOS 10.13 with py3.7" + os: osx + osx_image: xcode9.4 # macOS 10.13 + env: + - MATRIX_EVAL="" + - PYTHON_VERSION=B37 + - MACOS_VERSION=HighSierra + - KLAYOUT_BUILD=true + - BREW_BUNDLE=true + + - name: "KLayout macOS 10.12 with py3.7" + os: osx + osx_image: xcode8.3 # macOS 10.12 + env: + - MATRIX_EVAL="" + - PYTHON_VERSION=B37 + - MACOS_VERSION=Sierra + - KLAYOUT_BUILD=true + - BREW_BUNDLE=true + + - name: "KLayout macOS 10.11 with py3.7" + os: osx + osx_image: xcode8 # macOS 10.11 + env: + - MATRIX_EVAL="" + - PYTHON_VERSION=B37 + - MACOS_VERSION=ElCapitan + - KLAYOUT_BUILD=true + - BREW_BUNDLE=true + + # Python 2 + - name: "KLayout macOS 10.13 with py2.7" + os: osx + osx_image: xcode9.4 # macOS 10.13 + env: + - MATRIX_EVAL="" + - PYTHON_VERSION=Sys + - MACOS_VERSION=HighSierra + - KLAYOUT_BUILD=true + - BREW_BUNDLE=true + + - name: "KLayout macOS 10.12 with py2.7" + os: osx + osx_image: xcode8.3 # macOS 10.12 + env: + - MATRIX_EVAL="" + - PYTHON_VERSION=Sys + - MACOS_VERSION=Sierra + - KLAYOUT_BUILD=true + - BREW_BUNDLE=true + + - name: "KLayout macOS 10.11 with py2.7" + os: osx + osx_image: xcode8 # macOS 10.11 + env: + - MATRIX_EVAL="" + - PYTHON_VERSION=Sys + - MACOS_VERSION=ElCapitan + - KLAYOUT_BUILD=true + - BREW_BUNDLE=true before_install: - env - rvm install ruby --latest - gem install dropbox-deployment - eval "${MATRIX_EVAL}" + - if [ "$BREW_BUNDLE" = true ]; then + find "$(brew --prefix)/Caskroom/"*'/.metadata' -type f -name '*.rb' | xargs grep 'EOS.undent' --files-with-matches | xargs sed -i '' 's/EOS.undent/EOS/'; + brew update; + brew bundle; + fi - if [ "${PIP_UPDATE}" == "1" ]; then pip --version; pip install --upgrade pip || sudo pip install --upgrade pip; @@ -100,15 +217,20 @@ before_install: fi - python -c "import distutils.sysconfig as sysconfig; print(sysconfig.__file__)" -install: - - python setup.py build - - python setup.py bdist_wheel - - python setup.py install - -script: - - 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))' +script: + - if [ "$PYTHON_BUILD" = true ]; then + python setup.py build; + python setup.py bdist_wheel; + python setup.py install; + mkdir -p deploy/dist-pymod; + cp -a dist/* deploy/dist-pymod/; + 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 after_success: - dropbox-deployment diff --git a/Brewfile b/Brewfile index f84c801df..0d5580505 100644 --- a/Brewfile +++ b/Brewfile @@ -1,2 +1,4 @@ tap "homebrew/core" brew "python3" +brew "python@2", link: false +brew "qt" diff --git a/Changelog b/Changelog index cd4730eb6..ef0c3ce59 100644 --- a/Changelog +++ b/Changelog @@ -5,11 +5,23 @@ For details see: https://github.com/klayoutmatthias/klayout/wiki/klayout---Standalone-KLayout-Python-Module -0.25.5 (2018-12-30): +0.25.5 (2018-09-30): -* YET TO BE RELEASED * Bugfix: https://github.com/klayoutmatthias/klayout/issues/162 GDS2 LIBNAME was not maintained on "File/Save". +* Bugfix: https://github.com/klayoutmatthias/klayout/issues/166 + Internal error when writing GDS files (breaking of polygons) +* Bugfix: https://github.com/klayoutmatthias/klayout/issues/172 + DEF reader did not pull vias from LEF +* Bugfix: https://github.com/klayoutmatthias/klayout/issues/174 + Performance issue with many layers with width >1 +* Bugfix: https://github.com/klayoutmatthias/klayout/issues/176 + Painting issue with texts +* Bugfix: some potential memory corruption issues fixed + During the efforts for making the code base compatible + with MSVC, some potential candidates for memory corruption + have been identified and fixed. + These fixes are included in this release. 0.25.4 (2018-08-25): * Bugfix: https://github.com/klayoutmatthias/klayout/issues/121 diff --git a/Changelog.Debian b/Changelog.Debian index 9a8ba729a..9058860eb 100644 --- a/Changelog.Debian +++ b/Changelog.Debian @@ -6,9 +6,10 @@ klayout (0.26-1) unstable; urgency=low klayout (0.25.5-1) unstable; urgency=low - * YET TO BE RELEASED + * New features and bugfixes + - See changelog - -- Matthias Köfferlein Sat, 30 Dec 2018 23:15:23 +0200 + -- Matthias Köfferlein Sun, 30 Sep 2018 23:02:44 +0200 klayout (0.25.4-1) unstable; urgency=low diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..1654c3d96 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ +.PHONY: help build deploy test dropbox-deploy + +GITCOMMIT := $(shell git rev-parse --short HEAD) +KLAYOUT_VERSION := $(shell source version.sh && echo $$KLAYOUT_VERSION) + +.ONESHELL: + +default: help + +help: + @echo "For Mac OS only" + @echo "make build PYTHON_VERSION=B37" + @echo "make deploy PYTHON_VERSION=B37" + @echo "make test MACOS_VERSION=HighSierra" + @echo "Valid Mac OS Versions: [Yosemite, ElCapitan, Sierra, HighSierra]" + @echo "Valid Python Version: [nil, Sys, B37]" + +build: + @echo "Building for Mac $(GITCOMMIT)" + ./build4mac.py -p $(PYTHON_VERSION) -q Qt5Brew -c; \ + ./build4mac.py -p $(PYTHON_VERSION) -q Qt5Brew + +deploy: + @echo "Deploying 4 Mac $(GITCOMMIT)" + ./build4mac.py -p $(PYTHON_VERSION) -q Qt5Brew -y + +test: + @echo "Testing 4 Mac $(GITCOMMIT)" + qt5.pkg.macos-$(MACOS_VERSION)-release/klayout.app/Contents/MacOS/klayout -b -r test-pylib-script.py; \ + cd qt5.build.macos-$(MACOS_VERSION)-release; \ + ln -s klayout.app/Contents/MacOS/klayout klayout; \ + export TESTTMP=testtmp; \ + export TESTSRC=..; \ + ./ut_runner -h || true; \ + cd .. + +dropbox-deploy: + @echo "Preparing for dropbox deployment $(MACOS_VERSION) $(GITCOMMIT)" + mkdir -p deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION); \ + pwd; \ + ls -lah; \ + touch build.txt; \ + cp build.txt deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).log.txt; \ + hdiutil convert macbuild/Resources/klayoutDMGTemplate.dmg -format UDRW -o work-KLayout.dmg; \ + hdiutil resize -size 500m work-KLayout.dmg; \ + hdiutil attach work-KLayout.dmg -readwrite -noverify -quiet -mountpoint tempKLayout -noautoopen; \ + cp -a qt5.pkg.macos-$(MACOS_VERSION)-release/ tempKLayout/; \ + hdiutil detach tempKLayout; \ + hdiutil convert work-KLayout.dmg -format UDZO -imagekey zlib-level=9 -o deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg; \ + md5 -q deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg > deploy/$(MACOS_VERSION)/$(PYTHON_VERSION)/$(KLAYOUT_VERSION)/qt5.pkg.macos-$(MACOS_VERSION)-$(PYTHON_VERSION)-release-$(KLAYOUT_VERSION)-$(GITCOMMIT).dmg.md5; \ + rm work-KLayout.dmg diff --git a/build.bat b/build.bat index bdee5a50a..64dcc84ce 100644 --- a/build.bat +++ b/build.bat @@ -250,6 +250,11 @@ echo on "HAVE_64BIT_COORD=%HAVE_64BIT_COORD%" ^ "PREFIX=%option-bin%" ^ "BITS_PATH=%option-bits%\%compiler%\%arch%" ^ - %inst_path%\src\klayout.pro ^ -&& nmake %MAKE_OPT% ^ -&& nmake install + %inst_path%\src\klayout.pro || exit /b 1 + +rem start the build +nmake %MAKE_OPT% || exit /b 2 + +rem install the binaries +nmake install || exit /b 3 + diff --git a/dropbox-deployment.yml b/dropbox-deployment.yml index 945f867d8..f9ee0f21b 100644 --- a/dropbox-deployment.yml +++ b/dropbox-deployment.yml @@ -1,4 +1,4 @@ deploy: - dropbox_path: /Builds/klayout-pymod # The path to the folder on Dropbox where the files will go - artifacts_path: dist # can be a single file, or a path + 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/setup.py b/setup.py index f817cf5b0..bf862b4e1 100644 --- a/setup.py +++ b/setup.py @@ -148,8 +148,9 @@ class Config(object): elif platform.system() == "Darwin": return [] else: - # Avoids many "type-punned pointer" warnings - return ["-Wno-strict-aliasing"] + return ["-Wno-strict-aliasing", # Avoids many "type-punned pointer" warnings + "-std=c++0x", # because we use unordered_map/unordered_set + ] def link_args(self, mod): """ @@ -173,7 +174,7 @@ class Config(object): # build path and the loader will fail. args = [] args += ['-Wl,-soname,' + self.libname_of(mod)] - if not '_dbpi' in mod: + if '_dbpi' not in mod: loader_path = '$ORIGIN' else: loader_path = '$ORIGIN/..' diff --git a/src/laybasic/laybasic/layBitmapsToImage.cc b/src/laybasic/laybasic/layBitmapsToImage.cc index 57e547e4b..dbd8bbc64 100644 --- a/src/laybasic/laybasic/layBitmapsToImage.cc +++ b/src/laybasic/laybasic/layBitmapsToImage.cc @@ -386,13 +386,18 @@ render_scanline_cross (const uint32_t *dp, unsigned int ds, const lay::Bitmap *p } } -static void create_precursor_bitmaps (const std::vector &view_ops_in, const std::vector &pbitmaps_in, const lay::LineStyles &ls, unsigned int width, unsigned int height, std::map &precursors, QMutex *mutex) +static void create_precursor_bitmaps (const std::vector &view_ops_in, const std::vector &vo_map, const std::vector &pbitmaps_in, const std::vector &bm_map, const lay::LineStyles &ls, unsigned int width, unsigned int height, std::map &precursors, QMutex *mutex) { + tl_assert (bm_map.size () == vo_map.size ()); + // Styled lines with width > 1 are not rendered directly, but through an intermediate step. // We prepare the necessary precursor bitmaps now - for (unsigned int i = 0; i < view_ops_in.size (); ++i) { + for (unsigned int i = 0; i < vo_map.size (); ++i) { - const ViewOp &op = view_ops_in [i]; + unsigned int vo_index = vo_map [i]; + unsigned int bm_index = bm_map [i]; + + const ViewOp &op = view_ops_in [vo_index]; if (op.width () > 1 && ls.style (op.line_style_index ()).width () > 0) { // lock bitmaps against change by the redraw thread @@ -400,12 +405,12 @@ static void create_precursor_bitmaps (const std::vector &view_ops_i mutex->lock (); } - lay::Bitmap &bp = precursors.insert (std::make_pair (i, lay::Bitmap (width, height, 1.0))).first->second; + lay::Bitmap &bp = precursors.insert (std::make_pair (bm_index, lay::Bitmap (width, height, 1.0))).first->second; LineStyleInfo ls_info = ls.style (op.line_style_index ()); ls_info.scale_pattern (op.width ()); for (unsigned int y = 0; y < height; y++) { - render_scanline_std_edge (ls_info.pattern (), ls_info.pattern_stride (), pbitmaps_in [i], y, width, height, bp.scanline (y)); + render_scanline_std_edge (ls_info.pattern (), ls_info.pattern_stride (), pbitmaps_in [bm_index], y, width, height, bp.scanline (y)); } if (mutex) { @@ -418,7 +423,7 @@ static void create_precursor_bitmaps (const std::vector &view_ops_i } static void -bitmaps_to_image_rgb (const std::vector &view_ops_in, +bitmaps_to_image_rgb (const std::vector &view_ops_in, const std::vector &pbitmaps_in, const lay::DitherPattern &dp, const lay::LineStyles &ls, @@ -427,29 +432,33 @@ bitmaps_to_image_rgb (const std::vector &view_ops_in, bool transparent, QMutex *mutex) { - unsigned int n_in = (unsigned int) view_ops_in.size (); - std::vector bm_map; std::vector vo_map; - vo_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - vo_map.push_back (i); - } + vo_map.reserve (view_ops_in.size ()); + bm_map.reserve (view_ops_in.size ()); + unsigned int n_in = 0; - if (! use_bitmap_index) { - bm_map = vo_map; - } else { - bm_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - bm_map.push_back (view_ops_in [i].bitmap_index () < 0 ? i : view_ops_in [i].bitmap_index ()); + // drop invisible and empty bitmaps, build bitmap mask + for (unsigned int i = 0; i < view_ops_in.size (); ++i) { + + const lay::ViewOp &vop = view_ops_in [i]; + + unsigned int bi = (use_bitmap_index && vop.bitmap_index () >= 0) ? (unsigned int) vop.bitmap_index () : i; + const lay::Bitmap *pb = bi < pbitmaps_in.size () ? pbitmaps_in [bi] : 0; + + if ((vop.ormask () | ~vop.andmask ()) != 0 && pb && ! pb->empty ()) { + vo_map.push_back (i); + bm_map.push_back (bi); + ++n_in; } + } // Styled lines with width > 1 are not rendered directly, but through an intermediate step. // We prepare the necessary precursor bitmaps now std::map precursors; - create_precursor_bitmaps (view_ops_in, pbitmaps_in, ls, width, height, precursors, mutex); + create_precursor_bitmaps (view_ops_in, vo_map, pbitmaps_in, bm_map, ls, width, height, precursors, mutex); std::vector view_ops; std::vector pbitmaps; @@ -489,12 +498,13 @@ bitmaps_to_image_rgb (const std::vector &view_ops_in, unsigned int w = vop.width (); const lay::Bitmap *pb = 0; + unsigned int bm_index = bm_map[i]; if (bm_map [i] < pbitmaps_in.size ()) { if (w > 1 && ls.style (vop.line_style_index ()).width () > 0) { - tl_assert (precursors.find (i) != precursors.end ()); - pb = &precursors [i]; + tl_assert (precursors.find (bm_index) != precursors.end ()); + pb = &precursors [bm_index]; } else { - pb = pbitmaps_in [bm_map[i]]; + pb = pbitmaps_in [bm_index]; } } @@ -660,29 +670,33 @@ bitmaps_to_image_mono (const std::vector &view_ops_in, bool use_bitmap_index, QMutex *mutex) { - unsigned int n_in = (unsigned int) view_ops_in.size (); - std::vector bm_map; std::vector vo_map; - vo_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - vo_map.push_back (i); - } + vo_map.reserve (view_ops_in.size ()); + bm_map.reserve (view_ops_in.size ()); + unsigned int n_in = 0; - if (! use_bitmap_index) { - bm_map = vo_map; - } else { - bm_map.reserve (n_in); - for (unsigned int i = 0; i < n_in; ++i) { - bm_map.push_back (view_ops_in [i].bitmap_index () < 0 ? i : view_ops_in [i].bitmap_index ()); + // drop invisible and empty bitmaps, build bitmap mask + for (unsigned int i = 0; i < view_ops_in.size (); ++i) { + + const lay::ViewOp &vop = view_ops_in [i]; + + unsigned int bi = (use_bitmap_index && vop.bitmap_index () >= 0) ? (unsigned int) vop.bitmap_index () : i; + const lay::Bitmap *pb = bi < pbitmaps_in.size () ? pbitmaps_in [bi] : 0; + + if ((vop.ormask () | ~vop.andmask ()) != 0 && pb && ! pb->empty ()) { + vo_map.push_back (i); + bm_map.push_back (bi); + ++n_in; } + } // Styled lines with width > 1 are not rendered directly, but through an intermediate step. // We prepare the necessary precursor bitmaps now std::map precursors; - create_precursor_bitmaps (view_ops_in, pbitmaps_in, ls, width, height, precursors, mutex); + create_precursor_bitmaps (view_ops_in, vo_map, pbitmaps_in, bm_map, ls, width, height, precursors, mutex); std::vector view_ops; std::vector pbitmaps; @@ -722,16 +736,17 @@ bitmaps_to_image_mono (const std::vector &view_ops_in, unsigned int w = vop.width (); const lay::Bitmap *pb = 0; + unsigned int bm_index = bm_map[i]; if (bm_map [i] < pbitmaps_in.size ()) { if (w > 1 && ls.style (vop.line_style_index ()).width () > 0) { - tl_assert (precursors.find (i) != precursors.end ()); - pb = &precursors [i]; + tl_assert (precursors.find (bm_index) != precursors.end ()); + pb = &precursors [bm_index]; } else { - pb = pbitmaps_in [bm_map[i]]; + pb = pbitmaps_in [bm_index]; } } - if (pb != 0 + if (pb != 0 && w > 0 && ((pb->first_scanline () < y + slice && pb->last_scanline () > y) || w > 1) && (vop.ormask () | ~vop.andmask ()) != 0) { diff --git a/src/laybasic/laybasic/layRedrawLayerInfo.h b/src/laybasic/laybasic/layRedrawLayerInfo.h index 3befe4c33..60865b241 100644 --- a/src/laybasic/laybasic/layRedrawLayerInfo.h +++ b/src/laybasic/laybasic/layRedrawLayerInfo.h @@ -74,9 +74,10 @@ struct RedrawLayerInfo /** * @brief The layer index * - * The logical layer to draw. If this member is <0 and the cellview_index is <0, it is an invalid layer, - * which is ignored. If the cellview_index is >=0, it denotes a "cell frame" pseudo - * layer. It is set by the constructor. + * The logical layer to draw. The layer index can be <0 which indicates a + * layer with not layout source (cell_frame may be true to indicate a + * pseudo layer then). + * This attribute is set by the constructor. */ int layer_index; @@ -115,6 +116,14 @@ struct RedrawLayerInfo * This member is set by the constructor. */ bool inverse_prop_sel; + + /** + * @brief Returns true, if the layer needs to be drawn + */ + bool needs_drawing () const + { + return visible && enabled && (cell_frame || layer_index >= 0) && cellview_index >= 0; + } }; } diff --git a/src/laybasic/laybasic/layRedrawThread.cc b/src/laybasic/laybasic/layRedrawThread.cc index f71f15e00..757692ada 100644 --- a/src/laybasic/laybasic/layRedrawThread.cc +++ b/src/laybasic/laybasic/layRedrawThread.cc @@ -307,7 +307,7 @@ RedrawThread::do_start (bool clear, const db::Vector *shift_vector, const std::v } for (int i = 0; i < m_nlayers; ++i) { - if (m_layers [i].visible && m_layers [i].enabled) { + if (m_layers [i].needs_drawing ()) { schedule (new RedrawThreadTask (i)); } } diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.cc b/src/laybasic/laybasic/layRedrawThreadWorker.cc index a7d84268a..daabbdac3 100644 --- a/src/laybasic/laybasic/layRedrawThreadWorker.cc +++ b/src/laybasic/laybasic/layRedrawThreadWorker.cc @@ -1232,20 +1232,26 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c vertex = m_planes[3 + plane_group * (planes_per_layer / 3)]; // do not draw, if there is nothing to draw - if (mp_layout->cells () <= ci || vp.empty ()) { + if (mp_layout->cells () <= ci || vp.empty () || mp_layout->cell (ci).bbox (m_layer).empty ()) { return; } if (cell_var_cached (ci, trans)) { return; } + std::auto_ptr opt_bitmap; + lay::Bitmap *vertex_bitmap = dynamic_cast (vertex); + if (m_text_lazy_rendering && vertex_bitmap) { + opt_bitmap.reset (new lay::Bitmap (vertex_bitmap->width (), vertex_bitmap->height (), vertex_bitmap->resolution ())); + } + for (std::vector::const_iterator b = vp.begin (); b != vp.end (); ++b) { - draw_text_layer (drawing_context, ci, trans, *b, level, fill, frame, vertex, text); + draw_text_layer (drawing_context, ci, trans, *b, level, fill, frame, vertex, text, opt_bitmap.get ()); } } 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) +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, lay::Bitmap *opt_bitmap) { test_snapshot (0); @@ -1283,6 +1289,9 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c // paint the simplified box if (anything) { r.draw (trans * bbox, 0, frame, vertex, 0); + if (opt_bitmap) { + r.draw (trans * bbox, 0, 0, opt_bitmap, 0); + } } // do not dive further into hierarchy @@ -1318,6 +1327,9 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c test_snapshot (0); r.draw (*shape, trans, fill, frame, vertex, text); + if (opt_bitmap) { + r.draw (*shape, trans, 0, 0, opt_bitmap, 0); + } ++shape; --ntexts; @@ -1355,8 +1367,6 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c // dive down into the hierarchy .. if (need_to_dive) { - const lay::Bitmap *vertex_bitmap = dynamic_cast (vertex); - // create a set of boxes to look into std::vector vv = search_regions (cell_bbox, vp, level); @@ -1377,7 +1387,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c bool skip = false; if (m_text_lazy_rendering && qid != current_quad_id) { current_quad_id = qid; - skip = vertex_bitmap && skip_quad (inst.quad_box () & bbox, vertex_bitmap, trans); + skip = opt_bitmap && skip_quad (inst.quad_box () & bbox, opt_bitmap, trans); } if (skip) { @@ -1448,7 +1458,7 @@ RedrawThreadWorker::draw_text_layer (bool drawing_context, db::cell_index_type c db::ICplxTrans t (cell_inst.complex_trans (*p)); db::Box new_vp = db::Box (t.inverted () * *v); - draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text); + draw_text_layer (drawing_context, new_ci, trans * t, new_vp, level + 1, fill, frame, vertex, text, opt_bitmap); } @@ -1648,7 +1658,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_ // skip this quad if we have drawn something here already size_t qid = inst.quad_id (); bool skip = false; - if (m_text_lazy_rendering && qid != current_quad_id) { + if (qid != current_quad_id) { current_quad_id = qid; skip = skip_quad (inst.quad_box () & bbox, vertex_bitmap, trans); } diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.h b/src/laybasic/laybasic/layRedrawThreadWorker.h index 0b49a44d3..ea2a90a11 100644 --- a/src/laybasic/laybasic/layRedrawThreadWorker.h +++ b/src/laybasic/laybasic/layRedrawThreadWorker.h @@ -180,7 +180,7 @@ private: void draw_layer (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_box, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot); void draw_layer_wo_cache (int from_level, int to_level, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &vv, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text, const UpdateSnapshotCallback *update_snapshot); void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level); - void draw_text_layer (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level, lay::CanvasPlane *fill, lay::CanvasPlane *frame, lay::CanvasPlane *vertex, lay::CanvasPlane *text); + void draw_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, Bitmap *opt_bitmap); void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level); void draw_boxes (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const db::Box &redraw_region, int level); void draw_box_properties (bool drawing_context, db::cell_index_type ci, const db::CplxTrans &trans, const std::vector &redraw_regions, int level);