This commit is contained in:
bubnikv 2019-04-08 12:05:44 +02:00
commit 9bc93134f9
471 changed files with 12650 additions and 125974 deletions

View File

@ -34,6 +34,8 @@ option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
option(SLIC3R_SYNTAXONLY "Only perform source code correctness checking, no binary output (UNIX only)" 0)
set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux")
# Proposal for C++ unit tests and sandboxes
option(SLIC3R_BUILD_SANDBOXES "Build development sandboxes" OFF)
option(SLIC3R_BUILD_TESTS "Build unit tests" OFF)

View File

@ -1,26 +1,24 @@
_Q: Oh cool, a new RepRap slicer?_
A: Yes.
![Slic3rPE logo](/resources/icons/Slic3r.png?raw=true)
# Slic3r Prusa Edition
Slic3r
======
Prebuilt Windows, OSX and Linux binaries are available through the [git releases page](https://github.com/prusa3d/Slic3r/releases).
<img width=256 src=https://cloud.githubusercontent.com/assets/31754/22719818/09998c92-ed6d-11e6-9fa0-09de638f3a36.png />
Slic3r takes 3D models (STL, OBJ, AMF) and converts them into G-code instructions for
3D printers. It's compatible with any modern printer based on the RepRap toolchain,
including all those based on the Marlin, Sprinter and Repetier firmware. It also works
Slic3r takes 3D models (STL, OBJ, AMF) and converts them into G-code
instructions for FFF printers or PNG layers for mSLA 3D printers. It's
compatible with any modern printer based on the RepRap toolchain, including all
those based on the Marlin, Prusa, Sprinter and Repetier firmware. It also works
with Mach3, LinuxCNC and Machinekit controllers.
See the [project homepage](http://slic3r.org/) at slic3r.org and the
[manual](http://manual.slic3r.org/) for more information.
See the [project homepage](https://www.prusa3d.com/slic3r-prusa-edition/) and
the [documentation directory](doc/) for more information.
### What language is it written in?
The core geometric algorithms and data structures are written in C++,
and Perl is used for high-level flow abstraction, GUI and testing.
If you're wondering why Perl, see https://xkcd.com/224/
All user facing code is written in C++, and some legacy code as well as unit
tests are written in Perl. Perl is not required for either development or use
of Slic3r.
The C++ API is public and its use in other projects is encouraged.
The goal is to make Slic3r fully modular so that any part of its logic
@ -49,34 +47,23 @@ Other major features are:
* several infill patterns including honeycomb, spirals, Hilbert curves
* support material, raft, brim, skirt
* **standby temperature** and automatic wiping for multi-extruder printing
* customizable **G-code macros** and output filename with variable placeholders
* [customizable **G-code macros**](https://github.com/prusa3d/Slic3r/wiki/Slic3r-Prusa-Edition-Macro-Language) and output filename with variable placeholders
* support for **post-processing scripts**
* **cooling logic** controlling fan speed and dynamic print speed
### How to install?
### Development
You can download a precompiled package from [slic3r.org](http://slic3r.org/);
it will run without the need for any dependency.
If you want to compile the source yourself follow the instructions on one of these wiki pages:
* [Linux](https://github.com/alexrj/Slic3r/wiki/Running-Slic3r-from-git-on-GNU-Linux)
* [Windows](https://github.com/prusa3d/Slic3r/wiki/How-to-compile-Slic3r-Prusa-Edition-on-MS-Windows)
* [Mac OSX](https://github.com/alexrj/Slic3r/wiki/Running-Slic3r-from-git-on-OS-X)
If you want to compile the source yourself, follow the instructions on one of
these documentation pages:
* [Linux](doc/How%20to%20build%20-%20Linux%20et%20al.md)
* [macOS](doc/How%20to%20build%20-%20Mac%20OS.md)
* [Windows](doc/How%20to%20build%20-%20Windows.md)
### Can I help?
Sure! You can do the following to find things that are available to help with:
* [Pull Request Milestone](https://github.com/alexrj/Slic3r/milestone/31)
* Please comment in the related github issue that you are working on it so that other people know.
* Items in the [TODO](https://github.com/alexrj/Slic3r/wiki/TODO) wiki page.
* Please comment in the related github issue that you are working on it so that other people know.
* Drop me a line at aar@cpan.org.
* You can also find me (rarely) in #reprap and in #slic3r on [FreeNode](https://webchat.freenode.net) with the nickname _Sound_. Another contributor, _LoH_, is also in both channels.
* Add an [issue](https://github.com/alexrj/Slic3r/issues) to the github tracker if it isn't already present.
Before sending patches and pull requests contact me (preferably through opening a github issue or commenting on an existing, related, issue) to discuss your proposed
changes: this way we'll ensure nobody wastes their time and no conflicts arise
in development.
* Add an [issue](https://github.com/prusa3d/Slic3r/issues) to the github tracker if it isn't already present.
* Look at [issues labeled "volunteer needed"](https://github.com/prusa3d/Slic3r/issues?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3A%22volunteer+needed%22)
### What's Slic3r license?

23
deps/CMakeLists.txt vendored
View File

@ -32,6 +32,7 @@ if (NPROC EQUAL 0)
endif ()
set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir" CACHE PATH "Destination directory")
option(DEP_DEBUG "Build debug variants (only applicable on Windows)" ON)
option(DEP_WX_STABLE "Build against wxWidgets stable 3.0 as opposed to default 3.1 (Linux only)" OFF)
@ -73,7 +74,9 @@ else ()
include("deps-linux.cmake")
endif()
add_custom_target(deps ALL
if (MSVC)
add_custom_target(deps ALL
DEPENDS
dep_boost
dep_tbb
@ -81,8 +84,22 @@ add_custom_target(deps ALL
dep_wxwidgets
dep_gtest
dep_nlopt
dep_libpng
)
dep_zlib # on Windows we still need zlib
)
else()
add_custom_target(deps ALL
DEPENDS
dep_boost
dep_tbb
dep_libcurl
dep_wxwidgets
dep_gtest
dep_nlopt
)
endif()
# Note: I'm not using any of the LOG_xxx options in ExternalProject_Add() commands
# because they seem to generate bogus build files (possibly a bug in ExternalProject).

18
deps/deps-linux.cmake vendored
View File

@ -3,7 +3,6 @@ set(DEP_CMAKE_OPTS "-DCMAKE_POSITION_INDEPENDENT_CODE=ON")
include("deps-unix-common.cmake")
ExternalProject_Add(dep_boost
EXCLUDE_FROM_ALL 1
URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz"
@ -25,19 +24,6 @@ ExternalProject_Add(dep_boost
INSTALL_COMMAND "" # b2 does that already
)
ExternalProject_Add(dep_libpng
EXCLUDE_FROM_ALL 1
URL "https://github.com/glennrp/libpng/archive/v1.6.36.tar.gz"
URL_HASH SHA256=5bef5a850a9255365a2dc344671b7e9ef810de491bd479c2506ac3c337e2d84f
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
CMAKE_ARGS
-DPNG_SHARED=OFF
-DPNG_TESTS=OFF
${DEP_CMAKE_OPTS}
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
INSTALL_COMMAND ""
)
ExternalProject_Add(dep_libopenssl
EXCLUDE_FROM_ALL 1
URL "https://github.com/openssl/openssl/archive/OpenSSL_1_1_0g.tar.gz"
@ -55,7 +41,7 @@ ExternalProject_Add(dep_libopenssl
ExternalProject_Add(dep_libcurl
EXCLUDE_FROM_ALL 1
DEPENDS dep_libopenssl
DEPENDS dep_libopenssl
URL "https://curl.haxx.se/download/curl-7.58.0.tar.gz"
URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115
BUILD_IN_SOURCE 1
@ -127,7 +113,7 @@ ExternalProject_Add(dep_wxwidgets
--with-libxpm=builtin
--with-libjpeg=builtin
--with-libtiff=builtin
--with-zlib=builtin
--with-zlib
--with-expat=builtin
--disable-precomp-headers
--enable-debug_info

16
deps/deps-macos.cmake vendored
View File

@ -87,20 +87,6 @@ ExternalProject_Add(dep_libcurl
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
)
ExternalProject_Add(dep_libpng
EXCLUDE_FROM_ALL 1
URL "https://github.com/glennrp/libpng/archive/v1.6.36.tar.gz"
URL_HASH SHA256=5bef5a850a9255365a2dc344671b7e9ef810de491bd479c2506ac3c337e2d84f
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
CMAKE_ARGS
-DPNG_SHARED=OFF
-DPNG_TESTS=OFF
${DEP_CMAKE_OPTS}
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
INSTALL_COMMAND ""
)
ExternalProject_Add(dep_wxwidgets
EXCLUDE_FROM_ALL 1
URL "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.2/wxWidgets-3.1.2.tar.bz2"
@ -119,7 +105,7 @@ ExternalProject_Add(dep_wxwidgets
--with-libxpm=builtin
--with-libjpeg=builtin
--with-libtiff=builtin
--with-zlib=builtin
--with-zlib
--with-expat=builtin
--disable-debug
--disable-debug_flag

View File

@ -8,30 +8,27 @@ ExternalProject_Add(dep_tbb
CMAKE_ARGS
-DTBB_BUILD_SHARED=OFF
-DTBB_BUILD_TESTS=OFF
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
${DEP_CMAKE_OPTS}
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
)
ExternalProject_Add(dep_gtest
EXCLUDE_FROM_ALL 1
URL "https://github.com/google/googletest/archive/release-1.8.1.tar.gz"
URL_HASH SHA256=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c
CMAKE_ARGS -DBUILD_GMOCK=OFF ${DEP_CMAKE_OPTS}
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
CMAKE_ARGS -DBUILD_GMOCK=OFF ${DEP_CMAKE_OPTS} -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
)
ExternalProject_Add(dep_nlopt
EXCLUDE_FROM_ALL 1
URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz"
URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
CMAKE_ARGS
-DBUILD_SHARED_LIBS=OFF
-DNLOPT_PYTHON=OFF
-DNLOPT_OCTAVE=OFF
-DNLOPT_MATLAB=OFF
-DNLOPT_GUILE=OFF
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
${DEP_CMAKE_OPTS}
INSTALL_COMMAND make install "DESTDIR=${DESTDIR}"
INSTALL_COMMAND ""
)

View File

@ -62,7 +62,7 @@ ExternalProject_Add(dep_tbb
-DTBB_BUILD_SHARED=OFF
-DTBB_BUILD_TESTS=OFF
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
INSTALL_COMMAND ""
)
if (${DEP_DEBUG})
@ -70,7 +70,7 @@ if (${DEP_DEBUG})
ExternalProject_Add_Step(dep_tbb build_debug
DEPENDEES build
DEPENDERS install
COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
WORKING_DIRECTORY "${BINARY_DIR}"
)
endif ()
@ -86,7 +86,7 @@ ExternalProject_Add(dep_gtest
-Dgtest_force_shared_crt=ON
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
INSTALL_COMMAND ""
)
if (${DEP_DEBUG})
@ -94,7 +94,7 @@ if (${DEP_DEBUG})
ExternalProject_Add_Step(dep_gtest build_debug
DEPENDEES build
DEPENDERS install
COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
WORKING_DIRECTORY "${BINARY_DIR}"
)
endif ()
@ -114,7 +114,7 @@ ExternalProject_Add(dep_nlopt
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DCMAKE_DEBUG_POSTFIX=d
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
INSTALL_COMMAND ""
)
if (${DEP_DEBUG})
@ -122,7 +122,7 @@ if (${DEP_DEBUG})
ExternalProject_Add_Step(dep_nlopt build_debug
DEPENDEES build
DEPENDERS install
COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
WORKING_DIRECTORY "${BINARY_DIR}"
)
endif ()
@ -138,7 +138,7 @@ ExternalProject_Add(dep_zlib
"-DINSTALL_BIN_DIR=${CMAKE_CURRENT_BINARY_DIR}\\fallout" # I found no better way of preventing zlib from creating & installing DLLs :-/
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
INSTALL_COMMAND ""
)
if (${DEP_DEBUG})
@ -146,7 +146,7 @@ if (${DEP_DEBUG})
ExternalProject_Add_Step(dep_zlib build_debug
DEPENDEES build
DEPENDERS install
COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
WORKING_DIRECTORY "${BINARY_DIR}"
)
endif ()
@ -165,46 +165,6 @@ if (${DEP_DEBUG})
endif ()
ExternalProject_Add(dep_libpng
DEPENDS dep_zlib
EXCLUDE_FROM_ALL 1
URL "https://github.com/glennrp/libpng/archive/v1.6.36.tar.gz"
URL_HASH SHA256=5bef5a850a9255365a2dc344671b7e9ef810de491bd479c2506ac3c337e2d84f
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
CMAKE_ARGS
-DPNG_SHARED=OFF
-DPNG_TESTS=OFF
-DSKIP_INSTALL_FILES=ON # Prevent installation of man pages et al.
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
INSTALL_COMMAND ""
)
if (${DEP_DEBUG})
ExternalProject_Get_Property(dep_libpng BINARY_DIR)
ExternalProject_Add_Step(dep_libpng build_debug
DEPENDEES build
DEPENDERS install
COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj
WORKING_DIRECTORY "${BINARY_DIR}"
)
endif ()
# The following steps are unfortunately needed to remove the _static suffix on libraries
# (And also overwrite the dynamic .lib)
ExternalProject_Add_Step(dep_libpng fix_static
DEPENDEES install
COMMAND "${CMAKE_COMMAND}" -E rename libpng16_static.lib libpng16.lib
WORKING_DIRECTORY "${DESTDIR}\\usr\\local\\lib\\"
)
if (${DEP_DEBUG})
ExternalProject_Add_Step(dep_libpng fix_static_debug
DEPENDEES install
COMMAND "${CMAKE_COMMAND}" -E rename libpng16_staticd.lib libpng16d.lib
WORKING_DIRECTORY "${DESTDIR}\\usr\\local\\lib\\"
)
endif ()
if (${DEPS_BITS} EQUAL 32)
set(DEP_LIBCURL_TARGET "x86")
else ()

View File

@ -58,11 +58,20 @@ Note that Slic3r PE is tested with wxWidgets 3.0 somewhat sporadically and so th
### Build variant
By default Scli3r builds the release variant.
By default Slic3r builds the release variant.
To create a debug build, use the following CMake flag:
-DCMAKE_BUILD_TYPE=Debug
### Enabling address sanitizer
If you're using GCC/Clang compiler, it is possible to build Slic3r with the built-in address sanitizer enabled to help detect memory-corruption issues.
To enable it, simply use the following CMake flag:
-DSLIC3R_ASAN=1
This requires GCC>4.8 or Clang>3.1.
### Installation
At runtime, Slic3r needs a way to access its resource files. By default, it looks for a `resources` directory relative to its binary.

View File

@ -12,7 +12,7 @@ _Note:_ Thanks to [**@supermerill**](https://github.com/supermerill) for testing
### Dependencies
On Windows Slic3r is built against statically built libraries.
We provide a prebuilt package of all the needed dependencies.
We provide a prebuilt package of all the needed dependencies. This package only works on Visual Studio 2013, so if you are using a newer version of Visual Studio, you need to compile the dependencies yourself as per [below](#building-the-dependencies-package-yourself).
The package comes in a several variants:
- [64 bit, Release mode only](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-64.7z) (41 MB, 578 MB unpacked)
@ -28,7 +28,7 @@ Alternatively you can also compile the dependencies yourself, see below.
### Building Slic3r PE with Visual Studio
First obtain the Slic3 PE sources via either git or by extracting the source archive.
First obtain the Slic3r PE sources via either git or by extracting the source archive.
Then you will need to note down the so-called 'prefix path' to the dependencies, this is the location of the dependencies packages + `\usr\local` appended.
For example on 64 bits this would be `C:\local\destdir-64\usr\local`. The prefix path will need to be passed to CMake.
@ -66,7 +66,7 @@ There are several options for building from the command line:
To build with msbuild, use the same CMake command as in previous paragraph and then build using
msbuild /P:Configuration=Release ALL_BUILD.vcxproj
msbuild /m /P:Configuration=Release ALL_BUILD.vcxproj
To build with Ninja or nmake, replace the `-G` option in the CMake call with `-G Ninja` or `-G "NMake Makefiles"` , respectively.
Then use either `ninja` or `nmake` to start the build.
@ -84,15 +84,26 @@ Then `cd` into the `deps` directory and use these commands to build:
mkdir build
cd build
cmake .. -G "Visual Studio 12 Win64" -DDESTDIR="C:\local\destdir-custom"
msbuild ALL_BUILD.vcxproj
msbuild /m ALL_BUILD.vcxproj
You can also use the Visual Studio GUI or other generators as mentioned above.
The `DESTDIR` option is the location where the bundle will be installed.
This may be customized. If you leave it empty, the `DESTDIR` will be places inside the same `build` directory.
This may be customized. If you leave it empty, the `DESTDIR` will be placed inside the same `build` directory.
Warning: If the `build` directory is nested too deep inside other folders, various file paths during the build
become too long and the build might fail due to file writing errors (\*). For this reason, it is recommended to
place the `build` directory relatively close to the drive root.
Note that the build variant that you may choose using Visual Studio (i.e. _Release_ or _Debug_ etc.) when building the dependency package is **not relevant**.
The dependency build will by default build _both_ the _Release_ and _Debug_ variants regardless of what you choose in Visual Studio.
You can disable building of the debug variant by passing the `-DDEP_DEBUG=OFF` option to CMake, this will only produce a _Release_ build.
You can disable building of the debug variant by passing the
-DDEP_DEBUG=OFF
option to CMake, this will only produce a _Release_ build.
Refer to the CMake scripts inside the `deps` directory to see which dependencies are built in what versions and how this is done.
\*) Specifically, the problem arises when building boost. Boost build tool appends all build options into paths of
intermediate files, which are not handled correctly by either `b2.exe` or possibly `ninja` (?).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 790 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

17
resources/icons/cog.svg Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="machine_x2B_cog">
<path fill="#808080" d="M13.77,6.39c-0.13-0.47-0.32-0.92-0.55-1.33l0.43-1.3l-1.41-1.41l-1.3,0.43c-0.42-0.23-0.86-0.42-1.33-0.55
L9,1H7L6.39,2.23C5.92,2.36,5.47,2.54,5.06,2.78l-1.3-0.43L2.34,3.76l0.43,1.3C2.54,5.47,2.36,5.92,2.23,6.39L1,7v2l1.23,0.61
c0.13,0.47,0.32,0.92,0.55,1.33l-0.43,1.3l1.41,1.41l1.3-0.43c0.42,0.23,0.86,0.42,1.33,0.55L7,15h2l0.61-1.23
c0.47-0.13,0.92-0.32,1.33-0.55l1.3,0.43l1.41-1.41l-0.43-1.3c0.23-0.42,0.42-0.86,0.55-1.33L15,9V7L13.77,6.39z M8,13
c-2.76,0-5-2.24-5-5s2.24-5,5-5s5,2.24,5,5S10.76,13,8,13z"/>
<path fill="#ED6B21" d="M11.3,7.08c-0.07-0.27-0.18-0.52-0.31-0.76l0.25-0.74l-0.81-0.81L9.68,5.01C9.45,4.88,9.19,4.78,8.92,4.7
L8.57,4H7.43L7.08,4.7C6.81,4.78,6.55,4.88,6.32,5.01L5.58,4.77L4.77,5.58l0.25,0.74C4.88,6.55,4.78,6.81,4.7,7.08L4,7.43v1.14
l0.7,0.35c0.07,0.27,0.18,0.52,0.31,0.76l-0.25,0.74l0.81,0.81l0.74-0.25c0.24,0.13,0.49,0.24,0.76,0.31L7.43,12h1.14l0.35-0.7
c0.27-0.07,0.52-0.18,0.76-0.31l0.74,0.25l0.81-0.81l-0.25-0.74c0.13-0.24,0.24-0.49,0.31-0.76L12,8.57V7.43L11.3,7.08z M8,10.86
c-1.58,0-2.86-1.28-2.86-2.86S6.42,5.14,8,5.14S10.86,6.42,10.86,8S9.58,10.86,8,10.86z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="cooling">
<path fill="#808080" d="M14,1H2C1.45,1,1,1.45,1,2v12c0,0.55,0.45,1,1,1h12c0.55,0,1-0.45,1-1V2C15,1.45,14.55,1,14,1z M8,14
c-3.31,0-6-2.69-6-6s2.69-6,6-6s6,2.69,6,6S11.31,14,8,14z"/>
<g>
<path fill="#ED6B21" d="M7.86,7.14C7.94,7.41,8,7.7,8,8c0,1.66-1.34,3-3,3c-0.3,0-0.59-0.06-0.86-0.14C4.51,12.09,5.64,13,7,13
c1.66,0,3-1.34,3-3C10,8.64,9.09,7.51,7.86,7.14z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,8C6.34,8,5,6.66,5,5c0-0.3,0.06-0.59,0.14-0.86C3.91,4.51,3,5.64,3,7c0,1.66,1.34,3,3,3
c1.36,0,2.49-0.91,2.86-2.14C8.59,7.94,8.3,8,8,8z"/>
</g>
<g>
<path fill="#ED6B21" d="M10,6C8.64,6,7.51,6.91,7.14,8.14C7.41,8.06,7.7,8,8,8c1.66,0,3,1.34,3,3c0,0.3-0.06,0.59-0.14,0.86
C12.09,11.49,13,10.36,13,9C13,7.34,11.66,6,10,6z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,8c0-1.66,1.34-3,3-3c0.3,0,0.59,0.06,0.86,0.14C11.49,3.91,10.36,3,9,3C7.34,3,6,4.34,6,6
c0,1.36,0.91,2.49,2.14,2.86C8.06,8.59,8,8.3,8,8z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="extruder_x2B_funnel">
<rect x="1" y="1" display="none" fill="#808080" width="14" height="6"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="9.37" x2="8" y2="15"/>
<polygon display="none" fill="#808080" points="5,7 5,8 8,10 11,8 11,7 "/>
<g>
<path fill="#808080" d="M14,2l0,4h-3c-0.55,0-1,0.45-1,1v0.47L8,8.8L6,7.46V7c0-0.55-0.45-1-1-1L2,6l0-4H14 M14,1H2
C1.45,1,1,1.45,1,2v4c0,0.55,0.45,1,1,1h3v1l2.45,1.63C7.61,9.74,7.81,9.8,8,9.8c0.19,0,0.39-0.06,0.55-0.17L11,8V7h3
c0.55,0,1-0.45,1-1V2C15,1.45,14.55,1,14,1L14,1z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 941 B

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="infill">
<g>
<defs>
<polygon id="SVGID_1_" points="8,1.03 2,5.03 2,7.03 2,11.03 8,15.03 14,11.03 14,7.03 14,5.03 "/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" overflow="visible"/>
</clipPath>
<g clip-path="url(#SVGID_2_)">
<line fill="none" stroke="#ED6B21" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2.32" y1="11.59" x2="8.56" y2="1.34"/>
<line fill="none" stroke="#ED6B21" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="4.88" y1="13.15" x2="11.12" y2="2.9"/>
<line fill="none" stroke="#ED6B21" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.44" y1="14.71" x2="13.68" y2="4.46"/>
<line fill="none" stroke="#ED6B21" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="4.44" y1="2.34" x2="14.68" y2="8.59"/>
<line fill="none" stroke="#ED6B21" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2.88" y1="4.91" x2="13.12" y2="11.15"/>
<line fill="none" stroke="#ED6B21" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="1.32" y1="7.47" x2="11.56" y2="13.71"/>
</g>
</g>
<g>
<path fill="#808080" d="M8,2.23l5,3.33v1.46v3.46l-5,3.33l-5-3.33V7.03V5.56L8,2.23 M8,1.03l-6,4v2v4l6,4l6-4v-4v-2L8,1.03L8,1.03
z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,25 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g>
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="layers">
<g>
<rect x="7.98" y="105" fill="#FFFFFF" width="112.04" height="15"/>
</g>
<g>
<rect x="7.98" y="85.67" fill="#FFFFFF" width="112.04" height="13"/>
</g>
<g>
<rect x="7.98" y="66.33" fill="#FFFFFF" width="112.04" height="11"/>
</g>
<g>
<rect x="7.98" y="47" fill="#ED6B21" width="112.04" height="9"/>
</g>
<g>
<rect x="7.98" y="27.67" fill="#ED6B21" width="112.04" height="7"/>
</g>
<g>
<rect x="7.98" y="8.33" fill="#ED6B21" width="112.04" height="5"/>
<g>
<rect x="1" y="13" fill="#FFFFFF" width="14" height="2"/>
</g>
<g>
<rect x="1" y="10.6" fill="#FFFFFF" width="14" height="1.74"/>
</g>
<g>
<rect x="1" y="8.19" fill="#FFFFFF" width="14" height="1.47"/>
</g>
<g>
<rect x="1" y="5.79" fill="#ED6B21" width="14" height="1.2"/>
</g>
<g>
<rect x="1" y="3.39" fill="#ED6B21" width="14" height="0.93"/>
</g>
<g>
<rect x="1" y="0.99" fill="#FFFFFF" width="14" height="0.67"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 841 B

After

Width:  |  Height:  |  Size: 845 B

25
resources/icons/note.svg Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="notes">
<g>
<path fill="#808080" d="M11,2l0,12l-9,0L2,2H11 M11,1H2C1.45,1,1,1.45,1,2V14c0,0.55,0.45,1,1,1H11c0.55,0,1-0.45,1-1V2
C12,1.45,11.55,1,11,1L11,1z"/>
</g>
<path fill="#ED6B21" d="M14,3L14,3c-0.55,0-1,0.45-1,1v10c0,0.55,0.45,1,1,1h0c0.55,0,1-0.45,1-1V4C15,3.45,14.55,3,14,3z"/>
<polygon fill="#ED6B21" points="15,4 13,4 14,1 "/>
<g>
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="4" x2="10" y2="4"/>
</g>
<g>
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="6" x2="10" y2="6"/>
</g>
<g>
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="8" x2="10" y2="8"/>
</g>
<g>
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="10" x2="7" y2="10"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="output_x2B_page_x5F_white">
<g>
<path fill="#808080" d="M14.5,10c-0.27,0-0.5,0.23-0.5,0.5v3c0,0.27-0.23,0.5-0.5,0.5h-11C2.22,14,2,13.77,2,13.5v-11
C2,2.22,2.22,2,2.5,2h11C13.77,2,14,2.22,14,2.5v3C14,5.78,14.23,6,14.5,6l0,0C14.77,6,15,5.78,15,5.5v-4C15,1.23,14.77,1,14.5,1
h-13C1.23,1,1,1.23,1,1.5v13C1,14.77,1.23,15,1.5,15h13c0.27,0,0.5-0.23,0.5-0.5v-4C15,10.23,14.77,10,14.5,10L14.5,10z"/>
</g>
<path fill="#808080" d="M11,10h-0.04c-0.39,0.57-0.94,1.04-1.63,1.32c-1.83,0.73-3.91-0.16-4.64-1.99s0.16-3.91,1.99-4.64
C8.26,4.05,10.03,4.64,10.96,6H11V4.99c-0.11-0.11-0.2-0.23-0.32-0.33l-0.06-0.98L9.31,3.12L8.57,3.75
C8.23,3.71,7.88,3.7,7.54,3.74L6.81,3.09L5.48,3.62L5.4,4.6C5.12,4.81,4.87,5.05,4.66,5.32L3.69,5.37L3.12,6.69l0.63,0.75
C3.71,7.77,3.7,8.12,3.74,8.46L3.09,9.19l0.53,1.33L4.6,10.6c0.21,0.28,0.45,0.52,0.72,0.74l0.06,0.98l1.31,0.56l0.75-0.63
c0.34,0.05,0.68,0.05,1.03,0.01l0.73,0.65l1.33-0.53l0.08-0.98c0.15-0.11,0.27-0.26,0.4-0.39V10z"/>
<g>
<path fill="#ED6B21" d="M14.65,8.35c0.19-0.19,0.19-0.51,0-0.71l-2.29-2.29C12.16,5.16,12,5.22,12,5.5v1C12,6.78,11.77,7,11.5,7
h-3C8.23,7,8,7.22,8,7.5v1C8,8.77,8.23,9,8.5,9h3C11.77,9,12,9.23,12,9.5v1c0,0.27,0.16,0.34,0.35,0.15L14.65,8.35z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="printer">
<rect x="1" y="1" fill="#808080" width="1" height="14"/>
<rect x="14" y="1" fill="#808080" width="1" height="14"/>
<rect x="7.5" y="-1.5" transform="matrix(-1.836970e-16 1 -1 -1.836970e-16 13.5 -2.5)" fill="#808080" width="1" height="14"/>
<rect x="7.5" y="-5.5" transform="matrix(-1.836970e-16 1 -1 -1.836970e-16 9.5 -6.5)" fill="#808080" width="1" height="14"/>
<rect x="7" y="7" transform="matrix(-1.836970e-16 1 -1 -1.836970e-16 22 6)" fill="#808080" width="2" height="14"/>
<rect x="3" y="4" fill="#ED6B21" width="4" height="4"/>
<polygon fill="#ED6B21" points="5,9 4,8 6,8 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 958 B

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="skirt_x2B_brim">
<g id="skirt_x2B_brim_-_box">
<g>
<path fill="#808080" d="M8,3.26L12.12,6v1.17v2.88L8,12.8l-4.12-2.74V7.17V6L8,3.26 M8,2.06L2.88,5.47v1.71v3.41L8,14l5.12-3.41
V7.17V5.47L8,2.06L8,2.06z"/>
</g>
</g>
<g id="skirt_x2B_brim_-_box_1_">
<g>
<path fill="#ED6B21" d="M8,1.63l5.5,3.67v1.73v3.73L8,14.43l-5.5-3.67V7.03V5.3L8,1.63 M8,1.03l-6,4v2v4l6,4l6-4v-4v-2L8,1.03
L8,1.03z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 780 B

21
resources/icons/spool.svg Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="spool">
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="2" x2="2" y2="14"/>
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="14" y1="2" x2="14" y2="14"/>
<line fill="none" stroke="#ED6B21" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="3" x2="4" y2="13"/>
<line fill="none" stroke="#ED6B21" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="6" y1="3" x2="6" y2="13"/>
<line fill="none" stroke="#ED6B21" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="3" x2="8" y2="13"/>
<line fill="none" stroke="#ED6B21" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="10" y1="3" x2="10" y2="13"/>
<line fill="none" stroke="#ED6B21" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="12" y1="3" x2="12" y2="13"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="support">
<polygon fill="none" stroke="#808080" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="8,1
2.31,4.79 2.31,8.57 2.31,8.79 2.31,10.47 8,14.25 13.69,10.47 13.69,8.79 13.69,8.57 13.69,4.79 "/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="12.69" y1="15" x2="12.69" y2="12.44"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="13.87" y1="15" x2="13.87" y2="11.64"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2.13" y1="15" x2="2.13" y2="11.64"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.33" y1="15" x2="3.33" y2="12.44"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="4.51" y1="15" x2="4.51" y2="13.22"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="5.66" y1="15" x2="5.66" y2="14"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="10.34" y1="15" x2="10.34" y2="14"/>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="11.5" y1="15" x2="11.5" y2="13.22"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

16
resources/icons/time.svg Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="time">
<g>
<path fill="#808080" d="M8,2c3.31,0,6,2.69,6,6s-2.69,6-6,6s-6-2.69-6-6S4.69,2,8,2 M8,1C4.13,1,1,4.13,1,8s3.13,7,7,7s7-3.13,7-7
S11.87,1,8,1L8,1z"/>
</g>
<g>
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-miterlimit="10" x1="5" y1="4" x2="8" y2="8"/>
</g>
<line fill="none" stroke="#ED6B21" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="11.5" y1="8" x2="8" y2="8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 789 B

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="advanced_x2B_wrench">
<path fill="#808080" d="M7.39,3.69C7.32,3.46,7.23,3.24,7.11,3.03l0.22-0.65L6.62,1.67L5.97,1.89C5.76,1.77,5.54,1.68,5.31,1.61
L5,1H4L3.69,1.61C3.46,1.68,3.24,1.77,3.03,1.89L2.38,1.67L1.67,2.38l0.22,0.65C1.77,3.24,1.68,3.46,1.61,3.69L1,4v1l0.61,0.31
c0.07,0.23,0.16,0.46,0.27,0.67L1.67,6.62l0.71,0.71l0.65-0.22c0.21,0.12,0.43,0.21,0.67,0.28L4,8h1l0.31-0.61
c0.23-0.07,0.46-0.16,0.67-0.28l0.65,0.22l0.71-0.71L7.11,5.97c0.12-0.21,0.21-0.43,0.27-0.67L8,5V4L7.39,3.69z"/>
<path fill="#808080" d="M12.4,2.49c-0.05-0.17-0.11-0.33-0.2-0.48l0.15-0.46l-0.51-0.51L11.39,1.2c-0.15-0.08-0.31-0.15-0.48-0.2
l-0.22-0.44H9.98L9.76,1C9.59,1.05,9.43,1.11,9.28,1.2L8.82,1.04L8.31,1.55l0.15,0.46c-0.08,0.15-0.15,0.31-0.2,0.48L7.83,2.71
v0.71l0.44,0.22c0.05,0.17,0.11,0.33,0.2,0.48L8.31,4.58l0.51,0.51l0.46-0.15c0.15,0.08,0.31,0.15,0.48,0.2l0.22,0.44h0.71
l0.22-0.44c0.17-0.05,0.33-0.11,0.48-0.2l0.46,0.15l0.51-0.51L12.2,4.12c0.08-0.15,0.15-0.31,0.2-0.48l0.44-0.22V2.71L12.4,2.49z"
/>
<path fill="#ED6B21" d="M14.36,10.66c0.04-0.34,0.04-0.68,0-1.02L15,8.91L14.46,7.6l-0.97-0.07c-0.21-0.27-0.45-0.51-0.72-0.72
L12.7,5.84L11.39,5.3l-0.73,0.64c-0.34-0.04-0.68-0.04-1.02,0L8.91,5.3L7.6,5.84L7.53,6.81C7.26,7.02,7.02,7.26,6.81,7.53L5.84,7.6
L5.3,8.91l0.64,0.73c-0.04,0.34-0.04,0.68,0,1.02L5.3,11.39l0.54,1.31l0.97,0.07c0.21,0.27,0.45,0.51,0.72,0.72l0.07,0.97L8.91,15
l0.73-0.64c0.34,0.04,0.68,0.04,1.02,0L11.39,15l1.31-0.54l0.07-0.97c0.27-0.21,0.51-0.45,0.72-0.72l0.97-0.07L15,11.39
L14.36,10.66z"/>
<circle fill="#FFFFFF" cx="4.5" cy="4.5" r="1.92"/>
<circle fill="#FFFFFF" cx="10.33" cy="3.06" r="1.11"/>
<circle fill="#FFFFFF" cx="10.15" cy="10.15" r="2.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -21,30 +21,6 @@ add_subdirectory(libnest2d)
include_directories(${LIBDIR}/qhull/src)
#message(STATUS ${LIBDIR}/qhull/src)
# ##############################################################################
# Configure rasterizer target
# ##############################################################################
find_package(PNG QUIET)
option(RASTERIZER_FORCE_BUILTIN_LIBPNG "Force the usage of builting libpng instead of the system version." OFF)
if(PNG_FOUND AND NOT RASTERIZER_FORCE_BUILTIN_LIBPNG)
message(STATUS "Using system libpng.")
else()
set(ZLIB_LIBRARY "")
message(WARNING "Using builtin libpng. This can cause crashes on some platforms.")
set(SKIP_INSTALL_ALL 1) # Prevent png+zlib from creating install targets
add_subdirectory(png/zlib)
set(ZLIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/png/zlib ${CMAKE_CURRENT_BINARY_DIR}/png/zlib)
include_directories(${ZLIB_INCLUDE_DIR})
add_subdirectory(png/libpng)
set_target_properties(zlibstatic PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(png_static PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(PNG_LIBRARIES png_static zlibstatic)
set(PNG_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/png/libpng ${CMAKE_CURRENT_BINARY_DIR}/png/libpng)
endif()
add_subdirectory(libslic3r)
if (SLIC3R_GUI)
@ -60,10 +36,12 @@ if (SLIC3R_GUI)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set (wxWidgets_CONFIG_OPTIONS "--toolkit=gtk${SLIC3R_GTK}")
if (SLIC3R_WX_STABLE)
find_package(wxWidgets 3.0 REQUIRED COMPONENTS base core adv html gl)
else ()
find_package(wxWidgets 3.1 QUIET COMPONENTS base core adv html gl)
if (NOT wxWidgets_FOUND)
message(FATAL_ERROR "\nCould not find wxWidgets 3.1.\n"
"Hint: On Linux you can set -DSLIC3R_WX_STABLE=1 to use wxWidgets 3.0\n")
@ -115,12 +93,16 @@ endif ()
# Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries.
if (SLIC3R_GUI)
target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES})
target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES})
# Configure libcurl & OpenSSL
# Configure libcurl and its dependencies OpenSSL & zlib
find_package(CURL REQUIRED)
if (NOT MSVC)
# Required by libcurl
find_package(ZLIB REQUIRED)
endif()
target_include_directories(slic3r PRIVATE ${CURL_INCLUDE_DIRS})
target_link_libraries(slic3r CURL::libcurl)
target_link_libraries(slic3r ${CURL_LIBRARIES} ${ZLIB_LIBRARIES})
if (SLIC3R_STATIC)
if (NOT APPLE)
# libcurl is always linked dynamically to the system libcurl on OSX.
@ -155,7 +137,7 @@ if (MSVC)
add_executable(slic3r_app_gui WIN32 slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
add_dependencies(slic3r_app_gui slic3r)
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r")
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r" PDB_NAME "slic3r_gui")
add_executable(slic3r_app_console slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
@ -188,7 +170,7 @@ if (MSVC)
)
endif ()
elseif (XCODE)
# Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level
# Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level
add_custom_command(TARGET slic3r POST_BUILD
COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/resources"
COMMENT "Symlinking the resources directory into the build tree"

View File

@ -39,8 +39,7 @@ static void stl_record_neighbors(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b);
static void stl_initialize_facet_check_exact(stl_file *stl);
static void stl_initialize_facet_check_nearby(stl_file *stl);
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b);
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b);
static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b, float tolerance);
static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
@ -60,41 +59,40 @@ extern int stl_check_normal_vector(stl_file *stl,
int facet_num, int normal_fix_flag);
static void stl_update_connects_remove_1(stl_file *stl, int facet_num);
void
stl_check_facets_exact(stl_file *stl) {
/* This function builds the neighbors list. No modifications are made
* to any of the facets. The edges are said to match only if all six
* floats of the first edge matches all six floats of the second edge.
*/
stl_hash_edge edge;
stl_facet facet;
int i;
int j;
if (stl->error) return;
// This function builds the neighbors list. No modifications are made
// to any of the facets. The edges are said to match only if all six
// floats of the first edge matches all six floats of the second edge.
void stl_check_facets_exact(stl_file *stl)
{
if (stl->error)
return;
stl->stats.connected_edges = 0;
stl->stats.connected_facets_1_edge = 0;
stl->stats.connected_facets_2_edge = 0;
stl->stats.connected_facets_3_edge = 0;
stl_initialize_facet_check_exact(stl);
// If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
// Do it before the next step, as the next step stores references to the face indices in the hash tables and removing a facet
// will break the references.
for (int i = 0; i < stl->stats.number_of_facets;) {
stl_facet &facet = stl->facet_start[i];
if (facet.vertex[0] == facet.vertex[1] || facet.vertex[1] == facet.vertex[2] || facet.vertex[0] == facet.vertex[2]) {
// Remove the degenerate facet.
facet = stl->facet_start[--stl->stats.number_of_facets];
stl->stats.facets_removed += 1;
stl->stats.degenerate_facets += 1;
} else
++ i;
}
for(i = 0; i < stl->stats.number_of_facets; i++) {
facet = stl->facet_start[i];
// If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
if (facet.vertex[0] == facet.vertex[1] ||
facet.vertex[1] == facet.vertex[2] ||
facet.vertex[0] == facet.vertex[2]) {
stl->stats.degenerate_facets += 1;
stl_remove_facet(stl, i);
-- i;
continue;
}
for(j = 0; j < 3; j++) {
edge.facet_number = i;
// Connect neighbor edges.
stl_initialize_facet_check_exact(stl);
for (int i = 0; i < stl->stats.number_of_facets; i++) {
const stl_facet &facet = stl->facet_start[i];
for (int j = 0; j < 3; j++) {
stl_hash_edge edge;
edge.facet_number = i;
edge.which_edge = j;
stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
insert_hash_edge(stl, edge, stl_record_neighbors);
@ -109,9 +107,7 @@ stl_check_facets_exact(stl_file *stl) {
#endif
}
static void
stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
stl_vertex *a, stl_vertex *b) {
static void stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, const stl_vertex *a, const stl_vertex *b) {
if (stl->error) return;
@ -333,7 +329,9 @@ static void stl_free_edges(stl_file *stl)
}
}
free(stl->heads);
stl->heads = nullptr;
free(stl->tail);
stl->tail = nullptr;
}
static void stl_initialize_facet_check_nearby(stl_file *stl)

View File

@ -127,7 +127,6 @@ typedef struct {
typedef struct {
FILE *fp;
stl_facet *facet_start;
stl_edge *edge_start;
stl_hash_edge **heads;
stl_hash_edge *tail;
int M;
@ -142,7 +141,6 @@ typedef struct {
extern void stl_open(stl_file *stl, const char *file);
extern void stl_close(stl_file *stl);
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
extern void stl_print_edges(stl_file *stl, FILE *file);
extern void stl_print_neighbors(stl_file *stl, char *file);
extern void stl_put_little_int(FILE *fp, int value_in);
extern void stl_put_little_float(FILE *fp, float value_in);

View File

@ -33,24 +33,6 @@
#define SEEK_END 2
#endif
void
stl_print_edges(stl_file *stl, FILE *file) {
int i;
int edges_allocated;
if (stl->error) return;
edges_allocated = stl->stats.number_of_facets * 3;
for(i = 0; i < edges_allocated; i++) {
fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n",
stl->edge_start[i].facet_number,
stl->edge_start[i].p1(0), stl->edge_start[i].p1(1),
stl->edge_start[i].p1(2), stl->edge_start[i].p2(0),
stl->edge_start[i].p2(1), stl->edge_start[i].p2(2));
}
}
void
stl_stats_out(stl_file *stl, FILE *file, char *input_file) {
if (stl->error) return;

View File

@ -64,6 +64,7 @@ endif()
target_include_directories(ClipperBackend INTERFACE ${Boost_INCLUDE_DIRS} )
target_sources(ClipperBackend INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/geometries.hpp
${CMAKE_CURRENT_SOURCE_DIR}/clipper_polygon.hpp
${SRC_DIR}/libnest2d/utils/boost_alg.hpp )
target_compile_definitions(ClipperBackend INTERFACE LIBNEST2D_BACKEND_CLIPPER)

View File

@ -0,0 +1,72 @@
#ifndef CLIPPER_POLYGON_HPP
#define CLIPPER_POLYGON_HPP
#include <clipper.hpp>
namespace ClipperLib {
struct Polygon {
Path Contour;
Paths Holes;
inline Polygon() = default;
inline explicit Polygon(const Path& cont): Contour(cont) {}
inline explicit Polygon(const Paths& holes):
Holes(holes) {}
inline Polygon(const Path& cont, const Paths& holes):
Contour(cont), Holes(holes) {}
inline explicit Polygon(Path&& cont): Contour(std::move(cont)) {}
inline explicit Polygon(Paths&& holes): Holes(std::move(holes)) {}
inline Polygon(Path&& cont, Paths&& holes):
Contour(std::move(cont)), Holes(std::move(holes)) {}
};
inline IntPoint& operator +=(IntPoint& p, const IntPoint& pa ) {
// This could be done with SIMD
p.X += pa.X;
p.Y += pa.Y;
return p;
}
inline IntPoint operator+(const IntPoint& p1, const IntPoint& p2) {
IntPoint ret = p1;
ret += p2;
return ret;
}
inline IntPoint& operator -=(IntPoint& p, const IntPoint& pa ) {
p.X -= pa.X;
p.Y -= pa.Y;
return p;
}
inline IntPoint operator -(IntPoint& p ) {
IntPoint ret = p;
ret.X = -ret.X;
ret.Y = -ret.Y;
return ret;
}
inline IntPoint operator-(const IntPoint& p1, const IntPoint& p2) {
IntPoint ret = p1;
ret -= p2;
return ret;
}
inline IntPoint& operator *=(IntPoint& p, const IntPoint& pa ) {
p.X *= pa.X;
p.Y *= pa.Y;
return p;
}
inline IntPoint operator*(const IntPoint& p1, const IntPoint& p2) {
IntPoint ret = p1;
ret *= p2;
return ret;
}
}
#endif // CLIPPER_POLYGON_HPP

View File

@ -10,84 +10,15 @@
#include <libnest2d/geometry_traits.hpp>
#include <libnest2d/geometry_traits_nfp.hpp>
#include <clipper.hpp>
namespace ClipperLib {
using PointImpl = IntPoint;
using PathImpl = Path;
using HoleStore = std::vector<PathImpl>;
struct PolygonImpl {
PathImpl Contour;
HoleStore Holes;
inline PolygonImpl() = default;
inline explicit PolygonImpl(const PathImpl& cont): Contour(cont) {}
inline explicit PolygonImpl(const HoleStore& holes):
Holes(holes) {}
inline PolygonImpl(const Path& cont, const HoleStore& holes):
Contour(cont), Holes(holes) {}
inline explicit PolygonImpl(PathImpl&& cont): Contour(std::move(cont)) {}
inline explicit PolygonImpl(HoleStore&& holes): Holes(std::move(holes)) {}
inline PolygonImpl(Path&& cont, HoleStore&& holes):
Contour(std::move(cont)), Holes(std::move(holes)) {}
};
inline PointImpl& operator +=(PointImpl& p, const PointImpl& pa ) {
// This could be done with SIMD
p.X += pa.X;
p.Y += pa.Y;
return p;
}
inline PointImpl operator+(const PointImpl& p1, const PointImpl& p2) {
PointImpl ret = p1;
ret += p2;
return ret;
}
inline PointImpl& operator -=(PointImpl& p, const PointImpl& pa ) {
p.X -= pa.X;
p.Y -= pa.Y;
return p;
}
inline PointImpl operator -(PointImpl& p ) {
PointImpl ret = p;
ret.X = -ret.X;
ret.Y = -ret.Y;
return ret;
}
inline PointImpl operator-(const PointImpl& p1, const PointImpl& p2) {
PointImpl ret = p1;
ret -= p2;
return ret;
}
inline PointImpl& operator *=(PointImpl& p, const PointImpl& pa ) {
p.X *= pa.X;
p.Y *= pa.Y;
return p;
}
inline PointImpl operator*(const PointImpl& p1, const PointImpl& p2) {
PointImpl ret = p1;
ret *= p2;
return ret;
}
}
#include "clipper_polygon.hpp"
namespace libnest2d {
// Aliases for convinience
using ClipperLib::PointImpl;
using ClipperLib::PathImpl;
using ClipperLib::PolygonImpl;
using ClipperLib::HoleStore;
using PointImpl = ClipperLib::IntPoint;
using PathImpl = ClipperLib::Path;
using HoleStore = ClipperLib::Paths;
using PolygonImpl = ClipperLib::Polygon;
// Type of coordinate units used by Clipper
template<> struct CoordType<PointImpl> {
@ -158,33 +89,24 @@ template<> inline TCoord<PointImpl>& y(PointImpl& p)
#define DISABLE_BOOST_AREA
namespace _smartarea {
template<Orientation o>
inline double area(const PolygonImpl& /*sh*/) {
return std::nan("");
}
template<>
inline double area<Orientation::CLOCKWISE>(const PolygonImpl& sh) {
double a = 0;
std::for_each(sh.Holes.begin(), sh.Holes.end(), [&a](const PathImpl& h)
{
a -= ClipperLib::Area(h);
inline double area<Orientation::COUNTER_CLOCKWISE>(const PolygonImpl& sh) {
return std::accumulate(sh.Holes.begin(), sh.Holes.end(),
ClipperLib::Area(sh.Contour),
[](double a, const ClipperLib::Path& pt){
return a + ClipperLib::Area(pt);
});
return -ClipperLib::Area(sh.Contour) + a;
}
template<>
inline double area<Orientation::COUNTER_CLOCKWISE>(const PolygonImpl& sh) {
double a = 0;
std::for_each(sh.Holes.begin(), sh.Holes.end(), [&a](const PathImpl& h)
{
a += ClipperLib::Area(h);
});
return ClipperLib::Area(sh.Contour) + a;
inline double area<Orientation::CLOCKWISE>(const PolygonImpl& sh) {
return -area<Orientation::COUNTER_CLOCKWISE>(sh);
}
}
@ -228,9 +150,10 @@ template<> inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance)
// but throwing would be an overkill. Instead, we should warn the
// caller about the inability to create correct geometries
if(!found_the_contour) {
sh.Contour = r;
sh.Contour = std::move(r);
ClipperLib::ReversePath(sh.Contour);
sh.Contour.push_back(sh.Contour.front());
auto front_p = sh.Contour.front();
sh.Contour.emplace_back(std::move(front_p));
found_the_contour = true;
} else {
dout() << "Warning: offsetting result is invalid!";
@ -240,9 +163,10 @@ template<> inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance)
// TODO If there are multiple contours we can't be sure which hole
// belongs to the first contour. (But in this case the situation is
// bad enough to let it go...)
sh.Holes.push_back(r);
sh.Holes.emplace_back(std::move(r));
ClipperLib::ReversePath(sh.Holes.back());
sh.Holes.back().push_back(sh.Holes.back().front());
auto front_p = sh.Holes.back().front();
sh.Holes.back().emplace_back(std::move(front_p));
}
}
}
@ -390,34 +314,53 @@ inline void rotate(PolygonImpl& sh, const Radians& rads)
} // namespace shapelike
#define DISABLE_BOOST_NFP_MERGE
inline std::vector<PolygonImpl> _merge(ClipperLib::Clipper& clipper) {
inline std::vector<PolygonImpl> clipper_execute(
ClipperLib::Clipper& clipper,
ClipperLib::ClipType clipType,
ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd,
ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd)
{
shapelike::Shapes<PolygonImpl> retv;
ClipperLib::PolyTree result;
clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftNegative);
clipper.Execute(clipType, result, subjFillType, clipFillType);
retv.reserve(static_cast<size_t>(result.Total()));
std::function<void(ClipperLib::PolyNode*, PolygonImpl&)> processHole;
auto processPoly = [&retv, &processHole](ClipperLib::PolyNode *pptr) {
PolygonImpl poly(pptr->Contour);
poly.Contour.push_back(poly.Contour.front());
PolygonImpl poly;
poly.Contour.swap(pptr->Contour);
assert(!pptr->IsHole());
if(pptr->IsOpen()) {
auto front_p = poly.Contour.front();
poly.Contour.emplace_back(front_p);
}
for(auto h : pptr->Childs) { processHole(h, poly); }
retv.push_back(poly);
};
processHole = [&processPoly](ClipperLib::PolyNode *pptr, PolygonImpl& poly)
{
poly.Holes.push_back(pptr->Contour);
poly.Holes.back().push_back(poly.Holes.back().front());
poly.Holes.emplace_back(std::move(pptr->Contour));
assert(pptr->IsHole());
if(pptr->IsOpen()) {
auto front_p = poly.Holes.back().front();
poly.Holes.back().emplace_back(front_p);
}
for(auto c : pptr->Childs) processPoly(c);
};
auto traverse = [&processPoly] (ClipperLib::PolyNode *node)
{
for(auto ch : node->Childs) {
processPoly(ch);
}
for(auto ch : node->Childs) processPoly(ch);
};
traverse(&result);
@ -438,14 +381,13 @@ merge(const std::vector<PolygonImpl>& shapes)
for(auto& path : shapes) {
valid &= clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
for(auto& hole : path.Holes) {
valid &= clipper.AddPath(hole, ClipperLib::ptSubject, closed);
}
for(auto& h : path.Holes)
valid &= clipper.AddPath(h, ClipperLib::ptSubject, closed);
}
if(!valid) throw GeometryException(GeomErr::MERGE);
return _merge(clipper);
return clipper_execute(clipper, ClipperLib::ctUnion, ClipperLib::pftNegative);
}
}

View File

@ -966,7 +966,7 @@ private:
for(size_t i = 0; i < pckgrp.size(); i++) {
auto items = pckgrp[i];
pg.push_back({});
pg.emplace_back();
pg[i].reserve(items.size());
for(Item& itemA : items) {

View File

@ -261,7 +261,7 @@ template<class RawShape> class EdgeCache {
while(next != endit) {
contour_.emap.emplace_back(*(first++), *(next++));
contour_.full_distance += contour_.emap.back().length();
contour_.distances.push_back(contour_.full_distance);
contour_.distances.emplace_back(contour_.full_distance);
}
}
@ -276,10 +276,10 @@ template<class RawShape> class EdgeCache {
while(next != endit) {
hc.emap.emplace_back(*(first++), *(next++));
hc.full_distance += hc.emap.back().length();
hc.distances.push_back(hc.full_distance);
hc.distances.emplace_back(hc.full_distance);
}
holes_.push_back(hc);
holes_.emplace_back(std::move(hc));
}
}

View File

@ -63,7 +63,7 @@ public:
bool pack(Item& item, const Range& rem = Range()) {
auto&& r = static_cast<Subclass*>(this)->trypack(item, rem);
if(r) {
items_.push_back(*(r.item_ptr_));
items_.emplace_back(*(r.item_ptr_));
farea_valid_ = false;
}
return r;
@ -78,7 +78,7 @@ public:
if(r) {
r.item_ptr_->translation(r.move_);
r.item_ptr_->rotation(r.rot_);
items_.push_back(*(r.item_ptr_));
items_.emplace_back(*(r.item_ptr_));
farea_valid_ = false;
}
}

View File

@ -667,7 +667,7 @@ public:
addBin();
ItemList& not_packed = not_packeds[b];
for(unsigned idx = b; idx < store_.size(); idx+=bincount_guess) {
not_packed.push_back(store_[idx]);
not_packed.emplace_back(store_[idx]);
}
}

View File

@ -463,7 +463,7 @@ template<> inline std::string serialize<libnest2d::Formats::SVG>(
auto& v = *it;
hf.emplace_back(getX(v)*scale, getY(v)*scale);
};
holes.push_back(hf);
holes.emplace_back(std::move(hf));
}
Polygonf poly;

View File

@ -2,36 +2,10 @@
#define PRINTER_PARTS_H
#include <vector>
#include <clipper.hpp>
#ifndef CLIPPER_BACKEND_HPP
namespace ClipperLib {
using PointImpl = IntPoint;
using PathImpl = Path;
using HoleStore = std::vector<PathImpl>;
struct PolygonImpl {
PathImpl Contour;
HoleStore Holes;
inline PolygonImpl() {}
inline explicit PolygonImpl(const PathImpl& cont): Contour(cont) {}
inline explicit PolygonImpl(const HoleStore& holes):
Holes(holes) {}
inline PolygonImpl(const Path& cont, const HoleStore& holes):
Contour(cont), Holes(holes) {}
inline explicit PolygonImpl(PathImpl&& cont): Contour(std::move(cont)) {}
inline explicit PolygonImpl(HoleStore&& holes): Holes(std::move(holes)) {}
inline PolygonImpl(Path&& cont, HoleStore&& holes):
Contour(std::move(cont)), Holes(std::move(holes)) {}
};
}
#endif
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
using TestData = std::vector<ClipperLib::Path>;
using TestDataEx = std::vector<ClipperLib::PolygonImpl>;
using TestDataEx = std::vector<ClipperLib::Polygon>;
extern const TestData PRINTER_PART_POLYGONS;
extern const TestData STEGOSAUR_POLYGONS;

View File

@ -161,6 +161,8 @@ add_library(libslic3r STATIC
utils.cpp
Utils.hpp
MTUtils.hpp
Zipper.hpp
Zipper.cpp
SLA/SLABoilerPlate.hpp
SLA/SLABasePool.hpp
SLA/SLABasePool.cpp
@ -177,8 +179,8 @@ if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
add_precompiled_header(libslic3r pchheader.hpp FORCEINCLUDE)
endif ()
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB ${PNG_DEFINITIONS})
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} ${PNG_INCLUDE_DIRS} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB)
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(libslic3r
libnest2d
admesh
@ -188,7 +190,6 @@ target_link_libraries(libslic3r
nowide
${EXPAT_LIBRARIES}
${GLEW_LIBRARIES}
${PNG_LIBRARIES}
glu-libtess
polypartition
poly2tri

View File

@ -120,7 +120,7 @@ Slic3r::Polygon ClipperPath_to_Slic3rPolygon(const ClipperLib::Path &input)
{
Polygon retval;
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
retval.points.push_back(Point( (*pit).X, (*pit).Y ));
retval.points.emplace_back(pit->X, pit->Y);
return retval;
}
@ -128,7 +128,7 @@ Slic3r::Polyline ClipperPath_to_Slic3rPolyline(const ClipperLib::Path &input)
{
Polyline retval;
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
retval.points.push_back(Point( (*pit).X, (*pit).Y ));
retval.points.emplace_back(pit->X, pit->Y);
return retval;
}
@ -137,7 +137,7 @@ Slic3r::Polygons ClipperPaths_to_Slic3rPolygons(const ClipperLib::Paths &input)
Slic3r::Polygons retval;
retval.reserve(input.size());
for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
retval.push_back(ClipperPath_to_Slic3rPolygon(*it));
retval.emplace_back(ClipperPath_to_Slic3rPolygon(*it));
return retval;
}
@ -146,7 +146,7 @@ Slic3r::Polylines ClipperPaths_to_Slic3rPolylines(const ClipperLib::Paths &input
Slic3r::Polylines retval;
retval.reserve(input.size());
for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it)
retval.push_back(ClipperPath_to_Slic3rPolyline(*it));
retval.emplace_back(ClipperPath_to_Slic3rPolyline(*it));
return retval;
}
@ -171,7 +171,7 @@ Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
{
ClipperLib::Path retval;
for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
retval.push_back(ClipperLib::IntPoint( (*pit)(0), (*pit)(1) ));
retval.emplace_back((*pit)(0), (*pit)(1));
return retval;
}
@ -181,7 +181,7 @@ Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input)
ClipperLib::Path output;
output.reserve(input.points.size());
for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit)
output.push_back(ClipperLib::IntPoint( (*pit)(0), (*pit)(1) ));
output.emplace_back((*pit)(0), (*pit)(1));
return output;
}
@ -189,7 +189,7 @@ ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polygons &input)
{
ClipperLib::Paths retval;
for (Polygons::const_iterator it = input.begin(); it != input.end(); ++it)
retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it));
retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(*it));
return retval;
}
@ -197,7 +197,7 @@ ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input)
{
ClipperLib::Paths retval;
for (Polylines::const_iterator it = input.begin(); it != input.end(); ++it)
retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it));
retval.emplace_back(Slic3rMultiPoint_to_ClipperPath(*it));
return retval;
}
@ -226,7 +226,7 @@ ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType
ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit)
{
ClipperLib::Paths paths;
paths.push_back(std::move(input));
paths.emplace_back(std::move(input));
return _offset(std::move(paths), endType, delta, joinType, miterLimit);
}
@ -585,7 +585,7 @@ Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, co
Polylines polylines;
polylines.reserve(subject.size());
for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon)
polylines.push_back(*polygon); // implicit call to split_at_first_point()
polylines.emplace_back(polygon->operator Polyline()); // implicit call to split_at_first_point()
// perform clipping
Polylines retval = _clipper_pl(clipType, polylines, clip, safety_offset_);
@ -643,7 +643,7 @@ _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons
// convert Polylines to Lines
Lines retval;
for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline)
retval.push_back(*polyline);
retval.emplace_back(polyline->operator Line());
return retval;
}
@ -673,7 +673,7 @@ void traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval)
ordering_points.reserve(nodes.size());
for (ClipperLib::PolyNodes::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
Point p((*it)->Contour.front().X, (*it)->Contour.front().Y);
ordering_points.push_back(p);
ordering_points.emplace_back(p);
}
// perform the ordering
@ -684,7 +684,7 @@ void traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval)
for (ClipperLib::PolyNodes::iterator it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) {
// traverse the next depth
traverse_pt((*it)->Childs, retval);
retval->push_back(ClipperPath_to_Slic3rPolygon((*it)->Contour));
retval->emplace_back(ClipperPath_to_Slic3rPolygon((*it)->Contour));
if ((*it)->IsHole()) retval->back().reverse(); // ccw
}
}
@ -791,8 +791,8 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons)
Polygons out;
out.reserve(polytree.ChildCount());
for (int i = 0; i < polytree.ChildCount(); ++i)
out.push_back(ClipperPath_to_Slic3rPolygon(polytree.Childs[i]->Contour));
out.emplace_back(ClipperPath_to_Slic3rPolygon(polytree.Childs[i]->Contour));
return out;
}
}
}

View File

@ -28,8 +28,8 @@ namespace Slic3r {
//-----------------------------------------------------------
// legacy code from Clipper documentation
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons& expolygons);
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons);
void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons *expolygons);
Slic3r::ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree& polytree);
//-----------------------------------------------------------
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input);
@ -228,4 +228,4 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons);
}
#endif
#endif

View File

@ -175,6 +175,11 @@ struct AMFParserContext
bool mirrory_set;
float mirrorz;
bool mirrorz_set;
bool anything_set() const { return deltax_set || deltay_set || deltaz_set ||
rx_set || ry_set || rz_set ||
scalex_set || scaley_set || scalez_set ||
mirrorx_set || mirrory_set || mirrorz_set; }
};
struct Object {
@ -644,11 +649,7 @@ void AMFParserContext::endDocument()
continue;
}
for (const Instance &instance : object.second.instances)
#if ENABLE_VOLUMES_CENTERING_FIXES
{
#else
if (instance.deltax_set && instance.deltay_set) {
#endif // ENABLE_VOLUMES_CENTERING_FIXES
if (instance.anything_set()) {
ModelInstance *mi = m_model.objects[object.second.idx]->add_instance();
mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0));
mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0));

View File

@ -1034,6 +1034,15 @@ void GCode::_do_export(Print &print, FILE *file)
}
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
_write(file, m_writer.postamble());
// adds tags for time estimators
if (print.config().remaining_times.value)
{
_writeln(file, GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag);
if (m_silent_time_estimator_enabled)
_writeln(file, GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag);
}
print.throw_if_canceled();
// calculates estimated printing time
@ -2408,6 +2417,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
{
std::string gcode;
if (is_bridge(path.role()))
description += " (bridge)";
// go to first point of extrusion path
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
gcode += this->travel_to(

View File

@ -726,7 +726,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
GCodePreviewData::Range volumetric_rate_range;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)extrude_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
// constructs the polylines while traversing the moves
@ -776,6 +776,9 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
preview_data.ranges.width.update_from(width_range);
preview_data.ranges.feedrate.update_from(feedrate_range);
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
// we need to sort the layers by their z as they can be shuffled in case of sequential prints
std::sort(preview_data.extrusion.layers.begin(), preview_data.extrusion.layers.end(), [](const GCodePreviewData::Extrusion::Layer& l1, const GCodePreviewData::Extrusion::Layer& l2)->bool { return l1.z < l2.z; });
}
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
@ -807,7 +810,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
GCodePreviewData::Range feedrate_range;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)travel_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)travel_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
// constructs the polylines while traversing the moves
@ -855,6 +858,11 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
preview_data.ranges.height.update_from(height_range);
preview_data.ranges.width.update_from(width_range);
preview_data.ranges.feedrate.update_from(feedrate_range);
// we need to sort the polylines by their min z as they can be shuffled in case of sequential prints
std::sort(preview_data.travel.polylines.begin(), preview_data.travel.polylines.end(),
[](const GCodePreviewData::Travel::Polyline& p1, const GCodePreviewData::Travel::Polyline& p2)->bool
{ return unscale<double>(p1.polyline.bounding_box().min(2)) < unscale<double>(p2.polyline.bounding_box().min(2)); });
}
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
@ -864,7 +872,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
return;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)retraction_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)retraction_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
for (const GCodeMove& move : retraction_moves->second)
@ -877,6 +885,11 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
}
// we need to sort the positions by their z as they can be shuffled in case of sequential prints
std::sort(preview_data.retraction.positions.begin(), preview_data.retraction.positions.end(),
[](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2)->bool
{ return unscale<double>(p1.position(2)) < unscale<double>(p2.position(2)); });
}
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
@ -886,7 +899,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
return;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)unretraction_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)unretraction_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
for (const GCodeMove& move : unretraction_moves->second)
@ -899,6 +912,11 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);
}
// we need to sort the positions by their z as they can be shuffled in case of sequential prints
std::sort(preview_data.unretraction.positions.begin(), preview_data.unretraction.positions.end(),
[](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2)->bool
{ return unscale<double>(p1.position(2)) < unscale<double>(p2.position(2)); });
}
// Return an estimate of the memory consumed by the time estimator.

View File

@ -4,6 +4,7 @@
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/nowide/convert.hpp>
#ifdef WIN32
@ -11,6 +12,7 @@
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <shellapi.h>
// https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
// This routine appends the given argument to a command line such that CommandLineToArgvW will return the argument string unchanged.

View File

@ -171,6 +171,8 @@ namespace Slic3r {
const std::string GCodeTimeEstimator::Normal_First_M73_Output_Placeholder_Tag = "; NORMAL_FIRST_M73_OUTPUT_PLACEHOLDER";
const std::string GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag = "; SILENT_FIRST_M73_OUTPUT_PLACEHOLDER";
const std::string GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag = "; NORMAL_LAST_M73_OUTPUT_PLACEHOLDER";
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
: _mode(mode)
@ -306,9 +308,17 @@ namespace Slic3r {
sprintf(time_line, time_mask.c_str(), "0", _get_time_minutes(_time).c_str());
gcode_line = time_line;
}
// replaces placeholders for final line M73 with the real lines
else if (((_mode == Normal) && (gcode_line == Normal_Last_M73_Output_Placeholder_Tag)) ||
((_mode == Silent) && (gcode_line == Silent_Last_M73_Output_Placeholder_Tag)))
{
sprintf(time_line, time_mask.c_str(), "100", "0");
gcode_line = time_line;
}
else
gcode_line += "\n";
// add remaining time lines where needed
_parser.parse_line(gcode_line,
[this, &it_line_id, &g1_lines_count, &last_recorded_time, &time_line, &gcode_line, time_mask, interval](GCodeReader& reader, const GCodeReader::GCodeLine& line)

View File

@ -19,6 +19,8 @@ namespace Slic3r {
public:
static const std::string Normal_First_M73_Output_Placeholder_Tag;
static const std::string Silent_First_M73_Output_Placeholder_Tag;
static const std::string Normal_Last_M73_Output_Placeholder_Tag;
static const std::string Silent_Last_M73_Output_Placeholder_Tag;
enum EMode : unsigned char
{

View File

@ -246,6 +246,7 @@ public:
const Vec3d& get_mirror() const { return m_mirror; }
double get_mirror(Axis axis) const { return m_mirror(axis); }
bool is_left_handed() const { return m_mirror.x() * m_mirror.y() * m_mirror.z() < 0.; }
void set_mirror(const Vec3d& mirror);
void set_mirror(Axis axis, double mirror);

View File

@ -258,13 +258,18 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
#ifdef SLIC3R_DEBUG
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
#endif
if (bd.detect_angle(Geometry::deg2rad(this->region()->config().bridge_angle.value))) {
double custom_angle = Geometry::deg2rad(this->region()->config().bridge_angle.value);
if (bd.detect_angle(custom_angle)) {
bridges[idx_last].bridge_angle = bd.angle;
if (this->layer()->object()->config().support_material) {
polygons_append(this->bridged, bd.coverage());
this->unsupported_bridge_edges.append(bd.unsupported_edges());
}
}
} else if (custom_angle > 0) {
// Bridge was not detected (likely it is only supported at one side). Still it is a surface filled in
// using a bridging flow, therefore it makes sense to respect the custom bridging direction.
bridges[idx_last].bridge_angle = custom_angle;
}
// without safety offset, artifacts are generated (GH #2494)
surfaces_append(bottom, union_ex(grown, true), bridges[idx_last]);
}

View File

@ -56,6 +56,132 @@ public:
}
};
/// An std compatible random access iterator which uses indices to the source
/// vector thus resistant to invalidation caused by relocations. It also "knows"
/// its container. No comparison is neccesary to the container "end()" iterator.
/// The template can be instantiated with a different value type than that of
/// the container's but the types must be compatible. E.g. a base class of the
/// contained objects is compatible.
///
/// For a constant iterator, one can instantiate this template with a value
/// type preceded with 'const'.
template<class Vector, // The container type, must be random access...
class Value = typename Vector::value_type // The value type
>
class IndexBasedIterator {
static const size_t NONE = size_t(-1);
std::reference_wrapper<Vector> m_index_ref;
size_t m_idx = NONE;
public:
using value_type = Value;
using pointer = Value *;
using reference = Value &;
using difference_type = long;
using iterator_category = std::random_access_iterator_tag;
inline explicit
IndexBasedIterator(Vector& index, size_t idx):
m_index_ref(index), m_idx(idx) {}
// Post increment
inline IndexBasedIterator operator++(int) {
IndexBasedIterator cpy(*this); ++m_idx; return cpy;
}
inline IndexBasedIterator operator--(int) {
IndexBasedIterator cpy(*this); --m_idx; return cpy;
}
inline IndexBasedIterator& operator++() {
++m_idx; return *this;
}
inline IndexBasedIterator& operator--() {
--m_idx; return *this;
}
inline IndexBasedIterator& operator+=(difference_type l) {
m_idx += size_t(l); return *this;
}
inline IndexBasedIterator operator+(difference_type l) {
auto cpy = *this; cpy += l; return cpy;
}
inline IndexBasedIterator& operator-=(difference_type l) {
m_idx -= size_t(l); return *this;
}
inline IndexBasedIterator operator-(difference_type l) {
auto cpy = *this; cpy -= l; return cpy;
}
operator difference_type() { return difference_type(m_idx); }
/// Tesing the end of the container... this is not possible with std
/// iterators.
inline bool is_end() const { return m_idx >= m_index_ref.get().size();}
inline Value & operator*() const {
assert(m_idx < m_index_ref.get().size());
return m_index_ref.get().operator[](m_idx);
}
inline Value * operator->() const {
assert(m_idx < m_index_ref.get().size());
return &m_index_ref.get().operator[](m_idx);
}
/// If both iterators point past the container, they are equal...
inline bool operator ==(const IndexBasedIterator& other) {
size_t e = m_index_ref.get().size();
return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e);
}
inline bool operator !=(const IndexBasedIterator& other) {
return !(*this == other);
}
inline bool operator <=(const IndexBasedIterator& other) {
return (m_idx < other.m_idx) || (*this == other);
}
inline bool operator <(const IndexBasedIterator& other) {
return m_idx < other.m_idx && (*this != other);
}
inline bool operator >=(const IndexBasedIterator& other) {
return m_idx > other.m_idx || *this == other;
}
inline bool operator >(const IndexBasedIterator& other) {
return m_idx > other.m_idx && *this != other;
}
};
/// A very simple range concept implementation with iterator-like objects.
template<class It> class Range {
It from, to;
public:
// The class is ready for range based for loops.
It begin() const { return from; }
It end() const { return to; }
// The iterator type can be obtained this way.
using Type = It;
Range() = default;
Range(It &&b, It &&e):
from(std::forward<It>(b)), to(std::forward<It>(e)) {}
// Some useful container-like methods...
inline size_t size() const { return end() - begin(); }
inline bool empty() const { return size() == 0; }
};
}
#endif // MTUTILS_HPP

View File

@ -61,7 +61,7 @@ Model& Model::assign_copy(Model &&rhs)
this->objects = std::move(rhs.objects);
for (ModelObject *model_object : this->objects)
model_object->set_model(this);
rhs.objects.clear();
rhs.objects.clear();
return *this;
}
@ -556,19 +556,9 @@ std::string Model::propose_export_file_name_and_path() const
for (const ModelObject *model_object : this->objects)
for (ModelInstance *model_instance : model_object->instances)
if (model_instance->is_printable()) {
input_file = model_object->input_file;
if (! model_object->name.empty()) {
if (input_file.empty())
// model_object->input_file was empty, just use model_object->name
input_file = model_object->name;
else {
// Replace file name in input_file with model_object->name, but keep the path and file extension.
input_file = (boost::filesystem::path(model_object->name).parent_path().empty()) ?
(boost::filesystem::path(input_file).parent_path() / model_object->name).make_preferred().string() :
model_object->name;
}
}
if (! input_file.empty())
input_file = model_object->get_export_filename();
if (!input_file.empty())
goto end;
// Other instances will produce the same name, skip them.
break;
@ -651,7 +641,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
for (ModelInstance *model_instance : this->instances)
model_instance->set_model_object(this);
return *this;
return *this;
}
void ModelObject::assign_new_unique_ids_recursive()
@ -970,8 +960,8 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance)
}
}
}
std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); });
pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end());
std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); });
pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end());
Polygon hull;
int n = (int)pts.size();
@ -997,12 +987,16 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance)
return hull;
}
#if ENABLE_VOLUMES_CENTERING_FIXES
void ModelObject::center_around_origin(bool include_modifiers)
#else
void ModelObject::center_around_origin()
#endif // ENABLE_VOLUMES_CENTERING_FIXES
{
// calculate the displacements needed to
// center this object around the origin
#if ENABLE_VOLUMES_CENTERING_FIXES
BoundingBoxf3 bb = full_raw_mesh_bounding_box();
BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box();
#else
BoundingBoxf3 bb;
for (ModelVolume *v : this->volumes)
@ -1183,8 +1177,9 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
else {
TriangleMesh upper_mesh, lower_mesh;
// Transform the mesh by the combined transformation matrix
volume->mesh.transform(instance_matrix * volume_matrix);
// Transform the mesh by the combined transformation matrix.
// Flip the triangles in case the composite transformation is left handed.
volume->mesh.transform(instance_matrix * volume_matrix, true);
// Perform cut
TriangleMeshSlicer tms(&volume->mesh);
@ -1287,11 +1282,11 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
// XXX: this seems to be the only real usage of m_model, maybe refactor this so that it's not needed?
ModelObject* new_object = m_model->add_object();
new_object->name = this->name;
new_object->config = this->config;
new_object->instances.reserve(this->instances.size());
for (const ModelInstance *model_instance : this->instances)
new_object->add_instance(*model_instance);
new_object->name = this->name;
new_object->config = this->config;
new_object->instances.reserve(this->instances.size());
for (const ModelInstance *model_instance : this->instances)
new_object->add_instance(*model_instance);
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(*mesh));
#if !ENABLE_VOLUMES_CENTERING_FIXES
new_vol->center_geometry();
@ -1428,6 +1423,26 @@ void ModelObject::print_info() const
cout << "volume = " << mesh.volume() << endl;
}
std::string ModelObject::get_export_filename() const
{
std::string ret = input_file;
if (!name.empty())
{
if (ret.empty())
// input_file was empty, just use name
ret = name;
else
{
// Replace file name in input_file with name, but keep the path and file extension.
ret = (boost::filesystem::path(name).parent_path().empty()) ?
(boost::filesystem::path(ret).parent_path() / name).make_preferred().string() : name;
}
}
return ret;
}
void ModelVolume::set_material_id(t_model_material_id material_id)
{
m_material_id = material_id;
@ -1463,9 +1478,9 @@ int ModelVolume::extruder_id() const
bool ModelVolume::is_splittable() const
{
// the call mesh.has_multiple_patches() is expensive, so cache the value to calculate it only once
// the call mesh.is_splittable() is expensive, so cache the value to calculate it only once
if (m_is_splittable == -1)
m_is_splittable = (int)mesh.has_multiple_patches();
m_is_splittable = (int)mesh.is_splittable();
return m_is_splittable == 1;
}
@ -1605,6 +1620,7 @@ void ModelVolume::rotate(double angle, Axis axis)
case X: { rotate(angle, Vec3d::UnitX()); break; }
case Y: { rotate(angle, Vec3d::UnitY()); break; }
case Z: { rotate(angle, Vec3d::UnitZ()); break; }
default: break;
}
}
@ -1621,6 +1637,7 @@ void ModelVolume::mirror(Axis axis)
case X: { mirror(0) *= -1.0; break; }
case Y: { mirror(1) *= -1.0; break; }
case Z: { mirror(2) *= -1.0; break; }
default: break;
}
set_mirror(mirror);
}
@ -1707,7 +1724,6 @@ bool model_object_list_extended(const Model &model_old, const Model &model_new)
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type)
{
bool modifiers_differ = false;
size_t i_old, i_new;
for (i_old = 0, i_new = 0; i_old < model_object_old.volumes.size() && i_new < model_object_new.volumes.size();) {
const ModelVolume &mv_old = *model_object_old.volumes[i_old];

View File

@ -236,7 +236,11 @@ public:
// This method is used by the auto arrange function.
Polygon convex_hull_2d(const Transform3d &trafo_instance);
#if ENABLE_VOLUMES_CENTERING_FIXES
void center_around_origin(bool include_modifiers = true);
#else
void center_around_origin();
#endif // ENABLE_VOLUMES_CENTERING_FIXES
void ensure_on_bed();
void translate_instances(const Vec3d& vector);
void translate_instance(size_t instance_idx, const Vec3d& vector);
@ -271,6 +275,8 @@ public:
// Print object statistics to console.
void print_info() const;
std::string get_export_filename() const;
protected:
friend class Print;
friend class SLAPrint;
@ -390,6 +396,7 @@ public:
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
bool is_left_handed() const { return m_transformation.is_left_handed(); }
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
@ -494,6 +501,7 @@ public:
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
bool is_left_handed() const { return m_transformation.is_left_handed(); }
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }

View File

@ -556,29 +556,7 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
// TODO export the exact 2D projection. Cannot do it as libnest2d
// does not support concave shapes (yet).
ClipperLib::Path clpath;
//WIP Vojtech's optimization of the calculation of the convex hull is not working correctly yet.
#if 1
{
TriangleMesh rmesh = objptr->raw_mesh();
ModelInstance * finst = objptr->instances.front();
// Object instances should carry the same scaling and
// x, y rotation that is why we use the first instance.
// The next line will apply only the full mirroring and scaling
rmesh.transform(finst->get_matrix(true, true, false, false));
rmesh.rotate_x(float(finst->get_rotation()(X)));
rmesh.rotate_y(float(finst->get_rotation()(Y)));
// TODO export the exact 2D projection. Cannot do it as libnest2d
// does not support concave shapes (yet).
auto p = rmesh.convex_hull();
p.make_clockwise();
p.append(p.first_point());
clpath = Slic3rMultiPoint_to_ClipperPath(p);
}
#else
// Object instances should carry the same scaling and
// x, y rotation that is why we use the first instance.
{
@ -593,11 +571,10 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
p.append(p.first_point());
clpath = Slic3rMultiPoint_to_ClipperPath(p);
}
#endif
for(ModelInstance* objinst : objptr->instances) {
if(objinst) {
ClipperLib::PolygonImpl pn;
ClipperLib::Polygon pn;
pn.Contour = clpath;
// Efficient conversion to item.

View File

@ -10,7 +10,7 @@
#include "GCode/WipeTowerPrusaMM.hpp"
#include "Utils.hpp"
#include "PrintExport.hpp"
//#include "PrintExport.hpp"
#include <algorithm>
#include <limits>

View File

@ -208,7 +208,7 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("Horizontal width of the brim that will be printed around each object on the first layer.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->mode = comSimple;
def->default_value = new ConfigOptionFloat(0);
def = this->add("clip_multipart_objects", coBool);
@ -1375,6 +1375,7 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("(minimum)");
def->aliases = { "perimeter_offsets" };
def->min = 0;
def->max = 10000;
def->default_value = new ConfigOptionInt(3);
def = this->add("post_process", coStrings);

View File

@ -7,6 +7,7 @@
#include <vector>
#include <boost/log/trivial.hpp>
#include <boost/filesystem/path.hpp>
#include "Rasterizer/Rasterizer.hpp"
//#include <tbb/parallel_for.h>
@ -42,8 +43,9 @@ template<FilePrinterFormat format>
class FilePrinter {
public:
// Draw an ExPolygon which is a polygon inside a slice on the specified layer.
// Draw a polygon which is a polygon inside a slice on the specified layer.
void draw_polygon(const ExPolygon& p, unsigned lyr);
void draw_polygon(const ClipperLib::Polygon& p, unsigned lyr);
// Tell the printer how many layers should it consider.
void layers(unsigned layernum);
@ -71,7 +73,8 @@ public:
void finish_layer();
// Save all the layers into the file (or dir) specified in the path argument
void save(const std::string& path);
// An optional project name can be added to be used for the layer file names
void save(const std::string& path, const std::string& projectname = "");
// Save only the selected layer to the file specified in path argument.
void save_layer(unsigned lyr, const std::string& path);
@ -80,28 +83,35 @@ public:
// Provokes static_assert in the right way.
template<class T = void> struct VeryFalse { static const bool value = false; };
// This has to be explicitly implemented in the gui layer or a default zlib
// based implementation is needed. I don't have time for that and I'm delegating
// the implementation to the gui layer where the gui toolkit can cover this.
// This can be explicitly implemented in the gui layer or the default Zipper
// API in libslic3r with minz.
template<class Fmt> class LayerWriter {
public:
LayerWriter(const std::string& /*zipfile_path*/) {
LayerWriter(const std::string& /*zipfile_path*/)
{
static_assert(VeryFalse<Fmt>::value,
"No layer writer implementation provided!");
}
// Should create a new file within the zip with the given filename. It
// should also finish any previous entry.
void next_entry(const std::string& /*fname*/) {}
std::string get_name() { return ""; }
// Should create a new file within the archive and write the provided data.
void binary_entry(const std::string& /*fname*/,
const std::uint8_t* buf, size_t len);
// Test whether the object can still be used for writing.
bool is_ok() { return false; }
template<class T> LayerWriter& operator<<(const T& /*arg*/) {
// Write some data (text) into the current file (entry) within the archive.
template<class T> LayerWriter& operator<<(T&& /*arg*/) {
return *this;
}
void close() {}
// Flush the current entry into the archive.
void finalize() {}
};
// Implementation for PNG raster output
@ -110,14 +120,14 @@ public:
template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
{
struct Layer {
Raster first;
std::stringstream second;
Raster raster;
RawBytes rawbytes;
Layer() {}
Layer(const Layer&) = delete;
Layer(Layer&& m):
first(std::move(m.first))/*, second(std::move(m.second))*/ {}
raster(std::move(m.raster)) {}
};
// We will save the compressed PNG data into stringstreams which can be done
@ -135,14 +145,11 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
int m_cnt_fast_layers = 0;
std::string createIniContent(const std::string& projectname) {
// double layer_height = m_layer_height;
using std::string;
using std::to_string;
auto expt_str = to_string(m_exp_time_s);
auto expt_first_str = to_string(m_exp_time_first_s);
// auto stepnum_str = to_string(static_cast<unsigned>(800*layer_height));
auto layerh_str = to_string(m_layer_height);
const std::string cnt_fade_layers = to_string(m_cnt_fade_layers);
@ -211,41 +218,48 @@ public:
inline void draw_polygon(const ExPolygon& p, unsigned lyr) {
assert(lyr < m_layers_rst.size());
m_layers_rst[lyr].first.draw(p);
m_layers_rst[lyr].raster.draw(p);
}
inline void draw_polygon(const ClipperLib::Polygon& p, unsigned lyr) {
assert(lyr < m_layers_rst.size());
m_layers_rst[lyr].raster.draw(p);
}
inline void begin_layer(unsigned lyr) {
if(m_layers_rst.size() <= lyr) m_layers_rst.resize(lyr+1);
m_layers_rst[lyr].first.reset(m_res, m_pxdim, m_o);
m_layers_rst[lyr].raster.reset(m_res, m_pxdim, m_o);
}
inline void begin_layer() {
m_layers_rst.emplace_back();
m_layers_rst.front().first.reset(m_res, m_pxdim, m_o);
m_layers_rst.front().raster.reset(m_res, m_pxdim, m_o);
}
inline void finish_layer(unsigned lyr_id) {
assert(lyr_id < m_layers_rst.size());
m_layers_rst[lyr_id].first.save(m_layers_rst[lyr_id].second,
Raster::Compression::PNG);
m_layers_rst[lyr_id].first.reset();
m_layers_rst[lyr_id].rawbytes =
m_layers_rst[lyr_id].raster.save(Raster::Compression::PNG);
m_layers_rst[lyr_id].raster.reset();
}
inline void finish_layer() {
if(!m_layers_rst.empty()) {
m_layers_rst.back().first.save(m_layers_rst.back().second,
Raster::Compression::PNG);
m_layers_rst.back().first.reset();
m_layers_rst.back().rawbytes =
m_layers_rst.back().raster.save(Raster::Compression::PNG);
m_layers_rst.back().raster.reset();
}
}
template<class LyrFmt>
inline void save(const std::string& path) {
inline void save(const std::string& fpath, const std::string& prjname = "")
{
try {
LayerWriter<LyrFmt> writer(path);
LayerWriter<LyrFmt> writer(fpath);
if(!writer.is_ok()) return;
std::string project = writer.get_name();
std::string project = prjname.empty()?
boost::filesystem::path(fpath).stem().string() : prjname;
writer.next_entry("config.ini");
if(!writer.is_ok()) return;
@ -254,20 +268,19 @@ public:
for(unsigned i = 0; i < m_layers_rst.size() && writer.is_ok(); i++)
{
if(m_layers_rst[i].second.rdbuf()->in_avail() > 0) {
if(m_layers_rst[i].rawbytes.size() > 0) {
char lyrnum[6];
std::sprintf(lyrnum, "%.5d", i);
auto zfilename = project + lyrnum + ".png";
writer.next_entry(zfilename);
if(!writer.is_ok()) break;
writer << m_layers_rst[i].second.str();
// writer << m_layers_rst[i].second.rdbuf();
// we can keep the date for later calls of this method
//m_layers_rst[i].second.str("");
writer.binary_entry(zfilename,
m_layers_rst[i].rawbytes.data(),
m_layers_rst[i].rawbytes.size());
}
}
writer.finalize();
} catch(std::exception& e) {
BOOST_LOG_TRIVIAL(error) << e.what();
// Rethrow the exception
@ -285,13 +298,13 @@ public:
std::fstream out(loc, std::fstream::out | std::fstream::binary);
if(out.good()) {
m_layers_rst[i].first.save(out, Raster::Compression::PNG);
m_layers_rst[i].raster.save(out, Raster::Compression::PNG);
} else {
BOOST_LOG_TRIVIAL(error) << "Can't create file for layer";
}
out.close();
m_layers_rst[i].first.reset();
m_layers_rst[i].raster.reset();
}
void set_statistics(const std::vector<double> statistics)

View File

@ -1790,15 +1790,21 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
if (! volumes.empty()) {
// Compose mesh.
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
TriangleMesh mesh;
for (const ModelVolume *v : volumes)
{
TriangleMesh vol_mesh(v->mesh);
vol_mesh.transform(v->get_matrix());
TriangleMesh mesh(volumes.front()->mesh);
mesh.transform(volumes.front()->get_matrix(), true);
assert(mesh.repaired);
if (volumes.size() == 1 && mesh.repaired) {
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
stl_check_facets_exact(&mesh.stl);
}
for (size_t idx_volume = 1; idx_volume < volumes.size(); ++ idx_volume) {
const ModelVolume &model_volume = *volumes[idx_volume];
TriangleMesh vol_mesh(model_volume.mesh);
vol_mesh.transform(model_volume.get_matrix(), true);
mesh.merge(vol_mesh);
}
if (mesh.stl.stats.number_of_facets > 0) {
mesh.transform(m_trafo);
mesh.transform(m_trafo, true);
// apply XY shift
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
// perform actual slicing
@ -1819,9 +1825,13 @@ std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z,
// Compose mesh.
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
TriangleMesh mesh(volume.mesh);
mesh.transform(volume.get_matrix());
mesh.transform(volume.get_matrix(), true);
if (mesh.repaired) {
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
stl_check_facets_exact(&mesh.stl);
}
if (mesh.stl.stats.number_of_facets > 0) {
mesh.transform(m_trafo);
mesh.transform(m_trafo, true);
// apply XY shift
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
// perform actual slicing

View File

@ -1,7 +1,6 @@
#include "Rasterizer.hpp"
#include <ExPolygon.hpp>
#include <cstdint>
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
// For rasterizing
#include <agg/agg_basics.h>
@ -15,8 +14,8 @@
#include <agg/agg_rasterizer_scanline_aa.h>
#include <agg/agg_path_storage.h>
// For png compression
#include <png/writer.hpp>
// Experimental minz image write:
#include <miniz/miniz_tdef.h>
namespace Slic3r {
@ -91,6 +90,25 @@ public:
agg::render_scanlines(ras, scanlines, m_renderer);
}
void draw(const ClipperLib::Polygon &poly) {
agg::rasterizer_scanline_aa<> ras;
agg::scanline_p8 scanlines;
auto&& path = to_path(poly.Contour);
if(m_o == Origin::TOP_LEFT) flipy(path);
ras.add_path(path);
for(auto h : poly.Holes) {
auto&& holepath = to_path(h);
if(m_o == Origin::TOP_LEFT) flipy(holepath);
ras.add_path(holepath);
}
agg::render_scanlines(ras, scanlines, m_renderer);
}
inline void clear() {
m_raw_renderer.clear(ColorBlack);
}
@ -110,14 +128,36 @@ private:
return p(1) * SCALING_FACTOR/m_pxdim.h_mm;
}
agg::path_storage to_path(const Polygon& poly) {
agg::path_storage to_path(const Polygon& poly)
{
agg::path_storage path;
auto it = poly.points.begin();
path.move_to(getPx(*it), getPy(*it));
while(++it != poly.points.end())
while(++it != poly.points.end()) path.line_to(getPx(*it), getPy(*it));
path.line_to(getPx(poly.points.front()), getPy(poly.points.front()));
return path;
}
double getPx(const ClipperLib::IntPoint& p) {
return p.X * SCALING_FACTOR/m_pxdim.w_mm;
}
double getPy(const ClipperLib::IntPoint& p) {
return p.Y * SCALING_FACTOR/m_pxdim.h_mm;
}
agg::path_storage to_path(const ClipperLib::Path& poly)
{
agg::path_storage path;
auto it = poly.begin();
path.move_to(getPx(*it), getPy(*it));
while(++it != poly.end())
path.line_to(getPx(*it), getPy(*it));
path.line_to(getPx(poly.points.front()), getPy(poly.points.front()));
path.line_to(getPx(poly.front()), getPy(poly.front()));
return path;
}
@ -169,38 +209,36 @@ void Raster::clear()
m_impl->clear();
}
void Raster::draw(const ExPolygon &poly)
void Raster::draw(const ExPolygon &expoly)
{
m_impl->draw(expoly);
}
void Raster::draw(const ClipperLib::Polygon &poly)
{
assert(m_impl);
m_impl->draw(poly);
}
void Raster::save(std::ostream& stream, Compression comp)
{
assert(m_impl);
if(!stream.good()) return;
switch(comp) {
case Compression::PNG: {
png::writer<std::ostream> wr(stream);
wr.set_bit_depth(8);
wr.set_color_type(png::color_type_gray);
wr.set_width(resolution().width_px);
wr.set_height(resolution().height_px);
wr.set_compression_type(png::compression_type_default);
wr.write_info();
auto& b = m_impl->buffer();
auto ptr = reinterpret_cast<png::byte*>( b.data() );
unsigned stride =
sizeof(Impl::TBuffer::value_type) * resolution().width_px;
size_t out_len = 0;
void * rawdata = tdefl_write_image_to_png_file_in_memory(
b.data(),
int(resolution().width_px),
int(resolution().height_px), 1, &out_len);
for(unsigned r = 0; r < resolution().height_px; r++, ptr+=stride) {
wr.write_row(ptr);
}
if(rawdata == nullptr) break;
wr.write_end_info();
stream.write(static_cast<const char*>(rawdata),
std::streamsize(out_len));
MZ_FREE(rawdata);
break;
}
@ -217,4 +255,47 @@ void Raster::save(std::ostream& stream, Compression comp)
}
}
RawBytes Raster::save(Raster::Compression comp)
{
assert(m_impl);
std::uint8_t *ptr = nullptr; size_t s = 0;
switch(comp) {
case Compression::PNG: {
void *rawdata = tdefl_write_image_to_png_file_in_memory(
m_impl->buffer().data(),
int(resolution().width_px),
int(resolution().height_px), 1, &s);
if(rawdata == nullptr) break;
ptr = static_cast<std::uint8_t*>(rawdata);
break;
}
case Compression::RAW: {
auto header = std::string("P5 ") +
std::to_string(m_impl->resolution().width_px) + " " +
std::to_string(m_impl->resolution().height_px) + " " + "255 ";
auto sz = m_impl->buffer().size()*sizeof(Impl::TBuffer::value_type);
s = sz + header.size();
ptr = static_cast<std::uint8_t*>(MZ_MALLOC(s));
auto buff = reinterpret_cast<std::uint8_t*>(m_impl->buffer().data());
std::copy(buff, buff+sz, ptr + header.size());
}
}
return {ptr, s};
}
void RawBytes::MinzDeleter::operator()(uint8_t *rawptr)
{
MZ_FREE(rawptr);
}
}

View File

@ -3,11 +3,52 @@
#include <ostream>
#include <memory>
#include <vector>
#include <cstdint>
namespace ClipperLib { struct Polygon; }
namespace Slic3r {
class ExPolygon;
// Raw byte buffer paired with its size. Suitable for compressed PNG data.
class RawBytes {
class MinzDeleter {
public:
void operator()(std::uint8_t *rawptr);
};
std::unique_ptr<std::uint8_t, MinzDeleter> m_buffer = nullptr;
size_t m_size = 0;
public:
RawBytes() = default;
RawBytes(std::uint8_t *rawptr, size_t s): m_buffer(rawptr), m_size(s) {}
size_t size() const { return m_size; }
const uint8_t * data() { return m_buffer.get(); }
// /////////////////////////////////////////////////////////////////////////
// FIXME: the following is needed for MSVC2013 compatibility
// /////////////////////////////////////////////////////////////////////////
RawBytes(const RawBytes&) = delete;
RawBytes(RawBytes&& mv):
m_buffer(std::move(mv.m_buffer)), m_size(mv.m_size) {}
RawBytes& operator=(const RawBytes&) = delete;
RawBytes& operator=(RawBytes&& mv) {
m_buffer.swap(mv.m_buffer);
m_size = mv.m_size;
return *this;
}
// /////////////////////////////////////////////////////////////////////////
};
/**
* @brief Raster captures an anti-aliased monochrome canvas where vectorial
* polygons can be rasterized. Fill color is always white and the background is
@ -84,9 +125,12 @@ public:
/// Draw a polygon with holes.
void draw(const ExPolygon& poly);
void draw(const ClipperLib::Polygon& poly);
/// Save the raster on the specified stream.
void save(std::ostream& stream, Compression comp = Compression::RAW);
RawBytes save(Compression comp = Compression::RAW);
};
}

View File

@ -49,8 +49,8 @@ float SLAAutoSupports::distance_limit(float angle) const
}*/
SLAAutoSupports::SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices, const std::vector<float>& heights,
const Config& config, std::function<void(void)> throw_on_cancel)
: m_config(config), m_emesh(emesh), m_throw_on_cancel(throw_on_cancel)
const Config& config, std::function<void(void)> throw_on_cancel, std::function<void(int)> statusfn)
: m_config(config), m_emesh(emesh), m_throw_on_cancel(throw_on_cancel), m_statusfn(statusfn)
{
process(slices, heights);
project_onto_mesh(m_output);
@ -197,6 +197,9 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
PointGrid3D point_grid;
point_grid.cell_size = Vec3f(10.f, 10.f, 10.f);
double increment = 100.0 / layers.size();
double status = 0;
for (unsigned int layer_id = 0; layer_id < layers.size(); ++ layer_id) {
SLAAutoSupports::MyLayer *layer_top = &layers[layer_id];
SLAAutoSupports::MyLayer *layer_bottom = (layer_id > 0) ? &layers[layer_id - 1] : nullptr;
@ -252,6 +255,9 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
m_throw_on_cancel();
status += increment;
m_statusfn(int(std::round(status)));
#ifdef SLA_AUTOSUPPORTS_DEBUG
/*std::string layer_num_str = std::string((i<10 ? "0" : "")) + std::string((i<100 ? "0" : "")) + std::to_string(i);
output_expolygons(expolys_top, "top" + layer_num_str + ".svg");

View File

@ -24,7 +24,7 @@ public:
};
SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices,
const std::vector<float>& heights, const Config& config, std::function<void(void)> throw_on_cancel);
const std::vector<float>& heights, const Config& config, std::function<void(void)> throw_on_cancel, std::function<void(int)> statusfn);
const std::vector<sla::SupportPoint>& output() { return m_output; }
struct MyLayer;
@ -196,12 +196,13 @@ private:
static void output_structures(const std::vector<Structure> &structures);
#endif // SLA_AUTOSUPPORTS_DEBUG
std::function<void(void)> m_throw_on_cancel;
const sla::EigenMesh3D& m_emesh;
std::function<void(void)> m_throw_on_cancel;
std::function<void(int)> m_statusfn;
};
} // namespace Slic3r
#endif // SLAAUTOSUPPORTS_HPP_
#endif // SLAAUTOSUPPORTS_HPP_

View File

@ -755,9 +755,12 @@ public:
return m_compact_bridges;
}
template<class T> inline
typename std::enable_if<std::is_integral<T>::value, const Pillar&>::type
pillar(T id) const { assert(id >= 0); return m_pillars.at(size_t(id)); }
template<class T> inline const Pillar& pillar(T id) const {
static_assert(std::is_integral<T>::value, "Invalid index type");
assert(id >= 0 && id < m_pillars.size() &&
id < std::numeric_limits<size_t>::max());
return m_pillars[size_t(id)];
}
const Pad& create_pad(const TriangleMesh& object_supports,
const ExPolygons& baseplate,
@ -1463,7 +1466,7 @@ public:
m_cfg.head_back_radius_mm,
w);
if(t <= w || (hp(Z) + nn(Z) * w) < m_result.ground_level) {
if(t <= w) {
// Let's try to optimize this angle, there might be a
// viable normal that doesn't collide with the model
@ -1506,7 +1509,7 @@ public:
// save the verified and corrected normal
m_support_nmls.row(fidx) = nn;
if(t > w && (hp(Z) + nn(Z) * w) > m_result.ground_level) {
if(t > w) {
// mark the point for needing a head.
m_iheads.emplace_back(fidx);
} else if( polar >= 3*PI/4 ) {
@ -2237,6 +2240,18 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
return ret;
}
SlicedSupports SLASupportTree::slice(const std::vector<float> &heights,
float cr) const
{
TriangleMesh fullmesh = m_impl->merged_mesh();
fullmesh.merge(get_pad());
TriangleMeshSlicer slicer(&fullmesh);
SlicedSupports ret;
slicer.slice(heights, cr, &ret, get().ctl().cancelfn);
return ret;
}
const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate,
const PoolConfig& pcfg) const
{

View File

@ -181,6 +181,8 @@ public:
/// Get the sliced 2d layers of the support geometry.
SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
SlicedSupports slice(const std::vector<float>&, float closing_radius) const;
/// Adding the "pad" (base pool) under the supports
const TriangleMesh& add_pad(const SliceLayer& baseplate,
const PoolConfig& pcfg) const;

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,14 @@
#include "PrintExport.hpp"
#include "Point.hpp"
#include "MTUtils.hpp"
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
#include "Zipper.hpp"
namespace Slic3r {
enum SLAPrintStep : unsigned int {
slapsRasterize,
slapsValidate,
slapsMergeSlicesAndEval,
slapsRasterize,
slapsCount
};
@ -20,8 +22,7 @@ enum SLAPrintObjectStep : unsigned int {
slaposSupportPoints,
slaposSupportTree,
slaposBasePool,
slaposSliceSupports,
slaposIndexSlices,
slaposSliceSupports,
slaposCount
};
@ -33,7 +34,9 @@ using _SLAPrintObjectBase =
// Layers according to quantized height levels. This will be consumed by
// the printer (rasterizer) in the SLAPrint class.
using LevelID = long long;
// using coord_t = long long;
enum SliceOrigin { soSupport, soModel };
class SLAPrintObject : public _SLAPrintObjectBase
{
@ -41,8 +44,14 @@ private: // Prevents erroneous use by other classes.
using Inherited = _SLAPrintObjectBase;
public:
// I refuse to grantee copying (Tamas)
SLAPrintObject(const SLAPrintObject&) = delete;
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
const SLAPrintObjectConfig& config() const { return m_config; }
const Transform3d& trafo() const { return m_trafo; }
bool is_left_handed() const { return m_left_handed; }
struct Instance {
Instance(ModelID instance_id, const Point &shift, float rotation) : instance_id(instance_id), shift(shift), rotation(rotation) {}
@ -82,39 +91,145 @@ public:
// pad is not, then without the pad, otherwise the full value is returned.
double get_current_elevation() const;
// These two methods should be callable on the client side (e.g. UI thread)
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
// are ready. All the print objects are processed before slapsRasterize so
// it is safe to call them during and/or after slapsRasterize.
const std::vector<ExPolygons>& get_model_slices() const;
const std::vector<ExPolygons>& get_support_slices() const;
// This method returns the support points of this SLAPrintObject.
const std::vector<sla::SupportPoint>& get_support_points() const;
// An index record referencing the slices
// (get_model_slices(), get_support_slices()) where the keys are the height
// levels of the model in scaled-clipper coordinates. The levels correspond
// to the z coordinate of the object coordinate system.
struct SliceRecord {
using Key = float;
// The public Slice record structure. It corresponds to one printable layer.
class SliceRecord {
public:
// this will be the max limit of size_t
static const size_t NONE = size_t(-1);
using Idx = size_t;
static const Idx NONE = Idx(-1); // this will be the max limit of size_t
static const SliceRecord EMPTY;
Idx model_slices_idx = NONE;
Idx support_slices_idx = NONE;
private:
coord_t m_print_z = 0; // Top of the layer
float m_slice_z = 0.f; // Exact level of the slice
float m_height = 0.f; // Height of the sliced layer
size_t m_model_slices_idx = NONE;
size_t m_support_slices_idx = NONE;
const SLAPrintObject *m_po = nullptr;
public:
SliceRecord(coord_t key, float slicez, float height):
m_print_z(key), m_slice_z(slicez), m_height(height) {}
// The key will be the integer height level of the top of the layer.
coord_t print_level() const { return m_print_z; }
// Returns the exact floating point Z coordinate of the slice
float slice_level() const { return m_slice_z; }
// Returns the current layer height
float layer_height() const { return m_height; }
bool is_valid() const { return ! std::isnan(m_slice_z); }
const SLAPrintObject* print_obj() const { assert(m_po); return m_po; }
// Methods for setting the indices into the slice vectors.
void set_model_slice_idx(const SLAPrintObject &po, size_t id) {
m_po = &po; m_model_slices_idx = id;
}
void set_support_slice_idx(const SLAPrintObject& po, size_t id) {
m_po = &po; m_support_slices_idx = id;
}
const ExPolygons& get_slice(SliceOrigin o) const;
};
using SliceIndex = std::map<SliceRecord::Key, SliceRecord>;
private:
// Retrieve the slice index which is readable only after slaposIndexSlices
// is done.
const SliceIndex& get_slice_index() const;
template <class T> inline static T level(const SliceRecord& sr) {
static_assert(std::is_arithmetic<T>::value, "Arithmetic only!");
return std::is_integral<T>::value ? T(sr.print_level()) : T(sr.slice_level());
}
// I refuse to grantee copying (Tamas)
SLAPrintObject(const SLAPrintObject&) = delete;
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
template <class T> inline static SliceRecord create_slice_record(T val) {
static_assert(std::is_arithmetic<T>::value, "Arithmetic only!");
return std::is_integral<T>::value ? SliceRecord{ coord_t(val), 0.f, 0.f } : SliceRecord{ 0, float(val), 0.f };
}
// This is a template method for searching the slice index either by
// an integer key: print_level or a floating point key: slice_level.
// The eps parameter gives the max deviation in + or - direction.
//
// This method can be used in const or non-const contexts as well.
template<class Container, class T>
static auto closest_slice_record(
Container& cont,
T lvl,
T eps = std::numeric_limits<T>::max()) -> decltype (cont.begin())
{
if(cont.empty()) return cont.end();
if(cont.size() == 1 && std::abs(level<T>(cont.front()) - lvl) > eps)
return cont.end();
SliceRecord query = create_slice_record(lvl);
auto it = std::lower_bound(cont.begin(), cont.end(), query,
[](const SliceRecord& r1,
const SliceRecord& r2)
{
return level<T>(r1) < level<T>(r2);
});
T diff = std::abs(level<T>(*it) - lvl);
if(it != cont.begin()) {
auto it_prev = std::prev(it);
T diff_prev = std::abs(level<T>(*it_prev) - lvl);
if(diff_prev < diff) { diff = diff_prev; it = it_prev; }
}
if(diff > eps) it = cont.end();
return it;
}
const std::vector<ExPolygons>& get_model_slices() const { return m_model_slices; }
const std::vector<ExPolygons>& get_support_slices() const;
public:
// /////////////////////////////////////////////////////////////////////////
//
// These methods should be callable on the client side (e.g. UI thread)
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
// are ready. All the print objects are processed before slapsRasterize so
// it is safe to call them during and/or after slapsRasterize.
//
// /////////////////////////////////////////////////////////////////////////
// Retrieve the slice index.
const std::vector<SliceRecord>& get_slice_index() const {
return m_slice_index;
}
// Search slice index for the closest slice to given print_level.
// max_epsilon gives the allowable deviation of the returned slice record's
// level.
const SliceRecord& closest_slice_to_print_level(
coord_t print_level,
coord_t max_epsilon = std::numeric_limits<coord_t>::max()) const
{
auto it = closest_slice_record(m_slice_index, print_level, max_epsilon);
return it == m_slice_index.end() ? SliceRecord::EMPTY : *it;
}
// Search slice index for the closest slice to given slice_level.
// max_epsilon gives the allowable deviation of the returned slice record's
// level. Use SliceRecord::is_valid() to check the result.
const SliceRecord& closest_slice_to_slice_level(
float slice_level,
float max_epsilon = std::numeric_limits<float>::max()) const
{
auto it = closest_slice_record(m_slice_index, slice_level, max_epsilon);
return it == m_slice_index.end() ? SliceRecord::EMPTY : *it;
}
protected:
// to be called from SLAPrint only.
@ -127,11 +242,12 @@ protected:
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false)
{ this->m_config.apply_only(other, keys, ignore_nonexistent); }
void set_trafo(const Transform3d& trafo) {
m_transformed_rmesh.invalidate([this, &trafo](){ m_trafo = trafo; });
void set_trafo(const Transform3d& trafo, bool left_handed) {
m_transformed_rmesh.invalidate([this, &trafo, left_handed](){ m_trafo = trafo; m_left_handed = left_handed; });
}
void set_instances(const std::vector<Instance> &instances) { m_instances = instances; }
template<class InstVec> inline void set_instances(InstVec&& instances) { m_instances = std::forward<InstVec>(instances); }
// Invalidates the step, and its depending steps in SLAPrintObject and SLAPrint.
bool invalidate_step(SLAPrintObjectStep step);
bool invalidate_all_steps();
@ -145,8 +261,12 @@ protected:
private:
// Object specific configuration, pulled from the configuration layer.
SLAPrintObjectConfig m_config;
// Translation in Z + Rotation by Y and Z + Scaling / Mirroring.
Transform3d m_trafo = Transform3d::Identity();
// m_trafo is left handed -> 3x3 affine transformation has negative determinant.
bool m_left_handed = false;
std::vector<Instance> m_instances;
// Individual 2d slice polygons from lower z to higher z levels
@ -154,11 +274,9 @@ private:
// Exact (float) height levels mapped to the slices. Each record contains
// the index to the model and the support slice vectors.
SliceIndex m_slice_index;
std::vector<SliceRecord> m_slice_index;
// The height levels corrected and scaled up in integer values. This will
// be used at rasterization.
std::vector<LevelID> m_level_ids;
std::vector<float> m_model_height_levels;
// Caching the transformed (m_trafo) raw mesh of the object
mutable CachedObject<TriangleMesh> m_transformed_rmesh;
@ -169,6 +287,8 @@ private:
using PrintObjects = std::vector<SLAPrintObject*>;
using SliceRecord = SLAPrintObject::SliceRecord;
class TriangleMesh;
struct SLAPrintStatistics
@ -200,6 +320,37 @@ struct SLAPrintStatistics
}
};
// The implementation of creating zipped archives with wxWidgets
template<> class LayerWriter<Zipper> {
Zipper m_zip;
public:
LayerWriter(const std::string& zipfile_path): m_zip(zipfile_path) {}
void next_entry(const std::string& fname) { m_zip.add_entry(fname); }
void binary_entry(const std::string& fname,
const std::uint8_t* buf,
size_t l)
{
m_zip.add_entry(fname, buf, l);
}
template<class T> inline LayerWriter& operator<<(T&& arg) {
m_zip << std::forward<T>(arg); return *this;
}
bool is_ok() const {
return true; // m_zip blows up if something goes wrong...
}
// After finalize, no writing to the archive will have an effect. The only
// valid operation is to dispose the object calling the destructor which
// should close the file. This method can throw and signal potential errors
// when flushing the archive. This is why its present.
void finalize() { m_zip.finalize(); }
};
/**
* @brief This class is the high level FSM for the SLA printing process.
*
@ -214,6 +365,7 @@ private: // Prevents erroneous use by other classes.
typedef PrintBaseWithState<SLAPrintStep, slapsCount> Inherited;
public:
SLAPrint(): m_stepmask(slapsCount, true) {}
virtual ~SLAPrint() override { this->clear(); }
@ -229,31 +381,79 @@ public:
// Returns true if an object step is done on all objects and there's at least one object.
bool is_step_done(SLAPrintObjectStep step) const;
// Returns true if the last step was finished with success.
bool finished() const override { return this->is_step_done(slaposIndexSlices) && this->Inherited::is_step_done(slapsRasterize); }
bool finished() const override { return this->is_step_done(slaposSliceSupports) && this->Inherited::is_step_done(slapsRasterize); }
template<class Fmt> void export_raster(const std::string& fname) {
if(m_printer) m_printer->save<Fmt>(fname);
template<class Fmt = Zipper>
inline void export_raster(const std::string& fpath,
const std::string& projectname = "")
{
if(m_printer) m_printer->save<Fmt>(fpath, projectname);
}
const PrintObjects& objects() const { return m_objects; }
const SLAPrintConfig& print_config() const { return m_print_config; }
const SLAPrinterConfig& printer_config() const { return m_printer_config; }
const SLAMaterialConfig& material_config() const { return m_material_config; }
const SLAPrintObjectConfig& default_object_config() const { return m_default_object_config; }
std::string output_filename() const override;
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
std::string validate() const override;
// An aggregation of SliceRecord-s from all the print objects for each
// occupied layer. Slice record levels dont have to match exactly.
// They are unified if the level difference is within +/- SCALED_EPSILON
class PrintLayer {
coord_t m_level;
// The collection of slice records for the current level.
std::vector<std::reference_wrapper<const SliceRecord>> m_slices;
std::vector<ClipperLib::Polygon> m_transformed_slices;
template<class Container> void transformed_slices(Container&& c) {
m_transformed_slices = std::forward<Container>(c);
}
friend void SLAPrint::process();
public:
explicit PrintLayer(coord_t lvl) : m_level(lvl) {}
// for being sorted in their container (see m_printer_input)
bool operator<(const PrintLayer& other) const {
return m_level < other.m_level;
}
void add(const SliceRecord& sr) { m_slices.emplace_back(sr); }
coord_t level() const { return m_level; }
auto slices() const -> const decltype (m_slices)& { return m_slices; }
const std::vector<ClipperLib::Polygon> & transformed_slices() const {
return m_transformed_slices;
}
};
// The aggregated and leveled print records from various objects.
// TODO: use this structure for the preview in the future.
const std::vector<PrintLayer>& print_layers() const { return m_printer_input; }
private:
using SLAPrinter = FilePrinter<FilePrinterFormat::SLA_PNGZIP>;
using SLAPrinterPtr = std::unique_ptr<SLAPrinter>;
// Implement same logic as in SLAPrintObject
bool invalidate_step(SLAPrintStep st);
// Invalidate steps based on a set of parameters changed.
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
std::vector<float> calculate_heights(const BoundingBoxf3& bb,
float elevation,
float initial_layer_height,
float layer_height) const;
void fill_statistics();
SLAPrintConfig m_print_config;
SLAPrinterConfig m_printer_config;
SLAMaterialConfig m_material_config;
@ -262,23 +462,8 @@ private:
PrintObjects m_objects;
std::vector<bool> m_stepmask;
// Definition of the print input map. It consists of the slices indexed
// with scaled (clipper) Z coordinates. Also contains the instance
// transformations in scaled and filtered version. This is enough for the
// rasterizer to be able to draw every layer in the right position
using Layer = ExPolygons;
using LayerCopies = std::vector<SLAPrintObject::Instance>;
struct LayerRef {
std::reference_wrapper<const Layer> lref;
std::reference_wrapper<const LayerCopies> copies;
LayerRef(const Layer& lyr, const LayerCopies& cp) :
lref(std::cref(lyr)), copies(std::cref(cp)) {}
};
// One level may contain multiple slices from multiple objects and their
// supports
using LayerRefs = std::vector<LayerRef>;
std::map<LevelID, LayerRefs> m_printer_input;
// Ready-made data for rasterization.
std::vector<PrintLayer> m_printer_input;
// The printer itself
SLAPrinterPtr m_printer;
@ -286,6 +471,15 @@ private:
// Estimated print time, material consumed.
SLAPrintStatistics m_print_statistics;
class StatusReporter {
double m_st = 0;
public:
void operator() (SLAPrint& p, double st, const std::string& msg,
unsigned flags = SlicingStatus::DEFAULT);
double status() const { return m_st; }
} m_report_status;
friend SLAPrintObject;
};

View File

@ -20,9 +20,8 @@
// Disable synchronization of unselected instances
#define DISABLE_INSTANCES_SYNCH (0 && ENABLE_1_42_0_ALPHA1)
// Scene's GUI made using imgui library
#define ENABLE_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_IMGUI)
// Disable imgui dialog for move, rotate and scale gizmos
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
// Use wxDataViewRender instead of wxDataViewCustomRenderer
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
@ -34,8 +33,6 @@
// Changed algorithm to extract euler angles from rotation matrix
#define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
// Added minimum threshold for click and drag movements
#define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4)
// Modified initial default placement of generic subparts
#define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
// Bunch of fixes related to volumes centering
@ -59,4 +56,5 @@
// Toolbars and Gizmos use icons imported from svg files
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
#endif // _technologies_h_

View File

@ -55,7 +55,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& f
stl.stats.original_num_facets = stl.stats.number_of_facets;
stl_allocate(&stl);
for (int i = 0; i < stl.stats.number_of_facets; i++) {
for (uint32_t i = 0; i < stl.stats.number_of_facets; i++) {
stl_facet facet;
facet.vertex[0] = points[facets[i](0)].cast<float>();
facet.vertex[1] = points[facets[i](1)].cast<float>();
@ -125,9 +125,9 @@ void TriangleMesh::repair()
float tolerance = stl.stats.shortest_edge;
float increment = stl.stats.bounding_diameter / 10000.0;
int iterations = 2;
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
for (int i = 0; i < iterations; i++) {
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_nearby";
@ -143,7 +143,7 @@ void TriangleMesh::repair()
}
// remove_unconnected
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_remove_unconnected_facets";
#endif /* SLIC3R_TRACE_REPAIR */
@ -212,9 +212,9 @@ void TriangleMesh::check_topology()
float tolerance = stl.stats.shortest_edge;
float increment = stl.stats.bounding_diameter / 10000.0;
int iterations = 2;
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
for (int i = 0; i < iterations; i++) {
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
stl_check_facets_nearby(&stl, tolerance);
//printf(" Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed);
@ -273,6 +273,11 @@ void TriangleMesh::translate(float x, float y, float z)
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::translate(const Vec3f &displacement)
{
translate(displacement(0), displacement(1), displacement(2));
}
void TriangleMesh::rotate(float angle, const Axis &axis)
{
if (angle == 0.f)
@ -314,10 +319,15 @@ void TriangleMesh::mirror(const Axis &axis)
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::transform(const Transform3d& t)
void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
{
stl_transform(&stl, t);
stl_invalidate_shared_vertices(&stl);
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
this->repair();
stl_reverse_all_facets(&stl);
}
}
void TriangleMesh::align_to_origin()
@ -338,113 +348,79 @@ void TriangleMesh::rotate(double angle, Point* center)
this->translate(c(0), c(1), 0);
}
bool TriangleMesh::has_multiple_patches() const
/**
* Calculates whether or not the mesh is splittable.
*/
bool TriangleMesh::is_splittable() const
{
// we need neighbors
if (!this->repaired)
throw std::runtime_error("split() requires repair()");
if (this->stl.stats.number_of_facets == 0)
return false;
std::vector<unsigned char> visited;
find_unvisited_neighbors(visited);
std::vector<int> facet_queue(this->stl.stats.number_of_facets, 0);
std::vector<char> facet_visited(this->stl.stats.number_of_facets, false);
int facet_queue_cnt = 1;
facet_queue[0] = 0;
facet_visited[0] = true;
while (facet_queue_cnt > 0) {
int facet_idx = facet_queue[-- facet_queue_cnt];
facet_visited[facet_idx] = true;
for (int j = 0; j < 3; ++ j) {
int neighbor_idx = this->stl.neighbors_start[facet_idx].neighbor[j];
if (neighbor_idx != -1 && ! facet_visited[neighbor_idx])
facet_queue[facet_queue_cnt ++] = neighbor_idx;
}
}
// If any of the face was not visited at the first time, return "multiple bodies".
for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx)
if (! facet_visited[facet_idx])
return true;
return false;
// Try finding an unvisited facet. If there are none, the mesh is not splittable.
auto it = std::find(visited.begin(), visited.end(), false);
return it != visited.end();
}
size_t TriangleMesh::number_of_patches() const
/**
* Visit all unvisited neighboring facets that are reachable from the first unvisited facet,
* and return them.
*
* @param facet_visited A reference to a vector of booleans. Contains whether or not a
* facet with the same index has been visited.
* @return A deque with all newly visited facets.
*/
std::deque<uint32_t> TriangleMesh::find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const
{
// we need neighbors
// Make sure we're not operating on a broken mesh.
if (!this->repaired)
throw std::runtime_error("split() requires repair()");
if (this->stl.stats.number_of_facets == 0)
return false;
throw std::runtime_error("find_unvisited_neighbors() requires repair()");
std::vector<int> facet_queue(this->stl.stats.number_of_facets, 0);
std::vector<char> facet_visited(this->stl.stats.number_of_facets, false);
int facet_queue_cnt = 0;
size_t num_bodies = 0;
for (;;) {
// Find a seeding triangle for a new body.
int facet_idx = 0;
for (; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx)
if (! facet_visited[facet_idx]) {
// A seed triangle was found.
facet_queue[facet_queue_cnt ++] = facet_idx;
facet_visited[facet_idx] = true;
break;
}
if (facet_idx == this->stl.stats.number_of_facets)
// No seed found.
break;
++ num_bodies;
while (facet_queue_cnt > 0) {
int facet_idx = facet_queue[-- facet_queue_cnt];
facet_visited[facet_idx] = true;
for (int j = 0; j < 3; ++ j) {
int neighbor_idx = this->stl.neighbors_start[facet_idx].neighbor[j];
if (neighbor_idx != -1 && ! facet_visited[neighbor_idx])
facet_queue[facet_queue_cnt ++] = neighbor_idx;
}
}
// If the visited list is empty, populate it with false for every facet.
if (facet_visited.empty())
facet_visited = std::vector<unsigned char>(this->stl.stats.number_of_facets, false);
// Find the first unvisited facet.
std::queue<uint32_t> facet_queue;
std::deque<uint32_t> facets;
auto facet = std::find(facet_visited.begin(), facet_visited.end(), false);
if (facet != facet_visited.end()) {
uint32_t idx = uint32_t(facet - facet_visited.begin());
facet_queue.push(idx);
facet_visited[idx] = true;
facets.emplace_back(idx);
}
return num_bodies;
// Traverse all reachable neighbors and mark them as visited.
while (! facet_queue.empty()) {
uint32_t facet_idx = facet_queue.front();
facet_queue.pop();
for (int neighbor_idx : this->stl.neighbors_start[facet_idx].neighbor)
if (neighbor_idx != -1 && ! facet_visited[neighbor_idx]) {
facet_queue.push(uint32_t(neighbor_idx));
facet_visited[neighbor_idx] = true;
facets.emplace_back(uint32_t(neighbor_idx));
}
}
return facets;
}
/**
* Splits a mesh into multiple meshes when possible.
*
* @return A TriangleMeshPtrs with the newly created meshes.
*/
TriangleMeshPtrs TriangleMesh::split() const
{
TriangleMeshPtrs meshes;
std::vector<unsigned char> facet_visited(this->stl.stats.number_of_facets, false);
// we need neighbors
if (!this->repaired)
throw std::runtime_error("split() requires repair()");
// loop while we have remaining facets
// Loop while we have remaining facets.
std::vector<unsigned char> facet_visited;
TriangleMeshPtrs meshes;
for (;;) {
// get the first facet
std::queue<int> facet_queue;
std::deque<int> facets;
for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx) {
if (! facet_visited[facet_idx]) {
// if facet was not seen put it into queue and start searching
facet_queue.push(facet_idx);
break;
}
}
if (facet_queue.empty())
std::deque<uint32_t> facets = find_unvisited_neighbors(facet_visited);
if (facets.empty())
break;
while (! facet_queue.empty()) {
int facet_idx = facet_queue.front();
facet_queue.pop();
if (! facet_visited[facet_idx]) {
facets.emplace_back(facet_idx);
for (int j = 0; j < 3; ++ j)
facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]);
facet_visited[facet_idx] = true;
}
}
// Create a new mesh for the part that was just split off.
TriangleMesh* mesh = new TriangleMesh;
meshes.emplace_back(mesh);
mesh->stl.stats.type = inmemory;
@ -452,14 +428,15 @@ TriangleMeshPtrs TriangleMesh::split() const
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
stl_clear_error(&mesh->stl);
stl_allocate(&mesh->stl);
// Assign the facets to the new mesh.
bool first = true;
for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); ++ facet) {
for (auto facet = facets.begin(); facet != facets.end(); ++ facet) {
mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet];
stl_facet_stats(&mesh->stl, this->stl.facet_start[*facet], first);
}
}
return meshes;
}
@ -476,7 +453,7 @@ void TriangleMesh::merge(const TriangleMesh &mesh)
stl_reallocate(&this->stl);
// copy facets
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i)
for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++ i)
this->stl.facet_start[number_of_facets + i] = mesh.stl.facet_start[i];
// update size
@ -489,7 +466,7 @@ ExPolygons TriangleMesh::horizontal_projection() const
{
Polygons pp;
pp.reserve(this->stl.stats.number_of_facets);
for (int i = 0; i < this->stl.stats.number_of_facets; ++ i) {
for (uint32_t i = 0; i < this->stl.stats.number_of_facets; ++ i) {
stl_facet* facet = &this->stl.facet_start[i];
Polygon p;
p.points.resize(3);
@ -531,7 +508,7 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) c
BoundingBoxf3 bbox;
if (stl.v_shared == nullptr) {
// Using the STL faces.
for (int i = 0; i < this->facets_count(); ++ i) {
for (size_t i = 0; i < this->facets_count(); ++ i) {
const stl_facet &facet = this->stl.facet_start[i];
for (size_t j = 0; j < 3; ++ j)
bbox.merge(trafo * facet.vertex[j].cast<double>());
@ -656,7 +633,7 @@ void TriangleMeshSlicer::init(TriangleMesh *_mesh, throw_on_cancel_callback_type
};
std::vector<EdgeToFace> edges_map;
edges_map.assign(this->mesh->stl.stats.number_of_facets * 3, EdgeToFace());
for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
for (int i = 0; i < 3; ++ i) {
EdgeToFace &e2f = edges_map[facet_idx*3+i];
e2f.vertex_low = this->mesh->stl.v_indices[facet_idx].vertex[i];
@ -905,7 +882,6 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
const stl_normal &normal = this->mesh->stl.facet_start[facet_idx].normal;
// We may ignore this edge for slicing purposes, but we may still use it for object cutting.
FacetSliceType result = Slicing;
const stl_neighbors &nbr = this->mesh->stl.neighbors_start[facet_idx];
if (min_z == max_z) {
// All three vertices are aligned with slice_z.
line_out->edge_type = feHorizontal;
@ -917,8 +893,6 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
}
} else {
// Two vertices are aligned with the cutting plane, the third vertex is below or above the cutting plane.
int nbr_idx = j % 3;
int nbr_face = nbr.neighbor[nbr_idx];
// Is the third vertex below the cutting plane?
bool third_below = v0.z() < slice_z || v1.z() < slice_z || v2.z() < slice_z;
// Two vertices on the cutting plane, the third vertex is below the plane. Consider the edge to be part of the slice
@ -1697,7 +1671,7 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - slicing object";
float scaled_z = scale_(z);
for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
stl_facet* facet = &this->mesh->stl.facet_start[facet_idx];
// find facet extents

View File

@ -40,6 +40,7 @@ public:
void scale(float factor);
void scale(const Vec3d &versor);
void translate(float x, float y, float z);
void translate(const Vec3f &displacement);
void rotate(float angle, const Axis &axis);
void rotate(float angle, const Vec3d& axis);
void rotate_x(float angle) { this->rotate(angle, X); }
@ -49,7 +50,7 @@ public:
void mirror_x() { this->mirror(X); }
void mirror_y() { this->mirror(Y); }
void mirror_z() { this->mirror(Z); }
void transform(const Transform3d& t);
void transform(const Transform3d& t, bool fix_left_handed = false);
void align_to_origin();
void rotate(double angle, Point* center);
TriangleMeshPtrs split() const;
@ -68,18 +69,14 @@ public:
size_t facets_count() const { return this->stl.stats.number_of_facets; }
bool empty() const { return this->facets_count() == 0; }
// Returns true, if there are two and more connected patches in the mesh.
// Returns false, if one or zero connected patch is in the mesh.
bool has_multiple_patches() const;
// Count disconnected triangle patches.
size_t number_of_patches() const;
bool is_splittable() const;
stl_file stl;
bool repaired;
private:
void require_shared_vertices();
std::deque<uint32_t> find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const;
friend class TriangleMeshSlicer;
};

View File

@ -208,7 +208,7 @@ public:
// Shorten the dhms time by removing the seconds, rounding the dhm to full minutes
// and removing spaces.
static std::string short_time(const std::string &time)
inline std::string short_time(const std::string &time)
{
// Parse the dhms time format.
int days = 0;
@ -247,7 +247,7 @@ static std::string short_time(const std::string &time)
}
// Returns the given time is seconds in format DDd HHh MMm SSs
static std::string get_time_dhms(float time_in_secs)
inline std::string get_time_dhms(float time_in_secs)
{
int days = (int)(time_in_secs / 86400.0f);
time_in_secs -= (float)days * 86400.0f;

223
src/libslic3r/Zipper.cpp Normal file
View File

@ -0,0 +1,223 @@
#include <exception>
#include <sstream>
#include <iostream>
#include "Zipper.hpp"
#include "miniz/miniz_zip.h"
#include <boost/log/trivial.hpp>
#include "I18N.hpp"
//! macro used to mark string used at localization,
//! return same string
#define L(s) Slic3r::I18N::translate(s)
#if defined(_MSC_VER) && _MSC_VER <= 1800 || __cplusplus < 201103L
#define SLIC3R_NORETURN
#elif __cplusplus >= 201103L
#define SLIC3R_NORETURN [[noreturn]]
#endif
namespace Slic3r {
class Zipper::Impl {
public:
mz_zip_archive arch;
std::string m_zipname;
static std::string get_errorstr(mz_zip_error mz_err)
{
switch (mz_err)
{
case MZ_ZIP_NO_ERROR:
return "no error";
case MZ_ZIP_UNDEFINED_ERROR:
return L("undefined error");
case MZ_ZIP_TOO_MANY_FILES:
return L("too many files");
case MZ_ZIP_FILE_TOO_LARGE:
return L("file too large");
case MZ_ZIP_UNSUPPORTED_METHOD:
return L("unsupported method");
case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
return L("unsupported encryption");
case MZ_ZIP_UNSUPPORTED_FEATURE:
return L("unsupported feature");
case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
return L("failed finding central directory");
case MZ_ZIP_NOT_AN_ARCHIVE:
return L("not a ZIP archive");
case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
return L("invalid header or archive is corrupted");
case MZ_ZIP_UNSUPPORTED_MULTIDISK:
return L("unsupported multidisk archive");
case MZ_ZIP_DECOMPRESSION_FAILED:
return L("decompression failed or archive is corrupted");
case MZ_ZIP_COMPRESSION_FAILED:
return L("compression failed");
case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
return L("unexpected decompressed size");
case MZ_ZIP_CRC_CHECK_FAILED:
return L("CRC-32 check failed");
case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
return L("unsupported central directory size");
case MZ_ZIP_ALLOC_FAILED:
return L("allocation failed");
case MZ_ZIP_FILE_OPEN_FAILED:
return L("file open failed");
case MZ_ZIP_FILE_CREATE_FAILED:
return L("file create failed");
case MZ_ZIP_FILE_WRITE_FAILED:
return L("file write failed");
case MZ_ZIP_FILE_READ_FAILED:
return L("file read failed");
case MZ_ZIP_FILE_CLOSE_FAILED:
return L("file close failed");
case MZ_ZIP_FILE_SEEK_FAILED:
return L("file seek failed");
case MZ_ZIP_FILE_STAT_FAILED:
return L("file stat failed");
case MZ_ZIP_INVALID_PARAMETER:
return L("invalid parameter");
case MZ_ZIP_INVALID_FILENAME:
return L("invalid filename");
case MZ_ZIP_BUF_TOO_SMALL:
return L("buffer too small");
case MZ_ZIP_INTERNAL_ERROR:
return L("internal error");
case MZ_ZIP_FILE_NOT_FOUND:
return L("file not found");
case MZ_ZIP_ARCHIVE_TOO_LARGE:
return L("archive is too large");
case MZ_ZIP_VALIDATION_FAILED:
return L("validation failed");
case MZ_ZIP_WRITE_CALLBACK_FAILED:
return L("write calledback failed");
default:
break;
}
return "unknown error";
}
std::string formatted_errorstr() const
{
return L("Error with zip archive") + " " + m_zipname + ": " +
get_errorstr(arch.m_last_error) + "!";
}
SLIC3R_NORETURN void blow_up() const
{
throw std::runtime_error(formatted_errorstr());
}
bool is_alive()
{
return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
}
};
Zipper::Zipper(const std::string &zipfname, e_compression compression)
{
m_impl.reset(new Impl());
m_compression = compression;
m_impl->m_zipname = zipfname;
memset(&m_impl->arch, 0, sizeof(m_impl->arch));
// Initialize the archive data
if(!mz_zip_writer_init_file(&m_impl->arch, zipfname.c_str(), 0))
m_impl->blow_up();
}
Zipper::~Zipper()
{
if(m_impl->is_alive()) {
// Flush the current entry if not finished yet.
try { finish_entry(); } catch(...) {
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
}
if(!mz_zip_writer_finalize_archive(&m_impl->arch))
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
}
// The file should be closed no matter what...
if(!mz_zip_writer_end(&m_impl->arch))
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
}
Zipper::Zipper(Zipper &&m):
m_impl(std::move(m.m_impl)),
m_data(std::move(m.m_data)),
m_entry(std::move(m.m_entry)),
m_compression(m.m_compression) {}
Zipper &Zipper::operator=(Zipper &&m) {
m_impl = std::move(m.m_impl);
m_data = std::move(m.m_data);
m_entry = std::move(m.m_entry);
m_compression = m.m_compression;
return *this;
}
void Zipper::add_entry(const std::string &name)
{
if(!m_impl->is_alive()) return;
finish_entry(); // finish previous business
m_entry = name;
}
void Zipper::add_entry(const std::string &name, const uint8_t *data, size_t l)
{
if(!m_impl->is_alive()) return;
finish_entry();
mz_uint cmpr = MZ_NO_COMPRESSION;
switch (m_compression) {
case NO_COMPRESSION: cmpr = MZ_NO_COMPRESSION; break;
case FAST_COMPRESSION: cmpr = MZ_BEST_SPEED; break;
case TIGHT_COMPRESSION: cmpr = MZ_BEST_COMPRESSION; break;
}
if(!mz_zip_writer_add_mem(&m_impl->arch, name.c_str(), data, l, cmpr))
m_impl->blow_up();
m_entry.clear();
m_data.clear();
}
void Zipper::finish_entry()
{
if(!m_impl->is_alive()) return;
if(!m_data.empty() && !m_entry.empty()) {
mz_uint compression = MZ_NO_COMPRESSION;
switch (m_compression) {
case NO_COMPRESSION: compression = MZ_NO_COMPRESSION; break;
case FAST_COMPRESSION: compression = MZ_BEST_SPEED; break;
case TIGHT_COMPRESSION: compression = MZ_BEST_COMPRESSION; break;
}
if(!mz_zip_writer_add_mem(&m_impl->arch, m_entry.c_str(),
m_data.c_str(),
m_data.size(),
compression)) m_impl->blow_up();
}
m_data.clear();
m_entry.clear();
}
void Zipper::finalize()
{
finish_entry();
if(m_impl->is_alive()) if(!mz_zip_writer_finalize_archive(&m_impl->arch))
m_impl->blow_up();
}
}

90
src/libslic3r/Zipper.hpp Normal file
View File

@ -0,0 +1,90 @@
#ifndef ZIPPER_HPP
#define ZIPPER_HPP
#include <string>
#include <memory>
namespace Slic3r {
// Class for creating zip archives.
class Zipper {
public:
// Three compression levels supported
enum e_compression {
NO_COMPRESSION,
FAST_COMPRESSION,
TIGHT_COMPRESSION
};
private:
class Impl;
std::unique_ptr<Impl> m_impl;
std::string m_data;
std::string m_entry;
e_compression m_compression;
public:
// Will blow up in a runtime exception if the file cannot be created.
explicit Zipper(const std::string& zipfname,
e_compression level = NO_COMPRESSION);
~Zipper();
// No copies allwed, this is a file resource...
Zipper(const Zipper&) = delete;
Zipper& operator=(const Zipper&) = delete;
// Moving is fine.
// Zipper(Zipper&&) = default;
// Zipper& operator=(Zipper&&) = default;
// All becouse of VS2013:
Zipper(Zipper &&m);
Zipper& operator=(Zipper &&m);
/// Adding an entry means a file inside the new archive. Name param is the
/// name of the new file. To create directories, append a forward slash.
/// The previous entry is finished (see finish_entry)
void add_entry(const std::string& name);
/// Add a new binary file entry with an instantly given byte buffer.
/// This method throws exactly like finish_entry() does.
void add_entry(const std::string& name, const std::uint8_t* data, size_t l);
// Writing data to the archive works like with standard streams. The target
// within the zip file is the entry created with the add_entry method.
// Template taking only arithmetic values, that std::to_string can handle.
template<class T> inline
typename std::enable_if<std::is_arithmetic<T>::value, Zipper&>::type
operator<<(T &&val) {
return this->operator<<(std::to_string(std::forward<T>(val)));
}
// Template applied only for types that std::string can handle for append
// and copy. This includes c style strings...
template<class T> inline
typename std::enable_if<!std::is_arithmetic<T>::value, Zipper&>::type
operator<<(T &&val) {
if(m_data.empty()) m_data = std::forward<T>(val);
else m_data.append(val);
return *this;
}
/// Finishing an entry means that subsequent writes will no longer be
/// appended to the previous entry. They will be written into the internal
/// buffer and ones an entry is added, the buffer will bind to the new entry
/// If the buffer was written, but no entry was added, the buffer will be
/// cleared after this call.
///
/// This method will throw a runtime exception if an error occures. The
/// entry will still be open (with the data intact) but the state of the
/// file is up to minz after the erroneous write.
void finish_entry();
void finalize();
};
}
#endif // ZIPPER_HPP

View File

@ -2897,6 +2897,8 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi)
return ret;
}
#include <boost/nowide/cstdio.hpp>
NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
{
FILE* fp = NULL;
@ -2904,8 +2906,8 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
char* data = NULL;
NSVGimage* image = NULL;
fp = fopen(filename, "rb");
if (!fp) goto error;
fp = boost::nowide::fopen(filename, "rb");
if (!fp) goto error;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);

View File

@ -1,4 +0,0 @@
png++ is written by Alexander Shulgin (alex dot shulgin at gmail dot com)
Copyright (C) 2007,2008
When writing to me be sure to put png++: in the subject :-)

View File

@ -1,25 +0,0 @@
Copying png++ is subject to the following license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,60 +0,0 @@
Version 0.2.7:
- Added solid_pixel_buffer (patch by Andrey Potapov).
- Fixed some compilation problems on Win32.
Version 0.2.5:
- Fixed compatibility with newer libpng versions (>= 1.4)
- Fixed compilation on FreeBSD.
- Fixed tRNS handling with transformations.
- Added IO transformation debugging facility.
- Better organized test suite.
Version 0.2.3:
- Fixed numerous `already defined' errors due to require_color_space
implementation.
- Added `config.hpp'.
- Fixed `strerror' usage.
- Minor docs fixes.
Version 0.2.1:
- Added support for tRNS chunk.
- Added non-std IO streams support.
- Fixed 16-bit endianness problems.
- Improved test script.
Version 0.2.0:
- Added support for 16-bit data (RGB, RGBA, Grayscale and Gray+Alpha
color types)
- Added support for packed 1-, 2- or 4-bit pixels (Grayscale and
Indexed colors)
- Fixed interlace handling code which was severely broken
- Added possibility to process images without reading the entire
image into memory
- Internals are refactored while the client interface is mostly
unchanged
- Added intensive test suite
- Added documentation

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_COLOR_HPP_INCLUDED
#define PNGPP_COLOR_HPP_INCLUDED
#include "types.hpp"
namespace png
{
/**
* \brief PNG color struct extension. Adds constructors.
*/
struct color
: png_color
{
explicit color(byte r = 0, byte g = 0, byte b = 0)
{
this->red = r;
this->green = g;
this->blue = b;
}
/**
* \brief Initializes color with a copy of png_color object.
*/
color(png_color const& other)
{
this->red = other.red;
this->green = other.green;
this->blue = other.blue;
}
};
} // namespace png
#endif // PNGPP_COLOR_HPP_INCLUDED

View File

@ -1,74 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_END_INFO_HPP_INCLUDED
#define PNGPP_END_INFO_HPP_INCLUDED
#include "info_base.hpp"
namespace png
{
/**
* \brief Internal class to hold PNG ending %info.
*
* \see info, info_base
*/
class end_info
: public info_base
{
public:
end_info(io_base& io, png_struct* png)
: info_base(io, png)
{
}
void destroy()
{
assert(m_info);
png_destroy_info_struct(m_png, & m_info);
}
void read()
{
png_read_end(m_png, m_info);
}
void write() const
{
png_write_end(m_png, m_info);
}
// TODO: add methods to read/write text comments etc.
};
} // namespace png
#endif // PNGPP_END_INFO_HPP_INCLUDED

View File

@ -1,125 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_ERROR_HPP_INCLUDED
#define PNGPP_ERROR_HPP_INCLUDED
/* check if we have strerror_s or strerror_r, prefer the former which is C11 std */
#ifdef __STDC_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#define HAVE_STRERROR_S 1
#else
#undef HAVE_STRERROR_S
#endif
#include <string>
#include <stdexcept>
#include <cerrno>
#include <cstdlib>
#include <cstring>
namespace png
{
/**
* \brief Exception class to represent runtime errors related to
* png++ operation.
*/
class error
: public std::runtime_error
{
public:
/**
* \param message error description
*/
explicit error(std::string const& message)
: std::runtime_error(message)
{
}
};
/**
* \brief Exception class to represent standard library errors
* (generally IO).
*
* \see reader, writer
*/
class std_error
: public std::runtime_error
{
public:
/**
* Constructs an std_error object. The \a message string is
* appended with <tt>": "</tt> and the error description as
* returned by \c strerror(\a error).
*
* \param message error description
* \param error error number
*/
explicit std_error(std::string const& message, int errnum = errno)
: std::runtime_error((message + ": ") + thread_safe_strerror(errnum))
{
}
protected:
static std::string thread_safe_strerror(int errnum)
{
#define ERRBUF_SIZE 512
#ifdef HAVE_STRERROR_S
char buf[ERRBUF_SIZE] = { 0 };
strerror_s(buf, ERRBUF_SIZE, errnum);
return std::string(buf);
#else
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
char buf[ERRBUF_SIZE] = { 0 };
strerror_r(errnum, buf, ERRBUF_SIZE);
return std::string(buf);
#elif _GNU_SOURCE
/* GNU variant can return a pointer to static buffer instead of buf */
char buf[ERRBUF_SIZE] = { 0 };
return std::string(strerror_r(errnum, buf, ERRBUF_SIZE));
#else
return std::string("An error occured with errnum ") +
std::to_string(errnum) +
". Converting to the appropriate error message is disabled"
"in this instance of the png++ library.";
#endif
#endif
#undef ERRBUF_SIZE
}
};
} // namespace png
#endif // PNGPP_ERROR_HPP_INCLUDED

View File

@ -1,215 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_IMAGE_INFO_HPP_INCLUDED
#define PNGPP_IMAGE_INFO_HPP_INCLUDED
#include "types.hpp"
#include "palette.hpp"
#include "tRNS.hpp"
#include "pixel_traits.hpp"
namespace png
{
/**
* \brief Holds information about PNG image.
*
* \see image, generator, consumer
*/
class image_info
{
public:
/**
* \brief Constructs the image_info object with default values
* for color_type, interlace_type, compression_method and
* filter_type.
*/
image_info()
: m_width(0),
m_height(0),
m_bit_depth(0),
m_color_type(color_type_none),
m_interlace_type(interlace_none),
m_compression_type(compression_type_default),
m_filter_type(filter_type_default),
m_gamma(0.0)
{
}
uint_32 get_width() const
{
return m_width;
}
void set_width(uint_32 width)
{
m_width = width;
}
uint_32 get_height() const
{
return m_height;
}
void set_height(uint_32 height)
{
m_height = height;
}
color_type get_color_type() const
{
return m_color_type;
}
void set_color_type(color_type color_space)
{
m_color_type = color_space;
}
int get_bit_depth() const
{
return m_bit_depth;
}
void set_bit_depth(int bit_depth)
{
m_bit_depth = bit_depth;
}
interlace_type get_interlace_type() const
{
return m_interlace_type;
}
void set_interlace_type(interlace_type interlace)
{
m_interlace_type = interlace;
}
compression_type get_compression_type() const
{
return m_compression_type;
}
void set_compression_type(compression_type compression)
{
m_compression_type = compression;
}
filter_type get_filter_type() const
{
return m_filter_type;
}
void set_filter_type(filter_type filter)
{
m_filter_type = filter;
}
palette const& get_palette() const
{
return m_palette;
}
palette& get_palette()
{
return m_palette;
}
void set_palette(palette const& plte)
{
m_palette = plte;
}
/**
* \brief Removes all entries from the palette.
*/
void drop_palette()
{
m_palette.clear();
}
tRNS const& get_tRNS() const
{
return m_tRNS;
}
tRNS& get_tRNS()
{
return m_tRNS;
}
void set_tRNS(tRNS const& trns)
{
m_tRNS = trns;
}
double get_gamma() const
{
return m_gamma;
}
void set_gamma(double gamma)
{
m_gamma = gamma;
}
protected:
uint_32 m_width;
uint_32 m_height;
int m_bit_depth;
color_type m_color_type;
interlace_type m_interlace_type;
compression_type m_compression_type;
filter_type m_filter_type;
palette m_palette;
tRNS m_tRNS;
double m_gamma;
};
/**
* \brief Returns an image_info object with color_type and
* bit_depth fields setup appropriate for the \c pixel type.
*/
template< typename pixel >
image_info
make_image_info()
{
typedef pixel_traits< pixel > traits;
image_info info;
info.set_color_type(traits::get_color_type());
info.set_bit_depth(traits::get_bit_depth());
return info;
}
} // namespace png
#endif // PNGPP_IMAGE_INFO_HPP_INCLUDED

View File

@ -1,186 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_INFO_HPP_INCLUDED
#define PNGPP_INFO_HPP_INCLUDED
#include <cassert>
#include "info_base.hpp"
#include "image_info.hpp"
namespace png
{
/**
* \brief Holds information about PNG image. Adapter class for IO
* image operations.
*/
class info
: public info_base,
public image_info
{
public:
info(io_base& io, png_struct* png)
: info_base(io, png)
{
}
void read()
{
assert(m_png);
assert(m_info);
png_read_info(m_png, m_info);
png_get_IHDR(m_png,
m_info,
& m_width,
& m_height,
reinterpret_cast< int* >(& m_bit_depth),
reinterpret_cast< int* >(& m_color_type),
reinterpret_cast< int* >(& m_interlace_type),
reinterpret_cast< int* >(& m_compression_type),
reinterpret_cast< int* >(& m_filter_type));
if (png_get_valid(m_png, m_info, chunk_PLTE) == chunk_PLTE)
{
png_color* colors = 0;
int count = 0;
png_get_PLTE(m_png, m_info, & colors, & count);
m_palette.assign(colors, colors + count);
}
#ifdef PNG_tRNS_SUPPORTED
if (png_get_valid(m_png, m_info, chunk_tRNS) == chunk_tRNS)
{
if (m_color_type == color_type_palette)
{
int count;
byte* values;
if (png_get_tRNS(m_png, m_info, & values, & count, NULL)
!= PNG_INFO_tRNS)
{
throw error("png_get_tRNS() failed");
}
m_tRNS.assign(values, values + count);
}
}
#endif
#ifdef PNG_gAMA_SUPPORTED
if (png_get_valid(m_png, m_info, chunk_gAMA) == chunk_gAMA)
{
#ifdef PNG_FLOATING_POINT_SUPPORTED
if (png_get_gAMA(m_png, m_info, &m_gamma) != PNG_INFO_gAMA)
{
throw error("png_get_gAMA() failed");
}
#else
png_fixed_point gamma = 0;
if (png_get_gAMA_fixed(m_png, m_info, &gamma) != PNG_INFO_gAMA)
{
throw error("png_get_gAMA_fixed() failed");
}
m_gamma = gamma / 100000.0;
#endif
}
#endif
}
void write() const
{
assert(m_png);
assert(m_info);
sync_ihdr();
if (m_color_type == color_type_palette)
{
if (! m_palette.empty())
{
png_set_PLTE(m_png, m_info,
const_cast< color* >(& m_palette[0]),
(int) m_palette.size());
}
if (! m_tRNS.empty())
{
#ifdef PNG_tRNS_SUPPORTED
png_set_tRNS(m_png, m_info,
const_cast< byte* >(& m_tRNS[0]),
m_tRNS.size(),
NULL);
#else
throw error("attempted to write tRNS chunk; recompile with PNG_tRNS_SUPPORTED");
#endif
}
}
if (m_gamma > 0)
{
#ifdef PNG_gAMA_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
png_set_gAMA(m_png, m_info, m_gamma);
#else
png_set_gAMA_fixed(m_png, m_info,
(png_fixed_point)(m_gamma * 100000));
#endif
#else
throw error("attempted to write gAMA chunk; recompile with PNG_gAMA_SUPPORTED");
#endif
}
png_write_info(m_png, m_info);
}
void update()
{
assert(m_png);
assert(m_info);
sync_ihdr();
png_read_update_info(m_png, m_info);
}
protected:
void sync_ihdr(void) const
{
png_set_IHDR(m_png,
m_info,
m_width,
m_height,
m_bit_depth,
m_color_type,
m_interlace_type,
m_compression_type,
m_filter_type);
}
};
} // namespace png
#endif // PNGPP_INFO_HPP_INCLUDED

View File

@ -1,77 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_INFO_BASE_HPP_INCLUDED
#define PNGPP_INFO_BASE_HPP_INCLUDED
#include <cassert>
#include "error.hpp"
#include "types.hpp"
namespace png
{
class io_base;
/**
* \brief Internal class to hold PNG info or end_info.
*/
class info_base
{
info_base(info_base const&);
info_base& operator=(info_base const&);
public:
info_base(io_base& io, png_struct* png)
: m_io(io),
m_png(png),
m_info(png_create_info_struct(m_png))
{
}
png_info* get_png_info() const
{
return m_info;
}
png_info** get_png_info_ptr()
{
return & m_info;
}
protected:
io_base& m_io;
png_struct* m_png;
png_info* m_info;
};
} // namespace png
#endif // PNGPP_INFO_BASE_HPP_INCLUDED

View File

@ -1,467 +0,0 @@
/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_IO_BASE_HPP_INCLUDED
#define PNGPP_IO_BASE_HPP_INCLUDED
#include <cassert>
#include <cstdio>
#include <cstdarg>
#include "error.hpp"
#include "info.hpp"
#include "end_info.hpp"
static void
trace_io_transform(char const* fmt, ...)
{
#ifdef DEBUG_IO_TRANSFORM
va_list va;
va_start(va, fmt);
fprintf(stderr, "TRANSFORM_IO: ");
vfprintf(stderr, fmt, va);
va_end(va);
#endif
}
#define TRACE_IO_TRANSFORM trace_io_transform
namespace png
{
/**
* \brief Base class for PNG reader/writer classes.
*
* \see reader, writer
*/
class io_base
{
io_base(io_base const&);
io_base& operator=(io_base const&);
public:
explicit io_base(png_struct* png)
: m_png(png),
m_info(*this, m_png),
m_end_info(*this, m_png)
{
}
~io_base()
{
assert(! m_png);
assert(! m_info.get_png_info());
assert(! m_end_info.get_png_info());
}
png_struct* get_png_struct() const
{
return m_png;
}
info& get_info()
{
return m_info;
}
info const& get_info() const
{
return m_info;
}
image_info const& get_image_info() const
{
return m_info;
}
void set_image_info(image_info const& info)
{
static_cast< image_info& >(m_info) = info; // slice it
}
end_info& get_end_info()
{
return m_end_info;
}
end_info const& get_end_info() const
{
return m_end_info;
}
//////////////////////////////////////////////////////////////////////
// info accessors
//
uint_32 get_width() const
{
return m_info.get_width();
}
void set_width(uint_32 width)
{
m_info.set_width(width);
}
uint_32 get_height() const
{
return m_info.get_height();
}
void set_height(uint_32 height)
{
m_info.set_height(height);
}
color_type get_color_type() const
{
return m_info.get_color_type();
}
void set_color_type(color_type color_space)
{
m_info.set_color_type(color_space);
}
int get_bit_depth() const
{
return m_info.get_bit_depth();
}
void set_bit_depth(int bit_depth)
{
m_info.set_bit_depth(bit_depth);
}
interlace_type get_interlace_type() const
{
return m_info.get_interlace_type();
}
void set_interlace_type(interlace_type interlace)
{
m_info.set_interlace_type(interlace);
}
compression_type get_compression_type() const
{
return m_info.get_compression_type();
}
void set_compression_type(compression_type compression)
{
m_info.set_compression_type(compression);
}
filter_type get_filter_type() const
{
return m_info.get_filter_type();
}
void set_filter_type(filter_type filter)
{
m_info.set_filter_type(filter);
}
//////////////////////////////////////////////////////////////////////
bool has_chunk(chunk id)
{
return png_get_valid(m_png,
m_info.get_png_info(),
uint_32(id)) == uint_32(id);
}
#if defined(PNG_READ_EXPAND_SUPPORTED)
void set_gray_1_2_4_to_8() const
{
TRACE_IO_TRANSFORM("png_set_expand_gray_1_2_4_to_8\n");
png_set_expand_gray_1_2_4_to_8(m_png);
}
void set_palette_to_rgb() const
{
TRACE_IO_TRANSFORM("png_set_palette_to_rgb\n");
png_set_palette_to_rgb(m_png);
}
void set_tRNS_to_alpha() const
{
TRACE_IO_TRANSFORM("png_set_tRNS_to_alpha\n");
png_set_tRNS_to_alpha(m_png);
}
#endif // defined(PNG_READ_EXPAND_SUPPORTED)
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
void set_bgr() const
{
TRACE_IO_TRANSFORM("png_set_bgr\n");
png_set_bgr(m_png);
}
#endif
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
void set_gray_to_rgb() const
{
TRACE_IO_TRANSFORM("png_set_gray_to_rgb\n");
png_set_gray_to_rgb(m_png);
}
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
void set_rgb_to_gray(rgb_to_gray_error_action error_action
= rgb_to_gray_silent,
double red_weight = -1.0,
double green_weight = -1.0) const
{
TRACE_IO_TRANSFORM("png_set_rgb_to_gray: error_action=%d,"
" red_weight=%lf, green_weight=%lf\n",
error_action, red_weight, green_weight);
png_set_rgb_to_gray(m_png, error_action, red_weight, green_weight);
}
#else
void set_rgb_to_gray(rgb_to_gray_error_action error_action
= rgb_to_gray_silent,
fixed_point red_weight = -1,
fixed_point green_weight = -1) const
{
TRACE_IO_TRANSFORM("png_set_rgb_to_gray_fixed: error_action=%d,"
" red_weight=%d, green_weight=%d\n",
error_action, red_weight, green_weight);
png_set_rgb_to_gray_fixed(m_png, error_action,
red_weight, green_weight);
}
#endif // PNG_FLOATING_POINT_SUPPORTED
//////////////////////////////////////////////////////////////////////
// alpha channel transformations
//
#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
void set_strip_alpha() const
{
TRACE_IO_TRANSFORM("png_set_strip_alpha\n");
png_set_strip_alpha(m_png);
}
#endif
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) \
|| defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
void set_swap_alpha() const
{
TRACE_IO_TRANSFORM("png_set_swap_alpha\n");
png_set_swap_alpha(m_png);
}
#endif
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) \
|| defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
void set_invert_alpha() const
{
TRACE_IO_TRANSFORM("png_set_invert_alpha\n");
png_set_invert_alpha(m_png);
}
#endif
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
void set_filler(uint_32 filler, filler_type type) const
{
TRACE_IO_TRANSFORM("png_set_filler: filler=%08x, type=%d\n",
filler, type);
png_set_filler(m_png, filler, type);
}
#if !defined(PNG_1_0_X)
void set_add_alpha(uint_32 filler, filler_type type) const
{
TRACE_IO_TRANSFORM("png_set_add_alpha: filler=%08x, type=%d\n",
filler, type);
png_set_add_alpha(m_png, filler, type);
}
#endif
#endif // PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
void set_swap() const
{
TRACE_IO_TRANSFORM("png_set_swap\n");
png_set_swap(m_png);
}
#endif
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
void set_packing() const
{
TRACE_IO_TRANSFORM("png_set_packing\n");
png_set_packing(m_png);
}
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) \
|| defined(PNG_WRITE_PACKSWAP_SUPPORTED)
void set_packswap() const
{
TRACE_IO_TRANSFORM("png_set_packswap\n");
png_set_packswap(m_png);
}
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
void set_shift(byte red_bits, byte green_bits, byte blue_bits,
byte alpha_bits = 0) const
{
TRACE_IO_TRANSFORM("png_set_shift: red_bits=%d, green_bits=%d,"
" blue_bits=%d, alpha_bits=%d\n",
red_bits, green_bits, blue_bits, alpha_bits);
if (get_color_type() != color_type_rgb
|| get_color_type() != color_type_rgb_alpha)
{
throw error("set_shift: expected RGB or RGBA color type");
}
color_info bits;
bits.red = red_bits;
bits.green = green_bits;
bits.blue = blue_bits;
bits.alpha = alpha_bits;
png_set_shift(m_png, & bits);
}
void set_shift(byte gray_bits, byte alpha_bits = 0) const
{
TRACE_IO_TRANSFORM("png_set_shift: gray_bits=%d, alpha_bits=%d\n",
gray_bits, alpha_bits);
if (get_color_type() != color_type_gray
|| get_color_type() != color_type_gray_alpha)
{
throw error("set_shift: expected Gray or Gray+Alpha color type");
}
color_info bits;
bits.gray = gray_bits;
bits.alpha = alpha_bits;
png_set_shift(m_png, & bits);
}
#endif // PNG_READ_SHIFT_SUPPORTED || PNG_WRITE_SHIFT_SUPPORTED
#if defined(PNG_READ_INTERLACING_SUPPORTED) \
|| defined(PNG_WRITE_INTERLACING_SUPPORTED)
int set_interlace_handling() const
{
TRACE_IO_TRANSFORM("png_set_interlace_handling\n");
return png_set_interlace_handling(m_png);
}
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
void set_invert_mono() const
{
TRACE_IO_TRANSFORM("png_set_invert_mono\n");
png_set_invert_mono(m_png);
}
#endif
#if defined(PNG_READ_16_TO_8_SUPPORTED)
void set_strip_16() const
{
TRACE_IO_TRANSFORM("png_set_strip_16\n");
png_set_strip_16(m_png);
}
#endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
void set_read_user_transform(png_user_transform_ptr transform_fn)
{
TRACE_IO_TRANSFORM("png_set_read_user_transform_fn\n");
png_set_read_user_transform_fn(m_png, transform_fn);
}
#endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) \
|| defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
void set_user_transform_info(void* info, int bit_depth, int channels)
{
TRACE_IO_TRANSFORM("png_set_user_transform_info: bit_depth=%d,"
" channels=%d\n", bit_depth, channels);
png_set_user_transform_info(m_png, info, bit_depth, channels);
}
#endif
protected:
void* get_io_ptr() const
{
return png_get_io_ptr(m_png);
}
void set_error(char const* message)
{
assert(message);
m_error = message;
}
void reset_error()
{
m_error.clear();
}
/*
std::string const& get_error() const
{
return m_error;
}
*/
bool is_error() const
{
return !m_error.empty();
}
void raise_error()
{
longjmp(png_jmpbuf(m_png), -1);
}
static void raise_error(png_struct* png, char const* message)
{
io_base* io = static_cast< io_base* >(png_get_error_ptr(png));
io->set_error(message);
io->raise_error();
}
png_struct* m_png;
info m_info;
end_info m_end_info;
std::string m_error;
};
} // namespace png
#endif // PNGPP_IO_BASE_HPP_INCLUDED

View File

@ -1,35 +0,0 @@
Libpng 1.6.34 - September 29, 2017
This is a public release of libpng, intended for use in production codes.
Files available for download:
Source files with LF line endings (for Unix/Linux) and with a
"configure" script
libpng-1.6.34.tar.xz (LZMA-compressed, recommended)
libpng-1.6.34.tar.gz
Source files with CRLF line endings (for Windows), without the
"configure" script
lpng1634.7z (LZMA-compressed, recommended)
lpng1634.zip
Other information:
libpng-1.6.34-README.txt
libpng-1.6.34-LICENSE.txt
libpng-1.6.34-*.asc (armored detached GPG signatures)
Changes since the last public release (1.6.33):
Removed contrib/pngsuite/i*.png; some of these were incorrect and caused
test failures.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe)
or to glennrp at users.sourceforge.net
Glenn R-P

View File

@ -1,937 +0,0 @@
# CMakeLists.txt
# Copyright (C) 2007,2009-2017 Glenn Randers-Pehrson
# Written by Christian Ehrlicher, 2007
# Revised by Roger Lowman, 2009-2010
# Revised by Clifford Yapp, 2011-2012
# Revised by Roger Leigh, 2016
# Revised by Andreas Franek, 2016
# This code is released under the libpng license.
# For conditions of distribution and use, see the disclaimer
# and license in png.h
cmake_minimum_required(VERSION 3.0.2)
cmake_policy(VERSION 3.0.2)
# Set MacOSX @rpath usage globally.
if (POLICY CMP0020)
cmake_policy(SET CMP0020 NEW)
endif(POLICY CMP0020)
if (POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif(POLICY CMP0042)
# Use new variable expansion policy.
if (POLICY CMP0053)
cmake_policy(SET CMP0053 NEW)
endif(POLICY CMP0053)
if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif(POLICY CMP0054)
set(CMAKE_CONFIGURATION_TYPES "Release;Debug;MinSizeRel;RelWithDebInfo")
project(libpng ASM C)
set(PNGLIB_MAJOR 1)
set(PNGLIB_MINOR 6)
set(PNGLIB_RELEASE 34)
set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
# needed packages
#Allow users to specify location of Zlib,
# Useful if zlib is being built alongside this as a sub-project
set(PNG_BUILD_ZLIB ${CMAKE_CURRENT_SOURCE_DIR}/zlib)
if(NOT WIN32)
find_library(M_LIBRARY
NAMES m
PATHS /usr/lib /usr/local/lib
)
if(NOT M_LIBRARY)
message(STATUS "math lib 'libm' not found; floating point support disabled")
endif()
else()
# not needed on windows
set(M_LIBRARY "")
endif()
# COMMAND LINE OPTIONS
option(PNG_SHARED "Build shared lib" OFF)
option(PNG_STATIC "Build static lib" ON)
option(PNG_TESTS "Build libpng tests" OFF)
# Many more configuration options could be added here
option(PNG_FRAMEWORK "Build OS X framework" OFF)
option(PNG_DEBUG "Build with debug output" OFF)
option(PNGARG "Disable ANSI-C prototypes" OFF)
option(PNG_HARDWARE_OPTIMIZATIONS "Enable Hardware Optimizations" ON)
set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names")
set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings")
if(PNG_HARDWARE_OPTIMIZATIONS)
# set definitions and sources for arm
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
set(PNG_ARM_NEON_POSSIBLE_VALUES check on off)
set(PNG_ARM_NEON "check" CACHE STRING "Enable ARM NEON optimizations:
check: (default) use internal checking code;
off: disable the optimizations;
on: turn on unconditionally.")
set_property(CACHE PNG_ARM_NEON PROPERTY STRINGS
${PNG_ARM_NEON_POSSIBLE_VALUES})
list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index)
if(index EQUAL -1)
message(FATAL_ERROR
" PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]")
elseif(NOT ${PNG_ARM_NEON} STREQUAL "no")
set(libpng_arm_sources
arm/arm_init.c
arm/filter_neon.S
arm/filter_neon_intrinsics.c)
if(${PNG_ARM_NEON} STREQUAL "on")
add_definitions(-DPNG_ARM_NEON_OPT=2)
elseif(${PNG_ARM_NEON} STREQUAL "check")
add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED)
endif()
else()
add_definitions(-DPNG_ARM_NEON_OPT=0)
endif()
endif()
# set definitions and sources for powerpc
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*" )
set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off)
set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations:
off: disable the optimizations.")
set_property(CACHE PNG_POWERPC_VSX PROPERTY STRINGS
${PNG_POWERPC_VSX_POSSIBLE_VALUES})
list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index)
if(index EQUAL -1)
message(FATAL_ERROR
" PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]")
elseif(NOT ${PNG_POWERPC_VSX} STREQUAL "no")
set(libpng_powerpc_sources
powerpc/powerpc_init.c
powerpc/filter_vsx_intrinsics.c)
if(${PNG_POWERPC_VSX} STREQUAL "on")
add_definitions(-DPNG_POWERPC_VSX_OPT=2)
endif()
else()
add_definitions(-DPNG_POWERPC_VSX_OPT=0)
endif()
endif()
# set definitions and sources for intel
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*" )
set(PNG_INTEL_SSE_POSSIBLE_VALUES on off)
set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations:
off: disable the optimizations")
set_property(CACHE PNG_INTEL_SSE PROPERTY STRINGS
${PNG_INTEL_SSE_POSSIBLE_VALUES})
list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index)
if(index EQUAL -1)
message(FATAL_ERROR
" PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]")
elseif(NOT ${PNG_INTEL_SSE} STREQUAL "no")
set(libpng_intel_sources
intel/intel_init.c
intel/filter_sse2_intrinsics.c)
if(${PNG_INTEL_SSE} STREQUAL "on")
add_definitions(-DPNG_INTEL_SSE_OPT=1)
endif()
else()
add_definitions(-DPNG_INTEL_SSE_OPT=0)
endif()
endif()
# set definitions and sources for MIPS
if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*" )
set(PNG_MIPS_MSA_POSSIBLE_VALUES on off)
set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations:
off: disable the optimizations")
set_property(CACHE PNG_MIPS_MSA PROPERTY STRINGS
${PNG_MIPS_MSA_POSSIBLE_VALUES})
list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index)
if(index EQUAL -1)
message(FATAL_ERROR
" PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]")
elseif(NOT ${PNG_MIPS_MSA} STREQUAL "no")
set(libpng_mips_sources
mips/mips_init.c
mips/filter_msa_intrinsics.c)
if(${PNG_MIPS_MSA} STREQUAL "on")
add_definitions(-DPNG_MIPS_MSA_OPT=2)
endif()
else()
add_definitions(-DPNG_MIPS_MSA_OPT=0)
endif()
endif()
endif(PNG_HARDWARE_OPTIMIZATIONS)
# SET LIBNAME
set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR})
# to distinguish between debug and release lib
set(CMAKE_DEBUG_POSTFIX "d")
include(CheckCSourceCompiles)
option(ld-version-script "Enable linker version script" ON)
if(ld-version-script AND NOT APPLE)
# Check if LD supports linker scripts.
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 {
global: sym;
local: *;
};
VERS_2 {
global: sym2;
main;
} VERS_1;
")
set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'")
check_c_source_compiles("void sym(void) {}
void sym2(void) {}
int main(void) {return 0;}
" HAVE_LD_VERSION_SCRIPT)
if(NOT HAVE_LD_VERSION_SCRIPT)
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE} "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
check_c_source_compiles("void sym(void) {}
void sym2(void) {}
int main(void) {return 0;}
" HAVE_SOLARIS_LD_VERSION_SCRIPT)
endif()
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE})
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
endif()
# Find symbol prefix. Likely obsolete and unnecessary with recent
# toolchains (it's not done in many other projects).
function(symbol_prefix)
set(SYMBOL_PREFIX)
execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E" "-"
INPUT_FILE /dev/null
OUTPUT_VARIABLE OUT
RESULT_VARIABLE STATUS)
if(CPP_FAIL)
message(WARNING "Failed to run the C preprocessor")
endif()
string(REPLACE "\n" ";" OUT "${OUT}")
foreach(line ${OUT})
string(REGEX MATCH "^PREFIX=" found_match "${line}")
if(found_match)
STRING(REGEX REPLACE "^PREFIX=(.*\)" "\\1" prefix "${line}")
string(REGEX MATCH "__USER_LABEL_PREFIX__" found_match "${prefix}")
if(found_match)
STRING(REGEX REPLACE "(.*)__USER_LABEL_PREFIX__(.*)" "\\1\\2" prefix "${prefix}")
endif()
set(SYMBOL_PREFIX "${prefix}")
endif()
endforeach()
message(STATUS "Symbol prefix: ${SYMBOL_PREFIX}")
set(SYMBOL_PREFIX "${SYMBOL_PREFIX}" PARENT_SCOPE)
endfunction()
if(UNIX)
symbol_prefix()
endif()
find_program(AWK NAMES gawk awk)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(NOT AWK OR ANDROID)
# No awk available to generate sources; use pre-built pnglibconf.h
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt
${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h)
add_custom_target(genfiles) # Dummy
else()
include(CMakeParseArguments)
# Generate .chk from .out with awk
# generate_chk(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
function(generate_chk)
set(options)
set(oneValueArgs INPUT OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT _GC_INPUT)
message(FATAL_ERROR "Invalid arguments. generate_out requires input.")
endif()
if (NOT _GC_OUTPUT)
message(FATAL_ERROR "Invalid arguments. generate_out requires output.")
endif()
add_custom_command(OUTPUT "${_GC_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
"-DINPUT=${_GC_INPUT}"
"-DOUTPUT=${_GC_OUTPUT}"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake"
DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endfunction()
# Generate .out from .c with awk
# generate_out(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
function(generate_out)
set(options)
set(oneValueArgs INPUT OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT _GO_INPUT)
message(FATAL_ERROR "Invalid arguments. generate_out requires input.")
endif()
if (NOT _GO_OUTPUT)
message(FATAL_ERROR "Invalid arguments. generate_out requires output.")
endif()
add_custom_command(OUTPUT "${_GO_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
"-DINPUT=${_GO_INPUT}"
"-DOUTPUT=${_GO_OUTPUT}"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake"
DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endfunction()
# Generate specific source file with awk
# generate_source(OUTPUT outputfile [DEPENDS dep1 [dep2...]])
function(generate_source)
set(options)
set(oneValueArgs OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT _GSO_OUTPUT)
message(FATAL_ERROR "Invalid arguments. generate_source requires output.")
endif()
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
"-DOUTPUT=${_GSO_OUTPUT}"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake"
DEPENDS ${_GSO_DEPENDS}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endfunction()
# Copy file
function(generate_copy source destination)
add_custom_command(OUTPUT "${destination}"
COMMAND "${CMAKE_COMMAND}" -E remove "${destination}"
COMMAND "${CMAKE_COMMAND}" -E copy "${source}"
"${destination}"
DEPENDS "${source}")
endfunction()
# Generate scripts/pnglibconf.h
generate_source(OUTPUT "scripts/pnglibconf.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
# Generate pnglibconf.c
generate_source(OUTPUT "pnglibconf.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
if(PNG_PREFIX)
set(PNGLIBCONF_H_EXTRA_DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst")
set(PNGPREFIX_H_EXTRA_DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out")
endif()
generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
# Generate pnglibconf.h
generate_source(OUTPUT "pnglibconf.h"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
${PNGLIBCONF_H_EXTRA_DEPENDS})
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
# Generate pngprefix.h
generate_source(OUTPUT "pngprefix.h"
DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS})
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def")
add_custom_target(symbol-check DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk")
generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
"${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
"${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
add_custom_target(genvers DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
add_custom_target(gensym DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
add_custom_target("genprebuilt"
COMMAND "${CMAKE_COMMAND}"
"-DOUTPUT=scripts/pnglibconf.h.prebuilt"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
# A single target handles generation of all generated files. If
# they are dependend upon separately by multiple targets, this
# confuses parallel make (it would require a separate top-level
# target for each file to track the dependencies properly).
add_custom_target(genfiles DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/libpng.sym"
"${CMAKE_CURRENT_BINARY_DIR}/libpng.vers"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
"${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out")
endif(NOT AWK OR ANDROID)
# OUR SOURCES
set(libpng_public_hdrs
png.h
pngconf.h
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
)
set(libpng_private_hdrs
pngpriv.h
pngdebug.h
pnginfo.h
pngstruct.h
)
if(AWK AND NOT ANDROID)
list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h")
endif()
set(libpng_sources
${libpng_public_hdrs}
${libpng_private_hdrs}
png.c
pngerror.c
pngget.c
pngmem.c
pngpread.c
pngread.c
pngrio.c
pngrtran.c
pngrutil.c
pngset.c
pngtrans.c
pngwio.c
pngwrite.c
pngwtran.c
pngwutil.c
${libpng_arm_sources}
${libpng_intel_sources}
${libpng_mips_sources}
${libpng_powerpc_sources}
)
set(pngtest_sources
pngtest.c
)
set(pngvalid_sources
contrib/libtests/pngvalid.c
)
set(pngstest_sources
contrib/libtests/pngstest.c
)
set(pngunknown_sources
contrib/libtests/pngunknown.c
)
set(pngimage_sources
contrib/libtests/pngimage.c
)
set(pngfix_sources
contrib/tools/pngfix.c
)
set(png_fix_itxt_sources
contrib/tools/png-fix-itxt.c
)
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
endif(MSVC)
if(PNG_DEBUG)
add_definitions(-DPNG_DEBUG)
endif()
# NOW BUILD OUR TARGET
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR})
unset(PNG_LIB_TARGETS)
if(PNG_SHARED)
add_library(png SHARED ${libpng_sources})
set(PNG_LIB_TARGETS png)
set_target_properties(png PROPERTIES OUTPUT_NAME ${PNG_LIB_NAME})
add_dependencies(png genfiles)
if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name
set_target_properties(png PROPERTIES PREFIX "lib")
set_target_properties(png PROPERTIES IMPORT_PREFIX "lib")
endif()
target_link_libraries(png ${ZLIB_LIBRARY} ${M_LIBRARY})
if(UNIX AND AWK)
if(HAVE_LD_VERSION_SCRIPT)
set_target_properties(png PROPERTIES LINK_FLAGS
"-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT)
set_target_properties(png PROPERTIES LINK_FLAGS
"-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
endif()
endif()
endif()
if(PNG_STATIC)
# does not work without changing name
set(PNG_LIB_NAME_STATIC png_static)
add_library(png_static STATIC ${libpng_sources})
add_dependencies(png_static genfiles)
# MSVC doesn't use a different file extension for shared vs. static
# libs. We are able to change OUTPUT_NAME to remove the _static
# for all other platforms.
if(NOT MSVC)
set_target_properties(png_static PROPERTIES
OUTPUT_NAME "${PNG_LIB_NAME}"
CLEAN_DIRECT_OUTPUT 1)
else()
set_target_properties(png_static PROPERTIES
OUTPUT_NAME "${PNG_LIB_NAME}_static"
CLEAN_DIRECT_OUTPUT 1)
endif()
list(APPEND PNG_LIB_TARGETS png_static)
if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name
set_target_properties(png_static PROPERTIES PREFIX "lib")
endif()
target_link_libraries(png_static ${ZLIB_LIBRARY} ${M_LIBRARY})
endif()
if(PNG_FRAMEWORK)
set(PNG_LIB_NAME_FRAMEWORK png_framework)
add_library(png_framework SHARED ${libpng_sources})
add_dependencies(png_framework genfiles)
list(APPEND PNG_LIB_TARGETS png_framework)
set_target_properties(png_framework PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION ${PNGLIB_VERSION}
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PNGLIB_MAJOR}.${PNGLIB_MINOR}
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PNGLIB_VERSION}
MACOSX_FRAMEWORK_IDENTIFIER org.libpng.libpng
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
PUBLIC_HEADER "${libpng_public_hdrs}"
OUTPUT_NAME png)
target_link_libraries(png_framework ${ZLIB_LIBRARY} ${M_LIBRARY})
endif()
if(NOT PNG_LIB_TARGETS)
message(SEND_ERROR
"No library variant selected to build. "
"Please enable at least one of the following options: "
" PNG_STATIC, PNG_SHARED, PNG_FRAMEWORK")
endif()
if(PNG_SHARED AND WIN32)
set_target_properties(png PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
endif()
function(png_add_test)
set(options)
set(oneValueArgs NAME COMMAND)
set(multiValueArgs OPTIONS FILES)
cmake_parse_arguments(_PAT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT _PAT_NAME)
message(FATAL_ERROR "Invalid arguments. png_add_test requires name.")
endif()
if (NOT _PAT_COMMAND)
message(FATAL_ERROR "Invalid arguments. png_add_test requires command.")
endif()
set(TEST_OPTIONS "${_PAT_OPTIONS}")
set(TEST_FILES "${_PAT_FILES}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/test.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake" @ONLY)
if(CMAKE_MAJOR_VERSION GREATER 2) # have generator expressions
add_test(NAME "${_PAT_NAME}"
COMMAND "${CMAKE_COMMAND}"
"-DLIBPNG=$<TARGET_FILE:png>"
"-DTEST_COMMAND=$<TARGET_FILE:${_PAT_COMMAND}>"
-P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
else() # old 2.x add_test; limited and won't work well on Windows
# Note LIBPNG is a dummy value as there are no generator expressions
add_test("${_PAT_NAME}" "${CMAKE_COMMAND}"
"-DLIBPNG=${CMAKE_CURRENT_BINARY_DIR}/libpng.so"
"-DTEST_COMMAND=./${_PAT_COMMAND}"
-P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
endif()
endfunction()
if(PNG_TESTS AND PNG_SHARED)
# Find test PNG files by globbing, but sort lists to ensure
# consistency between different filesystems.
file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png")
list(SORT PNGSUITE_PNGS)
file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png")
list(SORT TEST_PNGS)
set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png")
add_executable(pngtest ${pngtest_sources})
target_link_libraries(pngtest png)
png_add_test(NAME pngtest COMMAND pngtest FILES "${PNGTEST_PNG}")
add_executable(pngvalid ${pngvalid_sources})
target_link_libraries(pngvalid png)
png_add_test(NAME pngvalid-gamma-16-to-8
COMMAND pngvalid OPTIONS --gamma-16-to-8)
png_add_test(NAME pngvalid-gamma-alpha-mode
COMMAND pngvalid OPTIONS --gamma-alpha-mode)
png_add_test(NAME pngvalid-gamma-background
COMMAND pngvalid OPTIONS --gamma-background)
png_add_test(NAME pngvalid-gamma-expand16-alpha-mode
COMMAND pngvalid OPTIONS --gamma-alpha-mode --expand16)
png_add_test(NAME pngvalid-gamma-expand16-background
COMMAND pngvalid OPTIONS --gamma-background --expand16)
png_add_test(NAME pngvalid-gamma-expand16-transform
COMMAND pngvalid OPTIONS --gamma-transform --expand16)
png_add_test(NAME pngvalid-gamma-sbit
COMMAND pngvalid OPTIONS --gamma-sbit)
png_add_test(NAME pngvalid-gamma-threshold
COMMAND pngvalid OPTIONS --gamma-threshold)
png_add_test(NAME pngvalid-gamma-transform
COMMAND pngvalid OPTIONS --gamma-transform)
png_add_test(NAME pngvalid-progressive-interlace-standard
COMMAND pngvalid OPTIONS --standard --progressive-read --interlace)
png_add_test(NAME pngvalid-progressive-size
COMMAND pngvalid OPTIONS --size --progressive-read)
png_add_test(NAME pngvalid-progressive-standard
COMMAND pngvalid OPTIONS --standard --progressive-read)
png_add_test(NAME pngvalid-standard
COMMAND pngvalid OPTIONS --standard)
png_add_test(NAME pngvalid-transform
COMMAND pngvalid OPTIONS --transform)
add_executable(pngstest ${pngstest_sources})
target_link_libraries(pngstest png)
foreach(gamma_type 1.8 linear none sRGB)
foreach(alpha_type none alpha)
set(PNGSTEST_FILES)
foreach(test_png ${TEST_PNGS})
string(REGEX MATCH ".*-linear[-.].*" TEST_PNG_LINEAR "${test_png}")
string(REGEX MATCH ".*-sRGB[-.].*" TEST_PNG_SRGB "${test_png}")
string(REGEX MATCH ".*-1.8[-.].*" TEST_PNG_G18 "${test_png}")
string(REGEX MATCH ".*-alpha-.*" TEST_PNG_ALPHA "${test_png}")
set(TEST_PNG_VALID TRUE)
if(TEST_PNG_ALPHA)
if (NOT "${alpha_type}" STREQUAL "alpha")
set(TEST_PNG_VALID FALSE)
endif()
else()
if ("${alpha_type}" STREQUAL "alpha")
set(TEST_PNG_VALID FALSE)
endif()
endif()
if(TEST_PNG_LINEAR)
if(NOT "${gamma_type}" STREQUAL "linear")
set(TEST_PNG_VALID FALSE)
endif()
elseif(TEST_PNG_SRGB)
if(NOT "${gamma_type}" STREQUAL "sRGB")
set(TEST_PNG_VALID FALSE)
endif()
elseif(TEST_PNG_G18)
if(NOT "${gamma_type}" STREQUAL "1.8")
set(TEST_PNG_VALID FALSE)
endif()
else()
if(NOT "${gamma_type}" STREQUAL "none")
set(TEST_PNG_VALID FALSE)
endif()
endif()
if(TEST_PNG_VALID)
list(APPEND PNGSTEST_FILES "${test_png}")
endif()
endforeach()
# Should already be sorted, but sort anyway to be certain.
list(SORT PNGSTEST_FILES)
png_add_test(NAME pngstest-${gamma_type}-${alpha_type}
COMMAND pngstest
OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log
FILES ${PNGSTEST_FILES})
endforeach()
endforeach()
add_executable(pngunknown ${pngunknown_sources})
target_link_libraries(pngunknown png)
png_add_test(NAME pngunknown-discard COMMAND pngunknown OPTIONS --strict default=discard FILES "${PNGTEST_PNG}")
png_add_test(NAME pngunknown-IDAT COMMAND pngunknown OPTIONS --strict default=discard IDAT=save FILES "${PNGTEST_PNG}")
png_add_test(NAME pngunknown-if-safe COMMAND pngunknown OPTIONS --strict default=if-safe FILES "${PNGTEST_PNG}")
png_add_test(NAME pngunknown-sAPI COMMAND pngunknown OPTIONS --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save FILES "${PNGTEST_PNG}")
png_add_test(NAME pngunknown-save COMMAND pngunknown OPTIONS --strict default=save FILES "${PNGTEST_PNG}")
png_add_test(NAME pngunknown-sTER COMMAND pngunknown OPTIONS --strict sTER=if-safe FILES "${PNGTEST_PNG}")
png_add_test(NAME pngunknown-vpAg COMMAND pngunknown OPTIONS --strict vpAg=if-safe FILES "${PNGTEST_PNG}")
add_executable(pngimage ${pngimage_sources})
target_link_libraries(pngimage png)
png_add_test(NAME pngimage-quick COMMAND pngimage OPTIONS --list-combos --log FILES ${PNGSUITE_PNGS})
png_add_test(NAME pngimage-full COMMAND pngimage OPTIONS --exhaustive --list-combos --log FILES ${PNGSUITE_PNGS})
endif()
if(PNG_SHARED)
add_executable(pngfix ${pngfix_sources})
target_link_libraries(pngfix png)
set(PNG_BIN_TARGETS pngfix)
add_executable(png-fix-itxt ${png_fix_itxt_sources})
target_link_libraries(png-fix-itxt ${ZLIB_LIBRARY} ${M_LIBRARY})
list(APPEND PNG_BIN_TARGETS png-fix-itxt)
endif()
# Set a variable with CMake code which:
# Creates a symlink from src to dest (if possible) or alternatively
# copies if different.
include(CMakeParseArguments)
function(CREATE_SYMLINK DEST_FILE)
cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN})
if(NOT S_TARGET AND NOT S_FILE)
message(FATAL_ERROR "Specify either a TARGET or a FILE for CREATE_SYMLINK to link to.")
endif(NOT S_TARGET AND NOT S_FILE)
if(S_TARGET AND S_FILE)
message(FATAL_ERROR "CREATE_SYMLINK called with both source file ${S_FILE} and build target ${S_TARGET} arguments - can only handle 1 type per call.")
endif(S_TARGET AND S_FILE)
if(S_FILE)
# If we don't need to symlink something that's coming from a build target,
# we can go ahead and symlink/copy at configure time.
if(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
execute_process(
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
else(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
endif(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
endif(S_FILE)
if(S_TARGET)
# We need to use generator expressions, which can be a bit tricky, so for
# simplicity make the symlink a POST_BUILD step and use the TARGET
# signature of add_custom_command.
if(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
add_custom_command(TARGET ${S_TARGET} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_if_different $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE}
)
else(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
add_custom_command(TARGET ${S_TARGET} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E create_symlink $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE}
)
endif(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS)
endif(S_TARGET)
endfunction()
# Create source generation scripts.
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genchk.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genout.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/gensrc.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake @ONLY)
# libpng is a library so default to 'lib'
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR lib)
endif(NOT DEFINED CMAKE_INSTALL_LIBDIR)
# CREATE PKGCONFIG FILES
# we use the same files like ./configure, so we have to set its vars
# Only do this on Windows for Cygwin - the files don't make much sense outside
# a UNIX look alike
if(NOT WIN32 OR CYGWIN OR MINGW)
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
set(includedir ${CMAKE_INSTALL_PREFIX}/include)
set(LIBS "-lz -lm")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in
${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY)
CREATE_SYMLINK(libpng.pc FILE ${PNGLIB_NAME}.pc)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in
${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config @ONLY)
CREATE_SYMLINK(libpng-config FILE ${PNGLIB_NAME}-config)
endif(NOT WIN32 OR CYGWIN OR MINGW)
# SET UP LINKS
if(PNG_SHARED)
set_target_properties(png PROPERTIES
# VERSION 16.${PNGLIB_RELEASE}.1.6.34
VERSION 16.${PNGLIB_RELEASE}.0
SOVERSION 16
CLEAN_DIRECT_OUTPUT 1)
endif()
# If CMake > 2.4.x, we set a variable used below to export
# targets to an export file.
# TODO: Use VERSION_GREATER after our cmake_minimum_required >= 2.6.2
if(CMAKE_MAJOR_VERSION GREATER 1 AND CMAKE_MINOR_VERSION GREATER 4)
set(PNG_EXPORT_RULE EXPORT libpng)
elseif(CMAKE_MAJOR_VERSION GREATER 2) # future proof
set(PNG_EXPORT_RULE EXPORT libpng)
endif()
# INSTALL
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
install(TARGETS ${PNG_LIB_TARGETS}
${PNG_EXPORT_RULE}
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(PNG_SHARED)
# Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin
if(CYGWIN OR MINGW)
CREATE_SYMLINK(libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} TARGET png)
install(FILES $<TARGET_LINKER_FILE_DIR:png>/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif(CYGWIN OR MINGW)
if(NOT WIN32)
CREATE_SYMLINK(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png)
install(FILES $<TARGET_LINKER_FILE_DIR:png>/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif(NOT WIN32)
endif(PNG_SHARED)
if(PNG_STATIC)
if(NOT WIN32 OR CYGWIN OR MINGW)
CREATE_SYMLINK( libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static)
install(FILES $<TARGET_LINKER_FILE_DIR:png_static>/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif(NOT WIN32 OR CYGWIN OR MINGW)
endif()
endif()
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
install(FILES ${libpng_public_hdrs} DESTINATION include)
install(FILES ${libpng_public_hdrs} DESTINATION include/${PNGLIB_NAME})
endif()
if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL )
if(NOT WIN32 OR CYGWIN OR MINGW)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config
DESTINATION bin)
endif(NOT WIN32 OR CYGWIN OR MINGW)
endif()
if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL )
install(TARGETS ${PNG_BIN_TARGETS}
RUNTIME DESTINATION bin)
endif()
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
# Install man pages
if(NOT PNG_MAN_DIR)
set(PNG_MAN_DIR "share/man")
endif()
install(FILES libpng.3 libpngpf.3 DESTINATION ${PNG_MAN_DIR}/man3)
install(FILES png.5 DESTINATION ${PNG_MAN_DIR}/man5)
# Install pkg-config files
if(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config
DESTINATION bin)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config
DESTINATION bin)
endif(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW)
endif()
# On versions of CMake that support it, create an export file CMake
# users can include() to import our targets
if(PNG_EXPORT_RULE AND NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL )
install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake)
endif()
# what's with libpng-manual.txt and all the extra files?
# UNINSTALL
# do we need this?
# DIST
# do we need this?
# to create msvc import lib for mingw compiled shared lib
# pexports libpng.dll > libpng.def
# lib /def:libpng.def /machine:x86

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