diff --git a/3rdparty/README.md b/3rdparty/README.md index 1cab5dab1d..d58be29b99 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -1,242 +1,247 @@ = CMake external projects to build krita's dependencies on Linux, Windows or OSX = If you need to build Krita's dependencies for the following reasons: * you develop on Windows and aren't using Emerge * you develop on OSX and aren't using Homebrew * you want to build a generic, distro-agnostic version of Krita for Linux * you develop on Linux, but some dependencies aren't available for your distribution and you know what you're doing, you can use the following guide to build the dependencies that Krita needs. If you develop on Linux and your distribution has the dependencies available, YOU DO NOT NEED THIS GUIDE AND YOU SHOULD STOP READING NOW Otherwise you risk major confusion. == Prerequisites == Note: on all operating systems the entire procedure is done in a terminal window. 1. git: https://git-scm.com/downloads. Make sure git is in your path 2. cmake 3.3.2: https://cmake.org/download/. Make sure cmake is in your path. 3. Make sure you have a compiler: * Linux: gcc, minimum version 4.8 * OSX: clang, you need to install xcode for this - * Windows: (http://tdm-gcc.tdragon.net/, version 5.1). MSVC cannot build G'Mic correctly. Remember to install the OpenMP plugin in tdm-gcc. Make sure mingw's bin folder is in your path. + * Windows: mingw-w64 5.4 (by mingw-builds) + - 32-bit (x86) target: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/5.4.0/threads-posix/dwarf/ + - 64-bit (x64) target: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/5.4.0/threads-posix/seh/ + Make sure mingw's bin folder is in your path. It might be a good + idea to create a batch file which sets the path and start cmd. + MSVC is *not* supported at the moment. 4. If you compile Qt on Windows, you will also need Python: https://www.python.org. Make sure to have python.exe in your path. == Setup your environment == == Prepare your directory layout == 1. Make a toplevel build directory, say $HOME/dev or c:\dev. We'll refer to this directory as BUILDROOT. You can use a variable for this, on WINDOWS %BUILDROOT%, on OSX and Linux $BUILDROOT. You will have to replace BUILDROOT with $BUILDROOT or %BUILDROOT whenever you copy and paste a command, depending on your operating system. 2. Checkout krita in BUILDROOT cd BUILDROOT git clone git://anongit.kde.org/krita.git 3. Create the build directory mkdir BUILDROOT/b 4. Create the downloads directory mkdir BUILDROOT/d 5. Create the install directory mkdir BUILDROOT/i == Prepare the externals build == 1. enter the BUILDROOT/b directory 2. run cmake: * Linux: export PATH=$BUILDROOT/i/bin export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty \ -DINSTALL_ROOT=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DCMAKE_INSTALL_PREFIX=BUILDROOT/i * OSX: export PATH=$BUILDROOT/i/bin export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty/ \ -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DINSTALL_ROOT=$BUILDROOT/i * Windows 32 bits: TODO * Windows 64 bits: Note that the cmake command needs to point to your BUILDROOT like /dev/d, not c:\dev\d. set PATH=%BUILDROOT%\i\bin\;%BUILDROOT%\i\lib;%PATH% set PYTHONHOME=%BUILDROOT%/i (only if you want to build your own python) set PATH=BUILDROOT\i\bin\;BUILDROOT\i\lib;%PATH% cmake ..\krita\3rdparty -DEXTERNALS_DOWNLOAD_DIR=/dev/d -DINSTALL_ROOT=/dev/i -G "MinGW Makefiles" 3. build the packages: With a judicious application of DEPENDS statements, it's possible to build it all in one go, but in my experience that fails always, so it's better to build the dependencies independently. If you want to use the included version of Python (can be used on Windows to build Qt instead of installing Python separately): cmake --build . --config RelWithDebInfo --target ext_python On Windows: cmake --build . --config RelWithDebInfo --target ext_patch cmake --build . --config RelWithDebInfo --target ext_png2ico cmake --build . --config RelWithDebInfo --target ext_gettext On all operating systems: cmake --build . --config RelWithDebInfo --target ext_qt cmake --build . --config RelWithDebInfo --target ext_zlib cmake --build . --config RelWithDebInfo --target ext_boost Note about boost: check if the headers are installed into i/include/boost, but not into i/include/boost-1.61/boost cmake --build . --config RelWithDebInfo --target ext_eigen3 cmake --build . --config RelWithDebInfo --target ext_exiv2 cmake --build . --config RelWithDebInfo --target ext_fftw3 On Windows: set FFTW_LIB_DIR=%BUILDROOT%\i\lib dlltool.exe -k --output-lib %FFTW_LIB_DIR%\libfftw3-3.a --input-def %FFTW_LIB_DIR%\libfftw3-3.def dlltool.exe -k --output-lib %FFTW_LIB_DIR%\libfftw3f-3.a --input-def %FFTW_LIB_DIR%\libfftw3f-3.def dlltool.exe -k --output-lib %FFTW_LIB_DIR%\libfftw3l-3.a --input-def %FFTW_LIB_DIR%\libfftw3l-3.def On all operating systems cmake --build . --config RelWithDebInfo --target ext_ilmbase cmake --build . --config RelWithDebInfo --target ext_jpeg cmake --build . --config RelWithDebInfo --target ext_lcms2 cmake --build . --config RelWithDebInfo --target ext_ocio cmake --build . --config RelWithDebInfo --target ext_openexr Note for OSX: On OSX, you need to first build openexr; that will fail; then you need to set the rpath for the two utilities correctly, then try to build openexr again. install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./b44ExpLogTable install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./dwaLookups On All operating systems: cmake --build . --config RelWithDebInfo --target ext_png cmake --build . --config RelWithDebInfo --target ext_tiff cmake --build . --config RelWithDebInfo --target ext_gsl cmake --build . --config RelWithDebInfo --target ext_vc cmake --build . --config RelWithDebInfo --target ext_libraw On Windows cmake --build . --config RelWithDebInfo --target ext_freetype cmake --build . --config RelWithDebInfo --target ext_poppler On Linux cmake --build . --config RelWithDebInfo --target ext_kcrash Everywhere else: cmake --build . --config RelWithDebInfo --target ext_kwindowsystem On Windows, if you want to include DrMingw for dumping backtrace on crash: cmake --build . --config RelWithDebInfo --target ext_drmingw Note: poppler should be buildable on Linux as well with a home-built freetype and fontconfig, but I don't know how to make fontconfig find freetype, and on Linux, fontconfig is needed for poppler. Poppler is needed for PDF import. Note 2: libcurl still isn't available. Note 3: if you want to build a release, you need to get the binary gettext archives from files.kde.org/krita/build/dependencies: http://files.kde.org/krita/build/dependencies/gettext0.19.8.1-iconv1.14-shared-32.zip http://files.kde.org/krita/build/dependencies/gettext0.19.8.1-iconv1.14-shared-64.zip Take care, these zips contain a libstdc++-6.dll that you don't want in your path when building. == Build Krita == 1. Make a krita build directory: mkdir BUILDROOT/build 2. Enter the BUILDROOT/build 3. Run On Windows Depending on what you want to use, run this command for MSBuild: cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -DPACKAGERS_BUILD=ON -Wno-dev -DDEFINE_NO_DEPRECATED=1 Or this to use jom (faster compiling, uses all cores, ships with QtCreator/pre-built Qt binaries): cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -DPACKAGERS_BUILD=ON -Wno-dev -DDEFINE_NO_DEPRECATED=1 On Linux cmake ../krita -DCMAKE_INSTALL_PREFIX=BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DPACKAGERS_BUILD=ON -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfobg On OSX cmake ../krita -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DPACKAGERS_BUILD=ON -DBUNDLE_INSTALL_DIR=$BUILDROOT/i/bin -DCMAKE_BUILD_TYPE=RelWithDebInfo 4. Run On Linux and OSX make make install On Windows Either use MSBuild to build (-- /m tells msbuild to use all your cores): cmake --build . --config RelWithDebInfo --target INSTALL -- /m Or use jom which should be in a path similar to C:\Qt\Qt5.6.0\Tools\QtCreator\bin\jom.exe. So, from the same folder, instead of running cmake run: "C:\Qt\Qt5.6.0\Tools\QtCreator\bin\jom.exe" install 6. Run krita: On Linux BUILDROOT/i/bin/krita On Windows BUILDROOT\i\bin\krita.exe On OSX BUILDROOT/i/bin/krita.app/Contents/MacOS/krita == Packaging a Windows Build == If you want to create a stripped down version of Krita to distribute, after building everything just copy the makepkg.bat file from the "windows" folder inside krita root source folder to BUILDROOT and run it. That will copy the necessary files into the specified folder and leave behind developer related files, so the resulting folder will be a smaller install folder. == Common Issues == - On Windows, if you get a 'mspdb140.dll' missing alert window, it means you did not run the bat file. Make sure to include the quotes in the command: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" - On Windows, if you get an error about Qt5Core.dll missing/not found or nmake exit with an error that mention QT_PLUGIN_PATH, you have to copy a couple of dlls in the Qt build directory, look for the N.B. in the Qt instructions at the start of the Readme. - If you receive an error while compiling about "missing QtCore5.cmake", or something similar, check to make sure qmake is in your PATH. Restart your command line after any changes are made. diff --git a/3rdparty/ext_boost/CMakeLists.txt b/3rdparty/ext_boost/CMakeLists.txt index 8928bd7b78..29963a806a 100755 --- a/3rdparty/ext_boost/CMakeLists.txt +++ b/3rdparty/ext_boost/CMakeLists.txt @@ -1,90 +1,86 @@ SET(PREFIX_ext_boost "${EXTPREFIX}" ) if (MSVC) if (${CMAKE_GENERATOR} STREQUAL "Visual Studio 14 2015 Win64") ExternalProject_Add( ext_boost DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/boost_1_61_0.zip URL_MD5 015ae4afa6f3e597232bfe1dab949ace CONFIGURE_COMMAND /bootstrap.bat --prefix=${PREFIX_ext_boost} BUILD_COMMAND /b2.exe --with-system --build-dir=build-dir --prefix=${PREFIX_ext_boost} toolset=msvc-14.0 variant=release link=shared threading=multi architecture=x86 address-model=64 variant=release install INSTALL_COMMAND "" INSTALL_DIR ${EXTPREFIX_boost} UPDATE_COMMAND "" - ALWAYS 0 BUILD_IN_SOURCE 1 ) ExternalProject_Add_Step( ext_boost post_install COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_boost}/lib/boost_system-vc140-mt-1_61.dll ${PREFIX_ext_boost}/bin/boost_system-vc140-mt-1_61.dll DEPENDEES install ) else() ExternalProject_Add( ext_boost DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/boost_1_61_0.zip URL_MD5 015ae4afa6f3e597232bfe1dab949ace CONFIGURE_COMMAND /bootstrap.bat --prefix=${PREFIX_ext_boost} BUILD_COMMAND /b2.exe --with-system --build-dir=build-dir --prefix=${PREFIX_ext_boost} toolset=msvc-14.0 variant=release link=shared threading=multi architecture=x86 variant=release install INSTALL_COMMAND "" INSTALL_DIR ${EXTPREFIX_boost} UPDATE_COMMAND "" - ALWAYS 0 BUILD_IN_SOURCE 1 ) ExternalProject_Add_Step( ext_boost post_install COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_boost}/lib/boost_system-vc140-mt-1_61.dll ${PREFIX_ext_boost}/bin/boost_system-vc140-mt-1_61.dll DEPENDEES install ) endif() elseif(MINGW) string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" KRITA_boost_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) ExternalProject_Add( ext_boost DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/boost_1_61_0.zip URL_MD5 015ae4afa6f3e597232bfe1dab949ace CONFIGURE_COMMAND /bootstrap.bat gcc --prefix=${PREFIX_ext_boost} BUILD_COMMAND /b2.exe --with-system --build-dir=build-dir --prefix=${PREFIX_ext_boost} toolset=gcc variant=release link=shared threading=multi architecture=x86 variant=release install INSTALL_COMMAND "" INSTALL_DIR ${EXTPREFIX_boost} UPDATE_COMMAND "" - ALWAYS 0 BUILD_IN_SOURCE 1 ) ExternalProject_Add_Step( ext_boost post_install COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_boost}/lib/libboost_system-mgw${KRITA_boost_COMPILER_VERSION}-mt-1_61.dll ${PREFIX_ext_boost}/bin/ DEPENDEES install ) else() ExternalProject_Add( ext_boost DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/boost_1_61_0.tar.bz2 URL_MD5 6095876341956f65f9d35939ccea1a9f CONFIGURE_COMMAND /bootstrap.sh --prefix=${PREFIX_ext_boost} --with-libraries=system BUILD_COMMAND /b2 install INSTALL_COMMAND "" INSTALL_DIR ${PREFIX_ext_boost} UPDATE_COMMAND "" - ALWAYS 0 BUILD_IN_SOURCE 1 ) endif() diff --git a/3rdparty/ext_drmingw/CMakeLists.txt b/3rdparty/ext_drmingw/CMakeLists.txt index 3e7286b002..d979aaa0e0 100644 --- a/3rdparty/ext_drmingw/CMakeLists.txt +++ b/3rdparty/ext_drmingw/CMakeLists.txt @@ -1,40 +1,38 @@ SET (PREFIX_ext_drmingw "${EXTPREFIX}") if (MSVC OR MINGW) if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") ExternalProject_Add(ext_drmingw DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL https://github.com/jrfonseca/drmingw/releases/download/0.8.1/drmingw-0.8.1-win64.7z URL_HASH SHA1=8be29cc7efc0d611056c3b745e7f8de30d7c8baa INSTALL_DIR ${PREFIX_ext_drmingw} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo Deploying Dr. Mingw 64-bit binary and dependencies INSTALL_COMMAND ${CMAKE_COMMAND} -E copy /bin/dbghelp.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/exchndl.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/mgwhelp.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/symsrv.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/symsrv.yes ${PREFIX_ext_drmingw}/bin/ UPDATE_COMMAND "" - ALWAYS 0 ) else ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") ExternalProject_Add(ext_drmingw DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL https://github.com/jrfonseca/drmingw/releases/download/0.8.1/drmingw-0.8.1-win32.7z URL_HASH SHA1=5eefeefc392cae36afb891ca81e3756aa0d79644 INSTALL_DIR ${PREFIX_ext_drmingw} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo Deploying Dr. Mingw 32-bit binary and dependencies INSTALL_COMMAND ${CMAKE_COMMAND} -E copy /bin/dbghelp.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/exchndl.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/mgwhelp.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/symsrv.dll ${PREFIX_ext_drmingw}/bin/ COMMAND ${CMAKE_COMMAND} -E copy /bin/symsrv.yes ${PREFIX_ext_drmingw}/bin/ UPDATE_COMMAND "" - ALWAYS 0 ) endif ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") endif (MSVC OR MINGW) diff --git a/3rdparty/ext_eigen3/CMakeLists.txt b/3rdparty/ext_eigen3/CMakeLists.txt index 6e49a85622..c2088f386c 100644 --- a/3rdparty/ext_eigen3/CMakeLists.txt +++ b/3rdparty/ext_eigen3/CMakeLists.txt @@ -1,13 +1,12 @@ SET(EXTPREFIX_eigen3 "${EXTPREFIX}" ) ExternalProject_Add( ext_eigen3 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/eigen-eigen-07105f7124f9.tar.gz URL_MD5 135d8d43aaee5fb54cf5f3e981b1a6db INSTALL_DIR ${EXTPREFIX_eigen3} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/dart.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_eigen3} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 ) diff --git a/3rdparty/ext_exiv2/CMakeLists.txt b/3rdparty/ext_exiv2/CMakeLists.txt index 5c3838dfd0..b3c3eb2a5b 100755 --- a/3rdparty/ext_exiv2/CMakeLists.txt +++ b/3rdparty/ext_exiv2/CMakeLists.txt @@ -1,17 +1,16 @@ SET(PREFIX_ext_exiv2 "${EXTPREFIX}" ) ExternalProject_Add( ext_exiv2 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/exiv2-0.25.tar.gz URL_MD5 258d4831b30f75a01e0234065c6c2806 PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/tzname.patch COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch_mingw.patch INSTALL_DIR ${PREFIX_ext_exiv2} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_exiv2} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DEXIV2_ENABLE_BUILD_SAMPLES=OFF -DEXIV2_ENABLE_BUILD_PO=OFF -DEXIV2_ENABLE_NLS=OFF -DICONV_INCLUDE_DIR=${PREFIX_ext_exiv2}/include UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_iconv ext_zlib ext_expat ) diff --git a/3rdparty/ext_expat/CMakeLists.txt b/3rdparty/ext_expat/CMakeLists.txt index 8d297addd1..cc0b28043c 100755 --- a/3rdparty/ext_expat/CMakeLists.txt +++ b/3rdparty/ext_expat/CMakeLists.txt @@ -1,35 +1,33 @@ SET(PREFIX_ext_expat "${EXTPREFIX}" ) if (WIN32) ExternalProject_Add( ext_expat DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/expat-2.1.0.tar.gz URL_MD5 dd7dab7a5fea97d2a6a43f511449b7cd PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/expat-2.1.0-20130311.diff INSTALL_DIR ${PREFIX_ext_expat} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_expat} -DBUILD_tests=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ) else() ExternalProject_Add( ext_expat DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/expat-2.1.0.tar.gz URL_MD5 dd7dab7a5fea97d2a6a43f511449b7cd INSTALL_DIR ${PREFIX_ext_expat} CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_expat} ${GLOBAL_AUTOMAKE_PROFILE} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 ) endif() diff --git a/3rdparty/ext_fftw3/CMakeLists.txt b/3rdparty/ext_fftw3/CMakeLists.txt index 8baba645d8..f2dc3ec8cd 100755 --- a/3rdparty/ext_fftw3/CMakeLists.txt +++ b/3rdparty/ext_fftw3/CMakeLists.txt @@ -1,84 +1,79 @@ SET(PREFIX_ext_fftw3 "${EXTPREFIX}" ) if (MSVC) if (${CMAKE_GENERATOR} STREQUAL "Visual Studio 14 2015 Win64") ExternalProject_Add( ext_fftw3 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/fftw-3.3.4-dll64.zip URL_MD5 c4ec1e6d84e7a8b1cd61121d11d44ee4 INSTALL_DIR ${PREFIX_ext_fftw3} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo deploying fftw3 64 binary INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory /bin ${PREFIX_ext_fftw3}/bin COMMAND ${CMAKE_COMMAND} -E copy_directory /lib ${PREFIX_ext_fftw3}/lib COMMAND ${CMAKE_COMMAND} -E copy_directory /include ${PREFIX_ext_fftw3}/include UPDATE_COMMAND "" - ALWAYS 0 ) else() ExternalProject_Add( ext_fftw3 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/fftw-3.3.4-dll32.zip URL_MD5 03754fe2a7fbaf983b0cc9a728e0a5b3 INSTALL_DIR ${PREFIX_ext_fftw3} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo deploying fftw3 32 binary INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory /bin ${PREFIX_ext_fftw3}/bin COMMAND ${CMAKE_COMMAND} -E copy_directory /lib ${PREFIX_ext_fftw3}/lib COMMAND ${CMAKE_COMMAND} -E copy_directory /include ${PREFIX_ext_fftw3}/include UPDATE_COMMAND "" - ALWAYS 0 ) endif() elseif (MINGW) if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") ExternalProject_Add( ext_fftw3 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/fftw-3.3.4-dll64.zip URL_MD5 c4ec1e6d84e7a8b1cd61121d11d44ee4 INSTALL_DIR ${PREFIX_ext_fftw3} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo deploying fftw3 64-bit binary INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory /bin ${PREFIX_ext_fftw3}/bin COMMAND ${CMAKE_COMMAND} -E copy_directory /lib ${PREFIX_ext_fftw3}/lib COMMAND ${CMAKE_COMMAND} -E copy_directory /include ${PREFIX_ext_fftw3}/include UPDATE_COMMAND "" - ALWAYS 0 ) else("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") ExternalProject_Add( ext_fftw3 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/fftw-3.3.4-dll32.zip URL_MD5 03754fe2a7fbaf983b0cc9a728e0a5b3 INSTALL_DIR ${PREFIX_ext_fftw3} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo deploying fftw3 32-bit binary INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory /bin ${PREFIX_ext_fftw3}/bin COMMAND ${CMAKE_COMMAND} -E copy_directory /lib ${PREFIX_ext_fftw3}/lib COMMAND ${CMAKE_COMMAND} -E copy_directory /include ${PREFIX_ext_fftw3}/include UPDATE_COMMAND "" - ALWAYS 0 ) endif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") else () ExternalProject_Add( ext_fftw3 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/fftw-3.3.4.tar.gz URL_MD5 2edab8c06b24feeb3b82bbb3ebf3e7b3 INSTALL_DIR ${PREFIX_ext_fftw3} CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_fftw3} ${GLOBAL_AUTOMAKE_PROFILE} --enable-static=false --enable-shared=yes BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 ) endif () diff --git a/3rdparty/ext_fontconfig/CMakeLists.txt b/3rdparty/ext_fontconfig/CMakeLists.txt index 9bd9075895..a013c04fb8 100755 --- a/3rdparty/ext_fontconfig/CMakeLists.txt +++ b/3rdparty/ext_fontconfig/CMakeLists.txt @@ -1,13 +1,12 @@ SET(PREFIX_ext_fontconfig "${EXTPREFIX}" ) ExternalProject_Add( ext_fontconfig DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/fontconfig-2.12.0.tar.gz URL_MD5 d8b056231abcb6257db6dc6d745360b2 CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_fontconfig} ${GLOBAL_AUTOMAKE_PROFILE} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 ) diff --git a/3rdparty/ext_frameworks/CMakeLists.txt b/3rdparty/ext_frameworks/CMakeLists.txt index 9cf48b169f..4810deb6e2 100755 --- a/3rdparty/ext_frameworks/CMakeLists.txt +++ b/3rdparty/ext_frameworks/CMakeLists.txt @@ -1,239 +1,226 @@ SET(EXTPREFIX_frameworks "${EXTPREFIX}" ) # # All needed frameworks: # # Archive # Config # WidgetsAddons # Completion # CoreAddons # GuiAddons # I18n # ItemModels # ItemViews # WindowSystem # On Linux: # KCrash ExternalProject_Add( ext_extra_cmake_modules DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/extra-cmake-modules-5.24.0.zip URL_MD5 e0c19ba97ebd964f9bdc9110c64ce96a PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/ecm_install_to_share.diff INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 ) ExternalProject_Add( ext_karchive DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/karchive-5.24.0.zip URL_MD5 739843accfe9bd85ab2f1582722cf01e INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_extra_cmake_modules ) ExternalProject_Add( ext_kconfig DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kconfig-5.24.0.zip URL_MD5 f87ecff795eb76e4ec6561758a5baf87 PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/kconfig.diff INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_karchive ) ExternalProject_Add( ext_kwidgetsaddons DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kwidgetsaddons-5.24.0.zip URL_MD5 0e399b427814a4814c65a3cf407f9d79 INSTALL_DIR ${EXTPREFIX_frameworks} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/kwidgetsaddons.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kconfig ) ExternalProject_Add( ext_kcompletion DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kcompletion-5.24.0.zip URL_MD5 e8764251ab45005aa81dba242852300c INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kwidgetsaddons ) ExternalProject_Add( ext_kcoreaddons DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kcoreaddons-5.24.0.zip URL_MD5 2885878625b19ad0300ef3770b897112 INSTALL_DIR ${EXTPREFIX_frameworks} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/desktoptojson.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kcompletion ) ExternalProject_Add( ext_kguiaddons DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kguiaddons-5.24.0.zip URL_MD5 9bdadbc57d0634816ef80ee9798c3d6c INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kcoreaddons ) ExternalProject_Add( ext_ki18n DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.17/ki18n-5.17.0.zip URL_MD5 7d60380d09f98defbf878ea9daba0fbb INSTALL_DIR ${EXTPREFIX_frameworks} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/ki18n.diff COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/ki18n-appdatalocation.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kguiaddons ) ExternalProject_Add( ext_kitemmodels DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kitemmodels-5.24.0.zip URL_MD5 ff41589f48395fc01d5fc7887593779d INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_ki18n ) ExternalProject_Add( ext_kitemviews DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kitemviews-5.24.0.zip URL_MD5 33f638d027a3011a6a69f7484eee3287 INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kitemmodels ) ExternalProject_Add( ext_kimageformats DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kimageformats-5.24.0.zip URL_MD5 c1964516bcb2bfe882858f0c0913deb5 INSTALL_DIR ${EXTPREFIX_frameworks} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/kimageformats.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kitemviews ) ExternalProject_Add( ext_kwindowsystem DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kwindowsystem-5.24.0.zip URL_MD5 5915e4f63ded983af6db7db3a6cbae1a INSTALL_DIR ${EXTPREFIX_frameworks} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/kwindowsystem-x11.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kimageformats ) ExternalProject_Add( ext_kcrash DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://download.kde.org/Attic/frameworks/5.24/kcrash-5.24.0.zip URL_MD5 a2e41e6650105fc3ac8fbd44afbae4fe INSTALL_DIR ${EXTPREFIX_frameworks} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} -DBUILD_TESTING=false UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_kwindowsystem ) diff --git a/3rdparty/ext_freetype/CMakeLists.txt b/3rdparty/ext_freetype/CMakeLists.txt index e53643a284..13cddbfed9 100755 --- a/3rdparty/ext_freetype/CMakeLists.txt +++ b/3rdparty/ext_freetype/CMakeLists.txt @@ -1,12 +1,11 @@ SET(PREFIX_ext_freetype "${EXTPREFIX}" ) ExternalProject_Add( ext_freetype DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/freetype-2.6.5.tar.gz URL_MD5 31b2276515d9ee1c7f37d9c9f4f3145a INSTALL_DIR ${PREFIX_ext_freetype} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_freetype} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 ) diff --git a/3rdparty/ext_gettext/CMakeLists.txt b/3rdparty/ext_gettext/CMakeLists.txt index b72178076b..519c77b81f 100644 --- a/3rdparty/ext_gettext/CMakeLists.txt +++ b/3rdparty/ext_gettext/CMakeLists.txt @@ -1,32 +1,30 @@ SET(PREFIX_ext_gettext "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_gettext DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/gettext-0.18.tar.gz URL_MD5 d52a3e061032a1ed13856d42fc86f0fd PATCH_COMMAND ${PATCH_COMMAND} --binary -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/gettext-0.18-20130319.diff INSTALL_DIR ${PREFIX_ext_gettext} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_gettext} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ext_iconv ) else (MSVC OR MINGW) ExternalProject_Add( ext_gettext DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/gettext-0.19.8.tar.gz URL_MD5 e4fffc004f21596becd1055cf36be31d INSTALL_DIR ${PREFIX_ext_gettext} CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_gettext} --disable-java ${GLOBAL_AUTOMAKE_PROFILE} --disable-native-java BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_iconv ) endif (MSVC OR MINGW) diff --git a/3rdparty/ext_gsl/CMakeLists.txt b/3rdparty/ext_gsl/CMakeLists.txt index 38f32cefd6..2a02f23889 100644 --- a/3rdparty/ext_gsl/CMakeLists.txt +++ b/3rdparty/ext_gsl/CMakeLists.txt @@ -1,28 +1,26 @@ # # From https://github.com/ampl/gsl. which adds CMake support to gsl # SET(EXTPREFIX_gsl "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_gsl DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} GIT_REPOSITORY https://github.com/ampl/gsl.git GIT_TAG 709cc572279e4a56b0e218b834f202c1b3f757af INSTALL_DIR ${EXTPREFIX_gsl} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_gsl} -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 ) else() ExternalProject_Add( ext_gsl DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/gsl-2.1.tar.gz URL_MD5 625f4105fcf653822a96294c1b801ad4 INSTALL_DIR ${EXTPREFIX_gsl} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_gsl} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DGSL_SHARED=ON UPDATE_COMMAND "" - ALWAYS 0 ) endif() diff --git a/3rdparty/ext_iconv/CMakeLists.txt b/3rdparty/ext_iconv/CMakeLists.txt index 4087a298af..9b7f799db8 100755 --- a/3rdparty/ext_iconv/CMakeLists.txt +++ b/3rdparty/ext_iconv/CMakeLists.txt @@ -1,31 +1,29 @@ SET(PREFIX_ext_iconv "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_iconv DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/win-iconv-0.0.6.tar.bz2 URL_MD5 1e97ed4d9e7379ff0ee22077256e8c58 INSTALL_DIR ${PREFIX_ext_iconv} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_iconv} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 ) else () ExternalProject_Add( ext_iconv DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libiconv-1.14.tar.gz URL_MD5 e34509b1623cec449dfeb73d7ce9c6c6 INSTALL_DIR ${PREFIX_ext_iconv} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/iconv.diff CONFIGURE_COMMAND ./configure --prefix=${PREFIX_ext_iconv} ${GLOBAL_AUTOMAKE_PROFILE} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" BUILD_IN_SOURCE 1 - ALWAYS 0 ) endif () diff --git a/3rdparty/ext_ilmbase/CMakeLists.txt b/3rdparty/ext_ilmbase/CMakeLists.txt index 0ca9f2d2ef..f37f669482 100755 --- a/3rdparty/ext_ilmbase/CMakeLists.txt +++ b/3rdparty/ext_ilmbase/CMakeLists.txt @@ -1,37 +1,36 @@ SET(PREFIX_ext_ilmbase "${EXTPREFIX}" ) ExternalProject_Add( ext_ilmbase DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/ilmbase-2.2.0.tar.gz URL_MD5 b540db502c5fa42078249f43d18a4652 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_ilmbase} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DNAMESPACE_VERSIONING=OFF UPDATE_COMMAND "" - ALWAYS 0 ) if (MSVC) ExternalProject_Add_Step( ext_ilmbase post_install COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/Half.dll ${PREFIX_ext_ilmbase}/bin/Half.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/Iex.dll ${PREFIX_ext_ilmbase}/bin/Iex.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/Imath.dll ${PREFIX_ext_ilmbase}/bin/Imath.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/IlmThread.dll ${PREFIX_ext_ilmbase}/bin/IlmThread.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/IexMath.dll ${PREFIX_ext_ilmbase}/bin/IexMath.dll DEPENDEES install ) endif() if (MINGW) ExternalProject_Add_Step( ext_ilmbase post_install COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/libHalf.dll ${PREFIX_ext_ilmbase}/bin/libHalf.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/libIex.dll ${PREFIX_ext_ilmbase}/bin/libIex.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/libImath.dll ${PREFIX_ext_ilmbase}/bin/libImath.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/libIlmThread.dll ${PREFIX_ext_ilmbase}/bin/libIlmThread.dll COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_ilmbase}/lib/libIexMath.dll ${PREFIX_ext_ilmbase}/bin/libIexMath.dll DEPENDEES install ) endif() diff --git a/3rdparty/ext_jpeg/CMakeLists.txt b/3rdparty/ext_jpeg/CMakeLists.txt index 168603644c..834fdc4a52 100755 --- a/3rdparty/ext_jpeg/CMakeLists.txt +++ b/3rdparty/ext_jpeg/CMakeLists.txt @@ -1,27 +1,25 @@ SET(PREFIX_ext_jpeg "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_jpeg DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libjpeg-turbo-1.5.0.tar.gz URL_MD5 3fc5d9b6a8bce96161659ae7a9939257 INSTALL_DIR ${PREFIX_ext_jpeg} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_jpeg} -DWITH_SIMD=OFF -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 ) else() ExternalProject_Add( ext_jpeg DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libjpeg-turbo-1.5.0.tar.gz URL_MD5 3fc5d9b6a8bce96161659ae7a9939257 CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_jpeg} ${GLOBAL_AUTOMAKE_PROFILE} --without-simd BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 ) endif() diff --git a/3rdparty/ext_lcms2/CMakeLists.txt b/3rdparty/ext_lcms2/CMakeLists.txt index 032e759376..6323ec1de9 100755 --- a/3rdparty/ext_lcms2/CMakeLists.txt +++ b/3rdparty/ext_lcms2/CMakeLists.txt @@ -1,29 +1,27 @@ SET(PREFIX_ext_lcms2 "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_lcms2 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/lcms2-2.8.tar.gz URL_MD5 87a5913f1a52464190bb655ad230539c PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/lcms2-2.8-20160725.diff INSTALL_DIR ${PREFIX_ext_lcms2} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_lcms2} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DBUILD_TESTS=FALSE -DBUILD_UTILS=FALSE -DBUILD_STATIC=FALSE UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ) else (MSVC OR MINGW) ExternalProject_Add( ext_lcms2 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/lcms2-2.8.tar.gz URL_MD5 87a5913f1a52464190bb655ad230539c CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_lcms2} ${GLOBAL_AUTOMAKE_PROFILE} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 ) endif (MSVC OR MINGW) diff --git a/3rdparty/ext_libraw/CMakeLists.txt b/3rdparty/ext_libraw/CMakeLists.txt index d212a94c4b..a1c7266401 100755 --- a/3rdparty/ext_libraw/CMakeLists.txt +++ b/3rdparty/ext_libraw/CMakeLists.txt @@ -1,14 +1,13 @@ SET(PREFIX_ext_libraw "${EXTPREFIX}" ) ExternalProject_Add( ext_libraw DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/LibRaw-0.17.1.tar.gz URL_MD5 1d272599e73b2c1d718621b68dcae5a8 PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/libraw.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_libraw} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_lcms2 ext_jpeg ) diff --git a/3rdparty/ext_libxml2/CMakeLists.txt b/3rdparty/ext_libxml2/CMakeLists.txt index f5c023e0c6..c625da2475 100755 --- a/3rdparty/ext_libxml2/CMakeLists.txt +++ b/3rdparty/ext_libxml2/CMakeLists.txt @@ -1,31 +1,29 @@ SET(PREFIX_ext_libxml2 "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_libxml2 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libxml2-sources-2.9.3.tar.gz URL_MD5 817ee2f5297e9763097074575903682d INSTALL_DIR ${PREFIX_ext_libxml2} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/libxml2-2.8.0-20110105.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_libxml2} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ext_iconv ext_zlib ) else (MSVC OR MINGW) ExternalProject_Add( ext_libxml2 DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libxml2-sources-2.9.3.tar.gz URL_MD5 817ee2f5297e9763097074575903682d INSTALL_DIR ${PREFIX_ext_libxml2} CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_libxml2} ${GLOBAL_AUTOMAKE_PROFILE} --with-python-install-dir=${PREFIX_ext_libxml2} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_iconv ext_zlib ) endif (MSVC OR MINGW) diff --git a/3rdparty/ext_libxslt/CMakeLists.txt b/3rdparty/ext_libxslt/CMakeLists.txt index d31d2b5aed..ef6950d787 100755 --- a/3rdparty/ext_libxslt/CMakeLists.txt +++ b/3rdparty/ext_libxslt/CMakeLists.txt @@ -1,30 +1,28 @@ SET(PREFIX_ext_libxslt "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_libxslt DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libxslt-1.1.29.tar.gz URL_MD5 a129d3c44c022de3b9dcf6d6f288d72e PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/libxslt-1.1.26-20101102.diff INSTALL_DIR ${PREFIX_ext_libxslt} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_libxslt} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ext_libxml2 ) else (MSVC OR MINGW) ExternalProject_Add( ext_libxslt DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libxslt-1.1.29.tar.gz URL_MD5 a129d3c44c022de3b9dcf6d6f288d72e CONFIGURE_COMMAND /configure --prefix=${PREFIX_ext_libxslt} ${GLOBAL_AUTOMAKE_PROFILE} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_libxml2 ) endif (MSVC OR MINGW) diff --git a/3rdparty/ext_ocio/CMakeLists.txt b/3rdparty/ext_ocio/CMakeLists.txt index 2b2e6703dd..3fa2cc7671 100644 --- a/3rdparty/ext_ocio/CMakeLists.txt +++ b/3rdparty/ext_ocio/CMakeLists.txt @@ -1,37 +1,35 @@ # # The latest opencolorio doesn't build on Windows without using boost::ptr, but if you build # it with boost::ptr, you cannot link to it because of missing dll exports, so build an older # ocio on Windows. # SET(EXTPREFIX_ocio "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_ocio DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/OpenColorIO-master.zip URL_MD5 7065faa41103ed27f5ea9b01b9e14c91 INSTALL_DIR ${EXTPREFIX_ocio} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_ocio} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} -DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_TRUELIGHT=OFF -DOCIO_BUILD_NUKE=OFF -DOCIO_BUILD_DOCS=OFF -DOCIO_BUILD_TESTS=OFF -DOCIO_BUILD_PYGLUE=OFF -DOCIO_BUILD_STATIC_JNIGLUE=OFF UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_boost ) else() ExternalProject_Add( ext_ocio DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/OpenColorIO-master.zip URL_MD5 7065faa41103ed27f5ea9b01b9e14c91 INSTALL_DIR ${EXTPREFIX_ocio} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_ocio} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_TRUELIGHT=OFF -DOCIO_BUILD_NUKE=OFF -DOCIO_BUILD_DOCS=OFF -DOCIO_BUILD_TESTS=OFF -DOCIO_BUILD_PYGLUE=OFF -DOCIO_BUILD_STATIC_JNIGLUE=OFF UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_boost ) endif() diff --git a/3rdparty/ext_openexr/CMakeLists.txt b/3rdparty/ext_openexr/CMakeLists.txt index 7b4f5c45a4..fc340108c1 100755 --- a/3rdparty/ext_openexr/CMakeLists.txt +++ b/3rdparty/ext_openexr/CMakeLists.txt @@ -1,33 +1,31 @@ SET(EXTPREFIX_openexr "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_openexr DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/openexr-2.2.0.tar.gz URL_MD5 b64e931c82aa3790329c21418373db4e PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/openexr.diff COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch_mingw.patch INSTALL_DIR ${EXTPREFIX_openexr} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_openexr} -DILMBASE_PACKAGE_PREFIX=${EXTPREFIX_openexr} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DNAMESPACE_VERSIONING=OFF UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_ilmbase ext_zlib ) else() ExternalProject_Add(ext_openexr DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/openexr-2.2.0.tar.gz URL_MD5 b64e931c82aa3790329c21418373db4e PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/openexr.diff INSTALL_DIR ${EXTPREFIX_openexr} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_openexr} -DILMBASE_PACKAGE_PREFIX=${EXTPREFIX_openexr} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DNAMESPACE_VERSIONING=OFF UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_ilmbase ext_zlib ) endif() diff --git a/3rdparty/ext_patch/CMakeLists.txt b/3rdparty/ext_patch/CMakeLists.txt index 110bd50717..314bff05ce 100755 --- a/3rdparty/ext_patch/CMakeLists.txt +++ b/3rdparty/ext_patch/CMakeLists.txt @@ -1,14 +1,13 @@ SET(PREFIX_ext_patch "${EXTPREFIX}" ) ExternalProject_Add( ext_patch DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/patch-2.5.9-7-bin.zip URL_MD5 b9c8b31d62f4b2e4f1887bbb63e8a905 INSTALL_DIR ${PREFIX_ext_patch} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo deploying patch.exe binary INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${PREFIX_ext_patch}/bin COMMAND ${CMAKE_COMMAND} -E copy bin/patch.exe ${PREFIX_ext_patch}/bin/myptch.exe UPDATE_COMMAND "" BUILD_IN_SOURCE 1 - ALWAYS 0 ) diff --git a/3rdparty/ext_png/CMakeLists.txt b/3rdparty/ext_png/CMakeLists.txt index bf67d146e3..b5ac62d0f6 100755 --- a/3rdparty/ext_png/CMakeLists.txt +++ b/3rdparty/ext_png/CMakeLists.txt @@ -1,13 +1,12 @@ SET(PREFIX_ext_png "${EXTPREFIX}" ) ExternalProject_Add( ext_png DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/libpng-1.6.23.tar.gz URL_MD5 3a8fb380b0fb39cb69efe47901917e38 INSTALL_DIR ${PREFIX_ext_png} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_png} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_zlib ) diff --git a/3rdparty/ext_png2ico/CMakeLists.txt b/3rdparty/ext_png2ico/CMakeLists.txt index 17e0b03204..1d44fe6274 100755 --- a/3rdparty/ext_png2ico/CMakeLists.txt +++ b/3rdparty/ext_png2ico/CMakeLists.txt @@ -1,16 +1,15 @@ SET(PREFIX_ext_png2ico "${EXTPREFIX}" ) ExternalProject_Add( ext_png2ico DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/png2ico.zip URL_MD5 5be668b436990255b75cce4ce03be282 INSTALL_DIR ${PREFIX_ext_png2ico} CONFIGURE_COMMAND "" BUILD_COMMAND ${CMAKE_COMMAND} -E echo deploying png2ico.exe binary INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${PREFIX_ext_png2ico}/bin COMMAND ${CMAKE_COMMAND} -E copy png2ico.exe ${PREFIX_ext_png2ico}/bin/png2ico.exe UPDATE_COMMAND "" BUILD_IN_SOURCE 1 - ALWAYS 0 ) diff --git a/3rdparty/ext_poppler/CMakeLists.txt b/3rdparty/ext_poppler/CMakeLists.txt index 3a0074dc7f..e2b3c9a785 100755 --- a/3rdparty/ext_poppler/CMakeLists.txt +++ b/3rdparty/ext_poppler/CMakeLists.txt @@ -1,13 +1,12 @@ SET(PREFIX_ext_poppler "${EXTPREFIX}" ) ExternalProject_Add( ext_poppler DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/poppler-0.45.0.tar.gz URL_MD5 02a81a20e24849feb1a2af4db1aca865 INSTALL_DIR ${PREFIX_ext_poppler} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/poppler_mingw.patch CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_poppler} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DBUILD_GTK_TESTS=OFF -DBUILD_QT5_TESTS=FALSE -BUILD_CPP_TESTS=FALSE -DENABLE_UTILS=FALSE -DENABLE_GLIB=FALSE -DENABLE_LIBOPENJPEG=FALSE UPDATE_COMMAND "" - ALWAYS 0 ) diff --git a/3rdparty/ext_pthreads/CMakeLists.txt b/3rdparty/ext_pthreads/CMakeLists.txt index b80490d507..42d539bab1 100755 --- a/3rdparty/ext_pthreads/CMakeLists.txt +++ b/3rdparty/ext_pthreads/CMakeLists.txt @@ -1,14 +1,13 @@ SET(PREFIX_ext_pthreads "${EXTPREFIX}" ) ExternalProject_Add( ext_pthreads DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/pthreads-w32-2-9-1-release.tar.gz URL_MD5 36ba827d6aa0fa9f9ae740a35626e2e3 INSTALL_DIR ${PREFIX_ext_pthreads} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/pthreads-w32-2-8-0-release-20110729.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_pthreads} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ) diff --git a/3rdparty/ext_qt/CMakeLists.txt b/3rdparty/ext_qt/CMakeLists.txt index 81fd754f82..3eb9ea4e6f 100644 --- a/3rdparty/ext_qt/CMakeLists.txt +++ b/3rdparty/ext_qt/CMakeLists.txt @@ -1,186 +1,183 @@ SET(EXTPREFIX_qt "${EXTPREFIX}") if (WIN32) ExternalProject_Add( ext_qt DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL https://download.qt.io/official_releases/qt/5.6/5.6.1-1/single/qt-everywhere-opensource-src-5.6.1-1.zip URL_MD5 9d7ea0cadcec7b5a63e8e83686756978 PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/disable-wintab.diff COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/qtgui-private-headers.diff COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/0001-Don-t-request-the-MIME-image-every-time-Windows-asks.patch COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/0002-Hack-always-return-we-support-DIBV5.patch COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/0003-Hack-for-fullscreen-workaround.patch INSTALL_DIR ${EXTPREFIX_qt} CONFIGURE_COMMAND /configure.bat -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdoc -skip qtenginio -skip qtgraphicaleffects -skip qtlocation -skip qtsensors -skip qtserialport -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtxmlpatterns -no-sql-sqlite -nomake examples -nomake tools -no-compile-examples -no-dbus -no-iconv -no-angle -no-ssl -no-openssl -no-wmf-backend -no-qml-debug -no-libproxy -no-system-proxies -no-nis -no-icu -no-mtdev -opensource -confirm-license -release -opengl desktop -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -prefix ${EXTPREFIX_qt} -platform win32-g++ # use this line for building Qt with debugging info enabled #CONFIGURE_COMMAND /configure.bat -release -force-debug-info -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdoc -skip qtenginio -skip qtgraphicaleffects -skip qtlocation -skip qtmultimedia -skip qtsensors -skip qtserialport -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtxmlpatterns -no-sql-sqlite -nomake examples -nomake tools -no-compile-examples -no-dbus -no-iconv -no-angle -no-ssl -no-openssl -no-wmf-backend -no-qml-debug -no-libproxy -no-system-proxies -no-nis -no-icu -no-mtdev -opensource -confirm-license -release -opengl desktop -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -prefix ${EXTPREFIX_qt} -platform win32-g++ BUILD_COMMAND mingw32-make INSTALL_COMMAND mingw32-make install UPDATE_COMMAND "" BUILD_IN_SOURCE 1 - ALWAYS 0 DEPENDS ext_patch ) elseif (NOT APPLE) ExternalProject_Add( ext_qt DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL https://download.qt.io/official_releases/qt/5.6/5.6.1-1/single/qt-everywhere-opensource-src-5.6.1-1.tar.gz URL_MD5 8fdec6d657bc370bd3183d8fe8e9c47a PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/qt-no-motion-compression.diff INSTALL_DIR ${EXTPREFIX_qt} CONFIGURE_COMMAND /configure -prefix ${EXTPREFIX_qt} -opensource -confirm-license -nomake examples -no-sql-sqlite -no-openssl -no-qml-debug -no-mtdev -no-journald -no-syslog -no-nis -no-cups -no-tslib -no-directfb -no-linuxfb -no-libproxy -no-pch -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-harfbuzz -qt-freetype -qt-xcb -qt-xkbcommon-x11 -optimized-qmake -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtenginio -skip qtgraphicaleffects -skip qtlocation -skip qtmultimedia -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtandroidextras -skip qtserialport BUILD_COMMAND $(MAKE) INSTALL_COMMAND $(MAKE) install UPDATE_COMMAND "" BUILD_IN_SOURCE 1 - ALWAYS 0 ) else( APPLE ) # XCODE_VERSION is set by CMake when using the Xcode generator, otherwise we need # to detect it manually here. if (NOT XCODE_VERSION) execute_process( COMMAND xcodebuild -version OUTPUT_VARIABLE xcodebuild_version OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_FILE /dev/null ) string(REGEX MATCH "Xcode ([0-9]([.][0-9])+)" version_match ${xcodebuild_version}) if (version_match) message(STATUS "${EXTPREFIX_qt}:Identified Xcode Version: ${CMAKE_MATCH_1}") set(XCODE_VERSION ${CMAKE_MATCH_1}) else() # If detecting Xcode version failed, set a crazy high version so we default # to the newest. set(XCODE_VERSION 99) message(WARNING "${EXTPREFIX_qt}:Failed to detect the version of an installed copy of Xcode, falling back to highest supported version. Set XCODE_VERSION to override.") endif(version_match) endif(NOT XCODE_VERSION) # ------------------------------------------------------------------------------- # Verify the Xcode installation on Mac OS like Qt5.7 does/will # If not stop now, the system isn't configured correctly for Qt. # No reason to even proceed. # ------------------------------------------------------------------------------- set(XCSELECT_OUTPUT) find_program(XCSELECT_PROGRAM "xcode-select") if(XCSELECT_PROGRAM) message(STATUS "${EXTPREFIX_qt}:Found XCSELECT_PROGRAM as ${XCSELECT_PROGRAM}") set(XCSELECT_COMMAND ${XCSELECT_PROGRAM} "--print-path") execute_process( COMMAND ${XCSELECT_COMMAND} RESULT_VARIABLE XCSELECT_COMMAND_RESULT OUTPUT_VARIABLE XCSELECT_COMMAND_OUTPUT ERROR_FILE /dev/null ) if(NOT XCSELECT_COMMAND_RESULT) # returned 0, we're ok. string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" XCSELECT_COMMAND_OUTPUT ${XCSELECT_COMMAND_OUTPUT}) else() string(REPLACE ";" " " XCSELECT_COMMAND_STR "${XCSELECT_COMMAND}") # message(STATUS "${XCSELECT_COMMAND_STR}") message(FATAL_ERROR "${EXTPREFIX_qt}:${XCSELECT_PROGRAM} test failed with status ${XCSELECT_COMMAND_RESULT}") endif() else() message(FATAL_ERROR "${EXTPREFIX_qt}:${XCSELECT_PROGRAM} not found. No Xcode is selected. Use xcode-select -switch to choose an Xcode version") endif() # Belts and suspenders # Beyond all the Xcode and Qt version checking, the proof of the pudding # lies in the success/failure of this command: xcrun --find xcrun. # On failure a patch is necessary, otherwise we're ok # So hard check xcrun now... set(XCRUN_OUTPUT) find_program(XCRUN_PROGRAM "xcrun") if(XCRUN_PROGRAM) message(STATUS "${EXTPREFIX_qt}:Found XCRUN_PROGRAM as ${XCRUN_PROGRAM}") set(XCRUN_COMMAND ${XCRUN_PROGRAM} "--find xcrun") execute_process( COMMAND ${XCRUN_COMMAND} RESULT_VARIABLE XCRUN_COMMAND_RESULT OUTPUT_VARIABLE XCRUN_COMMAND_OUTPUT ERROR_FILE /dev/null ) if(NOT XCRUN_COMMAND_RESULT) # returned 0, we're ok. string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" XCRUN_COMMAND_OUTPUT ${XCRUN_COMMAND_OUTPUT}) else() string(REPLACE ";" " " XCRUN_COMMAND_STR "${XCRUN_COMMAND}") # message(STATUS "${XCRUN_COMMAND_STR}") message(STATUS "${EXTPREFIX_qt}:xcrun test failed with status ${XCRUN_COMMAND_RESULT}") endif() else() message(STATUS "${EXTPREFIX_qt}:xcrun not found -- ${XCRUN_PROGRAM}") endif() # # Now configure ext_qt accordingly # if ((XCRUN_COMMAND_RESULT) AND (NOT (XCODE_VERSION VERSION_LESS 8.0.0))) # Fix Xcode xcrun related issue. # NOTE: This should be fixed by Qt 5.7.1 see here: http://code.qt.io/cgit/qt/qtbase.git/commit/?h=dev&id=77a71c32c9d19b87f79b208929e71282e8d8b5d9 # NOTE: but no one's holding their breath. set(ext_qt_PATCH_COMMAND $${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/gerrit-166202.diff COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/macdeploy-qt.diff COMMAND ${PATCH_COMMAND} -p1 -b -d /qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/qtbase-configure.patch COMMAND ${PATCH_COMMAND} -p1 -b -d /qtbase/mkspecs/features/mac -i ${CMAKE_CURRENT_SOURCE_DIR}/mac-default.patch) message(STATUS "${EXTPREFIX_qt}:Additional patches injected.") else() # No extra patches will be applied # NOTE: defaults for some untested scenarios like xcrun fails and xcode_version < 8. # NOTE: that is uncharted territory and (hopefully) a very unlikely scenario... set(ext_qt_PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/gerrit-166202.diff COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/macdeploy-qt.diff) endif() # Qt is big - try and parallelize if at all possible include(ProcessorCount) ProcessorCount(NUM_CORES) if(NOT NUM_CORES EQUAL 0) if (NUM_CORES GREATER 2) # be nice... MATH( EXPR NUM_CORES "${NUM_CORES} - 2" ) endif() set(PARALLEL_MAKE "make;-j${NUM_CORES}") message(STATUS "${EXTPREFIX_qt}:Parallelized make: ${PARALLEL_MAKE}") else() set(PARALLEL_MAKE "make") endif() ExternalProject_Add(ext_qt DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} LOG_DOWNLOAD ON LOG_UPDATE ON LOG_CONFIGURE ON LOG_BUILD ON LOG_TEST ON LOG_INSTALL ON BUILD_IN_SOURCE ON URL https://download.qt.io/official_releases/qt/5.7/5.7.0/single/qt-everywhere-opensource-src-5.7.0.tar.gz URL_MD5 9a46cce61fc64c20c3ac0a0e0fa41b42 PATCH_COMMAND ${ext_qt_PATCH_COMMAND} INSTALL_DIR ${EXTPREFIX_qt} CONFIGURE_COMMAND /configure -confirm-license -opensource -nomake examples -no-openssl -no-compile-examples -qt-freetype -qt-harfbuzz -opengl desktop -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtgraphicaleffects -skip qtlocation -skip qtmultimedia -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtxmlpatterns -prefix ${EXTPREFIX_qt} BUILD_COMMAND ${PARALLEL_MAKE} INSTALL_COMMAND make install UPDATE_COMMAND "" BUILD_IN_SOURCE 1 - ALWAYS 0 ) endif() diff --git a/3rdparty/ext_tiff/CMakeLists.txt b/3rdparty/ext_tiff/CMakeLists.txt index 32351b3987..e3b1faa91d 100755 --- a/3rdparty/ext_tiff/CMakeLists.txt +++ b/3rdparty/ext_tiff/CMakeLists.txt @@ -1,30 +1,28 @@ SET(EXTPREFIX_tiff "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_tiff DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/tiff-4.0.3.tar.gz URL_MD5 051c1068e6a0627f461948c365290410 PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/tiff-4.0.3-20130124.diff INSTALL_DIR ${EXTPREFIX_tiff} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_tiff} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ext_zlib ext_jpeg ) else (MSVC OR MINGW) ExternalProject_Add( ext_tiff DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/tiff-4.0.6.tar.gz URL_MD5 d1d2e940dea0b5ad435f21f03d96dd72 CONFIGURE_COMMAND /configure -prefix ${EXTPREFIX_tiff} ${GLOBAL_AUTOMAKE_PROFILE} BUILD_COMMAND make INSTALL_COMMAND make install UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_zlib ext_jpeg ) endif (MSVC OR MINGW) diff --git a/3rdparty/ext_vc/CMakeLists.txt b/3rdparty/ext_vc/CMakeLists.txt index 203f4bcca9..9c218bbfab 100755 --- a/3rdparty/ext_vc/CMakeLists.txt +++ b/3rdparty/ext_vc/CMakeLists.txt @@ -1,15 +1,14 @@ SET(PREFIX_ext_vc "${EXTPREFIX}" ) ExternalProject_Add( ext_vc DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/Vc-1.2.0.tar.gz URL_MD5 f2a213ae4bad0dcf4ec6469e4dad41c1 INSTALL_DIR ${PREFIX_ext_vc} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/vc1.2_malloc_free.patch CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_vc} -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} -DCMAKE_SYSTEM_PROCESSOR=x86 UPDATE_COMMAND "" - ALWAYS 0 ) diff --git a/3rdparty/ext_zlib/CMakeLists.txt b/3rdparty/ext_zlib/CMakeLists.txt index 2934bff647..1db66ffc49 100755 --- a/3rdparty/ext_zlib/CMakeLists.txt +++ b/3rdparty/ext_zlib/CMakeLists.txt @@ -1,30 +1,28 @@ SET(PREFIX_ext_zlib "${EXTPREFIX}" ) if (MSVC OR MINGW) ExternalProject_Add( ext_zlib DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/zlib-1.2.8.tar.gz URL_MD5 44d667c142d7cda120332623eab69f40 INSTALL_DIR ${PREFIX_ext_zlib} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/zlib-1.2.8-20130901.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_zlib} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 DEPENDS ext_patch ) else () ExternalProject_Add( ext_zlib DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} URL http://files.kde.org/krita/build/dependencies/zlib-1.2.8.tar.gz URL_MD5 44d667c142d7cda120332623eab69f40 INSTALL_DIR ${PREFIX_ext_zlib} PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/zlib-1.2.8-20130901.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_zlib} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} UPDATE_COMMAND "" - ALWAYS 0 ) endif () diff --git a/benchmarks/kis_bcontrast_benchmark.cpp b/benchmarks/kis_bcontrast_benchmark.cpp index 109c398700..bc5e8d04fd 100644 --- a/benchmarks/kis_bcontrast_benchmark.cpp +++ b/benchmarks/kis_bcontrast_benchmark.cpp @@ -1,100 +1,100 @@ /* * Copyright (c) 2010 Lukáš Tvrdý lukast.dev@gmail.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "kis_bcontrast_benchmark.h" #include "kis_benchmark_values.h" #include #include #include #include #include "filter/kis_filter_registry.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter.h" #include "kis_processing_information.h" #include "kis_selection.h" #include #include "krita_utils.h" void KisBContrastBenchmark::initTestCase() { m_colorSpace = KoColorSpaceRegistry::instance()->rgb8(); m_device = new KisPaintDevice(m_colorSpace); m_color = KoColor(m_colorSpace); srand(31524744); int r,g,b; KisSequentialIterator it(m_device, QRect(0, 0, GMP_IMAGE_WIDTH, GMP_IMAGE_HEIGHT)); do { r = rand() % 255; g = rand() % 255; b = rand() % 255; m_color.fromQColor(QColor(r,g,b)); memcpy(it.rawData(), m_color.data(), m_colorSpace->pixelSize()); } while (it.nextPixel()); } void KisBContrastBenchmark::cleanupTestCase() { } void KisBContrastBenchmark::benchmarkFilter() { KisFilterSP filter = KisFilterRegistry::instance()->value("brightnesscontrast"); - KisFilterConfigurationSP kfc = filter->defaultConfiguration(m_device); + KisFilterConfigurationSP kfc = filter->defaultConfiguration(); // Get the predefined configuration from a file QFile file(QString(FILES_DATA_DIR) + QDir::separator() + filter->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); kfc->fromXML(s); } QSize size = KritaUtils::optimalPatchSize(); QVector rects = KritaUtils::splitRectIntoPatches(QRect(0, 0, GMP_IMAGE_WIDTH,GMP_IMAGE_HEIGHT), size); QBENCHMARK{ Q_FOREACH (const QRect &rc, rects) { filter->process(m_device, rc, kfc); } } } QTEST_MAIN(KisBContrastBenchmark) diff --git a/benchmarks/kis_blur_benchmark.cpp b/benchmarks/kis_blur_benchmark.cpp index 80d24578ac..7c7057aaeb 100644 --- a/benchmarks/kis_blur_benchmark.cpp +++ b/benchmarks/kis_blur_benchmark.cpp @@ -1,92 +1,92 @@ /* * Copyright (c) 2010 Lukáš Tvrdý lukast.dev@gmail.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "kis_blur_benchmark.h" #include "kis_benchmark_values.h" #include #include #include #include #include "filter/kis_filter_registry.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter.h" #include "kis_processing_information.h" #include "kis_selection.h" #include void KisBlurBenchmark::initTestCase() { m_colorSpace = KoColorSpaceRegistry::instance()->rgb8(); m_device = new KisPaintDevice(m_colorSpace); m_color = KoColor(m_colorSpace); QColor qcolor(Qt::red); srand(31524744); int r,g,b; KisSequentialIterator it(m_device, QRect(0,0,GMP_IMAGE_WIDTH, GMP_IMAGE_HEIGHT)); do { r = rand() % 255; g = rand() % 255; b = rand() % 255; m_color.fromQColor(QColor(r,g,b)); memcpy(it.rawData(), m_color.data(), m_colorSpace->pixelSize()); } while (it.nextPixel()); } void KisBlurBenchmark::cleanupTestCase() { } void KisBlurBenchmark::benchmarkFilter() { KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); - KisFilterConfigurationSP kfc = filter->defaultConfiguration(m_device); + KisFilterConfigurationSP kfc = filter->defaultConfiguration(); // Get the predefined configuration from a file QFile file(QString(FILES_DATA_DIR) + QDir::separator() + filter->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); kfc->fromXML(s); } QBENCHMARK{ filter->process(m_device, QRect(0, 0, GMP_IMAGE_WIDTH,GMP_IMAGE_HEIGHT), kfc); } } QTEST_MAIN(KisBlurBenchmark) diff --git a/benchmarks/kis_filter_selections_benchmark.cpp b/benchmarks/kis_filter_selections_benchmark.cpp index 7c78cc8a1d..0ddf499615 100644 --- a/benchmarks/kis_filter_selections_benchmark.cpp +++ b/benchmarks/kis_filter_selections_benchmark.cpp @@ -1,293 +1,293 @@ /* * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_filter_selections_benchmark.h" #include "kis_painter.h" #include #include "testutil.h" #include "kis_transaction.h" #include #include "kis_datamanager.h" #define NUM_CYCLES 50 #define WARMUP_CYCLES 2 #define SHOW_WARMUPS 0 /** * Our filters don't know anything about applyAlphaU8Mask * That's why they treat semy-selected pixels badly * * If you have a hack in KisFilter - processSpecial(..) method * that takes into account this alpha mask then activate * the following define */ #define USE_GOOD_SELECTIONS 0 #define USE_UTIME 0 #if(USE_UTIME==1) #include class KisTimeCounter { public: KisTimeCounter() { m_factor = double(sysconf(_SC_CLK_TCK)) / 1000.0; restart(); } void restart() { times(&m_startTime); } double elapsed() { struct tms endTime; times(&endTime); return double(endTime.tms_utime - m_startTime.tms_utime) / m_factor; } private: struct tms m_startTime; double m_factor; }; #else /* if(USE_UTIME==0) */ typedef QTime KisTimeCounter; #endif void KisFilterSelectionsBenchmark::initSelection() { m_selection = new KisSelection(); KisPixelSelectionSP pixelSelection = m_selection->pixelSelection(); //67.2% deselected dbgKrita << "Deselected: 67.2%"; pixelSelection->dataManager()->clear(75, 75, 500, 320, 255); pixelSelection->dataManager()->clear(100, 100, 50, 50, quint8(0)); pixelSelection->dataManager()->clear(150, 150, 50, 50, quint8(0)); pixelSelection->dataManager()->clear(200, 200, 50, 50, quint8(0)); pixelSelection->dataManager()->clear(375, 195, 200, 200, quint8(0)); pixelSelection->dataManager()->clear(75, 195, 200, 200, quint8(0)); pixelSelection->dataManager()->clear(375, 75, 150, 150, quint8(0)); pixelSelection->dataManager()->clear(205, 105, 50, 50, quint8(128)); // 94.9% deselected // dbgKrita << "Deselected: 94.9%"; // pixelSelection->dataManager()->clear(75,75,500,320,255); // pixelSelection->dataManager()->clear(80,80,490,310,quint8(0)); pixelSelection->convertToQImage(0).save("TEST_FILTER_SELECTION.png"); } void KisFilterSelectionsBenchmark::initFilter(const QString &name) { m_filter = KisFilterRegistry::instance()->value(name); Q_ASSERT(m_filter); - m_configuration = m_filter->defaultConfiguration(0); + m_configuration = m_filter->defaultConfiguration(); dbgKrita << "Filter initialized:" << name; } void KisFilterSelectionsBenchmark::testFilter(const QString &name) { blockSignals(true); initFilter(name); testUsualSelections(WARMUP_CYCLES); testUsualSelections(NUM_CYCLES); testGoodSelections(WARMUP_CYCLES); testGoodSelections(NUM_CYCLES); testNoSelections(WARMUP_CYCLES); testNoSelections(NUM_CYCLES); testBitBltWOSelections(WARMUP_CYCLES); testBitBltWOSelections(NUM_CYCLES); testBitBltSelections(WARMUP_CYCLES); testBitBltSelections(NUM_CYCLES); blockSignals(false); } void KisFilterSelectionsBenchmark::testAll() { initSelection(); const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); QImage image(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); m_device = new KisPaintDevice(cs); m_device->convertFromQImage(image, 0, 0, 0); testFilter("brightnesscontrast"); testFilter("invert"); // testFilter("levels"); } void KisFilterSelectionsBenchmark::testUsualSelections(int num) { KisPaintDeviceSP projection = new KisPaintDevice(m_device->colorSpace()); double avTime; KisTimeCounter timer; QRect filterRect = m_selection->selectedExactRect(); timer.restart(); for (int i = 0; i < num; i++) { KisTransaction transac(projection, 0); m_filter->process(m_device, projection, m_selection, filterRect, m_configuration, 0); } avTime = double(timer.elapsed()) / num; projection->convertToQImage(0).save("TFS__USUAL_SELECTIONS.png"); if (num > WARMUP_CYCLES || SHOW_WARMUPS) dbgKrita << "Selections inside filter:\t\t" << avTime; } void KisFilterSelectionsBenchmark::testNoSelections(int num) { KisPaintDeviceSP projection = new KisPaintDevice(m_device->colorSpace()); double avTime; KisTimeCounter timer; QRect filterRect = m_selection->selectedExactRect(); timer.restart(); for (int i = 0; i < num; i++) { KisTransaction transac(projection, 0); m_filter->process(m_device, projection, 0, filterRect, m_configuration, 0); } avTime = double(timer.elapsed()) / num; projection->convertToQImage(0).save("TFS__NO_SELECTIONS.png"); if (num > WARMUP_CYCLES || SHOW_WARMUPS) dbgKrita << "No Selections:\t\t\t\t" << avTime; } void KisFilterSelectionsBenchmark::testGoodSelections(int num) { #if(USE_GOOD_SELECTIONS==1) KisPaintDeviceSP projection = new KisPaintDevice(m_device->colorSpace()); double avTime; KisTimeCounter timer; QRect filterRect = m_selection->selectedExactRect(); KisConstProcessingInformation src(m_device, filterRect.topLeft(), m_selection); KisProcessingInformation dst(projection, filterRect.topLeft(), 0); timer.restart(); for (int i = 0; i < num; i++) { KisTransaction transac(0, projection, 0); m_filter->processSpecial(src, dst, filterRect.size(), m_configuration, 0); } avTime = double(timer.elapsed()) / num; projection->convertToQImage(0).save("TFS__GOOD_SELECTIONS.png"); if (num > WARMUP_CYCLES || SHOW_WARMUPS) dbgKrita << "Selections with alpha (filter):\t" << avTime; #else /* if (USE_GOOD_SELECTIONS!=1) */ if (num > WARMUP_CYCLES || SHOW_WARMUPS) dbgKrita << "Selections with alpha (filter):\t [Disabled]"; #endif } void KisFilterSelectionsBenchmark::testBitBltWOSelections(int num) { KisPaintDeviceSP projection = new KisPaintDevice(m_device->colorSpace()); double avTime; KisTimeCounter timer; QRect filterRect = m_selection->selectedExactRect(); timer.restart(); for (int i = 0; i < num; i++) { KisPaintDeviceSP cacheDevice = new KisPaintDevice(projection->colorSpace()); KisTransaction transac(cacheDevice, 0); m_filter->process(m_device, projection, 0, filterRect, m_configuration, 0); KisPainter painter(projection); painter.beginTransaction(); painter.setCompositeOp(projection->colorSpace()->compositeOp(COMPOSITE_ALPHA_DARKEN)); painter.bitBlt(filterRect.topLeft(), cacheDevice, filterRect); painter.deleteTransaction(); } avTime = double(timer.elapsed()) / num; projection->convertToQImage(0).save("TFS__BITBLT_WO_SELECTIONS.png"); if (num > WARMUP_CYCLES || SHOW_WARMUPS) dbgKrita << "bitBlt w/o sel:\t\t\t" << avTime; } void KisFilterSelectionsBenchmark::testBitBltSelections(int num) { KisPaintDeviceSP projection = new KisPaintDevice(m_device->colorSpace()); double avTime; KisTimeCounter timer; QRect filterRect = m_selection->selectedExactRect(); timer.restart(); for (int i = 0; i < num; i++) { KisPaintDeviceSP cacheDevice = new KisPaintDevice(projection->colorSpace()); KisTransaction transac(cacheDevice, 0); m_filter->process(m_device, cacheDevice, 0, filterRect, m_configuration, 0); KisPainter gc(projection); gc.beginTransaction(); gc.setCompositeOp(projection->colorSpace()->compositeOp(COMPOSITE_ALPHA_DARKEN)); gc.setSelection(m_selection); gc.bitBlt(filterRect.topLeft(), cacheDevice, filterRect); gc.deleteTransaction(); } avTime = double(timer.elapsed()) / num; projection->convertToQImage(0).save("TFS__BITBLT_WITH_SELECTIONS.png"); if (num > WARMUP_CYCLES || SHOW_WARMUPS) dbgKrita << "bitBlt with sel:\t\t\t" << avTime; } QTEST_MAIN(KisFilterSelectionsBenchmark) diff --git a/libs/image/commands/kis_change_filter_command.h b/libs/image/commands/kis_change_filter_command.h index f949ec1480..7634b4059f 100644 --- a/libs/image/commands/kis_change_filter_command.h +++ b/libs/image/commands/kis_change_filter_command.h @@ -1,96 +1,96 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CHANGE_FILTER_COMMAND_H #define KIS_CHANGE_FILTER_COMMAND_H #include #include #include "kis_types.h" #include #include "filter/kis_filter_configuration.h" #include "kis_node.h" #include "kis_node_filter_interface.h" #include "filter/kis_filter_registry.h" #include "filter/kis_filter.h" #include "generator/kis_generator_registry.h" #include "generator/kis_generator.h" class KisChangeFilterCmd : public KUndo2Command { public: KisChangeFilterCmd(KisNodeSP node, const QString &filterNameBefore, const QString &xmlBefore, const QString &filterNameAfter, const QString &xmlAfter, bool useGeneratorRegistry) : KUndo2Command(kundo2_i18n("Change Filter")) { m_node = node; m_filterInterface = dynamic_cast(node.data()); Q_ASSERT(m_filterInterface); m_useGeneratorRegistry = useGeneratorRegistry; m_xmlBefore = xmlBefore; m_xmlAfter = xmlAfter; m_filterNameBefore = filterNameBefore; m_filterNameAfter = filterNameAfter; } public: virtual void redo() { m_filterInterface->setFilter(createConfiguration(m_filterNameAfter, m_xmlAfter)); m_node->setDirty(); } virtual void undo() { m_filterInterface->setFilter(createConfiguration(m_filterNameBefore, m_xmlBefore)); m_node->setDirty(); } private: KisFilterConfigurationSP createConfiguration(const QString &name, const QString &data) { KisFilterConfigurationSP config; if (m_useGeneratorRegistry) { KisGeneratorSP generator = KisGeneratorRegistry::instance()->value(name); - config = generator->defaultConfiguration(KisPaintDeviceSP()); + config = generator->defaultConfiguration(); } else { KisFilterSP filter = KisFilterRegistry::instance()->value(name); - config = filter->defaultConfiguration(KisPaintDeviceSP()); + config = filter->defaultConfiguration(); } config->fromXML(data); return config; } private: KisNodeSP m_node; KisNodeFilterInterface *m_filterInterface; bool m_useGeneratorRegistry; QString m_xmlBefore; QString m_xmlAfter; QString m_filterNameBefore; QString m_filterNameAfter; }; #endif diff --git a/libs/image/filter/kis_color_transformation_filter.cc b/libs/image/filter/kis_color_transformation_filter.cc index ab451b62dc..3b5457dec3 100644 --- a/libs/image/filter/kis_color_transformation_filter.cc +++ b/libs/image/filter/kis_color_transformation_filter.cc @@ -1,88 +1,88 @@ /* * Copyright (c) 2004, 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_color_transformation_filter.h" #include #include #include #include #include #ifndef NDEBUG #include #endif #include #include "kis_color_transformation_configuration.h" KisColorTransformationFilter::KisColorTransformationFilter(const KoID& id, const KoID & category, const QString & entry) : KisFilter(id, category, entry) { setSupportsLevelOfDetail(true); } KisColorTransformationFilter::~KisColorTransformationFilter() { } void KisColorTransformationFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.height() * applyRect.width()); } const KoColorSpace * cs = device->colorSpace(); KoColorTransformation * colorTransformation = 0; // Ew, casting KisColorTransformationConfigurationSP colorTransformationConfiguration(dynamic_cast(const_cast(config.data()))); if (colorTransformationConfiguration) { colorTransformation = colorTransformationConfiguration->colorTransformation(cs, this); } else { colorTransformation = createTransformation(cs, config); } if (!colorTransformation) return; KisSequentialIterator it(device, applyRect); int p = 0; int conseq; do { conseq = it.nConseqPixels(); colorTransformation->transform(it.oldRawData(), it.rawData(), conseq); if (progressUpdater) progressUpdater->setValue(p += conseq); } while(it.nextPixels(conseq)); if (!colorTransformationConfiguration) { delete colorTransformation; } } -KisFilterConfigurationSP KisColorTransformationFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisColorTransformationFilter::factoryConfiguration() const { return new KisColorTransformationConfiguration(id(), 0); } diff --git a/libs/image/filter/kis_color_transformation_filter.h b/libs/image/filter/kis_color_transformation_filter.h index 8666cb3a44..d2c7a4b971 100644 --- a/libs/image/filter/kis_color_transformation_filter.h +++ b/libs/image/filter/kis_color_transformation_filter.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KIS_COLOR_TRANSFORMATION_FILTER_H_ #define _KIS_COLOR_TRANSFORMATION_FILTER_H_ #include "kis_filter.h" #include "kritaimage_export.h" /** * This is a base class for filters that implement a filter for * \ref KoColorTransformation based filters. */ class KRITAIMAGE_EXPORT KisColorTransformationFilter : public KisFilter { public: KisColorTransformationFilter(const KoID& id, const KoID & category, const QString & entry); virtual ~KisColorTransformationFilter(); virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; /** * Create the color transformation that will be applied on the device. */ virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const = 0; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; #endif diff --git a/libs/image/filter/kis_filter_registry.cc b/libs/image/filter/kis_filter_registry.cc index d9fb0ae4f0..4e8143663b 100644 --- a/libs/image/filter/kis_filter_registry.cc +++ b/libs/image/filter/kis_filter_registry.cc @@ -1,81 +1,81 @@ /* * Copyright (c) 2003 Patrick Julien * Copyright (c) 2004 Cyrille Berger * Copyright (c) 2004-2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "filter/kis_filter_registry.h" #include #include #include #include #include #include "kis_debug.h" #include "kis_types.h" #include "kis_paint_device.h" #include "filter/kis_filter.h" #include "kis_filter_configuration.h" KisFilterRegistry::KisFilterRegistry(QObject *parent) : QObject(parent) { } KisFilterRegistry::~KisFilterRegistry() { dbgRegistry << "deleting KisFilterRegistry"; Q_FOREACH (KisFilterSP filter, values()) { remove(filter->id()); filter.clear(); } } KisFilterRegistry* KisFilterRegistry::instance() { KisFilterRegistry *reg = qApp->findChild(QString()); if (!reg) { reg = new KisFilterRegistry(qApp); KoPluginLoader::instance()->load("Krita/Filter", "Type == 'Service' and ([X-Krita-Version] == 28)"); } return reg; } void KisFilterRegistry::add(KisFilterSP item) { add(item->id(), item); } void KisFilterRegistry::add(const QString &id, KisFilterSP item) { KoGenericRegistry::add(id, item); emit(filterAdded(id)); } KisFilterConfigurationSP KisFilterRegistry::cloneConfiguration(const KisFilterConfigurationSP kfc) { Q_ASSERT(kfc); KisFilterSP filter = value(kfc->name()); - KisFilterConfigurationSP newkfc(filter->defaultConfiguration(KisPaintDeviceSP())); + KisFilterConfigurationSP newkfc(filter->defaultConfiguration()); newkfc->fromXML(kfc->toXML()); return newkfc; } diff --git a/libs/image/generator/kis_generator_registry.cpp b/libs/image/generator/kis_generator_registry.cpp index ee8a66511e..60c7e4f3ce 100644 --- a/libs/image/generator/kis_generator_registry.cpp +++ b/libs/image/generator/kis_generator_registry.cpp @@ -1,80 +1,80 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "generator/kis_generator_registry.h" #include #include #include #include #include #include "filter/kis_filter_configuration.h" #include "kis_debug.h" #include "kis_types.h" #include "kis_paint_device.h" #include "generator/kis_generator.h" KisGeneratorRegistry::KisGeneratorRegistry(QObject *parent) : QObject(parent) { } KisGeneratorRegistry::~KisGeneratorRegistry() { Q_FOREACH (KisGeneratorSP generator, values()) { remove(generator->id()); generator.clear(); } dbgRegistry << "deleting KisGeneratorRegistry"; } KisGeneratorRegistry* KisGeneratorRegistry::instance() { KisGeneratorRegistry *reg = qApp->findChild(QString()); if (!reg) { reg = new KisGeneratorRegistry(qApp); KoPluginLoader::instance()->load("Krita/Generator", "Type == 'Service' and ([X-Krita-Version] == 28)"); } return reg; } void KisGeneratorRegistry::add(KisGeneratorSP item) { dbgPlugins << "adding " << item->name(); add(item->id(), item); } void KisGeneratorRegistry::add(const QString &id, KisGeneratorSP item) { dbgPlugins << "adding " << item->name() << " with id " << id; KoGenericRegistry::add(id, item); emit(generatorAdded(id)); } KisFilterConfigurationSP KisGeneratorRegistry::cloneConfiguration(const KisFilterConfigurationSP kfc) { KisGeneratorSP filter = value(kfc->name()); - KisFilterConfigurationSP newkfc(filter->defaultConfiguration(KisPaintDeviceSP())); + KisFilterConfigurationSP newkfc(filter->defaultConfiguration()); newkfc->fromXML(kfc->toXML()); return newkfc; } diff --git a/libs/image/kis_base_processor.cpp b/libs/image/kis_base_processor.cpp index d0c57893ff..8390b707f2 100644 --- a/libs/image/kis_base_processor.cpp +++ b/libs/image/kis_base_processor.cpp @@ -1,198 +1,191 @@ /* * Copyright (c) 2004,2006-2007 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_base_processor.h" #include #include "kis_bookmarked_configuration_manager.h" #include "filter/kis_filter_configuration.h" #include "kis_paint_device.h" #include "kis_selection.h" class KisBaseProcessorConfigurationFactory : public KisSerializableConfigurationFactory { public: KisBaseProcessorConfigurationFactory(KisBaseProcessor* _generator) : m_generator(_generator) {} ~KisBaseProcessorConfigurationFactory() override {} KisSerializableConfigurationSP createDefault() override { - return m_generator->factoryConfiguration(KisPaintDeviceSP()); + return m_generator->factoryConfiguration(); } KisSerializableConfigurationSP create(const QDomElement& e) override { - KisSerializableConfigurationSP config = m_generator->factoryConfiguration(KisPaintDeviceSP()); + KisSerializableConfigurationSP config = m_generator->factoryConfiguration(); config->fromXML(e); return config; } private: KisBaseProcessor* m_generator; }; struct Q_DECL_HIDDEN KisBaseProcessor::Private { Private() : bookmarkManager(0) , supportsPainting(false) , supportsAdjustmentLayers(true) , supportsThreading(true) , showConfigurationWidget(true) , colorSpaceIndependence(FULLY_INDEPENDENT) { } KisBookmarkedConfigurationManager* bookmarkManager; KoID id; KoID category; // The category in the filter menu this filter fits QString entry; // the i18n'ed accelerated menu text QKeySequence shortcut; bool supportsPainting; bool supportsAdjustmentLayers; bool supportsThreading; bool showConfigurationWidget; ColorSpaceIndependence colorSpaceIndependence; }; KisBaseProcessor::KisBaseProcessor(const KoID& id, const KoID & category, const QString & entry) : d(new Private) { d->id = id; d->category = category; d->entry = entry; } void KisBaseProcessor::init(const QString& configEntryGroup) { d->bookmarkManager = new KisBookmarkedConfigurationManager(configEntryGroup, new KisBaseProcessorConfigurationFactory(this)); } KisBaseProcessor::~KisBaseProcessor() { delete d->bookmarkManager; delete d; } -KisFilterConfigurationSP KisBaseProcessor::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisBaseProcessor::factoryConfiguration() const { return new KisFilterConfiguration(id(), 0); } -KisFilterConfigurationSP KisBaseProcessor::defaultConfiguration(const KisPaintDeviceSP pd) const +KisFilterConfigurationSP KisBaseProcessor::defaultConfiguration() const { - KisFilterConfigurationSP fc = 0; -// if (bookmarkManager()) { -// fc = dynamic_cast(bookmarkManager()->defaultConfiguration()); -// } - if (!fc || !fc->isCompatible(pd)) { - fc = factoryConfiguration(pd); - } - return fc; + return factoryConfiguration(); } KisConfigWidget * KisBaseProcessor::createConfigurationWidget(QWidget *, const KisPaintDeviceSP) const { return 0; } KisBookmarkedConfigurationManager* KisBaseProcessor::bookmarkManager() { return d->bookmarkManager; } const KisBookmarkedConfigurationManager* KisBaseProcessor::bookmarkManager() const { return d->bookmarkManager; } QString KisBaseProcessor::id() const { return d->id.id(); } QString KisBaseProcessor::name() const { return d->id.name(); } KoID KisBaseProcessor::menuCategory() const { return d->category; } QString KisBaseProcessor::menuEntry() const { return d->entry; } QKeySequence KisBaseProcessor::shortcut() const { return d->shortcut; } void KisBaseProcessor::setShortcut(const QKeySequence & shortcut) { d->shortcut = shortcut; } bool KisBaseProcessor::supportsPainting() const { return d->supportsPainting; } bool KisBaseProcessor::supportsAdjustmentLayers() const { return d->supportsAdjustmentLayers; } bool KisBaseProcessor::supportsThreading() const { return d->supportsThreading; } ColorSpaceIndependence KisBaseProcessor::colorSpaceIndependence() const { return d->colorSpaceIndependence; } void KisBaseProcessor::setSupportsPainting(bool v) { d->supportsPainting = v; } void KisBaseProcessor::setSupportsAdjustmentLayers(bool v) { d->supportsAdjustmentLayers = v; } void KisBaseProcessor::setSupportsThreading(bool v) { d->supportsThreading = v; } void KisBaseProcessor::setColorSpaceIndependence(ColorSpaceIndependence v) { d->colorSpaceIndependence = v; } bool KisBaseProcessor::showConfigurationWidget() { return d->showConfigurationWidget; } void KisBaseProcessor::setShowConfigurationWidget(bool v) { d->showConfigurationWidget = v; } diff --git a/libs/image/kis_base_processor.h b/libs/image/kis_base_processor.h index 65c857da8a..0cb9c75f8a 100644 --- a/libs/image/kis_base_processor.h +++ b/libs/image/kis_base_processor.h @@ -1,167 +1,167 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_BASE_PROCESSOR_H_ #define _KIS_BASE_PROCESSOR_H_ #include #include #include #include #include "KoID.h" #include "KoColorSpace.h" #include "kis_types.h" #include "kis_shared.h" #include "kis_image.h" #include "kritaimage_export.h" class QWidget; class KisBookmarkedConfigurationManager; class KisFilterConfiguration; class KisConfigWidget; /** * Base class for classes that process areas of pixels. * Processors can either read in pixels and write out pixels * or just write out pixels, using a certain set of configuation * pixels. * * in-out processing is typically filtering: @see KisFilter. * out-only processing is typically generating: @see KisGenerator. * * Information about the area that needs to be processed is contained * @see KisProcessingInformation and @see KisConstProcessingInformation. */ class KRITAIMAGE_EXPORT KisBaseProcessor : public KisShared { friend class KisBaseProcessorConfigurationFactory; public: KisBaseProcessor(const KoID& id, const KoID & category, const QString & entry); virtual ~KisBaseProcessor(); /** * Return the configuration set as the default by the user or the default * configuration from the filter writer as returned by factoryConfiguration. * * This configuration is used by default for the configuration widget and * given to the process function if there is no configuration widget. * * @return the default configuration of this widget */ - KisFilterConfigurationSP defaultConfiguration(const KisPaintDeviceSP) const; + KisFilterConfigurationSP defaultConfiguration() const; /** * @return the bookmark manager for this processor */ KisBookmarkedConfigurationManager* bookmarkManager(); /** * @return the bookmark manager for this processor */ const KisBookmarkedConfigurationManager* bookmarkManager() const; /// @return Unique identification for this processor QString id() const; /// @return User-visible identification for this processor QString name() const; /// @return the submenu in the filters menu does processor want to go? KoID menuCategory() const; /// @return the i18n'ed string this filter wants to show itself in the menu QString menuEntry() const; /** * Return the default keyboard shortcut for activation of this filter * * @return the shortcut */ QKeySequence shortcut() const; /** * Create the configuration widget for this processor. * * @param parent the Qt owner widget of this widget * @param dev the paintdevice this filter will act on */ virtual KisConfigWidget * createConfigurationWidget(QWidget * parent, const KisPaintDeviceSP dev) const; // "Support" functions public: /** * If true, this filter can be used in painting tools as a paint operation */ bool supportsPainting() const; /// This filter can be used in adjustment layers bool supportsAdjustmentLayers() const; /** * This filter supports cutting up the work area and filtering * each chunk in a separate thread. Filters that need access to the * whole area for correct computations should return false. */ bool supportsThreading() const; /// If true, the filter wants to show a configuration widget bool showConfigurationWidget(); /** * Determine the colorspace independence of this filter. * @see ColorSpaceIndependence * * @return the degree of independence */ ColorSpaceIndependence colorSpaceIndependence() const; /// @return the default configuration as defined by whoever wrote the plugin - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; protected: void setSupportsPainting(bool v); void setSupportsAdjustmentLayers(bool v); void setSupportsThreading(bool v); void setColorSpaceIndependence(ColorSpaceIndependence v); void setShowConfigurationWidget(bool v); /** * Set the default shortcut for activation of this filter. */ void setShortcut(const QKeySequence & shortcut); protected: void init(const QString& configEntryGroup); private: struct Private; Private* const d; }; #endif diff --git a/libs/image/kis_colorspace_convert_visitor.cpp b/libs/image/kis_colorspace_convert_visitor.cpp index 26a001c56c..c56b3e85ed 100644 --- a/libs/image/kis_colorspace_convert_visitor.cpp +++ b/libs/image/kis_colorspace_convert_visitor.cpp @@ -1,160 +1,160 @@ /* * Copyright (c) 2005 C. Boemann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_colorspace_convert_visitor.h" #include "kis_image.h" #include "kis_paint_device.h" #include "kis_undo_adapter.h" #include "kis_adjustment_layer.h" #include "kis_paint_layer.h" #include "kis_group_layer.h" #include "lazybrush/kis_colorize_mask.h" #include "kis_external_layer_iface.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "filter/kis_filter.h" #include "kis_generator.h" #include "kis_generator_registry.h" #include "generator/kis_generator_layer.h" #include "kis_time_range.h" #include KisColorSpaceConvertVisitor::KisColorSpaceConvertVisitor(KisImageWSP image, const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) : KisNodeVisitor() , m_image(image) , m_srcColorSpace(srcColorSpace) , m_dstColorSpace(dstColorSpace) , m_renderingIntent(renderingIntent) , m_conversionFlags(conversionFlags) { } KisColorSpaceConvertVisitor::~KisColorSpaceConvertVisitor() { } bool KisColorSpaceConvertVisitor::visit(KisGroupLayer * layer) { convertPaintDevice(layer); KisLayerSP child = qobject_cast(layer->firstChild().data()); while (child) { child->accept(*this); child = qobject_cast(child->nextSibling().data()); } layer->resetCache(); return true; } bool KisColorSpaceConvertVisitor::visit(KisPaintLayer *layer) { return convertPaintDevice(layer); } bool KisColorSpaceConvertVisitor::visit(KisGeneratorLayer *layer) { layer->resetCache(); return true; } bool KisColorSpaceConvertVisitor::visit(KisAdjustmentLayer * layer) { // XXX: Make undoable! if (layer->filter()->name() == "perchannel") { // Per-channel filters need to be reset because of different number // of channels. This makes undo very tricky, but so be it. // XXX: Make this more generic for after 1.6, when we'll have many // channel-specific filters. KisFilterSP f = KisFilterRegistry::instance()->value("perchannel"); - layer->setFilter(f->defaultConfiguration(0)); + layer->setFilter(f->defaultConfiguration()); } layer->resetCache(); return true; } bool KisColorSpaceConvertVisitor::convertPaintDevice(KisLayer* layer) { if (*m_dstColorSpace == *layer->colorSpace()) return true; bool alphaLock = false; if (m_srcColorSpace->colorModelId() != m_dstColorSpace->colorModelId()) { layer->setChannelFlags(m_emptyChannelFlags); KisPaintLayer *paintLayer = 0; if ((paintLayer = dynamic_cast(layer))) { alphaLock = paintLayer->alphaLocked(); paintLayer->setChannelLockFlags(QBitArray()); } } KisImageSP image = m_image.toStrongRef(); if (!image) { return false; } if (layer->original()) { KUndo2Command* cmd = layer->original()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags); if (cmd) { image->undoAdapter()->addCommand(cmd); } } if (layer->paintDevice()) { KUndo2Command* cmd = layer->paintDevice()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags); if (cmd) { image->undoAdapter()->addCommand(cmd); } } if (layer->projection()) { KUndo2Command* cmd = layer->projection()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags); if (cmd) { image->undoAdapter()->addCommand(cmd); } } KisPaintLayer *paintLayer = 0; if ((paintLayer = dynamic_cast(layer))) { paintLayer->setAlphaLocked(alphaLock); } layer->setDirty(); layer->invalidateFrames(KisTimeRange::infinite(0), layer->extent()); return true; } bool KisColorSpaceConvertVisitor::visit(KisColorizeMask *mask) { KisImageSP image = m_image.toStrongRef(); if (!image) { return false; } KUndo2Command* cmd = mask->setColorSpace(m_dstColorSpace, m_renderingIntent, m_conversionFlags); if (cmd) { image->undoAdapter()->addCommand(cmd); } return true; } diff --git a/libs/image/kis_image.h b/libs/image/kis_image.h index a34ccf6054..ebea2f42ba 100644 --- a/libs/image/kis_image.h +++ b/libs/image/kis_image.h @@ -1,984 +1,985 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_H_ #define KIS_IMAGE_H_ #include #include #include #include #include #include #include #include "kis_paint_device.h" // msvc cannot handle forward declarations, so include kis_paint_device here #include "kis_types.h" #include "kis_shared.h" #include "kis_node_graph_listener.h" #include "kis_node_facade.h" #include "kis_image_interfaces.h" #include "kis_strokes_queue_undo_result.h" #include class KisDocument; class KoColorSpace; class KoColor; class KisCompositeProgressProxy; class KisActionRecorder; class KisUndoStore; class KisUndoAdapter; class KisImageSignalRouter; class KisPostExecutionUndoAdapter; class KisFilterStrategy; class KoColorProfile; class KisLayerComposition; class KisSpontaneousJob; class KisImageAnimationInterface; class KUndo2MagicString; class KisProofingConfiguration; namespace KisMetaData { class MergeStrategy; } /** * This is the image class, it contains a tree of KisLayer stack and * meta information about the image. And it also provides some * functions to manipulate the whole image. */ class KRITAIMAGE_EXPORT KisImage : public QObject, public KisStrokesFacade, public KisStrokeUndoFacade, public KisUpdatesFacade, public KisProjectionUpdateListener, public KisNodeFacade, public KisNodeGraphListener, public KisShared { Q_OBJECT public: /// @param colorSpace can be null. in that case it will be initialised to a default color space. KisImage(KisUndoStore *undoStore, qint32 width, qint32 height, const KoColorSpace *colorSpace, const QString& name); virtual ~KisImage(); public: // KisNodeGraphListener implementation void aboutToAddANode(KisNode *parent, int index); void nodeHasBeenAdded(KisNode *parent, int index); void aboutToRemoveANode(KisNode *parent, int index); void nodeChanged(KisNode * node); void invalidateAllFrames(); void notifySelectionChanged(); void requestProjectionUpdate(KisNode *node, const QRect& rect); void invalidateFrames(const KisTimeRange &range, const QRect &rect); void requestTimeSwitch(int time); public: // KisProjectionUpdateListener implementation void notifyProjectionUpdated(const QRect &rc); public: /** * Makes a copy of the image with all the layers. If possible, shallow * copies of the layers are made. * * \p exactCopy shows if the copied image should look *exactly* the same as * the other one (according to it's .kra xml representation). It means that * the layers will have the same UUID keys and, therefore, you are not * expected to use the copied image anywhere except for saving. Don't use * this option if you plan to work with the copied image later. */ KisImage* clone(bool exactCopy = false); /** * Render the projection onto a QImage. */ QImage convertToQImage(qint32 x1, qint32 y1, qint32 width, qint32 height, const KoColorProfile * profile); /** * Render the projection onto a QImage. * (this is an overloaded function) */ QImage convertToQImage(QRect imageRect, const KoColorProfile * profile); /** * XXX: docs! */ QImage convertToQImage(const QSize& scaledImageSize, const KoColorProfile *profile); /** * Calls KisUpdateScheduler::lock (XXX: APIDOX -- what does that mean?) */ void lock(); /** * Calls KisUpdateScheduler::unlock (XXX: APIDOX -- what does that mean?) */ void unlock(); /** * Returns true if lock() has been called more often than unlock(). */ bool locked() const; /** * @return the global selection object or 0 if there is none. The * global selection is always read-write. */ KisSelectionSP globalSelection() const; /** * Retrieve the next automatic layername (XXX: fix to add option to return Mask X) */ QString nextLayerName(const QString &baseName = "") const; /** * Set the automatic layer name counter one back. */ void rollBackLayerName(); /** * Resize the image to the specified rect. The resize * method handles the creating on an undo step itself. * * @param newRect the rect describing the new width, height and offset * of the image */ void resizeImage(const QRect& newRect); /** * Crop the image to the specified rect. The crop * method handles the creating on an undo step itself. * * @param newRect the rect describing the new width, height and offset * of the image */ void cropImage(const QRect& newRect); /** * Crop a node to @newRect. The node will *not* be moved anywhere, * it just drops some content */ void cropNode(KisNodeSP node, const QRect& newRect); /// XXX: ApiDox void scaleImage(const QSize &size, qreal xres, qreal yres, KisFilterStrategy *filterStrategy); /// XXX: ApiDox void scaleNode(KisNodeSP node, qreal scaleX, qreal scaleY, KisFilterStrategy *filterStrategy); /** * Execute a rotate transform on all layers in this image. * Image is resized to fit rotated image. */ void rotateImage(double radians); /** * Execute a rotate transform on on a subtree of this image. * Image is not resized. */ void rotateNode(KisNodeSP node, double radians); /** * Execute a shear transform on all layers in this image. */ void shear(double angleX, double angleY); /** * Shear a node and all its children. * @param angleX, @param angleY are given in degrees. */ void shearNode(KisNodeSP node, double angleX, double angleY); /** * Convert the image and all its layers to the dstColorSpace */ void convertImageColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); /** * Set the color space of the projection (and the root layer) * to dstColorSpace. No conversion is done for other layers, * their colorspace can differ. * NOTE: Note conversion is done, only regeneration, so no rendering * intent needed */ void convertProjectionColorSpace(const KoColorSpace *dstColorSpace); // Get the profile associated with this image const KoColorProfile * profile() const; /** * Set the profile of the image to the new profile and do the same for * all layers that have the same colorspace and profile of the image. * It doesn't do any pixel conversion. * * This is essential if you have loaded an image that didn't * have an embedded profile to which you want to attach the right profile. * * This does not create an undo action; only call it when creating or * loading an image. * * @returns false if the profile could not be assigned */ bool assignImageProfile(const KoColorProfile *profile); /** * Returns the current undo adapter. You can add new commands to the * undo stack using the adapter. This adapter is used for a backward * compatibility for old commands created before strokes. It blocks * all the porcessing at the scheduler, waits until it's finished * adn executes commands exclusively. */ KisUndoAdapter* undoAdapter() const; /** * This adapter is used by the strokes system. The commands are added * to it *after* redo() is done (in the scheduler context). They are * wrapped into a special command and added to the undo stack. redo() * in not called. */ KisPostExecutionUndoAdapter* postExecutionUndoAdapter() const; /** * Replace current undo store with the new one. The old store * will be deleted. * This method is used by KisDocument for dropping all the commands * during file loading. */ void setUndoStore(KisUndoStore *undoStore); /** * Return current undo store of the image */ KisUndoStore* undoStore(); /** * @return the action recorder associated with this image */ KisActionRecorder* actionRecorder() const; /** * Tell the image it's modified; this emits the sigImageModified * signal. This happens when the image needs to be saved */ void setModified(); /** * The default colorspace of this image: new layers will have this * colorspace and the projection will have this colorspace. */ const KoColorSpace * colorSpace() const; /** * X resolution in pixels per pt */ double xRes() const; /** * Y resolution in pixels per pt */ double yRes() const; /** * Set the resolution in pixels per pt. */ void setResolution(double xres, double yres); /** * Convert a document coordinate to a pixel coordinate. * * @param documentCoord PostScript Pt coordinate to convert. */ QPointF documentToPixel(const QPointF &documentCoord) const; /** * Convert a document coordinate to an integer pixel coordinate. * * @param documentCoord PostScript Pt coordinate to convert. */ QPoint documentToIntPixel(const QPointF &documentCoord) const; /** * Convert a document rectangle to a pixel rectangle. * * @param documentRect PostScript Pt rectangle to convert. */ QRectF documentToPixel(const QRectF &documentRect) const; /** * Convert a document rectangle to an integer pixel rectangle. * * @param documentRect PostScript Pt rectangle to convert. */ QRect documentToIntPixel(const QRectF &documentRect) const; /** * Convert a pixel coordinate to a document coordinate. * * @param pixelCoord pixel coordinate to convert. */ QPointF pixelToDocument(const QPointF &pixelCoord) const; /** * Convert an integer pixel coordinate to a document coordinate. * The document coordinate is at the centre of the pixel. * * @param pixelCoord pixel coordinate to convert. */ QPointF pixelToDocument(const QPoint &pixelCoord) const; /** * Convert a document rectangle to an integer pixel rectangle. * * @param pixelCoord pixel coordinate to convert. */ QRectF pixelToDocument(const QRectF &pixelCoord) const; /** * Return the width of the image */ qint32 width() const; /** * Return the height of the image */ qint32 height() const; /** * Return the size of the image */ QSize size() const { return QSize(width(), height()); } /** * @return the root node of the image node graph */ KisGroupLayerSP rootLayer() const; /** * Return the projection; that is, the complete, composited * representation of this image. */ KisPaintDeviceSP projection() const; /** * Return the number of layers (not other nodes) that are in this * image. */ qint32 nlayers() const; /** * Return the number of layers (not other node types) that are in * this image and that are hidden. */ qint32 nHiddenLayers() const; /** * Merge all visible layers and discard hidden ones. */ void flatten(); /** * Merge the specified layer with the layer * below this layer, remove the specified layer. */ void mergeDown(KisLayerSP l, const KisMetaData::MergeStrategy* strategy); /** * flatten the layer: that is, the projection becomes the layer * and all subnodes are removed. If this is not a paint layer, it will morph * into a paint layer. */ void flattenLayer(KisLayerSP layer); /** * Merges layers in \p mergedLayers and creates a new layer above * \p putAfter */ void mergeMultipleLayers(QList mergedLayers, KisNodeSP putAfter); /// @return the exact bounds of the image in pixel coordinates. QRect bounds() const; /** * Returns the actual bounds of the image, taking LevelOfDetail * into account. This value is used as a bounds() value of * KisDefaultBounds object. */ QRect effectiveLodBounds() const; /// use if the layers have changed _completely_ (eg. when flattening) void notifyLayersChanged(); /** * Sets the default color of the root layer projection. All the layers * will be merged on top of this very color */ void setDefaultProjectionColor(const KoColor &color); /** * \see setDefaultProjectionColor() */ KoColor defaultProjectionColor() const; void setRootLayer(KisGroupLayerSP rootLayer); /** * Add an annotation for this image. This can be anything: Gamma, EXIF, etc. * Note that the "icc" annotation is reserved for the color strategies. * If the annotation already exists, overwrite it with this one. */ void addAnnotation(KisAnnotationSP annotation); /** get the annotation with the given type, can return 0 */ KisAnnotationSP annotation(const QString& type); /** delete the annotation, if the image contains it */ void removeAnnotation(const QString& type); /** * Start of an iteration over the annotations of this image (including the ICC Profile) */ vKisAnnotationSP_it beginAnnotations(); /** end of an iteration over the annotations of this image */ vKisAnnotationSP_it endAnnotations(); /** * Called before the image is delted and sends the sigAboutToBeDeleted signal */ void notifyAboutToBeDeleted(); KisImageSignalRouter* signalRouter(); /** * Returns whether we can reselect current global selection * * \see reselectGlobalSelection() */ bool canReselectGlobalSelection(); /** * Returns the layer compositions for the image */ QList compositions(); /** * Adds a new layer composition, will be saved with the image */ void addComposition(KisLayerCompositionSP composition); /** * Remove the layer compostion */ void removeComposition(KisLayerCompositionSP composition); /** * Permit or deny the wrap-around mode for all the paint devices * of the image. Note that permitting the wraparound mode will not * necessarily activate it right now. To be activated the wrap * around mode should be 1) permitted; 2) supported by the * currently running stroke. */ void setWrapAroundModePermitted(bool value); /** * \return whether the wrap-around mode is permitted for this * image. If the wrap around mode is permitted and the * currently running stroke supports it, the mode will be * activated for all paint devices of the image. * * \see setWrapAroundMode */ bool wrapAroundModePermitted() const; /** * \return whether the wraparound mode is activated for all the * devices of the image. The mode is activated when both * factors are true: the user permitted it and the stroke * supports it */ bool wrapAroundModeActive() const; /** * \return curent level of detail which is used when processing the image. * Current working zoom = 2 ^ (- currentLevelOfDetail()). Default value is * null, which means we work on the original image. */ int currentLevelOfDetail() const; /** * Notify KisImage which level of detail should be used in the * lod-mode. Setting the mode does not guarantee the LOD to be * used. It will be activated only when the stokes supports it. */ void setDesiredLevelOfDetail(int lod); /** * Relative position of the mirror axis center * 0,0 - topleft corner of the image * 1,1 - bottomright corner of the image */ QPointF mirrorAxesCenter() const; /** * Sets the relative position of the axes center * \see mirrorAxesCenter() for details */ void setMirrorAxesCenter(const QPointF &value) const; public Q_SLOTS: /** * Explicitly start regeneration of LoD planes of all the devices * in the image. This call should be performed when the user is idle, * just to make the quality of image updates better. */ void explicitRegenerateLevelOfDetail(); public: /** * Blocks usage of level of detail functionality. After this method * has been called, no new strokes will use LoD. */ void setLevelOfDetailBlocked(bool value); /** * \see setLevelOfDetailBlocked() */ bool levelOfDetailBlocked() const; /** * Notifies that the node collapsed state has changed */ void notifyNodeCollpasedChanged(); KisImageAnimationInterface *animationInterface() const; /** * @brief setProofingConfiguration, this sets the image's proofing configuration, and signals * the proofingConfiguration has changed. * @param proofingConfig - the kis proofing config that will be used instead. */ void setProofingConfiguration(KisProofingConfigurationSP proofingConfig); /** * @brief proofingConfiguration * @return the proofing configuration of the image. */ KisProofingConfigurationSP proofingConfiguration() const; public: bool startIsolatedMode(KisNodeSP node); void stopIsolatedMode(); KisNodeSP isolatedModeRoot() const; Q_SIGNALS: /** * Emitted whenever an action has caused the image to be * recomposited. * * @param rc The rect that has been recomposited. */ void sigImageUpdated(const QRect &); /** Emitted whenever the image has been modified, so that it doesn't match with the version saved on disk. */ void sigImageModified(); /** * The signal is emitted when the size of the image is changed. * \p oldStillPoint and \p newStillPoint give the receiver the * hint about how the new and old rect of the image correspond to * each other. They specify the point of the image around which * the conversion was done. This point will stay still on the * user's screen. That is the \p newStillPoint of the new image * will be painted at the same screen position, where \p * oldStillPoint of the old image was painted. * * \param oldStillPoint is a still point represented in *old* * image coordinates * * \param newStillPoint is a still point represented in *new* * image coordinates */ void sigSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint); void sigProfileChanged(const KoColorProfile * profile); void sigColorSpaceChanged(const KoColorSpace* cs); void sigResolutionChanged(double xRes, double yRes); void sigRequestNodeReselection(KisNodeSP activeNode, const KisNodeList &selectedNodes); /** * Inform the model that a node was changed */ void sigNodeChanged(KisNodeSP node); /** * Inform that the image is going to be deleted */ void sigAboutToBeDeleted(); /** * The signal is emitted right after a node has been connected * to the graph of the nodes. * * WARNING: you must not request any graph-related information * about the node being run in a not-scheduler thread. If you need * information about the parent/siblings of the node connect * with Qt::DirectConnection, get needed information and then * emit another Qt::AutoConnection signal to pass this information * to your thread. See details of the implementation * in KisDummiesfacadeBase. */ void sigNodeAddedAsync(KisNodeSP node); /** * This signal is emitted right before a node is going to removed * from the graph of the nodes. * * WARNING: you must not request any graph-related information * about the node being run in a not-scheduler thread. * * \see comment in sigNodeAddedAsync() */ void sigRemoveNodeAsync(KisNodeSP node); /** * Emitted when the root node of the image has changed. * It happens, e.g. when we flatten the image. When * this happens the receiver should reload information * about the image */ void sigLayersChangedAsync(); /** * Emitted when the UI has requested the undo of the last stroke's * operation. The point is, we cannot deal with the internals of * the stroke without its creator knowing about it (which most * probably cause a crash), so we just forward this request from * the UI to the creator of the stroke. * * If your tool supports undoing part of its work, just listen to * this signal and undo when it comes */ void sigUndoDuringStrokeRequested(); /** * Emitted when the UI has requested the cancellation of * the stroke. The point is, we cannot cancel the stroke * without its creator knowing about it (which most probably * cause a crash), so we just forward this request from the UI * to the creator of the stroke. * * If your tool supports cancelling of its work in the middle * of operation, just listen to this signal and cancel * the stroke when it comes */ void sigStrokeCancellationRequested(); /** * Emitted when the image decides that the stroke should better * be ended. The point is, we cannot just end the stroke * without its creator knowing about it (which most probably * cause a crash), so we just forward this request from the UI * to the creator of the stroke. * * If your tool supports long strokes that may involve multiple * mouse actions in one stroke, just listen to this signal and * end the stroke when it comes. */ void sigStrokeEndRequested(); /** * Same as sigStrokeEndRequested() but is not emitted when the active node * is changed. */ void sigStrokeEndRequestedActiveNodeFiltered(); /** * Emitted when the isolated mode status has changed. * * Can be used by the receivers to catch a fact of forcefully * stopping the isolated mode by the image when some complex * action was requested */ void sigIsolatedModeChanged(); /** * Emitted when one or more nodes changed the collapsed state * */ void sigNodeCollapsedChanged(); /** * Emitted when the proofing configuration of the image is being changed. * */ void sigProofingConfigChanged(); public Q_SLOTS: KisCompositeProgressProxy* compositeProgressProxy(); bool isIdle(bool allowLocked = false); /** * @brief barrierLock APIDOX * @param readOnly */ void barrierLock(bool readOnly = false); /** * @brief barrierLock APIDOX * @param readOnly */ bool tryBarrierLock(bool readOnly = false); /** * @brief barrierLock APIDOX * @param readOnly */ void waitForDone(); KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy); void addJob(KisStrokeId id, KisStrokeJobData *data); void endStroke(KisStrokeId id); bool cancelStroke(KisStrokeId id); /** * @brief blockUpdates block updating the image projection */ void blockUpdates(); /** * @brief unblockUpdates unblock updating the image project. This * only restarts the scheduler and does not schedule a full refresh. */ void unblockUpdates(); /** * Disables notification of the UI about the changes in the image. * This feature is used by KisProcessingApplicator. It is needed * when we change the size of the image. In this case, the whole * image will be reloaded into UI by sigSizeChanged(), so there is * no need to inform the UI about individual dirty rects. */ void disableUIUpdates(); /** * \see disableUIUpdates */ void enableUIUpdates(); /** * Disables the processing of all the setDirty() requests that * come to the image. The incoming requests are effectively * *dropped*. * * This feature is used by KisProcessingApplicator. For many cases * it provides its own updates interface, which recalculates the * whole subtree of nodes. But while we change any particular * node, it can ask for an update itself. This method is a way of * blocking such intermediate (and excessive) requests. * * NOTE: this is a convenience function for setProjectionUpdatesFilter() * that installs a predefined filter that eats everything. Please * note that these calls are *not* recursive */ void disableDirtyRequests(); /** * \see disableDirtyRequests() */ void enableDirtyRequests(); /** * Installs a filter object that will filter all the incoming projection update * requests. If the filter return true, the incoming update is dropped. * * NOTE: you cannot set filters recursively! */ void setProjectionUpdatesFilter(KisProjectionUpdatesFilterSP filter); /** * \see setProjectionUpdatesFilter() */ KisProjectionUpdatesFilterSP projectionUpdatesFilter() const; void refreshGraphAsync(KisNodeSP root = KisNodeSP()); void refreshGraphAsync(KisNodeSP root, const QRect &rc); void refreshGraphAsync(KisNodeSP root, const QRect &rc, const QRect &cropRect); /** * Triggers synchronous recomposition of the projection */ void refreshGraph(KisNodeSP root = KisNodeSP()); void refreshGraph(KisNodeSP root, const QRect& rc, const QRect &cropRect); void initialRefreshGraph(); /** * Initiate a stack regeneration skipping the recalculation of the * filthy node's projection. * * Works exactly as pseudoFilthy->setDirty() with the only * exception that pseudoFilthy::updateProjection() will not be * called. That is used by KisRecalculateTransformMaskJob to avoid * cyclic dependencies. */ void requestProjectionUpdateNoFilthy(KisNodeSP pseudoFilthy, const QRect &rc, const QRect &cropRect); /** * Adds a spontaneous job to the updates queue. * * A spontaneous job may do some trivial tasks in the background, * like updating the outline of selection or purging unused tiles * from the existing paint devices. */ void addSpontaneousJob(KisSpontaneousJob *spontaneousJob); /** * This method is called by the UI (*not* by the creator of the * stroke) when it thinks the current stroke should undo its last * action, for example, when the user presses Ctrl+Z while some * stroke is active. * * If the creator of the stroke supports undoing of intermediate * actions, it will be notified about this request and can undo * its last action. */ void requestUndoDuringStroke(); /** * This method is called by the UI (*not* by the creator of the * stroke) when it thinks current stroke should be cancelled. If * there is a running stroke that has already been detached from * its creator (ended or cancelled), it will be forcefully * cancelled and reverted. If there is an open stroke present, and * if its creator supports cancelling, it will be notified about * the request and the stroke will be cancelled */ void requestStrokeCancellation(); /** * This method requests the last stroke executed on the image to become undone. * If the stroke is not ended, or if all the Lod0 strokes are completed, the method * returns UNDO_FAIL. If the last Lod0 is going to be finished soon, then UNDO_WAIT * is returned and the caller should just wait for its completion and call global undo * instead. UNDO_OK means one unfinished stroke has been undone. */ UndoResult tryUndoUnfinishedLod0Stroke(); /** * This method is called when image or some other part of Krita * (*not* the creator of the stroke) decides that the stroke * should be ended. If the creator of the stroke supports it, it * will be notified and the stroke will be cancelled */ void requestStrokeEnd(); /** * Same as requestStrokeEnd() but is called by view manager when * the current node is changed. Use to dintinguish * sigStrokeEndRequested() and * sigStrokeEndRequestedActiveNodeFiltered() which are used by * KisNodeJugglerCompressed */ void requestStrokeEndActiveNode(); private: KisImage(const KisImage& rhs, KisUndoStore *undoStore, bool exactCopy); KisImage& operator=(const KisImage& rhs); void emitSizeChanged(); void resizeImageImpl(const QRect& newRect, bool cropLayers); void rotateImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, bool resizeImage, double radians); void shearImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, bool resizeImage, double angleX, double angleY, const QPointF &origin); void safeRemoveTwoNodes(KisNodeSP node1, KisNodeSP node2); void refreshHiddenArea(KisNodeSP rootNode, const QRect &preparedArea); void requestProjectionUpdateImpl(KisNode *node, const QRect& rect, const QRect &cropRect); friend class KisImageResizeCommand; void setSize(const QSize& size); friend class KisImageSetProjectionColorSpaceCommand; void setProjectionColorSpace(const KoColorSpace * colorSpace); friend class KisDeselectGlobalSelectionCommand; friend class KisReselectGlobalSelectionCommand; friend class KisSetGlobalSelectionCommand; friend class KisImageTest; + friend class Document; // For libkis /** * Replaces the current global selection with globalSelection. If * \p globalSelection is empty, removes the selection object, so that * \ref globalSelection() will return 0 after that. */ void setGlobalSelection(KisSelectionSP globalSelection); /** * Deselects current global selection. * \ref globalSelection() will return 0 after that. */ void deselectGlobalSelection(); /** * Reselects current deselected selection * * \see deselectGlobalSelection() */ void reselectGlobalSelection(); private: class KisImagePrivate; KisImagePrivate * m_d; }; #endif // KIS_IMAGE_H_ diff --git a/libs/image/kis_selection_filters.h b/libs/image/kis_selection_filters.h index 1f39fa776b..1a72adf1cf 100644 --- a/libs/image/kis_selection_filters.h +++ b/libs/image/kis_selection_filters.h @@ -1,154 +1,155 @@ /* * Copyright (c) 2005 Michael Thaler * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SELECTION_FILTERS_H #define KIS_SELECTION_FILTERS_H #include "kis_types.h" #include "kritaimage_export.h" #include #include class KUndo2MagicString; class KRITAIMAGE_EXPORT KisSelectionFilter { public: virtual ~KisSelectionFilter(); virtual void process(KisPixelSelectionSP pixelSelection, const QRect &rect) = 0; virtual KUndo2MagicString name(); virtual QRect changeRect(const QRect &rect); protected: void computeBorder(qint32 *circ, qint32 xradius, qint32 yradius); void rotatePointers(quint8 **p, quint32 n); void computeTransition(quint8* transition, quint8** buf, qint32 width); }; class KRITAIMAGE_EXPORT KisErodeSelectionFilter : public KisSelectionFilter { public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; class KRITAIMAGE_EXPORT KisDilateSelectionFilter : public KisSelectionFilter { public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; class KRITAIMAGE_EXPORT KisBorderSelectionFilter : public KisSelectionFilter { public: KisBorderSelectionFilter(qint32 xRadius, qint32 yRadius); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_xRadius; qint32 m_yRadius; }; class KRITAIMAGE_EXPORT KisFeatherSelectionFilter : public KisSelectionFilter { public: KisFeatherSelectionFilter(qint32 radius); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_radius; }; class KRITAIMAGE_EXPORT KisGrowSelectionFilter : public KisSelectionFilter { public: KisGrowSelectionFilter(qint32 xRadius, qint32 yRadius); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_xRadius; qint32 m_yRadius; }; class KRITAIMAGE_EXPORT KisShrinkSelectionFilter : public KisSelectionFilter { public: KisShrinkSelectionFilter(qint32 xRadius, qint32 yRadius, bool edgeLock); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_xRadius; qint32 m_yRadius; qint32 m_edgeLock; }; class KRITAIMAGE_EXPORT KisSmoothSelectionFilter : public KisSelectionFilter { public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; class KRITAIMAGE_EXPORT KisInvertSelectionFilter : public KisSelectionFilter { +public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; #endif // KIS_SELECTION_FILTERS_H diff --git a/libs/image/recorder/kis_recorded_filter_action.cpp b/libs/image/recorder/kis_recorded_filter_action.cpp index 04dc26b937..5052a43f11 100644 --- a/libs/image/recorder/kis_recorded_filter_action.cpp +++ b/libs/image/recorder/kis_recorded_filter_action.cpp @@ -1,175 +1,175 @@ /* * Copyright (c) 2007 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "recorder/kis_recorded_filter_action.h" #include #include #include "kis_image.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_layer.h" #include "kis_node.h" #include "kis_selection.h" #include "kis_transaction.h" #include "kis_undo_adapter.h" #include "kis_selection_mask.h" #include "kis_config_widget.h" #include "kis_node_query_path.h" #include "kis_play_info.h" struct Q_DECL_HIDDEN KisRecordedFilterAction::Private { Private() : filterConfiguration(0) { } const KisFilter* filter; QRect rect; KisFilterConfigurationSP configuration() { if (!filterConfiguration) { - filterConfiguration = filter->defaultConfiguration(0); + filterConfiguration = filter->defaultConfiguration(); if (filterConfiguration) { filterConfiguration->fromXML(configstr); } } return filterConfiguration; } void setConfiguration(KisFilterConfigurationSP conf) { filterConfiguration = conf; configstr = conf->toXML(); } void setConfig(const QString& cfg) { filterConfiguration = 0; configstr = cfg; } const QString& config() { return configstr; } private: QString configstr; KisFilterConfigurationSP filterConfiguration; }; KisRecordedFilterAction::KisRecordedFilterAction(QString name, const KisNodeQueryPath& path, const KisFilter* filter, const KisFilterConfigurationSP fc) : KisRecordedNodeAction("FilterAction", name, path), d(new Private) { Q_ASSERT(filter); d->filter = filter; if (fc) { d->setConfig(fc->toXML()); } } KisRecordedFilterAction::KisRecordedFilterAction(const KisRecordedFilterAction& rhs) : KisRecordedNodeAction(rhs), d(new Private(*rhs.d)) { } KisRecordedFilterAction::~KisRecordedFilterAction() { delete d; } void KisRecordedFilterAction::play(KisNodeSP node, const KisPlayInfo& _info, KoUpdater* _updater) const { KisFilterConfigurationSP kfc = d->configuration(); KisPaintDeviceSP dev = node->paintDevice(); KisLayerSP layer = qobject_cast(node.data()); QRect r1 = dev->extent(); KisTransaction transaction(kundo2_i18n("Filter: \"%1\"", d->filter->name()), dev); KisImageWSP image = _info.image(); r1 = r1.intersected(image->bounds()); if (layer && layer->selection()) { r1 = r1.intersected(layer->selection()->selectedExactRect()); } d->filter->process(dev, dev, layer->selection(), r1, kfc, _updater); node->setDirty(r1); transaction.commit(_info.undoAdapter()); } void KisRecordedFilterAction::toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* context) const { KisRecordedAction::toXML(doc, elt, context); elt.setAttribute("filter", d->filter->id()); // Save configuration KisFilterConfigurationSP kfc = d->configuration(); if (kfc) { QDomElement filterConfigElt = doc.createElement("Params"); kfc->toXML(doc, filterConfigElt); elt.appendChild(filterConfigElt); } } KisRecordedAction* KisRecordedFilterAction::clone() const { return new KisRecordedFilterAction(*this); } const KisFilter* KisRecordedFilterAction::filter() const { return d->filter; } const KisFilterConfigurationSP KisRecordedFilterAction::filterConfiguration() const { return d->configuration(); } void KisRecordedFilterAction::setFilterConfiguration(KisFilterConfigurationSP config) { d->setConfiguration(config); } KisRecordedFilterActionFactory::KisRecordedFilterActionFactory() : KisRecordedActionFactory("FilterAction") { } KisRecordedFilterActionFactory::~KisRecordedFilterActionFactory() { } KisRecordedAction* KisRecordedFilterActionFactory::fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*) { QString name = elt.attribute("name"); KisNodeQueryPath pathnode = KisNodeQueryPath::fromString(elt.attribute("path")); const KisFilterSP filter = KisFilterRegistry::instance()->get(elt.attribute("filter")); if (filter) { - KisFilterConfigurationSP config = filter->defaultConfiguration(0); + KisFilterConfigurationSP config = filter->defaultConfiguration(); QDomElement paramsElt = elt.firstChildElement("Params"); if (config && !paramsElt.isNull()) { config->fromXML(paramsElt); } KisRecordedFilterAction* rfa = new KisRecordedFilterAction(name, pathnode, filter, config); return rfa; } else { return 0; } } diff --git a/libs/image/recorder/kis_recorded_paint_action.cpp b/libs/image/recorder/kis_recorded_paint_action.cpp index 50332e34d5..2a54566646 100644 --- a/libs/image/recorder/kis_recorded_paint_action.cpp +++ b/libs/image/recorder/kis_recorded_paint_action.cpp @@ -1,467 +1,467 @@ /* * Copyright (c) 2007,2010 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "recorder/kis_recorded_paint_action.h" #include #include #include #include #include #include #include "kis_node.h" #include "kis_mask_generator.h" #include "kis_painter.h" #include #include "kis_paintop_registry.h" #include "kis_transaction.h" #include "kis_undo_adapter.h" #include #include #include "kis_paint_device.h" #include "kis_image.h" #include "kis_layer.h" #include "kis_play_info.h" #include "kis_node_query_path.h" #include // Recorder #include "kis_recorded_action_factory_registry.h" #include "kis_recorded_action_load_context.h" #include "kis_recorded_action_save_context.h" #include #include #include #include #include struct Q_DECL_HIDDEN KisRecordedPaintAction::Private { KisPaintOpPresetSP paintOpPreset; KoColor foregroundColor; KoColor backgroundColor; qreal opacity; ///< opacity in the range 0.0 -> 100.0 bool paintIncremental; QString compositeOp; KisPainter::StrokeStyle strokeStyle; KisPainter::FillStyle fillStyle; const KoPattern* pattern; const KoAbstractGradient* gradient; KisFilterConfigurationSP generator; }; KisRecordedPaintAction::KisRecordedPaintAction(const QString & id, const QString & name, const KisNodeQueryPath& path, const KisPaintOpPresetSP paintOpPreset) : KisRecordedNodeAction(id, name, path) , d(new Private) { if (paintOpPreset) { d->paintOpPreset = paintOpPreset; } d->opacity = 1.0; d->paintIncremental = true; d->compositeOp = COMPOSITE_OVER; d->strokeStyle = KisPainter::StrokeStyleBrush; d->fillStyle = KisPainter::FillStyleNone; d->pattern = 0; d->gradient = 0; } KisRecordedPaintAction::KisRecordedPaintAction(const KisRecordedPaintAction& rhs) : KisRecordedNodeAction(rhs), d(new Private(*rhs.d)) { } KisRecordedPaintAction::~KisRecordedPaintAction() { delete d; } void KisRecordedPaintAction::toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* context) const { KisRecordedAction::toXML(doc, elt, context); // Paint op presset if (d->paintOpPreset) { QDomElement paintopPressetElt = doc.createElement("PaintopPreset"); d->paintOpPreset->toXML(doc, paintopPressetElt); elt.appendChild(paintopPressetElt); } // ForegroundColor QDomElement foregroundColorElt = doc.createElement("ForegroundColor"); d->foregroundColor.toXML(doc, foregroundColorElt); elt.appendChild(foregroundColorElt); // BackgroundColor QDomElement backgroundColorElt = doc.createElement("BackgroundColor"); d->backgroundColor.toXML(doc, backgroundColorElt); elt.appendChild(backgroundColorElt); // Opacity elt.setAttribute("opacity", KisDomUtils::toString(d->opacity)); // paintIncremental elt.setAttribute("paintIncremental", d->paintIncremental); // compositeOp elt.setAttribute("compositeOp", d->compositeOp); // Save stroke style switch(d->strokeStyle) { case KisPainter::StrokeStyleNone: elt.setAttribute("strokeStyle", "None"); break; case KisPainter::StrokeStyleBrush: elt.setAttribute("strokeStyle", "Brush"); break; } // Save fill style switch(d->fillStyle) { case KisPainter::FillStyleNone: elt.setAttribute("fillStyle", "None"); break; case KisPainter::FillStyleForegroundColor: elt.setAttribute("fillStyle", "PaintColor"); break; case KisPainter::FillStyleBackgroundColor: elt.setAttribute("fillStyle", "AlternativeColor"); break; case KisPainter::FillStylePattern: elt.setAttribute("fillStyle", "Pattern"); context->savePattern(d->pattern); elt.setAttribute("pattern", d->pattern->name()); break; case KisPainter::FillStyleGradient: elt.setAttribute("fillStyle", "Gradient"); context->saveGradient(d->gradient); elt.setAttribute("gradient", d->gradient->name()); break; case KisPainter::FillStyleStrokes: elt.setAttribute("fillStyle", "Strokes"); break; case KisPainter::FillStyleGenerator: elt.setAttribute("fillStyle", "Generator"); if (d->generator) { elt.setAttribute("generator", d->generator->name()); QDomElement filterConfigElt = doc.createElement("Generator"); d->generator->toXML(doc, filterConfigElt); elt.appendChild(filterConfigElt); } break; } } KisPaintOpPresetSP KisRecordedPaintAction::paintOpPreset() const { return d->paintOpPreset; } void KisRecordedPaintAction::setPaintOpPreset(KisPaintOpPresetSP preset) { d->paintOpPreset = preset; } qreal KisRecordedPaintAction::opacity() const { return d->opacity; } void KisRecordedPaintAction::setOpacity(qreal opacity) { d->opacity = opacity; } KoColor KisRecordedPaintAction::paintColor() const { return d->foregroundColor; } void KisRecordedPaintAction::setPaintColor(const KoColor& color) { d->foregroundColor = color; } KoColor KisRecordedPaintAction::backgroundColor() const { return d->backgroundColor; } void KisRecordedPaintAction::setBackgroundColor(const KoColor& color) { d->backgroundColor = color; } QString KisRecordedPaintAction::compositeOp() { return d->compositeOp; } void KisRecordedPaintAction::setCompositeOp(const QString& id) { d->compositeOp = id; } void KisRecordedPaintAction::setPaintIncremental(bool v) { d->paintIncremental = v; } void KisRecordedPaintAction::setStrokeStyle(KisPainter::StrokeStyle strokeStyle) { d->strokeStyle = strokeStyle; } void KisRecordedPaintAction::setFillStyle(KisPainter::FillStyle fillStyle) { d->fillStyle = fillStyle; } KisPainter::FillStyle KisRecordedPaintAction::fillStyle() const { return d->fillStyle; } void KisRecordedPaintAction::setPattern(const KoPattern* pattern) { d->pattern = pattern; } void KisRecordedPaintAction::setGradient(const KoAbstractGradient* gradient) { d->gradient = gradient; } void KisRecordedPaintAction::setGenerator(const KisFilterConfigurationSP generator) { d->generator = generator; } void KisRecordedPaintAction::play(KisNodeSP node, const KisPlayInfo& info, KoUpdater* _updater) const { dbgUI << "Play recorded paint action on node : " << node->name() ; KisTransaction transaction(node->paintDevice()); KisPaintDeviceSP target = 0; if (d->paintIncremental) { target = node->paintDevice(); } else { target = node->paintDevice()->createCompositionSourceDevice(); } KisPainter* painter = createPainter(target); painter->setProgress(_updater); if (d->paintIncremental) { painter->setCompositeOp(d->compositeOp); painter->setOpacity(d->opacity * 255); } else { painter->setCompositeOp(node->paintDevice()->colorSpace()->compositeOp(COMPOSITE_ALPHA_DARKEN)); painter->setOpacity(OPACITY_OPAQUE_U8); } painter->setPaintColor(d->foregroundColor); painter->setBackgroundColor(d->backgroundColor); painter->setStrokeStyle(d->strokeStyle); painter->setFillStyle(d->fillStyle); painter->setPattern(d->pattern); painter->setGradient(d->gradient); painter->setGenerator(d->generator); if (d->paintOpPreset) { painter->setPaintOpPreset(d->paintOpPreset, node, info.image()); } playPaint(info, painter); if (!d->paintIncremental) { KisPainter painter2(node->paintDevice()); painter2.setCompositeOp(d->compositeOp); painter2.setOpacity(d->opacity * 255); QVector dirtyRects = painter->takeDirtyRegion(); Q_FOREACH (const QRect &rc, dirtyRects) { painter2.bitBlt(rc.topLeft(), target, rc); } node->setDirty(painter2.takeDirtyRegion()); } else { node->setDirty(painter->takeDirtyRegion()); } delete painter; transaction.commit(info.undoAdapter()); } KisPainter* KisRecordedPaintAction::createPainter(KisPaintDeviceSP device) const { return new KisPainter(device); } void KisRecordedPaintActionFactory::setupPaintAction(KisRecordedPaintAction* action, const QDomElement& elt, const KisRecordedActionLoadContext* context) { QString name = elt.attribute("name"); qreal opacity = opacityFromXML(elt); dbgKrita << ppVar(opacity); bool paintIncremental = paintIncrementalFromXML(elt); QString compositeOp = compositeOpFromXML(elt); // Decode colors KoColor bC = backgroundColorFromXML(elt); KoColor fC = paintColorFromXML(elt); action->setName(name); action->setBackgroundColor(bC); action->setPaintColor(fC); action->setOpacity(opacity); action->setPaintIncremental(paintIncremental); action->setCompositeOp(compositeOp); // Load stroke style QString strokeAttr = elt.attribute("strokeStyle", "None"); if (strokeAttr == "Brush" ) { action->setStrokeStyle(KisPainter::StrokeStyleBrush); } else { // "None" action->setStrokeStyle(KisPainter::StrokeStyleNone); } // Save fill style QString fillAttr = elt.attribute("fillStyle", "None"); if (fillAttr == "PaintColor") { action->setFillStyle(KisPainter::FillStyleForegroundColor); } else if(fillAttr == "AlternativeColor") { action->setFillStyle(KisPainter::FillStyleBackgroundColor); } else if(fillAttr == "Pattern") { const KoPattern* pattern = context->pattern(elt.attribute("pattern")); if (pattern) { action->setFillStyle(KisPainter::FillStylePattern); action->setPattern(pattern); } else { action->setFillStyle(KisPainter::FillStyleNone); } } else if(fillAttr == "Gradient") { const KoAbstractGradient* gradient = context->gradient(elt.attribute("gradient")); if (gradient) { action->setFillStyle(KisPainter::FillStyleGradient); action->setGradient(gradient); } else { action->setFillStyle(KisPainter::FillStyleNone); } } else if(fillAttr == "Strokes") { action->setFillStyle(KisPainter::FillStyleStrokes); } else if(fillAttr == "Generator") { KisGeneratorSP g = KisGeneratorRegistry::instance()->value(elt.attribute("generator")); KisFilterConfigurationSP config = 0; if (g) { - config = g->defaultConfiguration(0); + config = g->defaultConfiguration(); QDomElement paramsElt = elt.firstChildElement("Generator"); if (config && !paramsElt.isNull()) { config->fromXML(paramsElt); } } if(config) { action->setFillStyle(KisPainter::FillStyleGenerator); action->setGenerator(config); } else { action->setFillStyle(KisPainter::FillStyleNone); } } } KisPaintOpPresetSP KisRecordedPaintActionFactory::paintOpPresetFromXML(const QDomElement& elt) { QDomElement settingsElt = elt.firstChildElement("PaintopPreset"); if (!settingsElt.isNull()) { KisPaintOpPresetSP settings = new KisPaintOpPreset; settings->fromXML(settingsElt); return settings; } else { errImage << "No found"; return 0; } } KoColor KisRecordedPaintActionFactory::paintColorFromXML(const QDomElement& elt) { return colorFromXML(elt, "ForegroundColor"); } KoColor KisRecordedPaintActionFactory::backgroundColorFromXML(const QDomElement& elt) { return colorFromXML(elt, "BackgroundColor"); } KoColor KisRecordedPaintActionFactory::colorFromXML(const QDomElement& elt, const QString& elementName) { QDomElement colorElt = elt.firstChildElement(elementName); KoColor bC; if (!colorElt.isNull()) { bC = KoColor::fromXML(colorElt.firstChildElement(), Integer8BitsColorDepthID.id(), QHash()); bC.setOpacity(quint8(255)); dbgImage << elementName << " color : " << bC.toQColor(); } else { dbgImage << "Warning: no <" << elementName << " /> found"; } return bC; } qreal KisRecordedPaintActionFactory::opacityFromXML(const QDomElement& elt) { return KisDomUtils::toDouble(elt.attribute("opacity", "1.0")); } bool KisRecordedPaintActionFactory::paintIncrementalFromXML(const QDomElement& elt) { return KisDomUtils::toInt(elt.attribute("paintIncremental", "1")); } QString KisRecordedPaintActionFactory::compositeOpFromXML(const QDomElement& elt) { return elt.attribute("compositeOp", COMPOSITE_OVER); } KisNodeQueryPath KisRecordedPaintActionFactory::nodeQueryPathFromXML(const QDomElement& elt) { return KisNodeQueryPath::fromString(elt.attribute("path")); } diff --git a/libs/image/tests/kis_adjustment_layer_test.cpp b/libs/image/tests/kis_adjustment_layer_test.cpp index dca96250c4..97814f4be1 100644 --- a/libs/image/tests/kis_adjustment_layer_test.cpp +++ b/libs/image/tests/kis_adjustment_layer_test.cpp @@ -1,117 +1,117 @@ /* * Copyright (c) 2007 Boudewijn Rempt boud@valdyas.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_adjustment_layer_test.h" #include #include #include #include "kis_adjustment_layer.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter.h" #include "filter/kis_filter_registry.h" #include "kis_image.h" #include "kis_selection.h" #include "kis_types.h" #include "kis_datamanager.h" #include "kis_pixel_selection.h" #include "testutil.h" void KisAdjustmentLayerTest::testCreation() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "adj layer test"); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); KisAdjustmentLayerSP test = new KisAdjustmentLayer(image, "test", kfc, 0); } void KisAdjustmentLayerTest::testSetSelection() { KisSelectionSP sel = new KisSelection(); const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "adj layer test"); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); sel->pixelSelection()->select(QRect(10, 10, 200, 200), 128); KisAdjustmentLayerSP l1 = new KisAdjustmentLayer(image, "bla", kfc, sel); QCOMPARE(sel->selectedExactRect(), l1->internalSelection()->selectedExactRect()); } void KisAdjustmentLayerTest::testInverted() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "adj layer test"); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); KisSelectionSP sel2 = new KisSelection(); sel2->pixelSelection()->invert(); KisAdjustmentLayerSP l2 = new KisAdjustmentLayer(image, "bla", kfc, sel2); QCOMPARE(sel2->selectedExactRect(), l2->internalSelection()->selectedExactRect()); KisSelectionSP sel3 = new KisSelection(); sel3->pixelSelection()->select(QRect(50, -10, 800, 30), 128); l2->setInternalSelection(sel3); } void KisAdjustmentLayerTest::testSelectionParent() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "adj layer test"); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); { KisAdjustmentLayerSP adjLayer = - new KisAdjustmentLayer(image, "bla", f->defaultConfiguration(0), 0); + new KisAdjustmentLayer(image, "bla", f->defaultConfiguration(), 0); QCOMPARE(adjLayer->internalSelection()->parentNode(), KisNodeWSP(adjLayer)); } { KisSelectionSP selection = new KisSelection(); KisAdjustmentLayerSP adjLayer = - new KisAdjustmentLayer(image, "bla", f->defaultConfiguration(0), selection); + new KisAdjustmentLayer(image, "bla", f->defaultConfiguration(), selection); QCOMPARE(adjLayer->internalSelection()->parentNode(), KisNodeWSP(adjLayer)); } { KisAdjustmentLayerSP adjLayer = - new KisAdjustmentLayer(image, "bla", f->defaultConfiguration(0), 0); + new KisAdjustmentLayer(image, "bla", f->defaultConfiguration(), 0); KisSelectionSP selection = new KisSelection(); adjLayer->setInternalSelection(selection); QCOMPARE(adjLayer->internalSelection()->parentNode(), KisNodeWSP(adjLayer)); } } QTEST_MAIN(KisAdjustmentLayerTest) diff --git a/libs/image/tests/kis_filter_mask_test.cpp b/libs/image/tests/kis_filter_mask_test.cpp index 71f2087d5d..6f16a2f4bb 100644 --- a/libs/image/tests/kis_filter_mask_test.cpp +++ b/libs/image/tests/kis_filter_mask_test.cpp @@ -1,125 +1,125 @@ /* * Copyright (c) 2007 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_filter_mask_test.h" #include #include #include "kis_selection.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "kis_filter_mask.h" #include "filter/kis_filter_registry.h" #include "kis_group_layer.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "kis_types.h" #include "kis_image.h" #include "testutil.h" #define IMAGE_WIDTH 1000 #define IMAGE_HEIGHT 1000 void KisFilterMaskTest::testCreation() { KisFilterMaskSP mask = new KisFilterMask(); } #define initImage(image, layer, device, mask) do { \ image = new KisImage(0, IMAGE_WIDTH, IMAGE_HEIGHT, 0, "tests"); \ layer = new KisPaintLayer(image, 0, 100, device); \ image->addNode(layer); \ image->addNode(mask, layer); \ } while(0) void KisFilterMaskTest::testProjectionNotSelected() { KisImageSP image; KisPaintLayerSP layer; const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); KisFilterMaskSP mask = new KisFilterMask(); mask->setFilter(kfc); // Check basic apply(). Shouldn't do anything, since nothing is selected yet. KisPaintDeviceSP projection = new KisPaintDevice(cs); initImage(image, layer, projection, mask); projection->convertFromQImage(qimage, 0, 0, 0); mask->initSelection(layer); mask->createNodeProgressProxy(); mask->select(qimage.rect(), MIN_SELECTED); mask->apply(projection, qimage.rect(), qimage.rect(), KisNode::N_FILTHY); QPoint errpoint; if (!TestUtil::compareQImages(errpoint, qimage, projection->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { projection->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtermasktest1.png"); QFAIL(QString("Failed to create identical image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); } } void KisFilterMaskTest::testProjectionSelected() { KisImageSP image; KisPaintLayerSP layer; const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); KisFilterMaskSP mask = new KisFilterMask(); mask->setFilter(kfc); mask->createNodeProgressProxy(); KisPaintDeviceSP projection = new KisPaintDevice(cs); initImage(image, layer, projection, mask); projection->convertFromQImage(qimage, 0, 0, 0); mask->initSelection(layer); mask->select(qimage.rect(), MAX_SELECTED); mask->apply(projection, qimage.rect(), qimage.rect(), KisNode::N_FILTHY); QCOMPARE(mask->exactBounds(), QRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT)); QPoint errpoint; if (!TestUtil::compareQImages(errpoint, inverted, projection->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { projection->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtermasktest2.png"); QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); } } QTEST_MAIN(KisFilterMaskTest) diff --git a/libs/image/tests/kis_filter_test.cpp b/libs/image/tests/kis_filter_test.cpp index 49ca7ac20d..7f081fc4ab 100644 --- a/libs/image/tests/kis_filter_test.cpp +++ b/libs/image/tests/kis_filter_test.cpp @@ -1,240 +1,240 @@ /* * Copyright (c) 2007 Boudewijn Rempt boud@valdyas.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_filter_test.h" #include #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_selection.h" #include "kis_processing_information.h" #include "filter/kis_filter.h" #include "testutil.h" #include "kis_pixel_selection.h" #include #include class TestFilter : public KisFilter { public: TestFilter() : KisFilter(KoID("test", "test"), KoID("test", "test"), "TestFilter") { } void processImpl(KisPaintDeviceSP src, const QRect& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const override { Q_UNUSED(src); Q_UNUSED(size); Q_UNUSED(config); Q_UNUSED(progressUpdater); } }; void KisFilterTest::testCreation() { TestFilter test; } void KisFilterTest::testWithProgressUpdater() { TestUtil::TestProgressBar * bar = new TestUtil::TestProgressBar(); KoProgressUpdater* pu = new KoProgressUpdater(bar); KoUpdaterPtr updater = pu->startSubtask(); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); KisPaintDeviceSP dev = new KisPaintDevice(cs); dev->convertFromQImage(qimage, 0, 0, 0); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc, updater); QPoint errpoint; if (!TestUtil::compareQImages(errpoint, inverted, dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtertest.png"); QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); } delete pu; delete bar; } void KisFilterTest::testSingleThreaded() { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); KisPaintDeviceSP dev = new KisPaintDevice(cs); dev->convertFromQImage(qimage, 0, 0, 0); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc); QPoint errpoint; if (!TestUtil::compareQImages(errpoint, inverted, dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtertest.png"); QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); } } void KisFilterTest::testDifferentSrcAndDst() { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); KisPaintDeviceSP src = new KisPaintDevice(cs); KisPaintDeviceSP dst = new KisPaintDevice(cs); KisSelectionSP sel = new KisSelection(new KisSelectionDefaultBounds(src)); sel->pixelSelection()->invert(); // select everything sel->updateProjection(); src->convertFromQImage(qimage, 0, 0, 0); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); f->process(src, dst, sel, QRect(QPoint(0,0), qimage.size()), kfc); QPoint errpoint; if (!TestUtil::compareQImages(errpoint, inverted, dst->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dst->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtertest.png"); QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); } } void KisFilterTest::testOldDataApiAfterCopy() { QRect updateRect(0,0,63,63); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); quint8 *whitePixel = new quint8[cs->pixelSize()]; cs->fromQColor(Qt::white, whitePixel); cs->setOpacity(whitePixel, OPACITY_OPAQUE_U8, 1); KisPaintDeviceSP tmp = new KisPaintDevice(cs); KisPaintDeviceSP src = new KisPaintDevice(cs); src->fill(0, 0, 50, 50, whitePixel); /** * Make a full copy here to catch the bug. * Buggy memento manager would make a commit * that is not good. */ KisPaintDeviceSP dst = new KisPaintDevice(*src); /** * This would write go to a new revision in a buggy * memento manager */ dst->clear(updateRect); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); /** * This filter reads from oldRawData, so if we have some * weirdness with transactions it will read from old and non-cleared * version of the device and we will see a black square instead * of empty device in tmp */ f->process(dst, tmp, 0, updateRect, kfc); /** * In theory, both devices: dst and tmp must be empty by now */ KisPaintDeviceSP reference = new KisPaintDevice(cs); QImage refImage = reference->convertToQImage(0,0,0,63,63); QImage dstImage = dst->convertToQImage(0,0,0,63,63); QImage tmpImage = tmp->convertToQImage(0,0,0,63,63); QPoint pt; QVERIFY(TestUtil::compareQImages(pt, refImage, dstImage)); QVERIFY(TestUtil::compareQImages(pt, refImage, tmpImage)); } void KisFilterTest::testBlurFilterApplicationRect() { QRect filterRect(10,10,40,40); QRect src1Rect(5,5,50,50); QRect src2Rect(0,0,60,60); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); quint8 *whitePixel = new quint8[cs->pixelSize()]; cs->fromQColor(Qt::white, whitePixel); cs->setOpacity(whitePixel, OPACITY_OPAQUE_U8, 1); KisPaintDeviceSP src1 = new KisPaintDevice(cs); src1->fill(src1Rect.left(),src1Rect.top(),src1Rect.width(),src1Rect.height(), whitePixel); KisPaintDeviceSP src2 = new KisPaintDevice(cs); src2->fill(src2Rect.left(),src2Rect.top(),src2Rect.width(),src2Rect.height(), whitePixel); KisPaintDeviceSP dst1 = new KisPaintDevice(cs); KisPaintDeviceSP dst2 = new KisPaintDevice(cs); KisFilterSP f = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); f->process(src1, dst1, 0, filterRect, kfc); f->process(src2, dst2, 0, filterRect, kfc); KisPaintDeviceSP reference = new KisPaintDevice(cs); reference->fill(filterRect.left(),filterRect.top(),filterRect.width(),filterRect.height(), whitePixel); QImage refImage = reference->convertToQImage(0,10,10,40,40); QImage dst1Image = dst1->convertToQImage(0,10,10,40,40); QImage dst2Image = dst2->convertToQImage(0,10,10,40,40); //dst1Image.save("DST1.png"); //dst2Image.save("DST2.png"); QPoint pt; QVERIFY(TestUtil::compareQImages(pt, refImage, dst1Image)); QVERIFY(TestUtil::compareQImages(pt, refImage, dst2Image)); } QTEST_MAIN(KisFilterTest) diff --git a/libs/image/tests/kis_image_test.cpp b/libs/image/tests/kis_image_test.cpp index c8db0dfbd7..477d936729 100644 --- a/libs/image/tests/kis_image_test.cpp +++ b/libs/image/tests/kis_image_test.cpp @@ -1,1015 +1,1015 @@ /* * Copyright (c) 2005 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_image_test.h" #include #include #include #include #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_image.h" #include "kis_paint_layer.h" #include "kis_group_layer.h" #include "kis_adjustment_layer.h" #include "kis_selection.h" #include #include #include "kis_keyframe_channel.h" #include "kis_selection_mask.h" #include "kis_layer_utils.h" #include "kis_annotation.h" #include "KisProofingConfiguration.h" #include "kis_undo_stores.h" #define IMAGE_WIDTH 128 #define IMAGE_HEIGHT 128 void KisImageTest::layerTests() { KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); QVERIFY(image->rootLayer() != 0); QVERIFY(image->rootLayer()->firstChild() == 0); KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8); image->addNode(layer); QVERIFY(image->rootLayer()->firstChild()->objectName() == layer->objectName()); } void KisImageTest::benchmarkCreation() { const QRect imageRect(0,0,3000,2000); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QList images; QList stores; QBENCHMARK { for (int i = 0; i < 10; i++) { stores << new KisSurrogateUndoStore(); } for (int i = 0; i < 10; i++) { KisImageSP image = new KisImage(stores.takeLast(), imageRect.width(), imageRect.height(), cs, "test image"); images << image; } } } #include "testutil.h" #include "kis_stroke_strategy.h" #include class ForbiddenLodStrokeStrategy : public KisStrokeStrategy { public: ForbiddenLodStrokeStrategy(std::function lodCallback) : m_lodCallback(lodCallback) { } KisStrokeStrategy* createLodClone(int levelOfDetail) override { Q_UNUSED(levelOfDetail); m_lodCallback(); return 0; } private: std::function m_lodCallback; }; void notifyVar(bool *value) { *value = true; } void KisImageTest::testBlockLevelOfDetail() { TestUtil::MaskParent p; QCOMPARE(p.image->currentLevelOfDetail(), 0); p.image->setDesiredLevelOfDetail(1); p.image->waitForDone(); QCOMPARE(p.image->currentLevelOfDetail(), 0); { bool lodCreated = false; KisStrokeId id = p.image->startStroke( new ForbiddenLodStrokeStrategy( std::bind(¬ifyVar, &lodCreated))); p.image->endStroke(id); p.image->waitForDone(); QVERIFY(lodCreated); } p.image->setLevelOfDetailBlocked(true); { bool lodCreated = false; KisStrokeId id = p.image->startStroke( new ForbiddenLodStrokeStrategy( std::bind(¬ifyVar, &lodCreated))); p.image->endStroke(id); p.image->waitForDone(); QVERIFY(!lodCreated); } p.image->setLevelOfDetailBlocked(false); p.image->setDesiredLevelOfDetail(1); { bool lodCreated = false; KisStrokeId id = p.image->startStroke( new ForbiddenLodStrokeStrategy( std::bind(¬ifyVar, &lodCreated))); p.image->endStroke(id); p.image->waitForDone(); QVERIFY(lodCreated); } } void KisImageTest::testConvertImageColorSpace() { const KoColorSpace *cs8 = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 1000, 1000, cs8, "stest"); KisPaintDeviceSP device1 = new KisPaintDevice(cs8); KisLayerSP paint1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration = filter->defaultConfiguration(); Q_ASSERT(configuration); KisLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration, 0); image->addNode(paint1, image->root()); image->addNode(blur1, image->root()); image->refreshGraph(); const KoColorSpace *cs16 = KoColorSpaceRegistry::instance()->rgb16(); image->lock(); image->convertImageColorSpace(cs16, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); image->unlock(); QVERIFY(*cs16 == *image->colorSpace()); QVERIFY(*cs16 == *image->root()->colorSpace()); QVERIFY(*cs16 == *paint1->colorSpace()); QVERIFY(*cs16 == *blur1->colorSpace()); QVERIFY(!image->root()->compositeOp()); QVERIFY(*cs16 == *paint1->compositeOp()->colorSpace()); QVERIFY(*cs16 == *blur1->compositeOp()->colorSpace()); image->refreshGraph(); } void KisImageTest::testGlobalSelection() { const KoColorSpace *cs8 = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 1000, 1000, cs8, "stest"); QCOMPARE(image->globalSelection(), KisSelectionSP(0)); QCOMPARE(image->canReselectGlobalSelection(), false); QCOMPARE(image->root()->childCount(), 0U); KisSelectionSP selection1 = new KisSelection(new KisDefaultBounds(image)); KisSelectionSP selection2 = new KisSelection(new KisDefaultBounds(image)); image->setGlobalSelection(selection1); QCOMPARE(image->globalSelection(), selection1); QCOMPARE(image->canReselectGlobalSelection(), false); QCOMPARE(image->root()->childCount(), 1U); image->setGlobalSelection(selection2); QCOMPARE(image->globalSelection(), selection2); QCOMPARE(image->canReselectGlobalSelection(), false); QCOMPARE(image->root()->childCount(), 1U); image->deselectGlobalSelection(); QCOMPARE(image->globalSelection(), KisSelectionSP(0)); QCOMPARE(image->canReselectGlobalSelection(), true); QCOMPARE(image->root()->childCount(), 0U); image->reselectGlobalSelection(); QCOMPARE(image->globalSelection(), selection2); QCOMPARE(image->canReselectGlobalSelection(), false); QCOMPARE(image->root()->childCount(), 1U); // mixed deselecting/setting/reselecting image->deselectGlobalSelection(); QCOMPARE(image->globalSelection(), KisSelectionSP(0)); QCOMPARE(image->canReselectGlobalSelection(), true); QCOMPARE(image->root()->childCount(), 0U); image->setGlobalSelection(selection1); QCOMPARE(image->globalSelection(), selection1); QCOMPARE(image->canReselectGlobalSelection(), false); QCOMPARE(image->root()->childCount(), 1U); } void KisImageTest::testCloneImage() { KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); QVERIFY(image->rootLayer() != 0); QVERIFY(image->rootLayer()->firstChild() == 0); KisAnnotationSP annotation = new KisAnnotation("mytype", "mydescription", QByteArray()); image->addAnnotation(annotation); QVERIFY(image->annotation("mytype")); KisProofingConfigurationSP proofing = toQShared(new KisProofingConfiguration()); image->setProofingConfiguration(proofing); QVERIFY(image->proofingConfiguration()); const KoColor defaultColor(Qt::green, image->colorSpace()); image->setDefaultProjectionColor(defaultColor); QCOMPARE(image->defaultProjectionColor(), defaultColor); KisLayerSP layer = new KisPaintLayer(image, "layer1", OPACITY_OPAQUE_U8); image->addNode(layer); KisLayerSP layer2 = new KisPaintLayer(image, "layer2", OPACITY_OPAQUE_U8); image->addNode(layer2); QVERIFY(layer->visible()); QVERIFY(layer2->visible()); QVERIFY(TestUtil::findNode(image->root(), "layer1")); QVERIFY(TestUtil::findNode(image->root(), "layer2")); QUuid uuid1 = layer->uuid(); QUuid uuid2 = layer2->uuid(); { KisImageSP newImage = image->clone(); KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1"); KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2"); QVERIFY(newLayer1); QVERIFY(newLayer2); QVERIFY(newLayer1->uuid() != uuid1); QVERIFY(newLayer2->uuid() != uuid2); KisAnnotationSP newAnnotation = newImage->annotation("mytype"); QVERIFY(newAnnotation); QVERIFY(newAnnotation != annotation); KisProofingConfigurationSP newProofing = newImage->proofingConfiguration(); QVERIFY(newProofing); QVERIFY(newProofing != proofing); QCOMPARE(newImage->defaultProjectionColor(), defaultColor); } { KisImageSP newImage = image->clone(true); KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1"); KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2"); QVERIFY(newLayer1); QVERIFY(newLayer2); QVERIFY(newLayer1->uuid() == uuid1); QVERIFY(newLayer2->uuid() == uuid2); } } void KisImageTest::testLayerComposition() { KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); QVERIFY(image->rootLayer() != 0); QVERIFY(image->rootLayer()->firstChild() == 0); KisLayerSP layer = new KisPaintLayer(image, "layer1", OPACITY_OPAQUE_U8); image->addNode(layer); KisLayerSP layer2 = new KisPaintLayer(image, "layer2", OPACITY_OPAQUE_U8); image->addNode(layer2); QVERIFY(layer->visible()); QVERIFY(layer2->visible()); KisLayerComposition comp(image, "comp 1"); comp.store(); layer2->setVisible(false); QVERIFY(layer->visible()); QVERIFY(!layer2->visible()); KisLayerComposition comp2(image, "comp 2"); comp2.store(); KisLayerCompositionSP comp3 = toQShared(new KisLayerComposition(image, "comp 3")); comp3->store(); image->addComposition(comp3); comp.apply(); QVERIFY(layer->visible()); QVERIFY(layer2->visible()); comp2.apply(); QVERIFY(layer->visible()); QVERIFY(!layer2->visible()); comp.apply(); QVERIFY(layer->visible()); QVERIFY(layer2->visible()); KisImageSP newImage = image->clone(); KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1"); KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2"); QVERIFY(newLayer1); QVERIFY(newLayer2); QVERIFY(newLayer1->visible()); QVERIFY(newLayer2->visible()); KisLayerComposition newComp1(comp, newImage); newComp1.apply(); QVERIFY(newLayer1->visible()); QVERIFY(newLayer2->visible()); KisLayerComposition newComp2(comp2, newImage); newComp2.apply(); QVERIFY(newLayer1->visible()); QVERIFY(!newLayer2->visible()); newComp1.apply(); QVERIFY(newLayer1->visible()); QVERIFY(newLayer2->visible()); QVERIFY(!newImage->compositions().isEmpty()); KisLayerCompositionSP newComp3 = newImage->compositions().first(); newComp3->apply(); QVERIFY(newLayer1->visible()); QVERIFY(!newLayer2->visible()); } #include "testutil.h" #include "kis_group_layer.h" #include "kis_transparency_mask.h" #include "kis_psd_layer_style.h" struct FlattenTestImage { FlattenTestImage() : refRect(0,0,512,512) , p(refRect) { image = p.image; undoStore = p.undoStore; layer1 = p.layer; layer5 = new KisPaintLayer(p.image, "paint5", 0.4 * OPACITY_OPAQUE_U8); layer5->disableAlphaChannel(true); layer2 = new KisPaintLayer(p.image, "paint2", OPACITY_OPAQUE_U8); tmask = new KisTransparencyMask(); // check channel flags // make addition composite op group1 = new KisGroupLayer(p.image, "group1", OPACITY_OPAQUE_U8); layer3 = new KisPaintLayer(p.image, "paint3", OPACITY_OPAQUE_U8); layer4 = new KisPaintLayer(p.image, "paint4", OPACITY_OPAQUE_U8); layer6 = new KisPaintLayer(p.image, "paint6", OPACITY_OPAQUE_U8); layer7 = new KisPaintLayer(p.image, "paint7", OPACITY_OPAQUE_U8); layer8 = new KisPaintLayer(p.image, "paint8", OPACITY_OPAQUE_U8); layer7->setCompositeOpId(COMPOSITE_ADD); layer8->setCompositeOpId(COMPOSITE_ADD); QRect rect1(100, 100, 100, 100); QRect rect2(150, 150, 150, 150); QRect tmaskRect(200,200,100,100); QRect rect3(400, 100, 100, 100); QRect rect4(500, 100, 100, 100); QRect rect5(50, 50, 100, 100); QRect rect6(50, 250, 100, 100); QRect rect7(50, 350, 50, 50); QRect rect8(50, 400, 50, 50); layer1->paintDevice()->fill(rect1, KoColor(Qt::red, p.image->colorSpace())); layer2->paintDevice()->fill(rect2, KoColor(Qt::green, p.image->colorSpace())); tmask->testingInitSelection(tmaskRect, layer2); layer3->paintDevice()->fill(rect3, KoColor(Qt::blue, p.image->colorSpace())); layer4->paintDevice()->fill(rect4, KoColor(Qt::yellow, p.image->colorSpace())); layer5->paintDevice()->fill(rect5, KoColor(Qt::green, p.image->colorSpace())); layer6->paintDevice()->fill(rect6, KoColor(Qt::cyan, p.image->colorSpace())); layer7->paintDevice()->fill(rect7, KoColor(Qt::red, p.image->colorSpace())); layer8->paintDevice()->fill(rect8, KoColor(Qt::green, p.image->colorSpace())); KisPSDLayerStyleSP style(new KisPSDLayerStyle()); style->dropShadow()->setEffectEnabled(true); style->dropShadow()->setDistance(10.0); style->dropShadow()->setSpread(80.0); style->dropShadow()->setSize(10); style->dropShadow()->setNoise(0); style->dropShadow()->setKnocksOut(false); style->dropShadow()->setOpacity(80.0); layer2->setLayerStyle(style); layer2->setCompositeOpId(COMPOSITE_ADD); group1->setCompositeOpId(COMPOSITE_ADD); p.image->addNode(layer5); p.image->addNode(layer2); p.image->addNode(tmask, layer2); p.image->addNode(group1); p.image->addNode(layer3, group1); p.image->addNode(layer4, group1); p.image->addNode(layer6); p.image->addNode(layer7); p.image->addNode(layer8); p.image->initialRefreshGraph(); // dbgKrita << ppVar(layer1->exactBounds()); // dbgKrita << ppVar(layer5->exactBounds()); // dbgKrita << ppVar(layer2->exactBounds()); // dbgKrita << ppVar(group1->exactBounds()); // dbgKrita << ppVar(layer3->exactBounds()); // dbgKrita << ppVar(layer4->exactBounds()); TestUtil::ExternalImageChecker chk("flatten", "imagetest"); QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial")); } QRect refRect; TestUtil::MaskParent p; KisImageSP image; KisSurrogateUndoStore *undoStore; KisPaintLayerSP layer1; KisPaintLayerSP layer2; KisTransparencyMaskSP tmask; KisGroupLayerSP group1; KisPaintLayerSP layer3; KisPaintLayerSP layer4; KisPaintLayerSP layer5; KisPaintLayerSP layer6; KisPaintLayerSP layer7; KisPaintLayerSP layer8; }; template KisLayerSP flattenLayerHelper(ContainerTest &p, KisLayerSP layer, bool nothingHappens = false) { QSignalSpy spy(p.image.data(), SIGNAL(sigNodeAddedAsync(KisNodeSP))); //p.image->flattenLayer(layer); KisLayerUtils::flattenLayer(p.image, layer); p.image->waitForDone(); if (nothingHappens) { Q_ASSERT(!spy.count()); return layer; } Q_ASSERT(spy.count() == 1); QList arguments = spy.takeFirst(); KisNodeSP newNode = arguments.first().value(); KisLayerSP newLayer = qobject_cast(newNode.data()); return newLayer; } void KisImageTest::testFlattenLayer() { FlattenTestImage p; TestUtil::ExternalImageChecker chk("flatten", "imagetest"); { QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD); KisLayerSP newLayer = flattenLayerHelper(p, p.layer2); //KisLayerSP newLayer = p.image->flattenLayer(p.layer2); //p.image->waitForDone(); QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer2_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); } { QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD); KisLayerSP newLayer = flattenLayerHelper(p, p.group1); //KisLayerSP newLayer = p.image->flattenLayer(p.group1); //p.image->waitForDone(); QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "02_group1_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_ADD); QCOMPARE(newLayer->exactBounds(), QRect(400, 100, 200, 100)); } { QCOMPARE(p.layer5->compositeOpId(), COMPOSITE_OVER); QCOMPARE(p.layer5->alphaChannelDisabled(), true); KisLayerSP newLayer = flattenLayerHelper(p, p.layer5, true); //KisLayerSP newLayer = p.image->flattenLayer(p.layer5); //p.image->waitForDone(); QVERIFY(chk.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "03_layer5_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(50, 50, 100, 100)); QCOMPARE(newLayer->alphaChannelDisabled(), true); } } #include template KisLayerSP mergeHelper(ContainerTest &p, KisLayerSP layer) { KisNodeSP parent = layer->parent(); const int newIndex = parent->index(layer) - 1; p.image->mergeDown(layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop")); //KisLayerUtils::mergeDown(p.image, layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop")); p.image->waitForDone(); KisLayerSP newLayer = qobject_cast(parent->at(newIndex).data()); return newLayer; } void KisImageTest::testMergeDown() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergedown_simple", "imagetest"); { QCOMPARE(p.layer5->compositeOpId(), COMPOSITE_OVER); QCOMPARE(p.layer5->alphaChannelDisabled(), true); KisLayerSP newLayer = mergeHelper(p, p.layer5); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer5_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->alphaChannelDisabled(), false); } { QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.layer2->alphaChannelDisabled(), false); KisLayerSP newLayer = mergeHelper(p, p.layer2); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "02_layer2_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(100, 100, 213, 217)); QCOMPARE(newLayer->alphaChannelDisabled(), false); } { QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.group1->alphaChannelDisabled(), false); KisLayerSP newLayer = mergeHelper(p, p.group1); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "03_group1_mergedown_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(100, 100, 500, 217)); QCOMPARE(newLayer->alphaChannelDisabled(), false); } } void KisImageTest::testMergeDownDestinationInheritsAlpha() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergedown_dst_inheritsalpha", "imagetest"); { QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.layer2->alphaChannelDisabled(), false); KisLayerSP newLayer = mergeHelper(p, p.layer2); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer2_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(50,50, 263, 267)); QCOMPARE(newLayer->alphaChannelDisabled(), false); } } void KisImageTest::testMergeDownDestinationCustomCompositeOp() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergedown_dst_customop", "imagetest"); { QCOMPARE(p.layer6->compositeOpId(), COMPOSITE_OVER); QCOMPARE(p.layer6->alphaChannelDisabled(), false); QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.group1->alphaChannelDisabled(), false); KisLayerSP newLayer = mergeHelper(p, p.layer6); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer6_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(50, 100, 550, 250)); QCOMPARE(newLayer->alphaChannelDisabled(), false); } } void KisImageTest::testMergeDownDestinationSameCompositeOpLayerStyle() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergedown_sameop_ls", "imagetest"); { QCOMPARE(p.group1->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.group1->alphaChannelDisabled(), false); QCOMPARE(p.layer2->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.layer2->alphaChannelDisabled(), false); KisLayerSP newLayer = mergeHelper(p, p.group1); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_group1_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(197, 100, 403, 217)); QCOMPARE(newLayer->alphaChannelDisabled(), false); } } void KisImageTest::testMergeDownDestinationSameCompositeOp() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergedown_sameop_fastpath", "imagetest"); { QCOMPARE(p.layer8->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.layer8->alphaChannelDisabled(), false); QCOMPARE(p.layer7->compositeOpId(), COMPOSITE_ADD); QCOMPARE(p.layer7->alphaChannelDisabled(), false); KisLayerSP newLayer = mergeHelper(p, p.layer8); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer8_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_ADD); QCOMPARE(newLayer->exactBounds(), QRect(50, 350, 50, 100)); QCOMPARE(newLayer->alphaChannelDisabled(), false); } } #include "kis_image_animation_interface.h" void KisImageTest::testMergeDownMultipleFrames() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergedown_simple", "imagetest"); QSet initialFrames; { KisLayerSP l = p.layer5; l->enableAnimation(); KisKeyframeChannel *channel = l->getKeyframeChannel(KisKeyframeChannel::Content.id(), true); channel->addKeyframe(10); channel->addKeyframe(20); channel->addKeyframe(30); QCOMPARE(channel->keyframeCount(), 4); initialFrames = KisLayerUtils::fetchLayerFramesRecursive(l); QCOMPARE(initialFrames.size(), 4); } { QCOMPARE(p.layer5->compositeOpId(), COMPOSITE_OVER); QCOMPARE(p.layer5->alphaChannelDisabled(), true); KisLayerSP newLayer = mergeHelper(p, p.layer5); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer5_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->alphaChannelDisabled(), false); QVERIFY(newLayer->isAnimated()); QSet newFrames = KisLayerUtils::fetchLayerFramesRecursive(newLayer); QCOMPARE(newFrames, initialFrames); foreach (int frame, newFrames) { KisImageAnimationInterface *interface = p.image->animationInterface(); int savedSwitchedTime = 0; interface->saveAndResetCurrentTime(frame, &savedSwitchedTime); QCOMPARE(newLayer->exactBounds(), QRect(100,100,100,100)); interface->restoreCurrentTime(&savedSwitchedTime); } p.undoStore->undo(); p.image->waitForDone(); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); } } template KisNodeSP mergeMultipleHelper(ContainerTest &p, QList selectedNodes, KisNodeSP putAfter) { QSignalSpy spy(p.image.data(), SIGNAL(sigNodeAddedAsync(KisNodeSP))); p.image->mergeMultipleLayers(selectedNodes, putAfter); //KisLayerUtils::mergeMultipleLayers(p.image, selectedNodes, putAfter); p.image->waitForDone(); Q_ASSERT(spy.count() == 1); QList arguments = spy.takeFirst(); KisNodeSP newNode = arguments.first().value(); return newNode; } void KisImageTest::testMergeMultiple() { FlattenTestImage p; TestUtil::ExternalImageChecker img("flatten", "imagetest"); TestUtil::ExternalImageChecker chk("mergemultiple", "imagetest"); { QList selectedNodes; selectedNodes << p.layer2 << p.group1 << p.layer6; { KisNodeSP newLayer = mergeMultipleHelper(p, selectedNodes, 0); //KisNodeSP newLayer = p.image->mergeMultipleLayers(selectedNodes, 0); //p.image->waitForDone(); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer8_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(50, 100, 550, 250)); } } p.p.undoStore->undo(); p.image->waitForDone(); // Test reversed order, the result must be the same { QList selectedNodes; selectedNodes << p.layer6 << p.group1 << p.layer2; { KisNodeSP newLayer = mergeMultipleHelper(p, selectedNodes, 0); //KisNodeSP newLayer = p.image->mergeMultipleLayers(selectedNodes, 0); //p.image->waitForDone(); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); QVERIFY(chk.checkDevice(newLayer->projection(), p.image, "01_layer8_layerproj")); QCOMPARE(newLayer->compositeOpId(), COMPOSITE_OVER); QCOMPARE(newLayer->exactBounds(), QRect(50, 100, 550, 250)); } } } void testMergeCrossColorSpaceImpl(bool useProjectionColorSpace, bool swapSpaces) { QRect refRect; TestUtil::MaskParent p; KisPaintLayerSP layer1; KisPaintLayerSP layer2; KisPaintLayerSP layer3; const KoColorSpace *cs2 = useProjectionColorSpace ? p.image->colorSpace() : KoColorSpaceRegistry::instance()->lab16(); const KoColorSpace *cs3 = KoColorSpaceRegistry::instance()->rgb16(); if (swapSpaces) { qSwap(cs2, cs3); } dbgKrita << "Testing testMergeCrossColorSpaceImpl:"; dbgKrita << " " << ppVar(cs2); dbgKrita << " " << ppVar(cs3); layer1 = p.layer; layer2 = new KisPaintLayer(p.image, "paint2", OPACITY_OPAQUE_U8, cs2); layer3 = new KisPaintLayer(p.image, "paint3", OPACITY_OPAQUE_U8, cs3); QRect rect1(100, 100, 100, 100); QRect rect2(150, 150, 150, 150); QRect rect3(250, 250, 200, 200); layer1->paintDevice()->fill(rect1, KoColor(Qt::red, layer1->colorSpace())); layer2->paintDevice()->fill(rect2, KoColor(Qt::green, layer2->colorSpace())); layer3->paintDevice()->fill(rect3, KoColor(Qt::blue, layer3->colorSpace())); p.image->addNode(layer2); p.image->addNode(layer3); p.image->initialRefreshGraph(); { KisLayerSP newLayer = mergeHelper(p, layer3); QCOMPARE(newLayer->colorSpace(), p.image->colorSpace()); p.undoStore->undo(); p.image->waitForDone(); } { layer2->disableAlphaChannel(true); KisLayerSP newLayer = mergeHelper(p, layer3); QCOMPARE(newLayer->colorSpace(), p.image->colorSpace()); p.undoStore->undo(); p.image->waitForDone(); } } void KisImageTest::testMergeCrossColorSpace() { testMergeCrossColorSpaceImpl(true, false); testMergeCrossColorSpaceImpl(true, true); testMergeCrossColorSpaceImpl(false, false); testMergeCrossColorSpaceImpl(false, true); } void KisImageTest::testMergeSelectionMasks() { QRect refRect; TestUtil::MaskParent p; QRect rect1(100, 100, 100, 100); QRect rect2(150, 150, 150, 150); QRect rect3(50, 50, 100, 100); KisPaintLayerSP layer1 = p.layer; layer1->paintDevice()->fill(rect1, KoColor(Qt::red, layer1->colorSpace())); p.image->initialRefreshGraph(); KisSelectionSP sel = new KisSelection(layer1->paintDevice()->defaultBounds()); sel->pixelSelection()->select(rect2, MAX_SELECTED); KisSelectionMaskSP mask1 = new KisSelectionMask(p.image); mask1->initSelection(sel, layer1); p.image->addNode(mask1, layer1); QVERIFY(!layer1->selection()); mask1->setActive(true); QCOMPARE(layer1->selection()->selectedExactRect(), QRect(150,150,150,150)); sel->pixelSelection()->select(rect3, MAX_SELECTED); KisSelectionMaskSP mask2 = new KisSelectionMask(p.image); mask2->initSelection(sel, layer1); p.image->addNode(mask2, layer1); QCOMPARE(layer1->selection()->selectedExactRect(), QRect(150,150,150,150)); mask2->setActive(true); QCOMPARE(layer1->selection()->selectedExactRect(), QRect(50,50,250,250)); QList selectedNodes; selectedNodes << mask2 << mask1; { KisNodeSP newLayer = mergeMultipleHelper(p, selectedNodes, 0); QCOMPARE(newLayer->parent(), KisNodeSP(layer1)); QCOMPARE((int)layer1->childCount(), 1); QCOMPARE(layer1->selection()->selectedExactRect(), QRect(50,50,250,250)); } } void KisImageTest::testFlattenImage() { FlattenTestImage p; KisImageSP image = p.image; TestUtil::ExternalImageChecker img("flatten", "imagetest"); { KisLayerUtils::flattenImage(p.image); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); p.undoStore->undo(); p.image->waitForDone(); QVERIFY(img.checkDevice(p.image->projection(), p.image, "00_initial")); } } QTEST_MAIN(KisImageTest) diff --git a/libs/image/tests/kis_layer_test.cpp b/libs/image/tests/kis_layer_test.cpp index 3b3386c30c..086bb15271 100644 --- a/libs/image/tests/kis_layer_test.cpp +++ b/libs/image/tests/kis_layer_test.cpp @@ -1,315 +1,315 @@ /* * Copyright (c) 2007 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_layer_test.h" #include #include #include #include #include #include #include "kis_paint_device.h" #include "kis_selection.h" #include "kis_filter_mask.h" #include "kis_transparency_mask.h" #include "kis_group_layer.h" #include "kis_paint_layer.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" void KisLayerTest::testCreation() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "layer test"); image->lock(); KisLayerSP layer = new TestLayer(image, "test", OPACITY_OPAQUE_U8); QCOMPARE(layer->name(), QString("test")); QCOMPARE(layer->opacity(), OPACITY_OPAQUE_U8); QCOMPARE(layer->image().data(), image.data()); QCOMPARE(layer->colorSpace(), image->colorSpace()); QCOMPARE(layer->visible(), true); QCOMPARE(layer->userLocked(), false); QCOMPARE(layer->temporary(), false); image->addNode(layer, image->rootLayer()); QBitArray channels(4); channels.fill(true); channels.setBit(1, false); layer->setChannelFlags(channels); QVERIFY(layer->channelFlags().count() == 4); QCOMPARE(layer->channelFlags().at(0), true); QCOMPARE(layer->channelFlags().at(1), false); QCOMPARE(layer->channelFlags().at(2), true); QCOMPARE(layer->channelFlags().at(3), true); layer->setOpacity(OPACITY_TRANSPARENT_U8); QCOMPARE(layer->opacity(), OPACITY_TRANSPARENT_U8); layer->setPercentOpacity(100); QCOMPARE(layer->opacity(), OPACITY_OPAQUE_U8); layer->setPercentOpacity(0); QCOMPARE(layer->opacity(), OPACITY_TRANSPARENT_U8); } void KisLayerTest::testOrdering() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "layer test"); image->lock(); KisLayerSP layer1 = new TestLayer(image, "layer1", OPACITY_OPAQUE_U8); KisLayerSP layer2 = new TestLayer(image, "layer2", OPACITY_OPAQUE_U8); KisLayerSP layer3 = new TestLayer(image, "layer3", OPACITY_OPAQUE_U8); QVERIFY(layer1->name() == "layer1"); QVERIFY(layer2->name() == "layer2"); QVERIFY(layer3->name() == "layer3"); /* +---------+ | layer 2 | | layer 3 | | layer 1 | |root | +---------+ */ QVERIFY(image->addNode(layer1, image->rootLayer())); QVERIFY(image->addNode(layer2, image->rootLayer())); QVERIFY(image->addNode(layer3, image->rootLayer(), layer1)); QCOMPARE((int) image->nlayers(), 4); QVERIFY(layer1->parent() == image->root()); QVERIFY(layer2->parent() == image->root()); QVERIFY(layer3->parent() == image->root()); QVERIFY(image->rootLayer()->firstChild() == layer1.data()); QVERIFY(image->rootLayer()->lastChild() == layer2.data()); QVERIFY(image->rootLayer()->at(0) == layer1.data()); QVERIFY(image->rootLayer()->at(1) == layer3.data()); QVERIFY(image->rootLayer()->at(2) == layer2.data()); QVERIFY(image->rootLayer()->index(layer1) == 0); QVERIFY(image->rootLayer()->index(layer3) == 1); QVERIFY(image->rootLayer()->index(layer2) == 2); QVERIFY(layer3->prevSibling() == layer1.data()); QVERIFY(layer2->prevSibling() == layer3.data()); QVERIFY(layer1->prevSibling() == 0); QVERIFY(layer3->nextSibling() == layer2.data()); QVERIFY(layer2->nextSibling() == 0); QVERIFY(layer1->nextSibling() == layer3.data()); /* +---------+ | layer 3 | | layer 2 | | layer 1 | |root | +---------+ */ QVERIFY(image->moveNode(layer2, image->rootLayer(), layer1)); QVERIFY(image->rootLayer()->at(0) == layer1.data()); QVERIFY(image->rootLayer()->at(1) == layer2.data()); QVERIFY(image->rootLayer()->at(2) == layer3.data()); QVERIFY(image->rootLayer()->firstChild() == layer1.data()); QVERIFY(image->rootLayer()->lastChild() == layer3.data()); QVERIFY(image->rootLayer()->index(layer1) == 0); QVERIFY(image->rootLayer()->index(layer2) == 1); QVERIFY(image->rootLayer()->index(layer3) == 2); QVERIFY(layer3->prevSibling() == layer2.data()); QVERIFY(layer2->prevSibling() == layer1.data()); QVERIFY(layer1->prevSibling() == 0); QVERIFY(layer3->nextSibling() == 0); QVERIFY(layer2->nextSibling() == layer3.data()); QVERIFY(layer1->nextSibling() == layer2.data()); } void KisLayerTest::testMoveNode() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "layer test"); image->lock(); KisLayerSP node1 = new TestLayer(image, "layer1", OPACITY_OPAQUE_U8); KisLayerSP node2 = new TestLayer(image, "layer2", OPACITY_OPAQUE_U8); KisLayerSP node3 = new TestLayer(image, "layer3", OPACITY_OPAQUE_U8); node1->setName("node1"); node2->setName("node2"); node3->setName("node3"); QVERIFY(image->addNode(node1)); QVERIFY(image->addNode(node2)); QVERIFY(image->addNode(node3)); QVERIFY(image->root()->at(0) == node1.data()); QVERIFY(image->root()->at(1) == node2.data()); QVERIFY(image->root()->at(2) == node3.data()); QVERIFY(image->moveNode(node3, image->root(), node1)); QVERIFY(image->root()->at(0) == node1.data()); QVERIFY(image->root()->at(1) == node3.data()); QVERIFY(image->root()->at(2) == node2.data()); } void KisLayerTest::testMoveLayer() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "layer test"); image->lock(); KisLayerSP node1 = new TestLayer(image, "layer1", OPACITY_OPAQUE_U8); KisLayerSP node2 = new TestLayer(image, "layer2", OPACITY_OPAQUE_U8); KisLayerSP node3 = new TestLayer(image, "layer3", OPACITY_OPAQUE_U8); node1->setName("node1"); node2->setName("node2"); node3->setName("node3"); QVERIFY(image->addNode(node1)); QVERIFY(image->addNode(node2)); QVERIFY(image->addNode(node3)); QVERIFY(image->root()->at(0) == node1.data()); QVERIFY(image->root()->at(1) == node2.data()); QVERIFY(image->root()->at(2) == node3.data()); QVERIFY(image->moveNode(node3, image->rootLayer(), node1)); QVERIFY(image->root()->at(0) == node1.data()); QVERIFY(image->root()->at(1) == node3.data()); QVERIFY(image->root()->at(2) == node2.data()); } /* +----------+ |root | | paint 1 | | fmask2 | | fmask1 | +----------+ */ void KisLayerTest::testMasksChangeRect() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); KisFilterMaskSP filterMask1 = new KisFilterMask(); KisFilterMaskSP filterMask2 = new KisFilterMask(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(0); - KisFilterConfigurationSP configuration2 = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(); + KisFilterConfigurationSP configuration2 = filter->defaultConfiguration(); filterMask1->setFilter(configuration1); filterMask2->setFilter(configuration2); image->addNode(filterMask1, paintLayer1); image->addNode(filterMask2, paintLayer1); QVERIFY(paintLayer1->hasEffectMasks()); QRect testRect(10, 10, 100, 100); QRect resultRect; resultRect = paintLayer1->changeRect(testRect, KisNode::N_FILTHY); QVERIFY2(resultRect == QRect(0, 0, 120, 120), "KisNode::N_FILTHY node should take masks into account"); resultRect = paintLayer1->changeRect(testRect, KisNode::N_ABOVE_FILTHY); QVERIFY2(resultRect == testRect, "KisNode::N_ABOVE_FILTHY node should NOT take " "masks into account"); /** * KisNode::N_BELOW_FILTHY, KisNode::N_FILTHY_PROJECTION * should not be use by the caller, because the walker * shoult not visit these node on a forward way. * So the behavoiur here is undefined. * * resultRect = paintLayer1->changeRect(testRect, KisNode::N_BELOW_FILTHY); * resultRect = paintLayer1->changeRect(testRect, KisNode::N_FILTHY_PROJECTION); */ } void KisLayerTest::testMoveLayerWithMaskThreaded() { /** * This test ensures that the layer's original() can be moved * while its projection is still being updated */ const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 2000, 2000, colorSpace, "walker test"); KisLayerSP paintLayer = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); image->addNode(paintLayer, image->rootLayer()); paintLayer->paintDevice()->fill(image->bounds(), KoColor(Qt::black, colorSpace)); KisTransparencyMaskSP transpMask = new KisTransparencyMask(); transpMask->initSelection(paintLayer); image->addNode(transpMask, paintLayer); for(int i = 0; i < 100; i++) { paintLayer->setDirty(); QTest::qSleep(1 + (qrand() & 63)); paintLayer->setX((i*67) % 1873); paintLayer->setY((i*23) % 1873); } } QTEST_MAIN(KisLayerTest) diff --git a/libs/image/tests/kis_recorded_filter_action_test.cpp b/libs/image/tests/kis_recorded_filter_action_test.cpp index 86675031db..94677fcb8b 100644 --- a/libs/image/tests/kis_recorded_filter_action_test.cpp +++ b/libs/image/tests/kis_recorded_filter_action_test.cpp @@ -1,45 +1,45 @@ /* * Copyright (c) 2007 Boudewijn Rempt boud@valdyas.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_recorded_filter_action_test.h" #include #include "recorder/kis_recorded_filter_action.h" #include #include #include "kis_paint_layer.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_image.h" #include "kis_paint_device.h" #include void KisRecordedFilterActionTest::testCreation() { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisFilterSP f = KisFilterRegistry::instance()->value("invert"); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); KisImageSP image = new KisImage(0, 10, 10, cs, "merge test"); KisPaintLayerSP layer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); KisRecordedFilterAction test("invert", KisNodeQueryPath::absolutePath(layer), f, kfc); } QTEST_MAIN(KisRecordedFilterActionTest) diff --git a/libs/image/tests/kis_simple_update_queue_test.cpp b/libs/image/tests/kis_simple_update_queue_test.cpp index 9024f60a92..f3905268ad 100644 --- a/libs/image/tests/kis_simple_update_queue_test.cpp +++ b/libs/image/tests/kis_simple_update_queue_test.cpp @@ -1,281 +1,281 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_simple_update_queue_test.h" #include #include #include #include "kis_group_layer.h" #include "kis_paint_layer.h" #include "kis_adjustment_layer.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_selection.h" #include "kis_update_job_item.h" #include "kis_simple_update_queue.h" #include "scheduler_utils.h" #include "lod_override.h" void KisSimpleUpdateQueueTest::testJobProcessing() { KisTestableUpdaterContext context(2); QRect imageRect(0,0,200,200); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,50,100); QRect dirtyRect2(0,0,100,100); QRect dirtyRect3(50,0,50,100); QRect dirtyRect4(150,150,50,50); QRect dirtyRect5(dirtyRect4); // theoretically, should be merged with 4 QVector jobs; KisWalkersList walkersList; /** * Process the queue and look what has been added into * the updater context */ KisTestableSimpleUpdateQueue queue; queue.addUpdateJob(paintLayer, dirtyRect1, imageRect, 0); queue.addUpdateJob(paintLayer, dirtyRect2, imageRect, 0); queue.addUpdateJob(paintLayer, dirtyRect3, imageRect, 0); queue.addUpdateJob(paintLayer, dirtyRect4, imageRect, 0); { TestUtil::LodOverride l(1, image); queue.addUpdateJob(paintLayer, dirtyRect5, imageRect, 1); } queue.processQueue(context); jobs = context.getJobs(); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect2)); QVERIFY(checkWalker(jobs[1]->walker(), dirtyRect4)); QCOMPARE(jobs.size(), 2); QCOMPARE(context.currentLevelOfDetail(), 0); walkersList = queue.getWalkersList(); QCOMPARE(walkersList.size(), 1); QVERIFY(checkWalker(walkersList[0], dirtyRect5, 1)); } void KisSimpleUpdateQueueTest::testSplitUpdate() { testSplit(false); } void KisSimpleUpdateQueueTest::testSplitFullRefresh() { testSplit(true); } void KisSimpleUpdateQueueTest::testSplit(bool useFullRefresh) { QRect imageRect(0,0,1024,1024); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,1000,1000); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); if(!useFullRefresh) { queue.addUpdateJob(paintLayer, dirtyRect1, imageRect, 0); } else { queue.addFullRefreshJob(paintLayer, dirtyRect1, imageRect, 0); } QCOMPARE(walkersList.size(), 4); QVERIFY(checkWalker(walkersList[0], QRect(0,0,512,512))); QVERIFY(checkWalker(walkersList[1], QRect(512,0,488,512))); QVERIFY(checkWalker(walkersList[2], QRect(0,512,512,488))); QVERIFY(checkWalker(walkersList[3], QRect(512,512,488,488))); queue.optimize(); //must change nothing QCOMPARE(walkersList.size(), 4); QVERIFY(checkWalker(walkersList[0], QRect(0,0,512,512))); QVERIFY(checkWalker(walkersList[1], QRect(512,0,488,512))); QVERIFY(checkWalker(walkersList[2], QRect(0,512,512,488))); QVERIFY(checkWalker(walkersList[3], QRect(512,512,488,488))); } void KisSimpleUpdateQueueTest::testChecksum() { QRect imageRect(0,0,512,512); QRect dirtyRect(100,100,100,100); const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), colorSpace, "test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisAdjustmentLayerSP adjustmentLayer = new KisAdjustmentLayer(image, "adj", 0, 0); image->lock(); image->addNode(paintLayer1, image->rootLayer()); image->addNode(adjustmentLayer, image->rootLayer()); image->unlock(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration = filter->defaultConfiguration(); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); { TestUtil::LodOverride l(1, image); queue.addUpdateJob(adjustmentLayer, dirtyRect, imageRect, 1); QCOMPARE(walkersList[0]->checksumValid(), true); QCOMPARE(walkersList[0]->levelOfDetail(), 1); } adjustmentLayer->setFilter(configuration); { TestUtil::LodOverride l(1, image); QCOMPARE(walkersList[0]->checksumValid(), false); } QVector jobs; KisTestableUpdaterContext context(2); { TestUtil::LodOverride l(1, image); queue.processQueue(context); } jobs = context.getJobs(); { TestUtil::LodOverride l(1, image); QCOMPARE(jobs[0]->walker()->checksumValid(), true); } } void KisSimpleUpdateQueueTest::testMixingTypes() { QRect imageRect(0,0,1024,1024); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,200,200); QRect dirtyRect2(0,0,200,200); QRect dirtyRect3(20,20,200,200); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); queue.addUpdateJob(paintLayer, dirtyRect1, imageRect, 0); queue.addFullRefreshJob(paintLayer, dirtyRect2, imageRect, 0); queue.addFullRefreshJob(paintLayer, dirtyRect3, imageRect, 0); queue.addUpdateNoFilthyJob(paintLayer, dirtyRect1, imageRect, 0); QCOMPARE(walkersList.size(), 3); QVERIFY(checkWalker(walkersList[0], QRect(0,0,200,200))); QVERIFY(checkWalker(walkersList[1], QRect(0,0,220,220))); QVERIFY(checkWalker(walkersList[2], QRect(0,0,200,200))); QCOMPARE(walkersList[0]->type(), KisBaseRectsWalker::UPDATE); QCOMPARE(walkersList[1]->type(), KisBaseRectsWalker::FULL_REFRESH); QCOMPARE(walkersList[2]->type(), KisBaseRectsWalker::UPDATE_NO_FILTHY); } void KisSimpleUpdateQueueTest::testSpontaneousJobsCompression() { KisTestableSimpleUpdateQueue queue; KisSpontaneousJobsList &jobsList = queue.getSpontaneousJobsList(); QVERIFY(queue.isEmpty()); QCOMPARE(queue.sizeMetric(), 0); QVERIFY(jobsList.isEmpty()); KisSpontaneousJob *job1 = new KisNoopSpontaneousJob(false); KisSpontaneousJob *job2 = new KisNoopSpontaneousJob(false); KisSpontaneousJob *job3 = new KisNoopSpontaneousJob(true); queue.addSpontaneousJob(job1); QVERIFY(!queue.isEmpty()); QCOMPARE(queue.sizeMetric(), 1); QCOMPARE(jobsList.size(), 1); QCOMPARE(jobsList[0], job1); queue.addSpontaneousJob(job2); QVERIFY(!queue.isEmpty()); QCOMPARE(queue.sizeMetric(), 2); QCOMPARE(jobsList.size(), 2); QCOMPARE(jobsList[0], job1); QCOMPARE(jobsList[1], job2); queue.addSpontaneousJob(job3); QVERIFY(!queue.isEmpty()); QCOMPARE(queue.sizeMetric(), 1); QCOMPARE(jobsList.size(), 1); QCOMPARE(jobsList[0], job3); } QTEST_MAIN(KisSimpleUpdateQueueTest) diff --git a/libs/image/tests/kis_update_scheduler_test.cpp b/libs/image/tests/kis_update_scheduler_test.cpp index 7c1f182a7c..65845a6e0c 100644 --- a/libs/image/tests/kis_update_scheduler_test.cpp +++ b/libs/image/tests/kis_update_scheduler_test.cpp @@ -1,432 +1,432 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_update_scheduler_test.h" #include #include #include #include "kis_group_layer.h" #include "kis_paint_layer.h" #include "kis_adjustment_layer.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_selection.h" #include "scheduler_utils.h" #include "kis_update_scheduler.h" #include "kis_updater_context.h" #include "kis_update_job_item.h" #include "kis_simple_update_queue.h" #include "../../sdk/tests/testutil.h" KisImageSP KisUpdateSchedulerTest::buildTestingImage() { QImage sourceImage1(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage sourceImage2(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); QRect imageRect = QRect(QPoint(0,0), sourceImage1.size()); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration = filter->defaultConfiguration(); Q_ASSERT(configuration); KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisPaintLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8 / 3); KisLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration, 0); paintLayer1->paintDevice()->convertFromQImage(sourceImage1, 0, 0, 0); paintLayer2->paintDevice()->convertFromQImage(sourceImage2, 0, 0, 0); image->lock(); image->addNode(paintLayer1); image->addNode(paintLayer2); image->addNode(blur1); image->unlock(); return image; } void KisUpdateSchedulerTest::testMerge() { KisImageSP image = buildTestingImage(); QRect imageRect = image->bounds(); KisNodeSP rootLayer = image->rootLayer(); KisNodeSP paintLayer1 = rootLayer->firstChild(); QCOMPARE(paintLayer1->name(), QString("paint1")); KisUpdateScheduler scheduler(image.data()); /** * Test synchronous Full Refresh */ scheduler.fullRefresh(rootLayer, image->bounds(), image->bounds()); QCOMPARE(rootLayer->exactBounds(), image->bounds()); QImage resultFRProjection = rootLayer->projection()->convertToQImage(0); resultFRProjection.save(QString(FILES_OUTPUT_DIR) + QDir::separator() + "scheduler_fr_merge_result.png"); /** * Test incremental updates */ rootLayer->projection()->clear(); const qint32 num = 4; qint32 width = imageRect.width() / num; qint32 lastWidth = imageRect.width() - width; QVector dirtyRects(num); for(qint32 i = 0; i < num-1; i++) { dirtyRects[i] = QRect(width*i, 0, width, imageRect.height()); } dirtyRects[num-1] = QRect(width*(num-1), 0, lastWidth, imageRect.height()); for(qint32 i = 0; i < num; i+=2) { scheduler.updateProjection(paintLayer1, dirtyRects[i], image->bounds()); } for(qint32 i = 1; i < num; i+=2) { scheduler.updateProjection(paintLayer1, dirtyRects[i], image->bounds()); } scheduler.waitForDone(); QCOMPARE(rootLayer->exactBounds(), image->bounds()); QImage resultDirtyProjection = rootLayer->projection()->convertToQImage(0); resultDirtyProjection.save(QString(FILES_OUTPUT_DIR) + QDir::separator() + "scheduler_dp_merge_result.png"); QPoint pt; QVERIFY(TestUtil::compareQImages(pt, resultFRProjection, resultDirtyProjection)); } void KisUpdateSchedulerTest::benchmarkOverlappedMerge() { KisImageSP image = buildTestingImage(); KisNodeSP rootLayer = image->rootLayer(); KisNodeSP paintLayer1 = rootLayer->firstChild(); QRect imageRect = image->bounds(); QCOMPARE(paintLayer1->name(), QString("paint1")); QCOMPARE(imageRect, QRect(0,0,640,441)); KisUpdateScheduler scheduler(image.data()); const qint32 xShift = 10; const qint32 yShift = 0; const qint32 numShifts = 64; QBENCHMARK{ QRect dirtyRect(0, 0, 200, imageRect.height()); for(int i = 0; i < numShifts; i++) { // dbgKrita << dirtyRect; scheduler.updateProjection(paintLayer1, dirtyRect, image->bounds()); dirtyRect.translate(xShift, yShift); } scheduler.waitForDone(); } } void KisUpdateSchedulerTest::testLocking() { KisImageSP image = buildTestingImage(); KisNodeSP rootLayer = image->rootLayer(); KisNodeSP paintLayer1 = rootLayer->firstChild(); QRect imageRect = image->bounds(); QCOMPARE(paintLayer1->name(), QString("paint1")); QCOMPARE(imageRect, QRect(0,0,640,441)); KisTestableUpdateScheduler scheduler(image.data(), 2); QRect dirtyRect1(0,0,50,100); QRect dirtyRect2(0,0,100,100); QRect dirtyRect3(50,0,50,100); QRect dirtyRect4(150,150,50,50); KisTestableUpdaterContext *context = scheduler.updaterContext(); QVector jobs; scheduler.updateProjection(paintLayer1, imageRect, imageRect); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); QVERIFY(checkWalker(jobs[0]->walker(), imageRect)); context->clear(); scheduler.lock(); scheduler.updateProjection(paintLayer1, dirtyRect1, imageRect); scheduler.updateProjection(paintLayer1, dirtyRect2, imageRect); scheduler.updateProjection(paintLayer1, dirtyRect3, imageRect); scheduler.updateProjection(paintLayer1, dirtyRect4, imageRect); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), false); QCOMPARE(jobs[1]->isRunning(), false); scheduler.unlock(); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), true); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect2)); QVERIFY(checkWalker(jobs[1]->walker(), dirtyRect4)); } void KisUpdateSchedulerTest::testExclusiveStrokes() { KisImageSP image = buildTestingImage(); KisNodeSP rootLayer = image->rootLayer(); KisNodeSP paintLayer1 = rootLayer->firstChild(); QRect imageRect = image->bounds(); QCOMPARE(paintLayer1->name(), QString("paint1")); QCOMPARE(imageRect, QRect(0,0,640,441)); QRect dirtyRect1(0,0,50,100); KisTestableUpdateScheduler scheduler(image.data(), 2); KisTestableUpdaterContext *context = scheduler.updaterContext(); QVector jobs; scheduler.updateProjection(paintLayer1, dirtyRect1, imageRect); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect1)); KisStrokeId id = scheduler.startStroke(new KisTestingStrokeStrategy("excl_", true, false)); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect1)); context->clear(); scheduler.endStroke(id); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); COMPARE_NAME(jobs[0], "excl_init"); scheduler.updateProjection(paintLayer1, dirtyRect1, imageRect); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); COMPARE_NAME(jobs[0], "excl_init"); context->clear(); scheduler.processQueues(); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); COMPARE_NAME(jobs[0], "excl_finish"); context->clear(); scheduler.processQueues(); jobs = context->getJobs(); QCOMPARE(jobs[0]->isRunning(), true); QCOMPARE(jobs[1]->isRunning(), false); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect1)); } void KisUpdateSchedulerTest::testEmptyStroke() { KisImageSP image = buildTestingImage(); KisStrokeId id = image->startStroke(new KisStrokeStrategy()); image->addJob(id, 0); image->endStroke(id); image->waitForDone(); } #include "kis_lazy_wait_condition.h" void KisUpdateSchedulerTest::testLazyWaitCondition() { { dbgKrita << "Not initialized"; KisLazyWaitCondition condition; QVERIFY(!condition.wait(50)); } { dbgKrita << "Initialized, not awake"; KisLazyWaitCondition condition; condition.initWaiting(); QVERIFY(!condition.wait(50)); condition.endWaiting(); } { dbgKrita << "Initialized, awake"; KisLazyWaitCondition condition; condition.initWaiting(); condition.wakeAll(); QVERIFY(condition.wait(50)); condition.endWaiting(); } { dbgKrita << "Initialized, not awake, then awake"; KisLazyWaitCondition condition; condition.initWaiting(); QVERIFY(!condition.wait(50)); condition.wakeAll(); QVERIFY(condition.wait(50)); condition.endWaiting(); } { dbgKrita << "Doublewait"; KisLazyWaitCondition condition; condition.initWaiting(); condition.initWaiting(); QVERIFY(!condition.wait(50)); condition.wakeAll(); QVERIFY(condition.wait(50)); QVERIFY(condition.wait(50)); condition.endWaiting(); } } #define NUM_THREADS 10 #define NUM_CYCLES 500 #define NTH_CHECK 3 class UpdatesBlockTester : public QRunnable { public: UpdatesBlockTester(KisUpdateScheduler *scheduler, KisNodeSP node) : m_scheduler(scheduler), m_node(node) { } void run() override { for (int i = 0; i < NUM_CYCLES; i++) { if(i % NTH_CHECK == 0) { m_scheduler->blockUpdates(); QTest::qSleep(1); // a bit of salt for crashiness ;) Q_ASSERT(!m_scheduler->haveUpdatesRunning()); m_scheduler->unblockUpdates(); } else { QRect updateRect(0,0,100,100); updateRect.moveTopLeft(QPoint((i%10)*100, (i%10)*100)); m_scheduler->updateProjection(m_node, updateRect, QRect(0,0,1100,1100)); } } } private: KisUpdateScheduler *m_scheduler; KisNodeSP m_node; }; void KisUpdateSchedulerTest::testBlockUpdates() { KisImageSP image = buildTestingImage(); KisNodeSP rootLayer = image->rootLayer(); KisNodeSP paintLayer1 = rootLayer->firstChild(); KisUpdateScheduler scheduler(image.data()); QThreadPool threadPool; threadPool.setMaxThreadCount(NUM_THREADS); for(int i = 0; i< NUM_THREADS; i++) { UpdatesBlockTester *tester = new UpdatesBlockTester(&scheduler, paintLayer1); threadPool.start(tester); } threadPool.waitForDone(); } #include "kis_update_time_monitor.h" void KisUpdateSchedulerTest::testTimeMonitor() { QVector dirtyRects; KisUpdateTimeMonitor::instance()->startStrokeMeasure(); KisUpdateTimeMonitor::instance()->reportMouseMove(QPointF(100, 0)); KisUpdateTimeMonitor::instance()->reportJobStarted((void*) 10); QTest::qSleep(300); KisUpdateTimeMonitor::instance()->reportJobStarted((void*) 20); QTest::qSleep(100); dirtyRects << QRect(10,10,10,10); KisUpdateTimeMonitor::instance()->reportJobFinished((void*) 10, dirtyRects); QTest::qSleep(100); dirtyRects.clear(); dirtyRects << QRect(30,30,10,10); KisUpdateTimeMonitor::instance()->reportJobFinished((void*) 20, dirtyRects); QTest::qSleep(500); KisUpdateTimeMonitor::instance()->reportUpdateFinished(QRect(10,10,10,10)); QTest::qSleep(300); KisUpdateTimeMonitor::instance()->reportUpdateFinished(QRect(30,30,10,10)); KisUpdateTimeMonitor::instance()->reportMouseMove(QPointF(130, 0)); KisUpdateTimeMonitor::instance()->endStrokeMeasure(); } void KisUpdateSchedulerTest::testLodSync() { KisImageSP image = buildTestingImage(); KisNodeSP rootLayer = image->root(); KisNodeSP paintLayer1 = rootLayer->firstChild(); QCOMPARE(paintLayer1->name(), QString("paint1")); image->setLevelOfDetailBlocked(false); image->setDesiredLevelOfDetail(2); image->explicitRegenerateLevelOfDetail(); image->waitForDone(); } QTEST_MAIN(KisUpdateSchedulerTest) diff --git a/libs/image/tests/kis_walkers_test.cpp b/libs/image/tests/kis_walkers_test.cpp index c202c671ce..9b110ec048 100644 --- a/libs/image/tests/kis_walkers_test.cpp +++ b/libs/image/tests/kis_walkers_test.cpp @@ -1,1226 +1,1226 @@ /* * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_walkers_test.h" #include "kis_base_rects_walker.h" #include "kis_refresh_subtree_walker.h" #include "kis_full_refresh_walker.h" #include #include #include #include "kis_paint_layer.h" #include "kis_group_layer.h" #include "kis_clone_layer.h" #include "kis_adjustment_layer.h" #include "kis_selection.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_filter_mask.h" #include "kis_transparency_mask.h" #define DEBUG_VISITORS QString nodeTypeString(KisMergeWalker::NodePosition position); QString nodeTypePostfix(KisMergeWalker::NodePosition position); /************** Test Implementation Of A Walker *********************/ class KisTestWalker : public KisMergeWalker { public: KisTestWalker() :KisMergeWalker(QRect()) { } QStringList popResult() { QStringList order(m_order); m_order.clear(); return order; } using KisMergeWalker::startTrip; protected: void registerChangeRect(KisProjectionLeafSP node, NodePosition position) override { QString postfix; if(!node->isLayer()) { postfix = "[skipped as not-a-layer]"; } #ifdef DEBUG_VISITORS dbgKrita<< "FW:"<< node->node()->name() <<'\t'<< nodeTypeString(position) << postfix; #endif if(postfix.isEmpty()) { m_order.append(node->node()->name()); } } void registerNeedRect(KisProjectionLeafSP node, NodePosition position) override { QString postfix; if(!node->isLayer()) { postfix = "[skipped as not-a-layer]"; } #ifdef DEBUG_VISITORS dbgKrita<< "BW:"<< node->node()->name() <<'\t'<< nodeTypeString(position) << postfix; #endif if(postfix.isEmpty()) { m_order.append(node->node()->name() + nodeTypePostfix(position)); } } protected: QStringList m_order; }; /************** Debug And Verify Code *******************************/ struct UpdateTestJob { QString updateAreaName; KisNodeSP startNode; QRect updateRect; QString referenceString; QRect accessRect; bool changeRectVaries; bool needRectVaries; }; void reportStartWith(QString nodeName, QRect rect = QRect()) { dbgKrita; if(!rect.isEmpty()) dbgKrita << "Start with:" << nodeName << rect; else dbgKrita << "Start with:" << nodeName; } QString nodeTypeString(KisMergeWalker::NodePosition position) { QString string; if(position & KisMergeWalker::N_TOPMOST) string="TOP"; else if(position & KisMergeWalker::N_BOTTOMMOST) string="BOT"; else string="NOR"; if(position & KisMergeWalker::N_ABOVE_FILTHY) string+="_ABOVE "; else if(position & KisMergeWalker::N_FILTHY) string+="_FILTH*"; else if(position & KisMergeWalker::N_FILTHY_PROJECTION) string+="_PROJE*"; else if(position & KisMergeWalker::N_FILTHY_ORIGINAL) string+="_ORIGI*_WARNINIG!!!: NOT USED"; else if(position & KisMergeWalker::N_BELOW_FILTHY) string+="_BELOW "; else if(position & KisMergeWalker::N_EXTRA) string+="_EXTRA*"; else qFatal("Impossible happened"); return string; } QString nodeTypePostfix(KisMergeWalker::NodePosition position) { QString string('_'); if(position & KisMergeWalker::N_TOPMOST) string += 'T'; else if(position & KisMergeWalker::N_BOTTOMMOST) string += 'B'; else string += 'N'; if(position & KisMergeWalker::N_ABOVE_FILTHY) string += 'A'; else if(position & KisMergeWalker::N_FILTHY) string += 'F'; else if(position & KisMergeWalker::N_FILTHY_PROJECTION) string += 'P'; else if(position & KisMergeWalker::N_FILTHY_ORIGINAL) string += 'O'; else if(position & KisMergeWalker::N_BELOW_FILTHY) string += 'B'; else if(position & KisMergeWalker::N_EXTRA) string += 'E'; else qFatal("Impossible happened"); return string; } void KisWalkersTest::verifyResult(KisBaseRectsWalker &walker, struct UpdateTestJob &job) { QStringList list; if(!job.referenceString.isEmpty()) { list = job.referenceString.split(','); } verifyResult(walker, list, job.accessRect, job.changeRectVaries, job.needRectVaries); } void KisWalkersTest::verifyResult(KisBaseRectsWalker &walker, QStringList reference, QRect accessRect, bool changeRectVaries, bool needRectVaries) { KisMergeWalker::LeafStack &list = walker.leafStack(); QStringList::const_iterator iter = reference.constBegin(); if(reference.size() != list.size()) { dbgKrita << "*** Seems like the walker returned stack of wrong size" << "( ref:" << reference.size() << "act:" << list.size() << ")"; dbgKrita << "*** We are going to crash soon... just wait..."; } Q_FOREACH (const KisMergeWalker::JobItem &item, list) { #ifdef DEBUG_VISITORS dbgKrita << item.m_leaf->node()->name() << '\t' << item.m_applyRect << '\t' << nodeTypeString(item.m_position); #endif QCOMPARE(item.m_leaf->node()->name(), *iter); iter++; } #ifdef DEBUG_VISITORS dbgKrita << "Result AR:\t" << walker.accessRect(); #endif QCOMPARE(walker.accessRect(), accessRect); QCOMPARE(walker.changeRectVaries(), changeRectVaries); QCOMPARE(walker.needRectVaries(), needRectVaries); } /************** Actual Testing **************************************/ /* +----------+ |root | | layer 5 | | group | | paint 4 | | paint 3 | | adj | | paint 2 | | paint 1 | +----------+ */ void KisWalkersTest::testUsualVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP adjustmentLayer = new KisAdjustmentLayer(image, "adj", 0, 0); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(adjustmentLayer, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(paintLayer4, groupLayer); KisTestWalker walker; { QString order("paint3,paint4,group,paint5,root," "root_TF,paint5_TA,group_NF,paint1_BB," "paint4_TA,paint3_NF,adj_NB,paint2_BB"); QStringList orderList = order.split(','); reportStartWith("paint3"); walker.startTrip(paintLayer3->projectionLeaf()); QVERIFY(walker.popResult() == orderList); } { QString order("adj,paint3,paint4,group,paint5,root," "root_TF,paint5_TA,group_NF,paint1_BB," "paint4_TA,paint3_NA,adj_NF,paint2_BB"); QStringList orderList = order.split(','); reportStartWith("adj"); walker.startTrip(adjustmentLayer->projectionLeaf()); QVERIFY(walker.popResult() == orderList); } { QString order("group,paint5,root," "root_TF,paint5_TA,group_NF,paint1_BB"); QStringList orderList = order.split(','); reportStartWith("group"); walker.startTrip(groupLayer->projectionLeaf()); QVERIFY(walker.popResult() == orderList); } } /* +----------+ |root | | layer 5 | | group | | mask 1 | | paint 4 | | paint 3 | | adj | | paint 2 | | paint 1 | +----------+ */ void KisWalkersTest::testVisitingWithTopmostMask() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP adjustmentLayer = new KisAdjustmentLayer(image, "adj", 0, 0); KisFilterMaskSP filterMask1 = new KisFilterMask(); filterMask1->initSelection(groupLayer); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(); filterMask1->setFilter(configuration1); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(adjustmentLayer, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(paintLayer4, groupLayer); // nasty mask! image->addNode(filterMask1, groupLayer); /** * The results must be the same as for testUsualVisiting */ KisTestWalker walker; { QString order("paint3,paint4,group,paint5,root," "root_TF,paint5_TA,group_NF,paint1_BB," "paint4_TA,paint3_NF,adj_NB,paint2_BB"); QStringList orderList = order.split(','); reportStartWith("paint3"); walker.startTrip(paintLayer3->projectionLeaf()); QVERIFY(walker.popResult() == orderList); } { QString order("adj,paint3,paint4,group,paint5,root," "root_TF,paint5_TA,group_NF,paint1_BB," "paint4_TA,paint3_NA,adj_NF,paint2_BB"); QStringList orderList = order.split(','); reportStartWith("adj"); walker.startTrip(adjustmentLayer->projectionLeaf()); QVERIFY(walker.popResult() == orderList); } { QString order("group,paint5,root," "root_TF,paint5_TA,group_NF,paint1_BB"); QStringList orderList = order.split(','); reportStartWith("group"); walker.startTrip(groupLayer->projectionLeaf()); QVERIFY(walker.popResult() == orderList); } } /* +----------+ |root | | layer 5 | | cplx 2 | | group | | paint 4 | | paint 3 | | cplx 1 | | paint 2 | | paint 1 | +----------+ */ void KisWalkersTest::testMergeVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer1 = new ComplexRectsLayer(image, "cplx1", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer2 = new ComplexRectsLayer(image, "cplx2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(complexRectsLayer2, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(complexRectsLayer1, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(paintLayer4, groupLayer); QRect testRect(10,10,10,10); // Empty rect to show we don't need any cropping QRect cropRect; KisMergeWalker walker(cropRect); { QString order("root,paint5,cplx2,group,paint1," "paint4,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect(-7,-7,44,44); reportStartWith("paint3"); walker.collectRects(paintLayer3, testRect); verifyResult(walker, orderList, accessRect, true, true); } { QString order("root,paint5,cplx2,group,paint1," "paint4,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect(-10,-10,50,50); reportStartWith("paint2"); walker.collectRects(paintLayer2, testRect); verifyResult(walker, orderList, accessRect, true, true); } { QString order("root,paint5,cplx2,group,paint1"); QStringList orderList = order.split(','); QRect accessRect(3,3,24,24); reportStartWith("paint5"); walker.collectRects(paintLayer5, testRect); verifyResult(walker, orderList, accessRect, false, true); } { /** * Test cropping */ QString order("root,paint5,cplx2,group,paint1," "paint4,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect(0,0,40,40); reportStartWith("paint2 (with cropping)"); walker.setCropRect(image->bounds()); walker.collectRects(paintLayer2, testRect); walker.setCropRect(cropRect); verifyResult(walker, orderList, accessRect, true, true); } { /** * Test uncropped values */ QString order("root,paint5,cplx2,group,paint1," "paint4,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect cropRect(9,9,12,12); QRect accessRect(cropRect); reportStartWith("paint2 (testing uncropped)"); walker.setCropRect(cropRect); walker.collectRects(paintLayer2, testRect); walker.setCropRect(cropRect); verifyResult(walker, orderList, accessRect, true, false); QCOMPARE(walker.uncroppedChangeRect(), QRect(4,4,22,22)); } } /* +------------+ |root | | layer 5 | | cplx 2 | | group | | paint 4 | | cplxacc 1 | | paint 3 | | cplx 1 | | paint 2 | | paint 1 | +------------+ */ void KisWalkersTest::testComplexAccessVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer1 = new ComplexRectsLayer(image, "cplx1", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer2 = new ComplexRectsLayer(image, "cplx2", OPACITY_OPAQUE_U8); KisLayerSP complexAccess = new ComplexAccessLayer(image, "cplxacc1", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(complexRectsLayer2, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(complexRectsLayer1, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(complexAccess, groupLayer); image->addNode(paintLayer4, groupLayer); QRect testRect(10,10,10,10); // Empty rect to show we don't need any cropping QRect cropRect; KisMergeWalker walker(cropRect); { QString order("root,paint5,cplx2,group,paint1," "paint4,cplxacc1,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect = QRect(-7,-7,44,44) | QRect(0,0,30,30).translated(70,0); reportStartWith("paint3"); walker.collectRects(paintLayer3, testRect); verifyResult(walker, orderList, accessRect, true, true); } } void KisWalkersTest::checkNotification(const KisMergeWalker::CloneNotification ¬ification, const QString &name, const QRect &rect) { QCOMPARE(notification.m_layer->name(), name); QCOMPARE(notification.m_dirtyRect, rect); } /* +--------------+ |root | | paint 3 <--+ | | cplx 2 | | | group <--+ | | | cplx 1 | | | | paint 2 | | | | clone 2 -+ | | | clone 1 ---+ | | paint 1 | +--------------+ */ void KisWalkersTest::testCloneNotificationsVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer1 = new ComplexRectsLayer(image, "cplx1", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer2 = new ComplexRectsLayer(image, "cplx2", OPACITY_OPAQUE_U8); KisLayerSP cloneLayer1 = new KisCloneLayer(paintLayer3, image, "clone1", OPACITY_OPAQUE_U8); KisLayerSP cloneLayer2 = new KisCloneLayer(groupLayer, image, "clone2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(cloneLayer1, image->rootLayer()); image->addNode(cloneLayer2, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(complexRectsLayer2, image->rootLayer()); image->addNode(paintLayer3, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(complexRectsLayer1, groupLayer); QRect testRect(10,10,10,10); QRect cropRect(5,5,507,507); KisMergeWalker walker(cropRect); { QString order("root,paint3,cplx2,group,clone2,clone1,paint1," "cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect = QRect(5,5,35,35); reportStartWith("paint2"); walker.collectRects(paintLayer2, testRect); verifyResult(walker, orderList, accessRect, true, true); const KisMergeWalker::CloneNotificationsVector vector = walker.cloneNotifications(); QCOMPARE(vector.size(), 1); checkNotification(vector[0], "group", QRect(7,7,16,16)); } } class TestingRefreshSubtreeWalker : public KisRefreshSubtreeWalker { public: TestingRefreshSubtreeWalker(QRect cropRect) : KisRefreshSubtreeWalker(cropRect) {} UpdateType type() const override { return FULL_REFRESH; } }; /* +----------+ |root | | layer 5 | | cplx 2 | | group | | paint 4 | | paint 3 | | cplx 1 | | paint 2 | | paint 1 | +----------+ */ void KisWalkersTest::testRefreshSubtreeVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer1 = new ComplexRectsLayer(image, "cplx1", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer2 = new ComplexRectsLayer(image, "cplx2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(complexRectsLayer2, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(complexRectsLayer1, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(paintLayer4, groupLayer); QRect testRect(10,10,10,10); // Empty rect to show we don't need any cropping QRect cropRect; TestingRefreshSubtreeWalker walker(cropRect); { QString order("root,paint5,cplx2,group,paint1," "paint4,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect(-10,-10,50,50); reportStartWith("root"); walker.collectRects(image->rootLayer(), testRect); verifyResult(walker, orderList, accessRect, true, true); } } /* +----------+ |root | | layer 5 | | cplx 2 | | group | | paint 4 | | paint 3 | | cplx 1 | | paint 2 | | paint 1 | +----------+ */ void KisWalkersTest::testFullRefreshVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer1 = new ComplexRectsLayer(image, "cplx1", OPACITY_OPAQUE_U8); KisLayerSP complexRectsLayer2 = new ComplexRectsLayer(image, "cplx2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(complexRectsLayer2, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(complexRectsLayer1, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(paintLayer4, groupLayer); QRect testRect(10,10,10,10); // Empty rect to show we don't need any cropping QRect cropRect; KisFullRefreshWalker walker(cropRect); { QString order("root,paint5,cplx2,group,paint1," "group,paint4,paint3,cplx1,paint2"); QStringList orderList = order.split(','); QRect accessRect(-10,-10,50,50); reportStartWith("root"); walker.collectRects(groupLayer, testRect); verifyResult(walker, orderList, accessRect, true, true); } } /* +----------+ |root | | layer 5 | | cache1 | | group | | paint 4 | | paint 3 | | paint 2 | | paint 1 | +----------+ */ void KisWalkersTest::testCachedVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); KisLayerSP cacheLayer1 = new CacheLayer(image, "cache1", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(cacheLayer1, image->rootLayer()); image->addNode(paintLayer5, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(paintLayer3, groupLayer); image->addNode(paintLayer4, groupLayer); QRect testRect(10,10,10,10); // Empty rect to show we don't need any cropping QRect cropRect; KisMergeWalker walker(cropRect); { QString order("root,paint5,cache1,group,paint1," "paint4,paint3,paint2"); QStringList orderList = order.split(','); QRect accessRect(0,0,30,30); reportStartWith("paint3"); walker.collectRects(paintLayer3, testRect); verifyResult(walker, orderList, accessRect, true, true); } { QString order("root,paint5,cache1"); QStringList orderList = order.split(','); QRect accessRect(10,10,10,10); reportStartWith("paint5"); walker.collectRects(paintLayer5, testRect); verifyResult(walker, orderList, accessRect, false, true); } } /* +----------+ |root | | paint 2 | | paint 1 | | fmask2 | | tmask | | fmask1 | +----------+ */ void KisWalkersTest::testMasksVisiting() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); KisFilterMaskSP filterMask1 = new KisFilterMask(); KisFilterMaskSP filterMask2 = new KisFilterMask(); KisTransparencyMaskSP transparencyMask = new KisTransparencyMask(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(0); - KisFilterConfigurationSP configuration2 = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(); + KisFilterConfigurationSP configuration2 = filter->defaultConfiguration(); filterMask1->setFilter(configuration1); filterMask2->setFilter(configuration2); QRect selection1(10, 10, 20, 10); QRect selection2(30, 15, 10, 10); QRect selection3(20, 10, 20, 10); filterMask1->testingInitSelection(selection1, paintLayer1); transparencyMask->testingInitSelection(selection2, paintLayer1); filterMask2->testingInitSelection(selection3, paintLayer1); image->addNode(filterMask1, paintLayer1); image->addNode(transparencyMask, paintLayer1); image->addNode(filterMask2, paintLayer1); QRect testRect(5,5,30,30); // Empty rect to show we don't need any cropping QRect cropRect; KisMergeWalker walker(cropRect); { QString order("root,paint2,paint1"); QStringList orderList = order.split(','); QRect accessRect(0,0,40,40); reportStartWith("tmask"); walker.collectRects(transparencyMask, testRect); verifyResult(walker, orderList, accessRect, true, false); } KisTestWalker twalker; { QString order("paint2,root," "root_TF,paint2_TA,paint1_BP"); QStringList orderList = order.split(','); reportStartWith("tmask"); twalker.startTrip(transparencyMask->projectionLeaf()); QCOMPARE(twalker.popResult(), orderList); } } /* +----------+ |root | | paint 2 | | paint 1 | | fmask2 | | tmask | | fmask1 | +----------+ */ void KisWalkersTest::testMasksVisitingNoFilthy() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); KisFilterMaskSP filterMask1 = new KisFilterMask(); KisFilterMaskSP filterMask2 = new KisFilterMask(); KisTransparencyMaskSP transparencyMask = new KisTransparencyMask(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(0); - KisFilterConfigurationSP configuration2 = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration1 = filter->defaultConfiguration(); + KisFilterConfigurationSP configuration2 = filter->defaultConfiguration(); filterMask1->setFilter(configuration1); filterMask2->setFilter(configuration2); QRect selection1(10, 10, 20, 10); QRect selection2(30, 15, 10, 10); QRect selection3(20, 10, 20, 10); filterMask1->testingInitSelection(selection1, paintLayer1); transparencyMask->testingInitSelection(selection2, paintLayer1); filterMask2->testingInitSelection(selection3, paintLayer1); image->addNode(filterMask1, paintLayer1); image->addNode(transparencyMask, paintLayer1); image->addNode(filterMask2, paintLayer1); QRect testRect(5,5,30,30); // Empty rect to show we don't need any cropping QRect cropRect; { KisMergeWalker walker(cropRect, KisMergeWalker::NO_FILTHY); QString order("root,paint2,paint1"); QStringList orderList = order.split(','); QRect accessRect(0,0,40,40); reportStartWith("tmask"); walker.collectRects(transparencyMask, testRect); verifyResult(walker, orderList, accessRect, true, false); } { KisMergeWalker walker(cropRect, KisMergeWalker::NO_FILTHY); QString order("root,paint2,paint1"); QStringList orderList = order.split(','); QRect accessRect(5,5,30,30); reportStartWith("paint1"); walker.collectRects(paintLayer1, testRect); verifyResult(walker, orderList, accessRect, false, false); } } /* +----------+ |root | | paint 2 | | paint 1 | | fmask2 | | tmask | | fmask1 | +----------+ */ void KisWalkersTest::testMasksOverlapping() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); KisFilterMaskSP filterMask1 = new KisFilterMask(); KisFilterMaskSP filterMask2 = new KisFilterMask(); KisTransparencyMaskSP transparencyMask = new KisTransparencyMask(); KisFilterSP blurFilter = KisFilterRegistry::instance()->value("blur"); KisFilterSP invertFilter = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(blurFilter); Q_ASSERT(invertFilter); - KisFilterConfigurationSP blurConfiguration = blurFilter->defaultConfiguration(0); - KisFilterConfigurationSP invertConfiguration = invertFilter->defaultConfiguration(0); + KisFilterConfigurationSP blurConfiguration = blurFilter->defaultConfiguration(); + KisFilterConfigurationSP invertConfiguration = invertFilter->defaultConfiguration(); filterMask1->setFilter(invertConfiguration); filterMask2->setFilter(blurConfiguration); QRect selection1(0, 0, 128, 128); QRect selection2(128, 0, 128, 128); QRect selection3(0, 64, 256, 128); filterMask1->testingInitSelection(selection1, paintLayer1); transparencyMask->testingInitSelection(selection2, paintLayer1); filterMask2->testingInitSelection(selection3, paintLayer1); image->addNode(filterMask1, paintLayer1); image->addNode(transparencyMask, paintLayer1); image->addNode(filterMask2, paintLayer1); // Empty rect to show we don't need any cropping QRect cropRect; QRect IMRect(10,10,50,50); QRect TMRect(135,10,40,40); QRect IMTMRect(10,10,256,40); QList updateList; { // FIXME: now we do not crop change rect if COMPOSITE_OVER is used! UpdateTestJob job = {"IM", paintLayer1, IMRect, "", QRect(0,0,0,0), true, false}; updateList.append(job); } { UpdateTestJob job = {"IM", filterMask1, IMRect, "", QRect(0,0,0,0), true, false}; updateList.append(job); } { UpdateTestJob job = {"IM", transparencyMask, IMRect, "root,paint2,paint1", QRect(5,10,60,55), true, false}; updateList.append(job); } { UpdateTestJob job = {"IM", filterMask2, IMRect, "root,paint2,paint1", IMRect, false, false}; updateList.append(job); } /******* Dirty rect: transparency mask *********/ { UpdateTestJob job = {"TM", paintLayer1, TMRect, "root,paint2,paint1", TMRect, false, false}; updateList.append(job); } { UpdateTestJob job = {"TM", filterMask1, TMRect, "root,paint2,paint1", TMRect, false, false}; updateList.append(job); } { UpdateTestJob job = {"TM", transparencyMask, TMRect, "root,paint2,paint1", TMRect, false, false}; updateList.append(job); } { UpdateTestJob job = {"TM", filterMask2, TMRect, "root,paint2,paint1", TMRect, false, false}; updateList.append(job); } /******* Dirty rect: invert + transparency mask *********/ { UpdateTestJob job = {"IMTM", paintLayer1, IMTMRect, "root,paint2,paint1", IMTMRect & selection2, true, false}; updateList.append(job); } { UpdateTestJob job = {"IMTM", filterMask1, IMTMRect, "root,paint2,paint1", IMTMRect & selection2, true, false}; updateList.append(job); } { UpdateTestJob job = {"IMTM", transparencyMask, IMTMRect, "root,paint2,paint1", IMTMRect, false, false}; updateList.append(job); } { UpdateTestJob job = {"IMTM", filterMask2, IMTMRect, "root,paint2,paint1", IMTMRect, false, false}; updateList.append(job); } Q_FOREACH (UpdateTestJob job, updateList) { KisMergeWalker walker(cropRect); reportStartWith(job.startNode->name(), job.updateRect); dbgKrita << "Area:" << job.updateAreaName; walker.collectRects(job.startNode, job.updateRect); verifyResult(walker, job); } } /* +----------+ |root | | adj | | paint 1 | +----------+ */ void KisWalkersTest::testRectsChecksum() { QRect imageRect(0,0,512,512); QRect dirtyRect(100,100,100,100); const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisAdjustmentLayerSP adjustmentLayer = new KisAdjustmentLayer(image, "adj", 0, 0); image->lock(); image->addNode(paintLayer1, image->rootLayer()); image->addNode(adjustmentLayer, image->rootLayer()); image->unlock(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); KisFilterConfigurationSP configuration; KisMergeWalker walker(imageRect); walker.collectRects(adjustmentLayer, dirtyRect); QCOMPARE(walker.checksumValid(), true); - configuration = filter->defaultConfiguration(0); + configuration = filter->defaultConfiguration(); adjustmentLayer->setFilter(configuration); QCOMPARE(walker.checksumValid(), false); walker.recalculate(dirtyRect); QCOMPARE(walker.checksumValid(), true); - configuration = filter->defaultConfiguration(0); + configuration = filter->defaultConfiguration(); configuration->setProperty("halfWidth", 20); configuration->setProperty("halfHeight", 20); adjustmentLayer->setFilter(configuration); QCOMPARE(walker.checksumValid(), false); walker.recalculate(dirtyRect); QCOMPARE(walker.checksumValid(), true); - configuration = filter->defaultConfiguration(0); + configuration = filter->defaultConfiguration(); configuration->setProperty("halfWidth", 21); configuration->setProperty("halfHeight", 21); adjustmentLayer->setFilter(configuration); QCOMPARE(walker.checksumValid(), false); walker.recalculate(dirtyRect); QCOMPARE(walker.checksumValid(), true); } void KisWalkersTest::testGraphStructureChecksum() { QRect imageRect(0,0,512,512); QRect dirtyRect(100,100,100,100); const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), colorSpace, "walker test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer1, image->rootLayer()); image->unlock(); KisMergeWalker walker(imageRect); walker.collectRects(paintLayer1, dirtyRect); QCOMPARE(walker.checksumValid(), true); image->lock(); image->addNode(paintLayer2, image->rootLayer()); image->unlock(); QCOMPARE(walker.checksumValid(), false); walker.recalculate(dirtyRect); QCOMPARE(walker.checksumValid(), true); image->lock(); image->moveNode(paintLayer1, image->rootLayer(), paintLayer2); image->unlock(); QCOMPARE(walker.checksumValid(), false); walker.recalculate(dirtyRect); QCOMPARE(walker.checksumValid(), true); image->lock(); image->removeNode(paintLayer1); image->unlock(); QCOMPARE(walker.checksumValid(), false); walker.recalculate(dirtyRect); QCOMPARE(walker.checksumValid(), true); } QTEST_MAIN(KisWalkersTest) diff --git a/libs/libkis/Document.cpp b/libs/libkis/Document.cpp index b07bd901d5..7dd2aac33a 100644 --- a/libs/libkis/Document.cpp +++ b/libs/libkis/Document.cpp @@ -1,449 +1,469 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Document.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include struct Document::Private { Private() {} QPointer document; bool ownsDocument {false}; }; Document::Document(KisDocument *document, bool ownsDocument, QObject *parent) : QObject(parent) , d(new Private) { d->document = document; d->ownsDocument = ownsDocument; } Document::~Document() { qDebug() << "Document" << this << "deleted"; + if (d->ownsDocument) { + KisPart::instance()->removeDocument(d->document); + delete d->document; + } + delete d; } bool Document::batchmode() const { if (!d->document) return false; return d->document->fileBatchMode(); } void Document::setBatchmode(bool value) { if (!d->document) return; d->document->setFileBatchMode(value); } Node *Document::activeNode() const { QList activeNodes; Q_FOREACH(QPointer view, KisPart::instance()->views()) { if (view && view->document() == d->document) { activeNodes << view->currentNode(); } } if (activeNodes.size() > 0) { return new Node(d->document->image(), activeNodes.first()); } return new Node(d->document->image(), d->document->image()->root()->firstChild()); } void Document::setActiveNode(Node* value) { if (!value->node()) return; KisMainWindow *mainWin = KisPart::instance()->currentMainwindow(); if (!mainWin) return; KisViewManager *viewManager = mainWin->viewManager(); if (!viewManager) return; KisNodeManager *nodeManager = viewManager->nodeManager(); if (!nodeManager) return; KisNodeSelectionAdapter *selectionAdapter = nodeManager->nodeSelectionAdapter(); if (!selectionAdapter) return; selectionAdapter->setActiveNode(value->node()); } QString Document::colorDepth() const { if (!d->document) return ""; return d->document->image()->colorSpace()->colorDepthId().id(); } QString Document::colorModel() const { if (!d->document) return ""; return d->document->image()->colorSpace()->colorModelId().id(); } QString Document::colorProfile() const { if (!d->document) return ""; return d->document->image()->colorSpace()->profile()->name(); } bool Document::setColorProfile(const QString &value) { if (!d->document) return false; if (!d->document->image()) return false; const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(value); if (!profile) return false; d->document->image()->lock(); bool retval = d->document->image()->assignImageProfile(profile); d->document->image()->unlock(); d->document->image()->setModified(); d->document->image()->initialRefreshGraph(); return retval; } bool Document::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile) { if (!d->document) return false; if (!d->document->image()) return false; const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, colorProfile); if (!colorSpace) return false; d->document->image()->lock(); d->document->image()->convertImageColorSpace(colorSpace, KoColorConversionTransformation::IntentPerceptual, KoColorConversionTransformation::HighQuality | KoColorConversionTransformation::NoOptimization); d->document->image()->unlock(); d->document->image()->setModified(); d->document->image()->initialRefreshGraph(); return true; } QString Document::documentInfo() const { QDomDocument doc = KisDocument::createDomDocument("document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1"); doc = d->document->documentInfo()->save(doc); return doc.toString(); } void Document::setDocumentInfo(const QString &document) { KoXmlDocument doc = KoXmlDocument(true); QString errorMsg; int errorLine, errorColumn; doc.setContent(document, &errorMsg, &errorLine, &errorColumn); d->document->documentInfo()->load(doc); } QString Document::fileName() const { if (!d->document) return QString::null; return d->document->url().toLocalFile(); } void Document::setFileName(QString value) { if (!d->document) return; d->document->setUrl(QUrl::fromLocalFile(value)); } int Document::height() const { if (!d->document) return 0; KisImageSP image = d->document->image(); if (!image) return 0; return image->height(); } void Document::setHeight(int value) { if (!d->document) return; KisImageSP image = d->document->image(); if (!image) return; QRect rc = image->bounds(); rc.setHeight(value); image->resizeImage(rc); } QString Document::name() const { if (!d->document) return ""; return d->document->documentInfo()->aboutInfo("title"); } void Document::setName(QString value) { if (!d->document) return; d->document->documentInfo()->setAboutInfo("title", value); } int Document::resolution() const { if (!d->document) return 0; KisImageSP image = d->document->image(); if (!image) return 0; return qRound(d->document->image()->xRes() * 72); } void Document::setResolution(int value) { if (!d->document) return; KisImageSP image = d->document->image(); if (!image) return; d->document->image()->setResolution(value / 72.0, value / 72.0); } Node *Document::rootNode() const { if (!d->document) return 0; KisImageSP image = d->document->image(); if (!image) return 0; return new Node(image, image->root()); } Selection *Document::selection() const { - return 0; + if (!d->document) return 0; + if (!d->document->image()) return 0; + if (!d->document->image()->globalSelection()) return 0; + return new Selection(d->document->image()->globalSelection()); } void Document::setSelection(Selection* value) { + if (!d->document) return; + if (!d->document->image()) return; + d->document->image()->setGlobalSelection(value->selection()); } int Document::width() const { if (!d->document) return 0; KisImageSP image = d->document->image(); if (!image) return 0; return image->width(); } void Document::setWidth(int value) { if (!d->document) return; KisImageSP image = d->document->image(); if (!image) return; QRect rc = image->bounds(); rc.setWidth(value); image->resizeImage(rc); } double Document::xRes() const { if (!d->document) return 0.0; if (!d->document->image()) return 0.0; return d->document->image()->xRes(); } void Document::setXRes(double xRes) const { if (!d->document) return; if (!d->document->image()) return; d->document->image()->setResolution(xRes, d->document->image()->yRes()); } double Document::yRes() const { if (!d->document) return 0.0; if (!d->document->image()) return 0.0; return d->document->image()->yRes(); } void Document::setyRes(double yRes) const { if (!d->document) return; if (!d->document->image()) return; d->document->image()->setResolution(d->document->image()->xRes(), yRes); } QByteArray Document::pixelData(int x, int y, int w, int h) const { QByteArray ba; if (!d->document) return ba; KisImageSP image = d->document->image(); if (!image) return ba; KisPaintDeviceSP dev = image->projection(); quint8 *data = new quint8[w * h * dev->pixelSize()]; dev->readBytes(data, x, y, w, h); ba = QByteArray((const char*)data, (int)(w * h * dev->pixelSize())); delete[] data; return ba; } bool Document::close() { if (d->ownsDocument) { KisPart::instance()->removeDocument(d->document); } bool retval = d->document->closeUrl(false); if (d->ownsDocument) { delete d->document; } return retval; } void Document::crop(int x, int y, int w, int h) { if (!d->document) return; KisImageSP image = d->document->image(); if (!image) return; QRect rc(x, y, w, h); image->cropImage(rc); } bool Document::exportImage(const QString &filename, const InfoObject &exportConfiguration) { if (!d->document) return false; return d->document->exportDocument(QUrl::fromLocalFile(filename)); } void Document::flatten() { if (!d->document) return; if (!d->document->image()) return; d->document->image()->lock(); d->document->image()->flatten(); d->document->image()->unlock(); d->document->image()->setModified(); d->document->image()->initialRefreshGraph(); } void Document::resizeImage(int w, int h) { if (!d->document) return; KisImageSP image = d->document->image(); if (!image) return; QRect rc = image->bounds(); rc.setWidth(w); rc.setHeight(h); image->resizeImage(rc); } bool Document::save() { if (!d->document) return false; return d->document->save(); } bool Document::saveAs(const QString &filename) { if (!d->document) return false; return d->document->saveAs(QUrl::fromLocalFile(filename)); } void Document::openView() { + // UNIMPLEMENTED } Node* Document::createNode(const QString &name, const QString &nodeType) { if (!d->document) return 0; if (!d->document->image()) return 0; KisImageSP image = d->document->image(); Node *node = 0; if (nodeType == "paintlayer") { node = new Node(image, new KisPaintLayer(image, name, OPACITY_OPAQUE_U8)); } else if (nodeType == "grouplayer") { node = new Node(image, new KisGroupLayer(image, name, OPACITY_OPAQUE_U8)); } else if (nodeType == "filelayer") { node = new Node(image, new KisFileLayer(image, name, OPACITY_OPAQUE_U8)); } else if (nodeType == "filterlayer") { node = new Node(image, new KisAdjustmentLayer(image, name, 0, 0)); } else if (nodeType == "filllayer") { node = new Node(image, new KisGeneratorLayer(image, name, 0, 0)); } else if (nodeType == "clonelayer") { node = new Node(image, new KisCloneLayer(0, image, name, OPACITY_OPAQUE_U8)); } else if (nodeType == "vectorlayer") { node = new Node(image, new KisShapeLayer(d->document->shapeController(), image, name, OPACITY_OPAQUE_U8)); } else if (nodeType == "transparencymask") { node = new Node(image, new KisTransparencyMask()); } else if (nodeType == "filtermask") { node = new Node(image, new KisFilterMask()); } else if (nodeType == "transformmask") { node = new Node(image, new KisTransformMask()); } else if (nodeType == "localselectionmask") { node = new Node(image, new KisSelectionMask(image)); } return node; } +Node *Document::mergeDown(Node *node) +{ + if (!d->document) return 0; + // UNINMPLEMENTED + return 0; +} + QPointer Document::document() const { return d->document; } diff --git a/libs/libkis/Document.h b/libs/libkis/Document.h index d928cd32f2..7bea2304f0 100644 --- a/libs/libkis/Document.h +++ b/libs/libkis/Document.h @@ -1,264 +1,280 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBKIS_DOCUMENT_H #define LIBKIS_DOCUMENT_H #include #include "kritalibkis_export.h" #include "libkis.h" class KisDocument; /** * Document */ class KRITALIBKIS_EXPORT Document : public QObject { Q_OBJECT Q_DISABLE_COPY(Document) public: explicit Document(KisDocument *document, bool ownsDocument = false, QObject *parent = 0); virtual ~Document(); public Q_SLOTS: bool batchmode() const; void setBatchmode(bool value); Node* activeNode() const; void setActiveNode(Node* value); /** * colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return the color depth. */ QString colorDepth() const; /** * @brief colorModel retrieve the current color model of this document: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @return the internal color model string. */ QString colorModel() const; /** * @return the name of the current color profile */ QString colorProfile() const; /** * @brief setColorProfile set the color profile of the image to the given profile. The profile has to * be registered with krita and be compatible with the current color model and depth; the image data * is not converted. * @param colorProfile * @return false if the colorProfile name does not correspond to to a registered profile or if assigning * the profile failed. */ bool setColorProfile(const QString &colorProfile); /** * @brief setColorSpace convert the nodes and the image to the given colorspace. The conversion is * done with Perceptual as intent, High Quality and No LCMS Optimizations as flags and no blackpoint * compensation. * * @param colorModel A string describing the color model of the image: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param colorProfile a valid color profile for this color model and color depth combination. * @return false the combination of these arguments does not correspond to a colorspace. */ bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); /** * @brief documentInfo creates and XML document representing document and author information. * @return a string containing a valid XML document */ QString documentInfo() const; void setDocumentInfo(const QString &document); QString fileName() const; void setFileName(QString value); int height() const; void setHeight(int value); QString name() const; void setName(QString value); /** * @return the resolution in pixels per inch */ int resolution() const; /** * @brief setResolution set the resolution of the image; this does not scale the image * @param value the resolution in pixels per inch */ void setResolution(int value); Node* rootNode() const; + /** + * @brief selection Create a Selection object around the global selection, if there is one. + * @return the global selection or None if there is no global selection. + */ Selection* selection() const; + + /** + * @brief setSelection set or replace the global selection + * @param value a valid selection object. + */ void setSelection(Selection* value); int width() const; void setWidth(int value); /** * @return xRes the horizontal resolution of the image in pixels per pt (there are 72 pts to an inch) */ double xRes() const; void setXRes(double xRes) const; /** * @return yRes the vertical resolution of the image in pixels per pt (there are 72 pts to an inch) */ double yRes() const; void setyRes(double yRes) const; /** * @brief pixelData reads the given rectangle from the image projection and returns it as a byte * array. The pixel data starts top-left, and is ordered row-first. * * The byte array can be interpreted as follows: 8 bits images have one byte per channel, * and as many bytes as there are channels. 16 bits integer images have two bytes per channel, * representing an unsigned short. 16 bits float images have two bytes per channel, representing * a half, or 16 bits float. 32 bits float images have four bytes per channel, representing a * float. * * You can read outside the image boundaries; those pixels will be transparent black. * * The order of channels is: * *
    *
  • Integer RGBA: Blue, Green, Red, Alpha *
  • Float RGBA: Red, Green, Blue, Alpha *
  • LabA: L, a, b, Alpha *
  • CMYKA: Cyan, Magenta, Yellow, Key, Alpha *
  • XYZA: X, Y, Z, A *
  • YCbCrA: Y, Cb, Cr, Alpha *
* * The byte array is a copy of the original image data. In Python, you can use bytes, bytearray * and the struct module to interpret the data and construct, for instance, a Pillow Image object. * * @param x x position from where to start reading * @param y y position from where to start reading * @param w row length to read * @param h number of rows to read * @return a QByteArray with the pixel data. The byte array may be empty. */ QByteArray pixelData(int x, int y, int w, int h) const; bool close(); void crop(int x, int y, int w, int h); bool exportImage(const QString &filename, const InfoObject &exportConfiguration); void flatten(); void resizeImage(int w, int h); bool save(); bool saveAs(const QString &filename); void openView(); /** * @brief createNode create a new node of the given type. The node is not added * to the node hierarchy; you need to do that by finding the right parent node, * getting its list of child nodes and adding the node in the right place, then * calling Node::SetChildNodes * * @param name The name of the node * * @param nodeType The type of the node. Valid types are: *
    *
  • paintlayer *
  • grouplayer *
  • filelayer *
  • filterlayer *
  • filllayer *
  • clonelayer *
  • vectorlayer *
  • transparencymask *
  • filtermask *
  • transformmask *
  • localselectionmask *
* * When relevant, the new Node will have the colorspace of the image by default; * that can be changed with Node::setColorSpace. * * The settings and selections for relevant layer and mask types can also be set * after the Node has been created. * * @return the new Node. */ Node* createNode(const QString &name, const QString &nodeType); + /** + * @brief mergeDown merges the given node with the first visible node underneath this node in the layerstack + * @param node the node to merge down; this node will be removed from the layer stack + * @return the merged node + */ + Node *mergeDown(Node *node); + Q_SIGNALS: void nodeCreated(Node *node); private: friend class Krita; friend class Window; QPointer document() const; private: struct Private; Private *const d; }; #endif // LIBKIS_DOCUMENT_H diff --git a/libs/libkis/Filter.cpp b/libs/libkis/Filter.cpp index c9012e8d02..b9bc407c1a 100644 --- a/libs/libkis/Filter.cpp +++ b/libs/libkis/Filter.cpp @@ -1,103 +1,106 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Filter.h" #include #include #include #include #include #include #include struct Filter::Private { Private() {} QString name; InfoObject *configuration {0}; }; Filter::Filter() : QObject(0) , d(new Private) { } Filter::~Filter() { qDebug() << "Deleting filter" << d->name; delete d->configuration; delete d; } QString Filter::name() const { return d->name; } void Filter::setName(const QString &name) { d->name = name; delete d->configuration; - d->configuration = new InfoObject(); + + KisFilterSP filter = KisFilterRegistry::instance()->value(d->name); + d->configuration = new InfoObject(filter->defaultConfiguration()); } InfoObject* Filter::configuration() const { return d->configuration; } void Filter::setConfiguration(InfoObject* value) { d->configuration = value; } bool Filter::apply(Node *node, int x, int y, int w, int h) { - qDebug() << node << node->name() << node->locked() << node->paintDevice(); - if (node->locked()) return false; + KisFilterSP filter = KisFilterRegistry::instance()->value(d->name); + if (!filter) return false; + KisPaintDeviceSP dev = node->paintDevice(); if (!dev) return false; QRect applyRect = QRect(x, y, w, h); KisImageSP image = node->image(); if (image) { image->lock(); } KisFilterConfigurationSP config = static_cast(d->configuration->configuration().data()); - KisFilterSP filter = KisFilterRegistry::instance()->value(d->name); + filter->process(dev, applyRect, config); if (image) { image->unlock(); image->initialRefreshGraph(); } qDebug() << "filter applied!" << filter->changedRect(QRect(x, y, w, h), config, 0); return true; } diff --git a/libs/libkis/Filter.h b/libs/libkis/Filter.h index 05f1d920ac..3ca6fd2e51 100644 --- a/libs/libkis/Filter.h +++ b/libs/libkis/Filter.h @@ -1,97 +1,95 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBKIS_FILTER_H #define LIBKIS_FILTER_H #include #include "kritalibkis_export.h" #include "libkis.h" /** * Filter: represents a filter and its configuration. A filter is identified by * an internal name. The configuration for each filter is defined as an InfoObject: * a map of name and value pairs. * * Currently available filters are: * * 'autocontrast', 'blur', 'bottom edge detections', 'brightnesscontrast', 'burn', 'colorbalance', 'colortoalpha', 'colortransfer', * 'desaturate', 'dodge', 'emboss', 'emboss all directions', 'emboss horizontal and vertical', 'emboss horizontal only', * 'emboss laplascian', 'emboss vertical only', 'gaussian blur', 'gaussiannoisereducer', 'gradientmap', 'halftone', 'hsvadjustment', * 'indexcolors', 'invert', 'left edge detections', 'lens blur', 'levels', 'maximize', 'mean removal', 'minimize', 'motion blur', * 'noise', 'normalize', 'oilpaint', 'perchannel', 'phongbumpmap', 'pixelize', 'posterize', 'raindrops', 'randompick', * 'right edge detections', 'roundcorners', 'sharpen', 'smalltiles', 'sobel', 'threshold', 'top edge detections', 'unsharp', * 'wave', 'waveletnoisereducer'] */ class KRITALIBKIS_EXPORT Filter : public QObject { Q_OBJECT Q_DISABLE_COPY(Filter) - Q_PROPERTY(InfoObject* Configuration READ configuration WRITE setConfiguration) - public: /** * @brief Filter: create an empty filter object. Until a name is set, the filter cannot * be applied. */ explicit Filter(); virtual ~Filter(); public Q_SLOTS: /** * @brief name the internal name of this filter. * @return the name. */ QString name() const; /** * @brief setName set the filter's name to the given name. */ void setName(const QString &name); /** * @return the configuration object for the filter */ InfoObject* configuration() const; /** * @brief setConfiguration set the configuration object for the filter */ void setConfiguration(InfoObject* value); /** * @brief Apply the filter to the given node. * @param node the node to apply the filter to * @params x, y, w, h: describe the rectangle the filter should be apply. * This is always in image pixel coordinates and not relative to the x, y * of the node. * @return true if the filter was applied succesfully, or * false if the filter could not be applied because the node is locked or * does not have an editable paint device. */ bool apply(Node *node, int x, int y, int w, int h); private: struct Private; Private *const d; }; #endif // LIBKIS_FILTER_H diff --git a/libs/libkis/Generator.cpp b/libs/libkis/Generator.cpp index 267cb78d98..747e0c2515 100644 --- a/libs/libkis/Generator.cpp +++ b/libs/libkis/Generator.cpp @@ -1,53 +1,53 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Generator.h" struct Generator::Private { Private() {} }; Generator::Generator(QObject *parent) : QObject(parent) , d(new Private) { } Generator::~Generator() { delete d; } InfoObject* Generator::configuration() const { + // UNIMPLEMENTED return 0; } void Generator::setConfiguration(InfoObject* value) { + // UNIMPLEMENTED } - - - Node* Generator::createNode() { + // UNIMPLEMENTED return 0; } diff --git a/libs/libkis/Krita.cpp b/libs/libkis/Krita.cpp index 2aab1360ff..c2d32937c0 100644 --- a/libs/libkis/Krita.cpp +++ b/libs/libkis/Krita.cpp @@ -1,356 +1,358 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Krita.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "View.h" #include "Document.h" #include "Window.h" #include "ViewExtension.h" #include "DockWidgetFactoryBase.h" #include "Filter.h" #include "InfoObject.h" #include "Generator.h" Krita* Krita::s_instance = 0; struct Krita::Private { Private() {} QList viewExtensions; bool batchMode {false}; Notifier *notifier{new Notifier()}; }; Krita::Krita(QObject *parent) : QObject(parent) , d(new Private) { qRegisterMetaType(); } Krita::~Krita() { qDeleteAll(d->viewExtensions); delete d->notifier; delete d; } QList Krita::actions() const { QList actionList; KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return actionList; } KActionCollection *actionCollection = mainWindow->actionCollection(); Q_FOREACH(QAction *action, actionCollection->actions()) { actionList << new Action(action->objectName(), action); } return actionList; } Action *Krita::action(const QString &name) const { KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return 0; } KActionCollection *actionCollection = mainWindow->actionCollection(); QAction *action = actionCollection->action(name); if (action) { return new Action(name, action); } return 0; } Document* Krita::activeDocument() const { KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return 0; } KisView *view = mainWindow->activeView(); if (!view) { return 0; } KisDocument *document = view->document(); return new Document(document); } void Krita::setActiveDocument(Document* value) { Q_FOREACH(KisView *view, KisPart::instance()->views()) { if (view->document() == value->document().data()) { view->activateWindow(); break; } } } bool Krita::batchmode() const { return d->batchMode; } void Krita::setBatchmode(bool value) { d->batchMode = value; } QList Krita::documents() const { QList ret; foreach(QPointer doc, KisPart::instance()->documents()) { ret << new Document(doc); } return ret; } QStringList Krita::filters() const { QStringList ls = KisFilterRegistry::instance()->keys(); qSort(ls); return ls; } Filter *Krita::filter(const QString &name) const { if (!filters().contains(name)) return 0; Filter *filter = new Filter(); filter->setName(name); KisFilterSP f = KisFilterRegistry::instance()->value(name); - KisFilterConfigurationSP fc = f->defaultConfiguration(0); + KisFilterConfigurationSP fc = f->defaultConfiguration(); InfoObject *info = new InfoObject(fc); filter->setConfiguration(info); return filter; } QStringList Krita::generators() const { QStringList ls = KisGeneratorRegistry::instance()->keys(); qSort(ls); return ls; } Generator *Krita::generator(const QString &name) const { + // UNIMPLEMENTED if (!generators().contains(name)) return 0; Generator *generator = new Generator(); // generator->setName(name); // KisGeneratorSP f = KisGeneratorRegistry::instance()->value(name); // KisGeneratorConfigurationSP fc = f->defaultConfiguration(0); // InfoObject *info = new InfoObject(fc); // generator->setConfiguration(info); return generator; } QStringList Krita::profiles(const QString &colorModel, const QString &colorDepth) const { QSet profileNames; QString id = KoColorSpaceRegistry::instance()->colorSpaceId(colorModel, colorDepth); QList profiles = KoColorSpaceRegistry::instance()->profilesFor(id); Q_FOREACH(const KoColorProfile *profile, profiles) { profileNames << profile->name(); } return profileNames.toList(); } bool Krita::addProfile(const QString &profilePath) { KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); return iccEngine->addProfile(profilePath); } Notifier* Krita::notifier() const { return d->notifier; } QString Krita::version() const { return KritaVersionWrapper::versionString(true); } QList Krita::views() const { QList ret; foreach(QPointer view, KisPart::instance()->views()) { ret << new View(view); } return ret; } Window *Krita::activeWindow() const { KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return 0; } return new Window(mainWindow); } QList Krita::windows() const { QList ret; foreach(QPointer mainWin, KisPart::instance()->mainWindows()) { ret << new Window(mainWin); } return ret; - } QList Krita::resources() const { + // UNIMPLEMENTED return QList (); } void Krita::setResources(QList value) { - + // UNIMPLEMENTED } void Krita::addDockWidget(DockWidget *dockWidget) { + // UNIMPLEMENTED } bool Krita::closeApplication() { qDebug() << "closeApplication called"; return false; } Document* Krita::createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile) { KisDocument *document = KisPart::instance()->createDocument(); KisPart::instance()->addDocument(document); const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, profile); Q_ASSERT(cs); QColor qc(Qt::white); qc.setAlpha(0); KoColor bgColor(qc, cs); if (!document->newImage(name, width, height, cs, bgColor, true, 1, "", 100.0)) { qDebug() << "Could not create a new image"; return 0; } Q_ASSERT(document->image()); qDebug() << document->image()->objectName(); return new Document(document, true); } Document* Krita::openDocument(const QString &filename) { KisDocument *document = KisPart::instance()->createDocument(); KisPart::instance()->addDocument(document); document->openUrl(QUrl::fromLocalFile(filename), KisDocument::OPEN_URL_FLAG_DO_NOT_ADD_TO_RECENT_FILES); return new Document(document); } Window* Krita::openWindow() { KisMainWindow *mw = KisPart::instance()->createMainWindow(); return new Window(mw); } Action *Krita::createAction(const QString &text) { KisAction *action = new KisAction(text, this); KisPart::instance()->addScriptAction(action); return new Action(action->objectName(), action); } void Krita::addViewExtension(ViewExtension* viewExtension) { d->viewExtensions.append(viewExtension); } QList< ViewExtension* > Krita::viewExtensions() { return d->viewExtensions; } void Krita::addDockWidgetFactory(DockWidgetFactoryBase* factory) { KoDockRegistry::instance()->add(factory); } Krita* Krita::instance() { if (!s_instance) { s_instance = new Krita; } return s_instance; } /** * Scripter.fromVariant(variant) * variant is a QVariant * returns instance of QObject-subclass * * This is a helper method for PyQt because PyQt cannot cast a variant to a QObject or QWidget */ QObject *Krita::fromVariant(const QVariant& v) { if (v.canConvert< QWidget* >()) { QObject* obj = qvariant_cast< QWidget* >(v); return obj; } else if (v.canConvert< QObject* >()) { QObject* obj = qvariant_cast< QObject* >(v); return obj; } else return 0; } diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp index ae26a872b0..8b9b997321 100644 --- a/libs/libkis/Node.cpp +++ b/libs/libkis/Node.cpp @@ -1,424 +1,460 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "Krita.h" #include "Node.h" #include "Channel.h" #include "Generator.h" #include "Filter.h" #include "Transformation.h" #include "Selection.h" struct Node::Private { Private() {} KisImageSP image; KisNodeSP node; }; Node::Node(KisImageSP image, KisNodeSP node, QObject *parent) : QObject(parent) , d(new Private) { d->image = image; d->node = node; } Node::~Node() { delete d; } bool Node::alphaLocked() const { if (!d->node) return false; KisPaintLayerSP paintLayer = qobject_cast(d->node.data()); if (paintLayer) { return paintLayer->alphaLocked(); } return false; } void Node::setAlphaLocked(bool value) { if (!d->node) return; KisPaintLayerSP paintLayer = qobject_cast(d->node.data()); if (paintLayer) { paintLayer->setAlphaLocked(value); } } QString Node::blendingMode() const { if (!d->node) return QString(); return d->node->compositeOpId(); } void Node::setBlendingMode(QString value) { if (!d->node) return; d->node->setCompositeOpId(value); } QList Node::channels() const { QList channels; if (!d->node) return channels; if (!d->node->inherits("KisLayer")) return channels; Q_FOREACH(KoChannelInfo *info, d->node->colorSpace()->channels()) { Channel *channel = new Channel(d->node, info); channels << channel; } return channels; } QList Node::childNodes() const { QList nodes; if (d->node) { int childCount = d->node->childCount(); for (int i = 0; i < childCount; ++i) { nodes << new Node(d->image, d->node->at(i)); } } return nodes; } +void Node::addChildNode(Node *child, Node *above) +{ + // UNIMPLEMENTED + if (!d->node) return; +} + void Node::setChildNodes(QList value) { + // UNIMPLEMENTED if (!d->node) return; } QString Node::colorLabel() const { + // UNIMPLEMENTED if (!d->node) return QString(); return QString(); } void Node::setColorLabel(QString value) { + // UNIMPLEMENTED if (!d->node) return; } QString Node::colorDepth() const { if (!d->node) return ""; return d->node->colorSpace()->colorDepthId().id(); } - - QString Node::colorModel() const { if (!d->node) return ""; return d->node->colorSpace()->colorModelId().id(); } QString Node::colorProfile() const { if (!d->node) return ""; return d->node->colorSpace()->profile()->name(); } void Node::setColorProfile(const QString &colorProfile) { - + // UNIMPLEMENTED } void Node::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile) { - + // UNIMPLEMENTED } bool Node::inheritAlpha() const { + // UNIMPLEMENTED if (!d->node) return false; return false; } void Node::setInheritAlpha(bool value) { + // UNIMPLEMENTED if (!d->node) return; } bool Node::locked() const { + // UNIMPLEMENTED if (!d->node) return false; return false; } void Node::setLocked(bool value) { + // UNIMPLEMENTED if (!d->node) return; } QString Node::name() const { if (!d->node) return QString(); return d->node->name(); } void Node::setName(QString value) { + // UNIMPLEMENTED if (!d->node) return; } int Node::opacity() const { if (!d->node) return 0; return d->node->opacity(); } void Node::setOpacity(int value) { if (!d->node) return; d->node->setOpacity(value); } Node* Node::parentNode() const { + // UNIMPLEMENTED if (!d->node) return 0; return 0; } void Node::setParentNode(Node* value) { + // UNIMPLEMENTED if (!d->node) return; } QString Node::type() const { + // UNIMPLEMENTED if (!d->node) return QString(); return QString(); } void Node::setType(QString value) { + // UNIMPLEMENTED if (!d->node) return; } bool Node::visible() const { + // UNIMPLEMENTED if (!d->node) return false; return false; } void Node::setVisible(bool value) { + // UNIMPLEMENTED if (!d->node) return; } InfoObject* Node::metaDataInfo() const { + // UNIMPLEMENTED if (!d->node) return 0; return 0; } void Node::setMetaDataInfo(InfoObject* value) { + // UNIMPLEMENTED if (!d->node) return; } Generator* Node::generator() const { + // UNIMPLEMENTED if (!d->node) return 0; return 0; } void Node::setGenerator(Generator* value) { + // UNIMPLEMENTED if (!d->node) return; } Filter* Node::filter() const { + // UNIMPLEMENTED if (!d->node) return 0; return 0; } void Node::setFilter(Filter* value) { + // UNIMPLEMENTED if (!d->node) return; } Transformation* Node::transformation() const { + // UNIMPLEMENTED if (!d->node) return 0; return 0; } void Node::setTransformation(Transformation* value) { + // UNIMPLEMENTED if (!d->node) return; } - -Selection* Node::selection() const -{ - if (!d->node) return 0; - return 0; -} - -void Node::setSelection(Selection* value) -{ - if (!d->node) return; -} - - QString Node::fileName() const { + // UNIMPLEMENTED if (!d->node) return QString(); return QString(); } void Node::setFileName(QString value) { + // UNIMPLEMENTED if (!d->node) return; } - QByteArray Node::pixelData(int x, int y, int w, int h) const { QByteArray ba; if (!d->node) return ba; + KisPaintDeviceSP dev = d->node->paintDevice(); + if (!dev) return ba; + + quint8 *data = new quint8[w * h * dev->pixelSize()]; + dev->readBytes(data, x, y, w, h); + ba = QByteArray((const char*)data, (int)(w * h * dev->pixelSize())); + delete[] data; + + return ba; +} + + +QByteArray Node::projectionPixelData(int x, int y, int w, int h) const +{ + QByteArray ba; + + if (!d->node) return ba; + KisPaintDeviceSP dev = d->node->projection(); quint8 *data = new quint8[w * h * dev->pixelSize()]; dev->readBytes(data, x, y, w, h); ba = QByteArray((const char*)data, (int)(w * h * dev->pixelSize())); delete[] data; return ba; } void Node::setPixelData(QByteArray value, int x, int y, int w, int h) { if (!d->node) return; KisPaintDeviceSP dev = d->node->paintDevice(); if (!dev) return; dev->writeBytes((const quint8*)value.constData(), x, y, w, h); } QRect Node::bounds() const { if (!d->node) return QRect(); return d->node->exactBounds(); } void Node::move(int x, int y) { + // UNIMPLEMENTED if (!d->node) return; } void Node::moveToParent(Node *parent) { + // UNIMPLEMENTED if (!d->node) return; } void Node::remove() { + // UNIMPLEMENTED if (!d->node) return; } Node* Node::duplicate() { + // UNIMPLEMENTED if (!d->node) return 0; return 0; } bool Node::save(const QString &filename, double xRes, double yRes) { if (!d->node) return false; if (filename.isEmpty()) return false; KisPaintDeviceSP projection = d->node->projection(); QRect bounds = d->node->exactBounds(); QString mimefilter = KisMimeDatabase::mimeTypeForFile(filename);; QScopedPointer doc(KisPart::instance()->createDocument()); KisImageSP dst = new KisImage(doc->createUndoStore(), bounds.width(), bounds.height(), projection->compositionSourceColorSpace(), d->node->name()); dst->setResolution(xRes, yRes); doc->setFileBatchMode(Krita::instance()->batchmode()); doc->setCurrentImage(dst); KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", d->node->opacity()); paintLayer->paintDevice()->makeCloneFrom(projection, bounds); dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0)); dst->initialRefreshGraph(); doc->setOutputMimeType(mimefilter.toLatin1()); bool r = doc->exportDocument(QUrl::fromLocalFile(filename)); if (!r) { qWarning() << doc->errorMessage(); } return r; } KisPaintDeviceSP Node::paintDevice() const { return d->node->paintDevice(); } KisImageSP Node::image() const { return d->image; } KisNodeSP Node::node() const { return d->node; } diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h index 9bbddc6d1d..63501952f6 100644 --- a/libs/libkis/Node.h +++ b/libs/libkis/Node.h @@ -1,301 +1,348 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBKIS_NODE_H #define LIBKIS_NODE_H #include #include #include "kritalibkis_export.h" #include "libkis.h" /** * Node */ class KRITALIBKIS_EXPORT Node : public QObject { Q_OBJECT Q_DISABLE_COPY(Node) public: explicit Node(KisImageSP image, KisNodeSP node, QObject *parent = 0); virtual ~Node(); public Q_SLOTS: /** * @brief alphaLocked checks whether the node is a paint layer and returns whether it is alpha locked * @return whether the paint layer is alpha locked, or false if the node is not a paint layer */ bool alphaLocked() const; /** * @brief setAlphaLocked set the layer to value if the the node is paint layer. */ void setAlphaLocked(bool value); /** * @return the blending mode of the layer. The values of the blending modes are defined in @see KoCompositeOpRegistry.h */ QString blendingMode() const; /** * @brief setBlendingMode set the blending mode of the node to the given value * @param value one of the string values from @see KoCompositeOpRegistry.h */ void setBlendingMode(QString value); /** * @brief channels creates a list of Channel objects that can be used individually to * show or hide certain channels, and to retrieve the contents of each channel in a * node separately. * * Only layers have channels, masks do not, and calling channels on a Node that is a mask * will return an empty list. * * @return the list of channels ordered in by position of the channels in pixel position */ QList channels() const; /** * Return a list of child nodes of the current node. The nodes are ordered from the bottommost up. * The function is not recursive. */ QList childNodes() const; + /** + * @brief addChildNode + * @param child + * @param above + */ + void addChildNode(Node *child, Node *above); + /** * @brief setChildNodes this replaces the existing set of child nodes with the new set. * @param value */ void setChildNodes(QList value); /** * colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return the color depth. */ QString colorDepth() const; /** * @brief colorModel retrieve the current color model of this document: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @return the internal color model string. */ QString colorModel() const; /** * @return the name of the current color profile */ QString colorProfile() const; /** * @brief setColorProfile set the color profile of the image to the given profile. The profile has to * be registered with krita and be compatible with the current color model and depth; the image data * is not converted. * @param colorProfile */ void setColorProfile(const QString &colorProfile); /** * @brief setColorSpace convert the node to the given colorspace * @param colorModel A string describing the color model of the node: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param colorProfile a valid color profile for this color model and color depth combinatiojn. */ void setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); QString colorLabel() const; void setColorLabel(QString value); bool inheritAlpha() const; void setInheritAlpha(bool value); bool locked() const; void setLocked(bool value); QString name() const; void setName(QString value); int opacity() const; void setOpacity(int value); Node* parentNode() const; void setParentNode(Node* value); QString type() const; void setType(QString value); bool visible() const; void setVisible(bool value); InfoObject* metaDataInfo() const; void setMetaDataInfo(InfoObject* value); Generator* generator() const; void setGenerator(Generator* value); Filter* filter() const; void setFilter(Filter* value); Transformation* transformation() const; void setTransformation(Transformation* value); - /** - * Get the embedded selection object. This does not return the local selection mask, - * which is a child node, but the embedded selection for filter and generator layers - * and for masks. - */ - Selection* selection() const; - void setSelection(Selection* value); - QString fileName() const; void setFileName(QString value); /** - * @brief pixelData reads the given rectangle from the Node's projection (that is, what the node + * @brief pixelData reads the given rectangle from the Node's paintable pixels, if those + * exist, and returns it as a byte array. The pixel data starts top-left, and is ordered row-first. + * + * The byte array can be interpreted as follows: 8 bits images have one byte per channel, + * and as many bytes as there are channels. 16 bits integer images have two bytes per channel, + * representing an unsigned short. 16 bits float images have two bytes per channel, representing + * a half, or 16 bits float. 32 bits float images have four bytes per channel, representing a + * float. + * + * You can read outside the node boundaries; those pixels will be transparent black. + * + * The order of channels is: + * + *
    + *
  • Integer RGBA: Blue, Green, Red, Alpha + *
  • Float RGBA: Red, Green, Blue, Alpha + *
  • GrayA: Gray, Alpha + *
  • Selection: selectedness + *
  • LabA: L, a, b, Alpha + *
  • CMYKA: Cyan, Magenta, Yellow, Key, Alpha + *
  • XYZA: X, Y, Z, A + *
  • YCbCrA: Y, Cb, Cr, Alpha + *
+ * + * The byte array is a copy of the original node data. In Python, you can use bytes, bytearray + * and the struct module to interpret the data and construct, for instance, a Pillow Image object. + * + * If you read the pixeldata of a mask, a filter or generator layer, you get the selection bytes, + * which is one channel with values in the range from 0..255. + * + * If you want to change the pixels of a node you can write the pixels back after manipulation + * with setPixelData(). This will only succeed on nodes with writable pixel data, e.g not on groups + * or file layers. + * + * @param x x position from where to start reading + * @param y y position from where to start reading + * @param w row length to read + * @param h number of rows to read + * @return a QByteArray with the pixel data. The byte array may be empty. + + */ + QByteArray pixelData(int x, int y, int w, int h) const; + + /** + * @brief projectionPixelData reads the given rectangle from the Node's projection (that is, what the node * looks like after all sub-Nodes (like layers in a group or masks on a layer) have been applied, * and returns it as a byte array. The pixel data starts top-left, and is ordered row-first. * * The byte array can be interpreted as follows: 8 bits images have one byte per channel, * and as many bytes as there are channels. 16 bits integer images have two bytes per channel, * representing an unsigned short. 16 bits float images have two bytes per channel, representing * a half, or 16 bits float. 32 bits float images have four bytes per channel, representing a * float. * * You can read outside the node boundaries; those pixels will be transparent black. * * The order of channels is: * *
    *
  • Integer RGBA: Blue, Green, Red, Alpha *
  • Float RGBA: Red, Green, Blue, Alpha *
  • GrayA: Gray, Alpha *
  • Selection: selectedness *
  • LabA: L, a, b, Alpha *
  • CMYKA: Cyan, Magenta, Yellow, Key, Alpha *
  • XYZA: X, Y, Z, A *
  • YCbCrA: Y, Cb, Cr, Alpha *
* * The byte array is a copy of the original node data. In Python, you can use bytes, bytearray * and the struct module to interpret the data and construct, for instance, a Pillow Image object. * * If you read the projection of a mask, you get the selection bytes, which is one channel with - * values in the range from 0..255. To read the selection mask of a filter layer or generator layer - * first get the Node's Selection object and read its pixel data. + * values in the range from 0..255. * * If you want to change the pixels of a node you can write the pixels back after manipulation * with setPixelData(). This will only succeed on nodes with writable pixel data, e.g not on groups * or file layers. * * @param x x position from where to start reading * @param y y position from where to start reading * @param w row length to read * @param h number of rows to read * @return a QByteArray with the pixel data. The byte array may be empty. */ - QByteArray pixelData(int x, int y, int w, int h) const; + QByteArray projectionPixelData(int x, int y, int w, int h) const; /** * @brief setPixelData writes the given bytes, of which there must be enough, into the * Node, if the Node has writable pixel data: * *
    *
  • paint layer: the layer's original pixels are overwritten *
  • filter layer, generator layer, any mask: the embedded selection's pixels are overwritten. * Note: for these *
* * File layers, Group layers, Clone layers cannot be written to. Calling setPixelData on * those layer types will silently do nothing. * * @param value the byte array representing the pixels. There must be enough bytes available. * Krita will take the raw pointer from the QByteArray and start reading, not stopping before * (number of channels * size of channel * w * h) bytes are read. * * @param x the x position to start writing from * @param y the y position to start writing from * @param w the width of each row * @param h the number of rows to write */ void setPixelData(QByteArray value, int x, int y, int w, int h); QRect bounds() const; void move(int x, int y); void moveToParent(Node *parent); void remove(); + /** + * @brief duplicate + * @return + */; Node* duplicate(); /** * @brief save exports the given node with this filename. The extension of the filename determins the filetype. * @param filename the filename including extension * @param xRes the horizontal resolution in pixels per pt (there are 72 pts in an inch) * @param yRes the horizontal resolution in pixels per pt (there are 72 pts in an inch) * @return true if saving succeeded, false if it failed. */ bool save(const QString &filename, double xRes, double yRes); private: friend class Filter; friend class Document; + friend class Selection; /** * @brief paintDevice gives access to the internal paint device of this Node * @return the paintdevice or 0 if the node does not have an editable paint device. */ KisPaintDeviceSP paintDevice() const; KisImageSP image() const; KisNodeSP node() const; struct Private; Private *const d; }; #endif // LIBKIS_NODE_H diff --git a/libs/libkis/Resource.cpp b/libs/libkis/Resource.cpp index ecb998984e..266b9da0df 100644 --- a/libs/libkis/Resource.cpp +++ b/libs/libkis/Resource.cpp @@ -1,68 +1,74 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Resource.h" struct Resource::Private { Private() {} }; Resource::Resource(QObject *parent) : QObject(parent) , d(new Private) { } Resource::~Resource() { delete d; } QString Resource::type() const { + // UNIMPLEMENTED return QString(); } void Resource::setType(QString value) { + // UNIMPLEMENTED } QString Resource::name() const { + // UNIMPLEMENTED return QString(); } void Resource::setName(QString value) { + // UNIMPLEMENTED } QString Resource::filename() const { + // UNIMPLEMENTED return QString(); } void Resource::setFilename(QString value) { + // UNIMPLEMENTED } diff --git a/libs/libkis/Selection.cpp b/libs/libkis/Selection.cpp index 16fddd34d2..cea57e5fc2 100644 --- a/libs/libkis/Selection.cpp +++ b/libs/libkis/Selection.cpp @@ -1,154 +1,241 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Selection.h" #include #include #include +#include #include +#include + struct Selection::Private { Private() {} KisSelectionSP selection; }; Selection::Selection(KisSelectionSP selection, QObject *parent) : QObject(parent) , d(new Private) { d->selection = selection; } Selection::Selection(QObject *parent) : QObject(parent) , d(new Private) { d->selection = new KisSelection(); } Selection::~Selection() { delete d; } int Selection::width() const { - return 0; + if (!d->selection) return 0; + return d->selection->selectedExactRect().width(); } int Selection::height() const { - return 0; + if (!d->selection) return 0; + return d->selection->selectedExactRect().height(); } int Selection::x() const { - return 0; + if (!d->selection) return 0; + return d->selection->x(); } int Selection::y() const { - return 0; + if (!d->selection) return 0; + return d->selection->y(); } void Selection::move(int x, int y) { - + if (!d->selection) return; + d->selection->pixelSelection()->moveTo(QPoint(x, y)); } void Selection::clear() { + if (!d->selection) return; + d->selection->clear(); } void Selection::contract(int value) { + if (!d->selection) return; + d->selection->pixelSelection()->select(QRect(x(), y(), width() - value, height() - value)); } void Selection::cut(Node* node) { + // UNIMPLEMENTED } -void Selection::paste(Node *source, Node*destination) +void Selection::paste(Node *source, Node *destination) { + // UNIMPLEMENTED +} +void Selection::erode() +{ + if (!d->selection) return; + KisErodeSelectionFilter esf; + QRect rc = esf.changeRect(d->selection->selectedExactRect()); + esf.process(d->selection->pixelSelection(), rc); } -void Selection::deselect() +void Selection::dilate() { + if (!d->selection) return; + KisDilateSelectionFilter dsf; + QRect rc = dsf.changeRect(d->selection->selectedExactRect()); + dsf.process(d->selection->pixelSelection(), rc); } -void Selection::expand(int value) +void Selection::border(int xRadius, int yRadius) { + if (!d->selection) return; + KisBorderSelectionFilter sf(xRadius, yRadius); + QRect rc = sf.changeRect(d->selection->selectedExactRect()); + sf.process(d->selection->pixelSelection(), rc); } -void Selection::feather(int value) +void Selection::feather(int radius) { + if (!d->selection) return; + KisFeatherSelectionFilter fsf(radius); + QRect rc = fsf.changeRect(d->selection->selectedExactRect()); + fsf.process(d->selection->pixelSelection(), rc); } -void Selection::fill(Node* node) +void Selection::grow(int xradius, int yradius) { + if (!d->selection) return; + KisGrowSelectionFilter gsf(xradius, yradius); + QRect rc = gsf.changeRect(d->selection->selectedExactRect()); + gsf.process(d->selection->pixelSelection(), rc); +} + + +void Selection::shrink(int xRadius, int yRadius, bool edgeLock) +{ + if (!d->selection) return; + KisShrinkSelectionFilter sf(xRadius, yRadius, edgeLock); + QRect rc = sf.changeRect(d->selection->selectedExactRect()); + sf.process(d->selection->pixelSelection(), rc); } -void Selection::grow(int value) +void Selection::smooth() { + if (!d->selection) return; + KisSmoothSelectionFilter sf; + QRect rc = sf.changeRect(d->selection->selectedExactRect()); + sf.process(d->selection->pixelSelection(), rc); } + void Selection::invert() { + if (!d->selection) return; + KisInvertSelectionFilter sf; + QRect rc = sf.changeRect(d->selection->selectedExactRect()); + sf.process(d->selection->pixelSelection(), rc); } void Selection::resize(int w, int h) { + if (!d->selection) return; + d->selection->pixelSelection()->select(QRect(x(), y(), w, h)); +} + +void Selection::select(int x, int y, int w, int h, int value) +{ + if (!d->selection) return; + d->selection->pixelSelection()->select(QRect(x, y, w, h), value); } -void Selection::rotate(int degrees) +void Selection::selectAll(Node *node, int value) { + if (!d->selection) return; + d->selection->pixelSelection()->select(node->node()->exactBounds(), value); } -void Selection::select(int x, int y, int w, int h, int value) +void Selection::replace(Selection *selection) { + if (!d->selection) return; + d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_REPLACE); } -void Selection::selectAll(Node *node) +void Selection::add(Selection *selection) { + if (!d->selection) return; + d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_ADD); } +void Selection::subtract(Selection *selection) +{ + if (!d->selection) return; + d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_SUBTRACT); +} + +void Selection::intersect(Selection *selection) +{ + if (!d->selection) return; + d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_INTERSECT); +} + + QByteArray Selection::pixelData(int x, int y, int w, int h) const { QByteArray ba; if (!d->selection) return ba; KisPaintDeviceSP dev = d->selection->projection(); quint8 *data = new quint8[w * h]; dev->readBytes(data, x, y, w, h); ba = QByteArray((const char*)data, (int)(w * h)); delete[] data; return ba; } void Selection::setPixelData(QByteArray value, int x, int y, int w, int h) { if (!d->selection) return; KisPixelSelectionSP dev = d->selection->pixelSelection(); if (!dev) return; dev->writeBytes((const quint8*)value.constData(), x, y, w, h); } +KisSelectionSP Selection::selection() const +{ + return d->selection; +} + diff --git a/libs/libkis/Selection.h b/libs/libkis/Selection.h index 817c3b2cb5..257a28e434 100644 --- a/libs/libkis/Selection.h +++ b/libs/libkis/Selection.h @@ -1,118 +1,132 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBKIS_SELECTION_H #define LIBKIS_SELECTION_H #include #include "kritalibkis_export.h" #include "libkis.h" #include /** * Selection */ class KRITALIBKIS_EXPORT Selection : public QObject { Q_OBJECT public: Selection(KisSelectionSP selection, QObject *parent = 0); explicit Selection(QObject *parent = 0); virtual ~Selection(); public Q_SLOTS: int width() const; int height() const; int x() const; int y() const; void move(int x, int y); void clear(); void contract(int value); void cut(Node* node); - void paste(Node *source, Node*destination); + void paste(Node *source, Node* destination); - void deselect(); + void erode(); - void expand(int value); + void dilate(); - void feather(int value); + void border(int xRadius, int yRadius); - void fill(Node* node); + void feather(int radius); - void grow(int value); + void grow(int xradius, int yradius); + + void shrink(int xRadius, int yRadius, bool edgeLock); + + void smooth(); void invert(); void resize(int w, int h); - void rotate(int degrees); - void select(int x, int y, int w, int h, int value); - void selectAll(Node *node); + void selectAll(Node *node, int value); + + void replace(Selection *selection); + + void add(Selection *selection); + + void subtract(Selection *selection); + + void intersect(Selection *selection); /** * @brief pixelData reads the given rectangle from the Selection's mask and returns it as a * byte array. The pixel data starts top-left, and is ordered row-first. * * The byte array will contain one byte for every pixel, representing the selectedness. 0 * is totally unselected, 255 is fully selected. * * You can read outside the Selection's boundaries; those pixels will be unselected. * * The byte array is a copy of the original selection data. * @param x x position from where to start reading * @param y y position from where to start reading * @param w row length to read * @param h number of rows to read * @return a QByteArray with the pixel data. The byte array may be empty. */ QByteArray pixelData(int x, int y, int w, int h) const; /** * @brief setPixelData writes the given bytes, of which there must be enough, into the * Selection. * * @param value the byte array representing the pixels. There must be enough bytes available. * Krita will take the raw pointer from the QByteArray and start reading, not stopping before * (w * h) bytes are read. * * @param x the x position to start writing from * @param y the y position to start writing from * @param w the width of each row * @param h the number of rows to write */ void setPixelData(QByteArray value, int x, int y, int w, int h); private: + friend class Document; + + KisSelectionSP selection() const; + struct Private; Private *const d; }; #endif // LIBKIS_SELECTION_H diff --git a/libs/libkis/Transformation.cpp b/libs/libkis/Transformation.cpp index f250ac9090..5c51f62885 100644 --- a/libs/libkis/Transformation.cpp +++ b/libs/libkis/Transformation.cpp @@ -1,48 +1,50 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Transformation.h" struct Transformation::Private { Private() {} }; Transformation::Transformation(QObject *parent) : QObject(parent) , d(new Private) { } Transformation::~Transformation() { delete d; } QString Transformation::definition() const { + // UNIMPLEMENTED return QString(); } void Transformation::setDefinition(QString value) { + // UNIMPLEMENTED } diff --git a/libs/libkis/View.cpp b/libs/libkis/View.cpp index d73699bcb6..a05c6094d8 100644 --- a/libs/libkis/View.cpp +++ b/libs/libkis/View.cpp @@ -1,95 +1,96 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "View.h" #include #include +#include +#include #include #include #include #include "Document.h" #include "Canvas.h" #include "Window.h" struct View::Private { Private() {} QPointer view; }; View::View(KisView* view, QObject *parent) : QObject(parent) , d(new Private) { d->view = view; } View::~View() { delete d; } Window* View::window() const { if (!d->view) return 0; KisMainWindow *mainwin = d->view->mainWindow(); Window *win = new Window(mainwin); return win; } Document* View::document() const { if (!d->view) return 0; Document *doc = new Document(d->view->document()); return doc; } bool View::visible() const { if (!d->view) return false; return d->view->isVisible(); } void View::setVisible() { if (!d->view) return; KisMainWindow *mainwin = d->view->mainWindow(); mainwin->setActiveView(d->view); mainwin->subWindowActivated(); } - Canvas* View::canvas() const { if (!d->view) return 0; Canvas *c = new Canvas(d->view->canvasBase()); return c; } void View::close(bool confirm) { if (!d->view) return; } KisView *View::view() { return d->view; } diff --git a/libs/ui/actions/kis_selection_action_factories.cpp b/libs/ui/actions/kis_selection_action_factories.cpp index 2000e51eb8..3882944334 100644 --- a/libs/ui/actions/kis_selection_action_factories.cpp +++ b/libs/ui/actions/kis_selection_action_factories.cpp @@ -1,641 +1,641 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_selection_action_factories.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisViewManager.h" #include "kis_canvas_resource_provider.h" #include "kis_clipboard.h" #include "kis_pixel_selection.h" #include "kis_paint_layer.h" #include "kis_image.h" #include "kis_image_barrier_locker.h" #include "kis_fill_painter.h" #include "kis_transaction.h" #include "kis_iterator_ng.h" #include "kis_processing_applicator.h" #include "kis_group_layer.h" #include "commands/kis_selection_commands.h" #include "commands/kis_image_layer_add_command.h" #include "kis_tool_proxy.h" #include "kis_canvas2.h" #include "kis_canvas_controller.h" #include "kis_selection_manager.h" #include "kis_transaction_based_command.h" #include "kis_selection_filters.h" #include "kis_shape_selection.h" #include "KisPart.h" #include "kis_shape_layer.h" #include #include #include #include "kis_canvas_resource_provider.h" #include "kis_figure_painting_tool_helper.h" namespace ActionHelper { void copyFromDevice(KisViewManager *view, KisPaintDeviceSP device, bool makeSharpClip = false) { KisImageWSP image = view->image(); if (!image) return; KisSelectionSP selection = view->selection(); QRect rc = (selection) ? selection->selectedExactRect() : image->bounds(); KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace()); Q_CHECK_PTR(clip); const KoColorSpace *cs = clip->colorSpace(); // TODO if the source is linked... copy from all linked layers?!? // Copy image data KisPainter::copyAreaOptimized(QPoint(), device, clip, rc); if (selection) { // Apply selection mask. KisPaintDeviceSP selectionProjection = selection->projection(); KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width()); KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width()); const KoColorSpace *selCs = selection->projection()->colorSpace(); for (qint32 y = 0; y < rc.height(); y++) { for (qint32 x = 0; x < rc.width(); x++) { /** * Sharp method is an exact reverse of COMPOSITE_OVER * so if you cover the cut/copied piece over its source * you get an exactly the same image without any seams */ if (makeSharpClip) { qreal dstAlpha = cs->opacityF(layerIt->rawData()); qreal sel = selCs->opacityF(selectionIt->oldRawData()); qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha); float mask = newAlpha / dstAlpha; cs->applyAlphaNormedFloatMask(layerIt->rawData(), &mask, 1); } else { cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1); } layerIt->nextPixel(); selectionIt->nextPixel(); } layerIt->nextRow(); selectionIt->nextRow(); } } KisClipboard::instance()->setClip(clip, rc.topLeft()); } } void KisSelectAllActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Select All")); if (!image->globalSelection()) { ap->applyCommand(new KisSetEmptyGlobalSelectionCommand(image), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); } struct SelectAll : public KisTransactionBasedCommand { SelectAll(KisImageSP image) : m_image(image) {} KisImageSP m_image; KUndo2Command* paint() override { KisSelectionSP selection = m_image->globalSelection(); KisSelectionTransaction transaction(selection->pixelSelection()); selection->pixelSelection()->select(m_image->bounds()); return transaction.endAndTake(); } }; ap->applyCommand(new SelectAll(image), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisDeselectActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KUndo2Command *cmd = new KisDeselectGlobalSelectionCommand(image); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisReselectActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KUndo2Command *cmd = new KisReselectGlobalSelectionCommand(image); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisFillActionFactory::run(const QString &fillSource, KisViewManager *view) { KisNodeSP node = view->activeNode(); if (!node || !node->hasEditablePaintDevice()) return; KisSelectionSP selection = view->selection(); QRect selectedRect = selection ? selection->selectedRect() : view->image()->bounds(); Q_UNUSED(selectedRect); KisPaintDeviceSP filled = node->paintDevice()->createCompositionSourceDevice(); Q_UNUSED(filled); bool usePattern = false; bool useBgColor = false; if (fillSource.contains("pattern")) { usePattern = true; } else if (fillSource.contains("bg")) { useBgColor = true; } KisProcessingApplicator applicator(view->image(), node, KisProcessingApplicator::NONE, KisImageSignalVector() << ModifiedSignal, kundo2_i18n("Flood Fill Layer")); KisResourcesSnapshotSP resources = new KisResourcesSnapshot(view->image(), node, view->resourceProvider()->resourceManager()); if (!fillSource.contains("opacity")) { resources->setOpacity(1.0); } KisProcessingVisitorSP visitor = new FillProcessingVisitor(QPoint(0, 0), // start position selection, resources, false, // fast mode usePattern, true, // fill only selection, 0, // feathering radius 0, // sizemod 80, // threshold, false, // unmerged useBgColor); applicator.applyVisitor(visitor, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); applicator.end(); } void KisClearActionFactory::run(KisViewManager *view) { // XXX: "Add saving of XML data for Clear action" view->canvasBase()->toolProxy()->deleteSelection(); } void KisImageResizeToSelectionActionFactory::run(KisViewManager *view) { // XXX: "Add saving of XML data for Image Resize To Selection action" KisSelectionSP selection = view->selection(); if (!selection) return; view->image()->cropImage(selection->selectedExactRect()); } void KisCutCopyActionFactory::run(bool willCut, bool makeSharpClip, KisViewManager *view) { KisImageSP image = view->image(); if (!image) return; bool haveShapesSelected = view->selectionManager()->haveShapesSelected(); if (haveShapesSelected) { // XXX: "Add saving of XML data for Cut/Copy of shapes" KisImageBarrierLocker locker(image); if (willCut) { view->canvasBase()->toolProxy()->cut(); } else { view->canvasBase()->toolProxy()->copy(); } } else { KisNodeSP node = view->activeNode(); if (!node) return; KisSelectionSP selection = view->selection(); if (selection.isNull()) return; { KisImageBarrierLocker locker(image); KisPaintDeviceSP dev = node->paintDevice(); if (!dev) { dev = node->projection(); } if (!dev) { view->showFloatingMessage( i18nc("floating message when cannot copy from a node", "Cannot copy pixels from this type of layer "), QIcon(), 3000, KisFloatingMessage::Medium); return; } if (dev->exactBounds().isEmpty()) { view->showFloatingMessage( i18nc("floating message when copying empty selection", "Selection is empty: no pixels were copied "), QIcon(), 3000, KisFloatingMessage::Medium); return; } ActionHelper::copyFromDevice(view, dev, makeSharpClip); } if (willCut) { KUndo2Command *command = 0; if (willCut && node->hasEditablePaintDevice()) { struct ClearSelection : public KisTransactionBasedCommand { ClearSelection(KisNodeSP node, KisSelectionSP sel) : m_node(node), m_sel(sel) {} KisNodeSP m_node; KisSelectionSP m_sel; KUndo2Command* paint() override { KisSelectionSP cutSelection = m_sel; // Shrinking the cutting area was previously used // for getting seamless cut-paste. Now we use makeSharpClip // instead. // QRect originalRect = cutSelection->selectedExactRect(); // static const int preciseSelectionThreshold = 16; // // if (originalRect.width() > preciseSelectionThreshold || // originalRect.height() > preciseSelectionThreshold) { // cutSelection = new KisSelection(*m_sel); // delete cutSelection->flatten(); // // KisSelectionFilter* filter = new KisShrinkSelectionFilter(1, 1, false); // // QRect processingRect = filter->changeRect(originalRect); // filter->process(cutSelection->pixelSelection(), processingRect); // } KisTransaction transaction(m_node->paintDevice()); m_node->paintDevice()->clearSelection(cutSelection); m_node->setDirty(cutSelection->selectedRect()); return transaction.endAndTake(); } }; command = new ClearSelection(node, selection); } KUndo2MagicString actionName = willCut ? kundo2_i18n("Cut") : kundo2_i18n("Copy"); KisProcessingApplicator *ap = beginAction(view, actionName); if (command) { ap->applyCommand(command, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL); } KisOperationConfiguration config(id()); config.setProperty("will-cut", willCut); endAction(ap, config.toXML()); } } } void KisCopyMergedActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; if (!view->blockUntillOperationsFinished(image)) return; image->barrierLock(); KisPaintDeviceSP dev = image->root()->projection(); ActionHelper::copyFromDevice(view, dev); image->unlock(); KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Copy Merged")); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisPasteActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KisPaintDeviceSP clip = KisClipboard::instance()->clip(image->bounds(), true); if (clip) { KisPaintLayer *newLayer = new KisPaintLayer(image.data(), image->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE_U8, clip); KisNodeSP aboveNode = view->activeLayer(); KisNodeSP parentNode = aboveNode ? aboveNode->parent() : image->root(); KUndo2Command *cmd = new KisImageLayerAddCommand(image, newLayer, parentNode, aboveNode); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL); endAction(ap, KisOperationConfiguration(id()).toXML()); } else { // XXX: "Add saving of XML data for Paste of shapes" view->canvasBase()->toolProxy()->paste(); } } void KisPasteNewActionFactory::run(KisViewManager *viewManager) { Q_UNUSED(viewManager); KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true); if (!clip) return; QRect rect = clip->exactBounds(); if (rect.isEmpty()) return; KisDocument *doc = KisPart::instance()->createDocument(); KisImageSP image = new KisImage(doc->createUndoStore(), rect.width(), rect.height(), clip->colorSpace(), i18n("Pasted")); KisPaintLayerSP layer = new KisPaintLayer(image.data(), image->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE_U8, clip->colorSpace()); KisPainter::copyAreaOptimized(QPoint(), clip, layer->paintDevice(), rect); image->addNode(layer.data(), image->rootLayer()); doc->setCurrentImage(image); KisPart::instance()->addDocument(doc); KisMainWindow *win = viewManager->mainWindow(); win->addViewAndNotifyLoadingCompleted(doc); } -void KisInvertSelectionOperaton::runFromXML(KisViewManager* view, const KisOperationConfiguration& config) +void KisInvertSelectionOperation::runFromXML(KisViewManager* view, const KisOperationConfiguration& config) { KisSelectionFilter* filter = new KisInvertSelectionFilter(); runFilter(filter, view, config); } void KisSelectionToVectorActionFactory::run(KisViewManager *view) { KisSelectionSP selection = view->selection(); if (selection->hasShapeSelection() || !selection->outlineCacheValid()) { return; } QPainterPath selectionOutline = selection->outlineCache(); QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform(); KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline)); shape->setShapeId(KoPathShapeId); /** * Mark a shape that it belongs to a shape selection */ if(!shape->userData()) { shape->setUserData(new KisShapeSelectionMarker); } KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Convert to Vector Selection")); ap->applyCommand(view->canvasBase()->shapeController()->addShape(shape), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } class KisShapeSelectionPaste : public KoOdfPaste { public: KisShapeSelectionPaste(KisViewManager* view) : m_view(view) { } ~KisShapeSelectionPaste() override { } bool process(const KoXmlElement & body, KoOdfReadStore & odfStore) override { KoOdfLoadingContext loadingContext(odfStore.styles(), odfStore.store()); KoShapeLoadingContext context(loadingContext, m_view->canvasBase()->shapeController()->resourceManager()); KoXmlElement child; QList shapes; forEachElement(child, body) { KoShape * shape = KoShapeRegistry::instance()->createShapeFromOdf(child, context); if (shape) { shapes.append(shape); } } if (!shapes.isEmpty()) { KisSelectionToolHelper helper(m_view->canvasBase(), kundo2_i18n("Convert shapes to vector selection")); helper.addSelectionShapes(shapes); } return true; } private: KisViewManager* m_view; }; void KisShapesToVectorSelectionActionFactory::run(KisViewManager* view) { QList shapes = view->canvasBase()->shapeManager()->selection()->selectedShapes(); KoShapeOdfSaveHelper saveHelper(shapes); KoDrag drag; drag.setOdf(KoOdf::mimeType(KoOdf::Text), saveHelper); QMimeData* mimeData = drag.mimeData(); Q_ASSERT(mimeData->hasFormat(KoOdf::mimeType(KoOdf::Text))); KisShapeSelectionPaste paste(view); paste.paste(KoOdf::Text, mimeData); } void KisSelectionToShapeActionFactory::run(KisViewManager *view) { KisSelectionSP selection = view->selection(); if (!selection->outlineCacheValid()) { return; } QPainterPath selectionOutline = selection->outlineCache(); QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform(); KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline)); shape->setShapeId(KoPathShapeId); KoColor fgColor = view->canvasBase()->resourceManager()->resource(KoCanvasResourceManager::ForegroundColor).value(); KoShapeStroke* border = new KoShapeStroke(1.0, fgColor.toQColor()); shape->setStroke(border); view->document()->shapeController()->addShape(shape); } void KisStrokeSelectionActionFactory::run(KisViewManager *view, StrokeSelectionOptions params) { KisImageWSP image = view->image(); if (!image) { return; } KisSelectionSP selection = view->selection(); if (!selection) { return; } int size = params.lineSize; KisPixelSelectionSP pixelSelection = selection->projection(); if (!pixelSelection->outlineCacheValid()) { pixelSelection->recalculateOutlineCache(); } QPainterPath outline = pixelSelection->outlineCache(); QColor color = params.color.toQColor(); KisNodeSP currentNode = view->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentKritaNode).value(); if (!currentNode->inherits("KisShapeLayer") && currentNode->childCount() == 0) { KoCanvasResourceManager * rManager = view->resourceProvider()->resourceManager(); KisPainter::StrokeStyle strokeStyle = KisPainter::StrokeStyleBrush; KisPainter::FillStyle fillStyle = params.fillStyle(); KisFigurePaintingToolHelper helper(kundo2_i18n("Draw Polyline"), image, currentNode, rManager , strokeStyle, fillStyle); helper.setFGColorOverride(params.color); helper.setSelectionOverride(0); QPen pen(Qt::red, size); pen.setJoinStyle(Qt::RoundJoin); if (fillStyle != KisPainter::FillStyleNone) { helper.paintPainterPathQPenFill(outline, pen, params.fillColor); } else { helper.paintPainterPathQPen(outline, pen, params.fillColor); } } else { QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform(); KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(outline)); shape->setShapeId(KoPathShapeId); KoShapeStroke* border = new KoShapeStroke(size, color); shape->setStroke(border); view->document()->shapeController()->addShape(shape); } image->setModified(); } void KisStrokeBrushSelectionActionFactory::run(KisViewManager *view, StrokeSelectionOptions params) { KisImageWSP image = view->image(); if (!image) { return; } KisSelectionSP selection = view->selection(); if (!selection) { return; } KisPixelSelectionSP pixelSelection = selection->projection(); if (!pixelSelection->outlineCacheValid()) { pixelSelection->recalculateOutlineCache(); } KisNodeSP currentNode = view->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentKritaNode).value(); if (!currentNode->inherits("KisShapeLayer") && currentNode->childCount() == 0) { KoCanvasResourceManager * rManager = view->resourceProvider()->resourceManager(); QPainterPath outline = pixelSelection->outlineCache(); KisPainter::StrokeStyle strokeStyle = KisPainter::StrokeStyleBrush; KisPainter::FillStyle fillStyle = KisPainter::FillStyleNone; KoColor color = params.color; KisFigurePaintingToolHelper helper(kundo2_i18n("Draw Polyline"), image, currentNode, rManager , strokeStyle, fillStyle); helper.setFGColorOverride(color); helper.setSelectionOverride(0); helper.paintPainterPath(outline); image->setModified(); } } diff --git a/libs/ui/actions/kis_selection_action_factories.h b/libs/ui/actions/kis_selection_action_factories.h index d5a285805d..b548a6486d 100644 --- a/libs/ui/actions/kis_selection_action_factories.h +++ b/libs/ui/actions/kis_selection_action_factories.h @@ -1,134 +1,134 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SELECTION_ACTION_FACTORIES_H #define __KIS_SELECTION_ACTION_FACTORIES_H #include "operations/kis_operation.h" #include "operations/kis_operation_configuration.h" #include "operations/kis_filter_selection_operation.h" #include "dialogs/kis_dlg_stroke_selection_properties.h" class KRITAUI_EXPORT KisNoParameterActionFactory : public KisOperation { public: KisNoParameterActionFactory(const QString &id) : KisOperation(id) {} void runFromXML(KisViewManager *view, const KisOperationConfiguration &config) { Q_UNUSED(config); run(view); } virtual void run(KisViewManager *view) = 0; }; struct KRITAUI_EXPORT KisSelectAllActionFactory : public KisNoParameterActionFactory { KisSelectAllActionFactory() : KisNoParameterActionFactory("select-all-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisDeselectActionFactory : public KisNoParameterActionFactory { KisDeselectActionFactory() : KisNoParameterActionFactory("deselect-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisReselectActionFactory : public KisNoParameterActionFactory { KisReselectActionFactory() : KisNoParameterActionFactory("reselect-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisFillActionFactory : public KisOperation { KisFillActionFactory() : KisOperation("fill-ui-action") {} void runFromXML(KisViewManager *view, const KisOperationConfiguration &config) { run(config.getString("fill-source", "fg"), view); } /** * \p fillColor may be one of three variants: * - "fg" --- foreground color * - "bg" --- background color * - "pattern" --- current pattern */ void run(const QString &fillSource, KisViewManager *view); }; struct KRITAUI_EXPORT KisClearActionFactory : public KisNoParameterActionFactory { KisClearActionFactory() : KisNoParameterActionFactory("clear-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisImageResizeToSelectionActionFactory : public KisNoParameterActionFactory { KisImageResizeToSelectionActionFactory() : KisNoParameterActionFactory("resize-to-selection-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisCutCopyActionFactory : public KisOperation { KisCutCopyActionFactory() : KisOperation("cut-copy-ui-action") {} void runFromXML(KisViewManager *view, const KisOperationConfiguration &config) { run(config.getBool("will-cut", false), config.getBool("use-sharp-clip", false), view); } void run(bool willCut, bool makeSharpClip, KisViewManager *view); }; struct KRITAUI_EXPORT KisCopyMergedActionFactory : public KisNoParameterActionFactory { KisCopyMergedActionFactory() : KisNoParameterActionFactory("copy-merged-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisPasteActionFactory : public KisNoParameterActionFactory { KisPasteActionFactory() : KisNoParameterActionFactory("paste-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisPasteNewActionFactory : public KisNoParameterActionFactory { KisPasteNewActionFactory() : KisNoParameterActionFactory("paste-new-ui-action") {} void run(KisViewManager *view); }; -struct KisInvertSelectionOperaton : public KisFilterSelectionOperation { - KisInvertSelectionOperaton() : KisFilterSelectionOperation("invertselection") {} +struct KisInvertSelectionOperation : public KisFilterSelectionOperation { + KisInvertSelectionOperation() : KisFilterSelectionOperation("invertselection") {} void runFromXML(KisViewManager *view, const KisOperationConfiguration &config); }; struct KRITAUI_EXPORT KisSelectionToVectorActionFactory : public KisNoParameterActionFactory { KisSelectionToVectorActionFactory() : KisNoParameterActionFactory("paste-new-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisShapesToVectorSelectionActionFactory : public KisNoParameterActionFactory { KisShapesToVectorSelectionActionFactory() : KisNoParameterActionFactory("paste-new-ui-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisSelectionToShapeActionFactory : public KisNoParameterActionFactory { KisSelectionToShapeActionFactory() : KisNoParameterActionFactory("selection-to-shape-action") {} void run(KisViewManager *view); }; struct KRITAUI_EXPORT KisStrokeSelectionActionFactory : public KisOperation { KisStrokeSelectionActionFactory() : KisOperation("selection-to-shape-action") {} void run(KisViewManager *view, StrokeSelectionOptions params); }; struct KRITAUI_EXPORT KisStrokeBrushSelectionActionFactory : public KisOperation { KisStrokeBrushSelectionActionFactory() : KisOperation("selection-to-shape-action") {} void run(KisViewManager *view, StrokeSelectionOptions params); }; #endif /* __KIS_SELECTION_ACTION_FACTORIES_H */ diff --git a/libs/ui/dialogs/kis_dlg_adj_layer_props.cc b/libs/ui/dialogs/kis_dlg_adj_layer_props.cc index 35509caf68..94db4175e7 100644 --- a/libs/ui/dialogs/kis_dlg_adj_layer_props.cc +++ b/libs/ui/dialogs/kis_dlg_adj_layer_props.cc @@ -1,144 +1,144 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_adj_layer_props.h" #include #include #include #include #include #include "kis_config_widget.h" #include "kis_transaction.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_layer.h" #include "kis_adjustment_layer.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "kis_group_layer.h" #include "kis_node_filter_interface.h" KisDlgAdjLayerProps::KisDlgAdjLayerProps(KisNodeSP node, KisNodeFilterInterface* nfi, KisPaintDeviceSP paintDevice, KisViewManager *view, KisFilterConfigurationSP configuration, const QString & layerName, const QString & caption, QWidget *parent, const char *name) : KoDialog(parent) , m_node(node) , m_paintDevice(paintDevice) , m_currentConfigWidget(0) , m_currentFilter(0) , m_currentConfiguration(0) , m_nodeFilterInterface(nfi) { setButtons(Ok | Cancel); setDefaultButton(Ok); setObjectName(name); m_currentConfiguration = configuration; if (m_currentConfiguration) { m_currentFilter = KisFilterRegistry::instance()->get(m_currentConfiguration->name()).data(); } setCaption(caption); QWidget * page = new QWidget(this); page->setObjectName("page widget"); QHBoxLayout * layout = new QHBoxLayout(page); layout->setMargin(0); setMainWidget(page); QVBoxLayout *v1 = new QVBoxLayout(); layout->addLayout(v1); QHBoxLayout *hl = new QHBoxLayout(); v1->addLayout(hl); QLabel * lblName = new QLabel(i18n("Layer name:"), page); lblName->setObjectName("lblName"); hl->addWidget(lblName, 0); m_layerName = new KLineEdit(page); m_layerName->setObjectName("m_layerName"); m_layerName->setText(layerName); m_layerName->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); hl->addWidget(m_layerName, 10); connect(m_layerName, SIGNAL(textChanged(const QString &)), this, SLOT(slotNameChanged(const QString &))); if (m_currentFilter) { m_currentConfigWidget = m_currentFilter->createConfigurationWidget(page, paintDevice); if (m_currentConfigWidget) { m_currentConfigWidget->setView(view); m_currentConfigWidget->setConfiguration(m_currentConfiguration); } } if (m_currentFilter == 0 || m_currentConfigWidget == 0) { QLabel * labelNoConfigWidget = new QLabel(i18n("No configuration options are available for this filter"), page); v1->addWidget(labelNoConfigWidget); } else { v1->addWidget(m_currentConfigWidget); connect(m_currentConfigWidget, SIGNAL(sigConfigurationUpdated()), SLOT(slotConfigChanged())); } enableButtonOk(!m_layerName->text().isEmpty()); } void KisDlgAdjLayerProps::slotNameChanged(const QString & text) { enableButtonOk(!text.isEmpty()); } KisFilterConfigurationSP KisDlgAdjLayerProps::filterConfiguration() const { if (m_currentConfigWidget) { KisFilterConfigurationSP config = dynamic_cast(m_currentConfigWidget->configuration().data()); if (config) { return config; } } - return m_currentFilter->defaultConfiguration(m_paintDevice); + return m_currentFilter->defaultConfiguration(); } QString KisDlgAdjLayerProps::layerName() const { return m_layerName->text(); } void KisDlgAdjLayerProps::slotConfigChanged() { enableButtonOk(true); KisFilterConfigurationSP config = filterConfiguration(); if (config) { m_nodeFilterInterface->setFilter(config); } m_node->setDirty(); } diff --git a/libs/ui/kis_bookmarked_filter_configurations_model.cc b/libs/ui/kis_bookmarked_filter_configurations_model.cc index db86ef3919..c7ae34d579 100644 --- a/libs/ui/kis_bookmarked_filter_configurations_model.cc +++ b/libs/ui/kis_bookmarked_filter_configurations_model.cc @@ -1,59 +1,59 @@ /* * Copyright (c) 2007 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_bookmarked_filter_configurations_model.h" #include #include #include struct KisBookmarkedFilterConfigurationsModel::Private { KisPaintDeviceSP thumb; KisFilterSP filter; }; KisBookmarkedFilterConfigurationsModel::KisBookmarkedFilterConfigurationsModel(KisPaintDeviceSP thumb, KisFilterSP filter) : KisBookmarkedConfigurationsModel(filter->bookmarkManager()), d(new Private) { d->thumb = thumb; d->filter = filter; } KisBookmarkedFilterConfigurationsModel::~KisBookmarkedFilterConfigurationsModel() { delete d; } QVariant KisBookmarkedFilterConfigurationsModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } return KisBookmarkedConfigurationsModel::data(index, role); } KisFilterConfigurationSP KisBookmarkedFilterConfigurationsModel::configuration(const QModelIndex &index) const { KisFilterConfigurationSP config = dynamic_cast(KisBookmarkedConfigurationsModel::configuration(index).data()); if (config) return config; - return d->filter->defaultConfiguration(d->thumb); + return d->filter->defaultConfiguration(); } diff --git a/libs/ui/kis_filter_manager.cc b/libs/ui/kis_filter_manager.cc index 541d5edd71..13e2fc6d51 100644 --- a/libs/ui/kis_filter_manager.cc +++ b/libs/ui/kis_filter_manager.cc @@ -1,350 +1,350 @@ /* * Copyright (c) 2007 Boudewijn Rempt * Copyright (c) 2007 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_filter_manager.h" #include #include #include #include #include #include #include // krita/image #include #include #include #include // krita/ui #include "KisViewManager.h" #include "kis_canvas2.h" #include #include "kis_action.h" #include "kis_action_manager.h" #include "kis_canvas_resource_provider.h" #include "dialogs/kis_dlg_filter.h" #include "strokes/kis_filter_stroke_strategy.h" #include "krita_utils.h" struct KisFilterManager::Private { Private() : reapplyAction(0) , actionCollection(0) , actionManager(0) , view(0) { } KisAction* reapplyAction; QHash filterActionMenus; QHash filters2Action; KActionCollection *actionCollection; KisActionManager *actionManager; KisViewManager *view; KisFilterConfigurationSP lastConfiguration; KisFilterConfigurationSP currentlyAppliedConfiguration; KisStrokeId currentStrokeId; QRect initialApplyRect; QSignalMapper actionsMapper; QPointer filterDialog; }; KisFilterManager::KisFilterManager(KisViewManager * view) : d(new Private) { d->view = view; } KisFilterManager::~KisFilterManager() { delete d; } void KisFilterManager::setView(QPointerimageView) { Q_UNUSED(imageView); } void KisFilterManager::setup(KActionCollection * ac, KisActionManager *actionManager) { d->actionCollection = ac; d->actionManager = actionManager; // Setup reapply action d->reapplyAction = d->actionManager->createAction("filter_apply_again"); d->reapplyAction->setEnabled(false); connect(d->reapplyAction, SIGNAL(triggered()), SLOT(reapplyLastFilter())); connect(&d->actionsMapper, SIGNAL(mapped(const QString&)), SLOT(showFilterDialog(const QString&))); // Setup list of filters QStringList keys = KisFilterRegistry::instance()->keys(); keys.sort(); Q_FOREACH (const QString &filterName, keys) { insertFilter(filterName); } connect(KisFilterRegistry::instance(), SIGNAL(filterAdded(QString)), SLOT(insertFilter(const QString &))); } void KisFilterManager::insertFilter(const QString & filterName) { Q_ASSERT(d->actionCollection); KisFilterSP filter = KisFilterRegistry::instance()->value(filterName); Q_ASSERT(filter); if (d->filters2Action.contains(filter.data())) { warnKrita << "Filter" << filterName << " has already been inserted"; return; } KoID category = filter->menuCategory(); KActionMenu* actionMenu = d->filterActionMenus[ category.id()]; if (!actionMenu) { actionMenu = new KActionMenu(category.name(), this); d->actionCollection->addAction(category.id(), actionMenu); d->filterActionMenus[category.id()] = actionMenu; } KisAction *action = new KisAction(filter->menuEntry(), this); action->setDefaultShortcut(filter->shortcut()); action->setActivationFlags(KisAction::ACTIVE_DEVICE); d->actionManager->addAction(QString("krita_filter_%1").arg(filterName), action); d->filters2Action[filter.data()] = action; actionMenu->addAction(action); d->actionsMapper.setMapping(action, filterName); connect(action, SIGNAL(triggered()), &d->actionsMapper, SLOT(map())); } void KisFilterManager::updateGUI() { if (!d->view) return; bool enable = false; KisNodeSP activeNode = d->view->activeNode(); enable = activeNode && activeNode->hasEditablePaintDevice(); d->reapplyAction->setEnabled(enable); for (QHash::iterator it = d->filters2Action.begin(); it != d->filters2Action.end(); ++it) { bool localEnable = enable; it.value()->setEnabled(localEnable); } } void KisFilterManager::reapplyLastFilter() { if (!d->lastConfiguration) return; apply(d->lastConfiguration); finish(); } void KisFilterManager::showFilterDialog(const QString &filterId) { if (d->filterDialog && d->filterDialog->isVisible()) { KisFilterSP filter = KisFilterRegistry::instance()->value(filterId); d->filterDialog->setFilter(filter); return; } connect(d->view->image(), SIGNAL(sigStrokeCancellationRequested()), SLOT(slotStrokeCancelRequested()), Qt::UniqueConnection); connect(d->view->image(), SIGNAL(sigStrokeEndRequested()), SLOT(slotStrokeEndRequested()), Qt::UniqueConnection); /** * The UI should show only after every running stroke is finished, * so a virtual barrier is added here. */ if (!d->view->blockUntillOperationsFinished(d->view->image())) { return; } Q_ASSERT(d->view); Q_ASSERT(d->view->activeNode()); KisPaintDeviceSP dev = d->view->activeNode()->paintDevice(); if (!dev) { warnKrita << "KisFilterManager::showFilterDialog(): Filtering was requested for illegal active layer!" << d->view->activeNode(); return; } KisFilterSP filter = KisFilterRegistry::instance()->value(filterId); if (dev->colorSpace()->willDegrade(filter->colorSpaceIndependence())) { // Warning bells! if (filter->colorSpaceIndependence() == TO_LAB16) { if (QMessageBox::warning(d->view->mainWindow(), i18nc("@title:window", "Krita"), i18n("The %1 filter will convert your %2 data to 16-bit L*a*b* and vice versa. ", filter->name(), dev->colorSpace()->name()), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) != QMessageBox::Ok) return; } else if (filter->colorSpaceIndependence() == TO_RGBA16) { if (QMessageBox::warning(d->view->mainWindow(), i18nc("@title:window", "Krita"), i18n("The %1 filter will convert your %2 data to 16-bit RGBA and vice versa. ", filter->name() , dev->colorSpace()->name()), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) != QMessageBox::Ok) return; } } if (filter->showConfigurationWidget()) { if (!d->filterDialog) { d->filterDialog = new KisDlgFilter(d->view , d->view->activeNode(), this, d->view->mainWindow()); d->filterDialog->setAttribute(Qt::WA_DeleteOnClose); } d->filterDialog->setFilter(filter); d->filterDialog->setVisible(true); } else { - apply(KisFilterConfigurationSP(filter->defaultConfiguration(d->view->activeNode()->original()))); + apply(KisFilterConfigurationSP(filter->defaultConfiguration())); finish(); } } void KisFilterManager::apply(KisFilterConfigurationSP filterConfig) { KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name()); KisImageWSP image = d->view->image(); if (d->currentStrokeId) { image->addJob(d->currentStrokeId, new KisFilterStrokeStrategy::CancelSilentlyMarker); image->cancelStroke(d->currentStrokeId); d->currentStrokeId.clear(); } else { image->waitForDone(); d->initialApplyRect = d->view->activeNode()->exactBounds(); } QRect applyRect = d->initialApplyRect; KisPaintDeviceSP paintDevice = d->view->activeNode()->paintDevice(); if (paintDevice && filter->needsTransparentPixels(filterConfig.data(), paintDevice->colorSpace())) { applyRect |= image->bounds(); } KoCanvasResourceManager *resourceManager = d->view->resourceProvider()->resourceManager(); KisResourcesSnapshotSP resources = new KisResourcesSnapshot(image, d->view->activeNode(), resourceManager); d->currentStrokeId = image->startStroke(new KisFilterStrokeStrategy(filter, KisFilterConfigurationSP(filterConfig), resources)); QRect processRect = filter->changedRect(applyRect, filterConfig.data(), 0); processRect &= image->bounds(); if (filter->supportsThreading()) { QSize size = KritaUtils::optimalPatchSize(); QVector rects = KritaUtils::splitRectIntoPatches(processRect, size); Q_FOREACH (const QRect &rc, rects) { image->addJob(d->currentStrokeId, new KisFilterStrokeStrategy::Data(rc, true)); } } else { image->addJob(d->currentStrokeId, new KisFilterStrokeStrategy::Data(processRect, false)); } d->currentlyAppliedConfiguration = filterConfig; } void KisFilterManager::finish() { Q_ASSERT(d->currentStrokeId); d->view->image()->endStroke(d->currentStrokeId); KisFilterSP filter = KisFilterRegistry::instance()->value(d->currentlyAppliedConfiguration->name()); if (filter->bookmarkManager()) { filter->bookmarkManager()->save(KisBookmarkedConfigurationManager::ConfigLastUsed, d->currentlyAppliedConfiguration.data()); } d->lastConfiguration = d->currentlyAppliedConfiguration; d->reapplyAction->setEnabled(true); d->reapplyAction->setText(i18n("Apply Filter Again: %1", filter->name())); d->currentStrokeId.clear(); d->currentlyAppliedConfiguration.clear(); } void KisFilterManager::cancel() { Q_ASSERT(d->currentStrokeId); d->view->image()->cancelStroke(d->currentStrokeId); d->currentStrokeId.clear(); d->currentlyAppliedConfiguration.clear(); } bool KisFilterManager::isStrokeRunning() const { return d->currentStrokeId; } void KisFilterManager::slotStrokeEndRequested() { if (d->currentStrokeId && d->filterDialog) { d->filterDialog->accept(); } } void KisFilterManager::slotStrokeCancelRequested() { if (d->currentStrokeId && d->filterDialog) { d->filterDialog->reject(); } } diff --git a/libs/ui/kis_mask_manager.cc b/libs/ui/kis_mask_manager.cc index a3963e8b7c..5a86188011 100644 --- a/libs/ui/kis_mask_manager.cc +++ b/libs/ui/kis_mask_manager.cc @@ -1,307 +1,307 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_mask_manager.h" #include #include #include #include #include #include #include #include "KisDocument.h" #include "KisViewManager.h" #include #include #include #include #include #include #include #include #include #include "dialogs/kis_dlg_adjustment_layer.h" #include "widgets/kis_mask_widgets.h" #include #include #include #include "dialogs/kis_dlg_adj_layer_props.h" #include #include #include #include #include "kis_node_commands_adapter.h" #include "commands/kis_selection_commands.h" #include "kis_iterator_ng.h" KisMaskManager::KisMaskManager(KisViewManager * view) : m_view(view) , m_imageView(0) , m_commandsAdapter(new KisNodeCommandsAdapter(m_view)) { } void KisMaskManager::setView(QPointerimageView) { m_imageView = imageView; } void KisMaskManager::setup(KActionCollection *actionCollection, KisActionManager *actionManager) { Q_UNUSED(actionCollection); Q_UNUSED(actionManager); } void KisMaskManager::updateGUI() { // XXX: enable/disable menu items according to whether there's a mask selected currently // XXX: disable the selection mask item if there's already a selection mask // YYY: doesn't KisAction do that already? } KisMaskSP KisMaskManager::activeMask() { if (m_imageView) { return m_imageView->currentMask(); } return 0; } KisPaintDeviceSP KisMaskManager::activeDevice() { KisMaskSP mask = activeMask(); return mask ? mask->paintDevice() : 0; } void KisMaskManager::activateMask(KisMaskSP mask) { Q_UNUSED(mask); } void KisMaskManager::masksUpdated() { m_view->updateGUI(); } void KisMaskManager::adjustMaskPosition(KisNodeSP node, KisNodeSP activeNode, bool avoidActiveNode, KisNodeSP &parent, KisNodeSP &above) { Q_ASSERT(node); Q_ASSERT(activeNode); if (!avoidActiveNode && activeNode->allowAsChild(node)) { parent = activeNode; above = activeNode->lastChild(); } else if (activeNode->parent() && activeNode->parent()->allowAsChild(node)) { parent = activeNode->parent(); above = activeNode; } else { KisNodeSP t = activeNode; while ((t = t->nextSibling())) { if (t->allowAsChild(node)) { parent = t; above = t->lastChild(); break; } } if (!t) { t = activeNode; while ((t = t->prevSibling())) { if (t->allowAsChild(node)) { parent = t; above = t->lastChild(); break; } } } if (!t && activeNode->parent()) { adjustMaskPosition(node, activeNode->parent(), true, parent, above); } else if (!t) { KisImageWSP image = m_view->image(); KisLayerSP layer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, image->colorSpace()); m_commandsAdapter->addNode(layer, activeNode, 0); parent = layer; above = 0; } } } void KisMaskManager::createMaskCommon(KisMaskSP mask, KisNodeSP activeNode, KisPaintDeviceSP copyFrom, const KUndo2MagicString& macroName, const QString &nodeType, const QString &nodeName, bool suppressSelection, bool avoidActiveNode, bool updateImage) { m_commandsAdapter->beginMacro(macroName); KisNodeSP parent; KisNodeSP above; adjustMaskPosition(mask, activeNode, avoidActiveNode, parent, above); KisLayerSP parentLayer = qobject_cast(parent.data()); Q_ASSERT(parentLayer); if (!suppressSelection) { if (copyFrom) { mask->initSelection(copyFrom, parentLayer); } else { mask->initSelection(m_view->selection(), parentLayer); } } //counting number of KisSelectionMask QList masks = parentLayer->childNodes(QStringList(nodeType),KoProperties()); int number = masks.count() + 1; mask->setName(nodeName + QString(" ") + QString::number(number)); m_commandsAdapter->addNode(mask, parentLayer, above, updateImage, updateImage); m_commandsAdapter->endMacro(); masksUpdated(); } void KisMaskManager::createSelectionMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool avoidActiveNode) { KisSelectionMaskSP mask = new KisSelectionMask(m_view->image()); createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Selection Mask"), "KisSelectionMask", i18n("Selection"), false, avoidActiveNode, false); mask->setActive(true); } void KisMaskManager::createTransparencyMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool avoidActiveNode) { KisMaskSP mask = new KisTransparencyMask(); createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Transparency Mask"), "KisTransparencyMask", i18n("Transparency Mask"), false, avoidActiveNode); } void KisMaskManager::createFilterMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool quiet, bool avoidActiveNode) { KisFilterMaskSP mask = new KisFilterMask(); createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Filter Mask"), "KisFilterMask", i18n("Filter Mask"), false, avoidActiveNode); /** * FIXME: We'll use layer's original for creation of a thumbnail. * Actually, we can't use it's projection as newly created mask * may be going to be inserted in the middle of the masks stack */ KisPaintDeviceSP originalDevice = mask->parent()->original(); KisDlgAdjustmentLayer dialog(mask, mask.data(), originalDevice, mask->name(), i18n("New Filter Mask"), m_view); // If we are supposed to not disturb the user, don't start asking them about things. if(quiet) { - KisFilterConfigurationSP filter = KisFilterRegistry::instance()->values().first()->defaultConfiguration(originalDevice); + KisFilterConfigurationSP filter = KisFilterRegistry::instance()->values().first()->defaultConfiguration(); if (filter) { mask->setFilter(filter); mask->setName(mask->name()); } return; } if (dialog.exec() == QDialog::Accepted) { KisFilterConfigurationSP filter = dialog.filterConfiguration(); if (filter) { QString name = dialog.layerName(); mask->setFilter(filter); mask->setName(name); } } else { m_commandsAdapter->undoLastCommand(); } } void KisMaskManager::createColorizeMask(KisNodeSP activeNode) { KisColorizeMaskSP mask = new KisColorizeMask(); createMaskCommon(mask, activeNode, 0, kundo2_i18n("Add Colorize Mask"), "KisColorizeMask", i18n("Colorize Mask"), true, false); mask->setImage(m_view->image()); mask->initializeCompositeOp(); delete mask->setColorSpace(mask->parent()->colorSpace()); } void KisMaskManager::createTransformMask(KisNodeSP activeNode) { KisTransformMaskSP mask = new KisTransformMask(); createMaskCommon(mask, activeNode, 0, kundo2_i18n("Add Transform Mask"), "KisTransformMask", i18n("Transform Mask"), true, false); } void KisMaskManager::maskProperties() { if (!activeMask()) return; if (activeMask()->inherits("KisFilterMask")) { KisFilterMask *mask = static_cast(activeMask().data()); KisLayerSP layer = qobject_cast(mask->parent().data()); if (! layer) return; KisPaintDeviceSP dev = layer->original(); if (!dev) { return; } KisDlgAdjLayerProps dlg(layer, mask, dev, m_view, mask->filter().data(), mask->name(), i18n("Filter Mask Properties"), m_view->mainWindow(), "dlgeffectmaskprops"); KisFilterConfigurationSP configBefore(mask->filter()); Q_ASSERT(configBefore); QString xmlBefore = configBefore->toXML(); if (dlg.exec() == QDialog::Accepted) { KisFilterConfigurationSP configAfter(dlg.filterConfiguration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); mask->setName(dlg.layerName()); if(xmlBefore != xmlAfter) { KisChangeFilterCmd *cmd = new KisChangeFilterCmd(mask, configBefore->name(), xmlBefore, configAfter->name(), xmlAfter, false); // FIXME: check whether is needed cmd->redo(); m_view->undoAdapter()->addCommand(cmd); m_view->document()->setModified(true); } } else { KisFilterConfigurationSP configAfter(dlg.filterConfiguration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); if(xmlBefore != xmlAfter) { mask->setFilter(KisFilterRegistry::instance()->cloneConfiguration(configBefore.data())); mask->setDirty(); } } } else { // Not much to show for transparency or selection masks? } } diff --git a/libs/ui/kis_selection_manager.cc b/libs/ui/kis_selection_manager.cc index 8057aac8ae..dcd88395fa 100644 --- a/libs/ui/kis_selection_manager.cc +++ b/libs/ui/kis_selection_manager.cc @@ -1,620 +1,620 @@ /* * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2007 Sven Langkamp * * The outline algorith uses the limn algorithm of fontutils by * Karl Berry and Kathryn Hargreaves * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_selection_manager.h" #include #include #include #include #include #include #include #include #include #include #include "KoCanvasController.h" #include "KoChannelInfo.h" #include "KoIntegerMaths.h" #include #include #include #include #include #include #include #include #include #include #include "kis_adjustment_layer.h" #include "kis_node_manager.h" #include "canvas/kis_canvas2.h" #include "kis_config.h" #include "kis_convolution_painter.h" #include "kis_convolution_kernel.h" #include "kis_debug.h" #include "KisDocument.h" #include "kis_fill_painter.h" #include "kis_group_layer.h" #include "kis_layer.h" #include "kis_statusbar.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "kis_painter.h" #include "kis_transaction.h" #include "kis_selection.h" #include "kis_types.h" #include "kis_canvas_resource_provider.h" #include "kis_undo_adapter.h" #include "kis_pixel_selection.h" #include "flake/kis_shape_selection.h" #include "commands/kis_selection_commands.h" #include "kis_selection_mask.h" #include "flake/kis_shape_layer.h" #include "kis_selection_decoration.h" #include "canvas/kis_canvas_decoration.h" #include "kis_node_commands_adapter.h" #include "kis_iterator_ng.h" #include "kis_clipboard.h" #include "KisViewManager.h" #include "kis_selection_filters.h" #include "kis_figure_painting_tool_helper.h" #include "KisView.h" #include "dialogs/kis_dlg_stroke_selection_properties.h" #include "actions/kis_selection_action_factories.h" #include "kis_action.h" #include "kis_action_manager.h" #include "operations/kis_operation_configuration.h" //new #include "kis_recorded_path_paint_action.h" #include "kis_node_query_path.h" #include "kis_tool_shape.h" KisSelectionManager::KisSelectionManager(KisViewManager * view) : m_view(view), m_doc(0), m_imageView(0), m_adapter(new KisNodeCommandsAdapter(view)), m_copy(0), m_copyMerged(0), m_cut(0), m_paste(0), m_pasteNew(0), m_cutToNewLayer(0), m_selectAll(0), m_deselect(0), m_clear(0), m_reselect(0), m_invert(0), m_copyToNewLayer(0), m_fillForegroundColor(0), m_fillBackgroundColor(0), m_fillPattern(0), m_imageResizeToSelection(0), m_selectionDecoration(0) { m_clipboard = KisClipboard::instance(); } KisSelectionManager::~KisSelectionManager() { } void KisSelectionManager::setup(KisActionManager* actionManager) { m_cut = actionManager->createStandardAction(KStandardAction::Cut, this, SLOT(cut())); m_copy = actionManager->createStandardAction(KStandardAction::Copy, this, SLOT(copy())); m_paste = actionManager->createStandardAction(KStandardAction::Paste, this, SLOT(paste())); KisAction *action = actionManager->createAction("copy_sharp"); connect(action, SIGNAL(triggered()), this, SLOT(copySharp())); action = actionManager->createAction("cut_sharp"); connect(action, SIGNAL(triggered()), this, SLOT(cutSharp())); m_pasteNew = actionManager->createAction("paste_new"); connect(m_pasteNew, SIGNAL(triggered()), this, SLOT(pasteNew())); m_pasteAt = actionManager->createAction("paste_at"); connect(m_pasteAt, SIGNAL(triggered()), this, SLOT(pasteAt())); m_copyMerged = actionManager->createAction("copy_merged"); connect(m_copyMerged, SIGNAL(triggered()), this, SLOT(copyMerged())); m_selectAll = actionManager->createAction("select_all"); connect(m_selectAll, SIGNAL(triggered()), this, SLOT(selectAll())); m_deselect = actionManager->createAction("deselect"); connect(m_deselect, SIGNAL(triggered()), this, SLOT(deselect())); m_clear = actionManager->createAction("clear"); connect(m_clear, SIGNAL(triggered()), SLOT(clear())); m_reselect = actionManager->createAction("reselect"); connect(m_reselect, SIGNAL(triggered()), this, SLOT(reselect())); m_invert = actionManager->createAction("invert"); m_invert->setOperationID("invertselection"); - actionManager->registerOperation(new KisInvertSelectionOperaton); + actionManager->registerOperation(new KisInvertSelectionOperation); m_copyToNewLayer = actionManager->createAction("copy_selection_to_new_layer"); connect(m_copyToNewLayer, SIGNAL(triggered()), this, SLOT(copySelectionToNewLayer())); m_cutToNewLayer = actionManager->createAction("cut_selection_to_new_layer"); connect(m_cutToNewLayer, SIGNAL(triggered()), this, SLOT(cutToNewLayer())); m_fillForegroundColor = actionManager->createAction("fill_selection_foreground_color"); connect(m_fillForegroundColor, SIGNAL(triggered()), this, SLOT(fillForegroundColor())); m_fillBackgroundColor = actionManager->createAction("fill_selection_background_color"); connect(m_fillBackgroundColor, SIGNAL(triggered()), this, SLOT(fillBackgroundColor())); m_fillPattern = actionManager->createAction("fill_selection_pattern"); connect(m_fillPattern, SIGNAL(triggered()), this, SLOT(fillPattern())); m_fillForegroundColorOpacity = actionManager->createAction("fill_selection_foreground_color_opacity"); connect(m_fillForegroundColorOpacity, SIGNAL(triggered()), this, SLOT(fillForegroundColorOpacity())); m_fillBackgroundColorOpacity = actionManager->createAction("fill_selection_background_color_opacity"); connect(m_fillBackgroundColorOpacity, SIGNAL(triggered()), this, SLOT(fillBackgroundColorOpacity())); m_fillPatternOpacity = actionManager->createAction("fill_selection_pattern_opacity"); connect(m_fillPatternOpacity, SIGNAL(triggered()), this, SLOT(fillPatternOpacity())); m_strokeShapes = actionManager->createAction("stroke_shapes"); connect(m_strokeShapes, SIGNAL(triggered()), this, SLOT(paintSelectedShapes())); m_toggleDisplaySelection = actionManager->createAction("toggle_display_selection"); connect(m_toggleDisplaySelection, SIGNAL(triggered()), this, SLOT(toggleDisplaySelection())); m_toggleDisplaySelection->setChecked(true); m_imageResizeToSelection = actionManager->createAction("resizeimagetoselection"); connect(m_imageResizeToSelection, SIGNAL(triggered()), this, SLOT(imageResizeToSelection())); action = actionManager->createAction("convert_to_vector_selection"); connect(action, SIGNAL(triggered()), SLOT(convertToVectorSelection())); action = actionManager->createAction("convert_shapes_to_vector_selection"); connect(action, SIGNAL(triggered()), SLOT(convertShapesToVectorSelection())); action = actionManager->createAction("convert_selection_to_shape"); connect(action, SIGNAL(triggered()), SLOT(convertToShape())); m_toggleSelectionOverlayMode = actionManager->createAction("toggle-selection-overlay-mode"); connect(m_toggleSelectionOverlayMode, SIGNAL(triggered()), SLOT(slotToggleSelectionDecoration())); m_strokeSelected = actionManager->createAction("stroke_selection"); connect(m_strokeSelected, SIGNAL(triggered()), SLOT(slotStrokeSelection())); QClipboard *cb = QApplication::clipboard(); connect(cb, SIGNAL(dataChanged()), SLOT(clipboardDataChanged())); } void KisSelectionManager::setView(QPointerimageView) { if (m_imageView && m_imageView->canvasBase()) { disconnect(m_imageView->canvasBase()->toolProxy(), SIGNAL(toolChanged(const QString&)), this, SLOT(clipboardDataChanged())); KoSelection *selection = m_imageView->canvasBase()->globalShapeManager()->selection(); selection->disconnect(this, SLOT(shapeSelectionChanged())); KisSelectionDecoration *decoration = qobject_cast(m_imageView->canvasBase()->decoration("selection").data()); if (decoration) { disconnect(SIGNAL(currentSelectionChanged()), decoration); } m_imageView->image()->undoAdapter()->disconnect(this); m_selectionDecoration = 0; } m_imageView = imageView; if (m_imageView) { KoSelection * selection = m_imageView->canvasBase()->globalShapeManager()->selection(); Q_ASSERT(selection); connect(selection, SIGNAL(selectionChanged()), this, SLOT(shapeSelectionChanged())); KisSelectionDecoration* decoration = qobject_cast(m_imageView->canvasBase()->decoration("selection").data()); if (!decoration) { decoration = new KisSelectionDecoration(m_imageView); decoration->setVisible(true); m_imageView->canvasBase()->addDecoration(decoration); } m_selectionDecoration = decoration; connect(this, SIGNAL(currentSelectionChanged()), decoration, SLOT(selectionChanged())); connect(m_imageView->image()->undoAdapter(), SIGNAL(selectionChanged()), SLOT(selectionChanged())); connect(m_imageView->canvasBase()->toolProxy(), SIGNAL(toolChanged(const QString&)), SLOT(clipboardDataChanged())); } } void KisSelectionManager::clipboardDataChanged() { m_view->updateGUI(); } bool KisSelectionManager::havePixelsSelected() { KisSelectionSP activeSelection = m_view->selection(); return activeSelection && !activeSelection->selectedRect().isEmpty(); } bool KisSelectionManager::havePixelsInClipboard() { return m_clipboard->hasClip(); } bool KisSelectionManager::haveShapesSelected() { if (m_view && m_view->canvasBase() && m_view->canvasBase()->shapeManager() && m_view->canvasBase()->shapeManager()->selection()->count()) { return m_view->canvasBase()->shapeManager()->selection()->count() > 0; } return false; } bool KisSelectionManager::haveShapesInClipboard() { KisShapeLayer *shapeLayer = dynamic_cast(m_view->activeLayer().data()); if (shapeLayer) { const QMimeData* data = QApplication::clipboard()->mimeData(); if (data) { QStringList mimeTypes = m_view->canvasBase()->toolProxy()->supportedPasteMimeTypes(); Q_FOREACH (const QString & mimeType, mimeTypes) { if (data->hasFormat(mimeType)) { return true; } } } } return false; } bool KisSelectionManager::havePixelSelectionWithPixels() { KisSelectionSP selection = m_view->selection(); if (selection && selection->hasPixelSelection()) { return !selection->pixelSelection()->selectedRect().isEmpty(); } return false; } void KisSelectionManager::updateGUI() { Q_ASSERT(m_view); Q_ASSERT(m_clipboard); if (!m_view || !m_clipboard) return; bool havePixelsSelected = this->havePixelsSelected(); bool havePixelsInClipboard = this->havePixelsInClipboard(); bool haveShapesSelected = this->haveShapesSelected(); bool haveShapesInClipboard = this->haveShapesInClipboard(); bool haveDevice = m_view->activeDevice(); KisLayerSP activeLayer = m_view->activeLayer(); KisImageWSP image = activeLayer ? activeLayer->image() : 0; bool canReselect = image && image->canReselectGlobalSelection(); bool canDeselect = image && image->globalSelection(); m_clear->setEnabled(haveDevice || havePixelsSelected || haveShapesSelected); m_cut->setEnabled(havePixelsSelected || haveShapesSelected); m_copy->setEnabled(havePixelsSelected || haveShapesSelected); m_paste->setEnabled(havePixelsInClipboard || haveShapesInClipboard); m_pasteAt->setEnabled(havePixelsInClipboard || haveShapesInClipboard); // FIXME: how about pasting shapes? m_pasteNew->setEnabled(havePixelsInClipboard); m_selectAll->setEnabled(true); m_deselect->setEnabled(canDeselect); m_reselect->setEnabled(canReselect); // m_load->setEnabled(true); // m_save->setEnabled(havePixelsSelected); updateStatusBar(); emit signalUpdateGUI(); } void KisSelectionManager::updateStatusBar() { if (m_view && m_view->statusBar()) { m_view->statusBar()->setSelection(m_view->image()); } } void KisSelectionManager::selectionChanged() { m_view->updateGUI(); emit currentSelectionChanged(); } void KisSelectionManager::cut() { KisCutCopyActionFactory factory; factory.run(true, false, m_view); } void KisSelectionManager::copy() { KisCutCopyActionFactory factory; factory.run(false, false, m_view); } void KisSelectionManager::cutSharp() { KisCutCopyActionFactory factory; factory.run(true, true, m_view); } void KisSelectionManager::copySharp() { KisCutCopyActionFactory factory; factory.run(false, true, m_view); } void KisSelectionManager::copyMerged() { KisCopyMergedActionFactory factory; factory.run(m_view); } void KisSelectionManager::paste() { KisPasteActionFactory factory; factory.run(m_view); } void KisSelectionManager::pasteAt() { //XXX } void KisSelectionManager::pasteNew() { KisPasteNewActionFactory factory; factory.run(m_view); } void KisSelectionManager::selectAll() { KisSelectAllActionFactory factory; factory.run(m_view); } void KisSelectionManager::deselect() { KisDeselectActionFactory factory; factory.run(m_view); } void KisSelectionManager::invert() { if(m_invert) m_invert->trigger(); } void KisSelectionManager::reselect() { KisReselectActionFactory factory; factory.run(m_view); } void KisSelectionManager::convertToVectorSelection() { KisSelectionToVectorActionFactory factory; factory.run(m_view); } void KisSelectionManager::convertShapesToVectorSelection() { KisShapesToVectorSelectionActionFactory factory; factory.run(m_view); } void KisSelectionManager::convertToShape() { KisSelectionToShapeActionFactory factory; factory.run(m_view); } void KisSelectionManager::clear() { KisClearActionFactory factory; factory.run(m_view); } void KisSelectionManager::fillForegroundColor() { KisFillActionFactory factory; factory.run("fg", m_view); } void KisSelectionManager::fillBackgroundColor() { KisFillActionFactory factory; factory.run("bg", m_view); } void KisSelectionManager::fillPattern() { KisFillActionFactory factory; factory.run("pattern", m_view); } void KisSelectionManager::fillForegroundColorOpacity() { KisFillActionFactory factory; factory.run("fg_opacity", m_view); } void KisSelectionManager::fillBackgroundColorOpacity() { KisFillActionFactory factory; factory.run("bg_opacity", m_view); } void KisSelectionManager::fillPatternOpacity() { KisFillActionFactory factory; factory.run("pattern_opacity", m_view); } void KisSelectionManager::copySelectionToNewLayer() { copy(); paste(); } void KisSelectionManager::cutToNewLayer() { cut(); paste(); } void KisSelectionManager::toggleDisplaySelection() { KIS_ASSERT_RECOVER_RETURN(m_selectionDecoration); m_selectionDecoration->toggleVisibility(); m_toggleDisplaySelection->blockSignals(true); m_toggleDisplaySelection->setChecked(m_selectionDecoration->visible()); m_toggleDisplaySelection->blockSignals(false); emit displaySelectionChanged(); } bool KisSelectionManager::displaySelection() { return m_toggleDisplaySelection->isChecked(); } void KisSelectionManager::shapeSelectionChanged() { KoShapeManager* shapeManager = m_view->canvasBase()->globalShapeManager(); KoSelection * selection = shapeManager->selection(); QList selectedShapes = selection->selectedShapes(); KoShapeStroke* border = new KoShapeStroke(0, Qt::lightGray); Q_FOREACH (KoShape* shape, shapeManager->shapes()) { if (dynamic_cast(shape->parent())) { if (selectedShapes.contains(shape)) shape->setStroke(border); else shape->setStroke(0); } } m_view->updateGUI(); } void KisSelectionManager::imageResizeToSelection() { KisImageResizeToSelectionActionFactory factory; factory.run(m_view); } void KisSelectionManager::paintSelectedShapes() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer = m_view->activeLayer(); if (!layer) return; QList shapes = m_view->canvasBase()->shapeManager()->selection()->selectedShapes(); KisPaintLayerSP paintLayer = new KisPaintLayer(image, i18n("Stroked Shapes"), OPACITY_OPAQUE_U8); KUndo2MagicString actionName = kundo2_i18n("Stroke Shapes"); m_adapter->beginMacro(actionName); m_adapter->addNode(paintLayer.data(), layer->parent().data(), layer.data()); KisFigurePaintingToolHelper helper(actionName, image, paintLayer.data(), m_view->resourceProvider()->resourceManager(), KisPainter::StrokeStyleBrush, KisPainter::FillStyleNone); Q_FOREACH (KoShape* shape, shapes) { QTransform matrix = shape->absoluteTransformation(0) * QTransform::fromScale(image->xRes(), image->yRes()); QPainterPath mapedOutline = matrix.map(shape->outline()); helper.paintPainterPath(mapedOutline); } m_adapter->endMacro(); } void KisSelectionManager::slotToggleSelectionDecoration() { KIS_ASSERT_RECOVER_RETURN(m_selectionDecoration); KisSelectionDecoration::Mode mode = m_selectionDecoration->mode() ? KisSelectionDecoration::Ants : KisSelectionDecoration::Mask; m_selectionDecoration->setMode(mode); emit displaySelectionChanged(); } bool KisSelectionManager::showSelectionAsMask() const { if (m_selectionDecoration) { return m_selectionDecoration->mode() == KisSelectionDecoration::Mask; } return false; } void KisSelectionManager::slotStrokeSelection() { KisImageWSP image = m_view->image(); if (!image ) { return; } KisNodeSP currentNode = m_view->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentKritaNode).value(); bool isVectorLayer = false; if (currentNode->inherits("KisShapeLayer")) { isVectorLayer = true; } QPointer dlg = new KisDlgStrokeSelection(image, m_view, isVectorLayer); if (dlg->exec() == QDialog::Accepted) { StrokeSelectionOptions params = dlg->getParams(); if (params.brushSelected){ KisStrokeBrushSelectionActionFactory factory; factory.run(m_view, params); } else { KisStrokeSelectionActionFactory factory; factory.run(m_view, params); } } delete dlg; } diff --git a/libs/ui/kis_selection_manager.h b/libs/ui/kis_selection_manager.h index 9c640baa24..ea6cb67ee2 100644 --- a/libs/ui/kis_selection_manager.h +++ b/libs/ui/kis_selection_manager.h @@ -1,181 +1,171 @@ /* * Copyright (c) 2004 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SELECTION_MANAGER_ #define KIS_SELECTION_MANAGER_ #include #include #include #include #include "KisView.h" #include class KisActionManager; class KisAction; class QAction; class KoViewConverter; class KisDocument; class KisViewManager; class KisClipboard; class KisNodeCommandsAdapter; class KisView; class KisSelectionFilter; class KisSelectionDecoration; /** * The selection manager is responsible selections * and the clipboard. */ class KRITAUI_EXPORT KisSelectionManager : public QObject { Q_OBJECT Q_PROPERTY(bool displaySelection READ displaySelection NOTIFY displaySelectionChanged); Q_PROPERTY(bool havePixelsSelected READ havePixelsSelected NOTIFY currentSelectionChanged); public: KisSelectionManager(KisViewManager * view); virtual ~KisSelectionManager(); void setup(KisActionManager* actionManager); void setView(QPointerimageView); public: /** * This function return if the selection should be displayed */ bool displaySelection(); bool showSelectionAsMask() const; public Q_SLOTS: void updateGUI(); void selectionChanged(); void clipboardDataChanged(); void cut(); void copy(); void cutSharp(); void copySharp(); void copyMerged(); void paste(); void pasteNew(); void pasteAt(); void cutToNewLayer(); void selectAll(); void deselect(); void invert(); void clear(); void fillForegroundColor(); void fillBackgroundColor(); void fillPattern(); void fillForegroundColorOpacity(); void fillBackgroundColorOpacity(); void fillPatternOpacity(); void reselect(); void convertToVectorSelection(); void convertShapesToVectorSelection(); void convertToShape(); void copySelectionToNewLayer(); void toggleDisplaySelection(); void shapeSelectionChanged(); void imageResizeToSelection(); void paintSelectedShapes(); void slotToggleSelectionDecoration(); void slotStrokeSelection(); Q_SIGNALS: void currentSelectionChanged(); void signalUpdateGUI(); void displaySelectionChanged(); void strokeSelected(); public: bool havePixelsSelected(); bool havePixelsInClipboard(); bool haveShapesSelected(); bool haveShapesInClipboard(); - /// Checks if the current selection is editabl and has some pixels selected in the pixel selection + /// Checks if the current selection is editable and has some pixels selected in the pixel selection bool havePixelSelectionWithPixels(); - // the following functions are needed for the siox tool - // they might be also useful on its own - void erode(); - void dilate(); - - void paint(QPainter& gc, const KoViewConverter &converter); - private: void fill(const KoColor& color, bool fillWithPattern, const QString& transactionText); void updateStatusBar(); - void copyFromDevice(KisPaintDeviceSP device); - void applySelectionFilter(KisSelectionFilter *filter); - KisViewManager * m_view; KisDocument * m_doc; QPointerm_imageView; KisClipboard * m_clipboard; KisNodeCommandsAdapter* m_adapter; KisAction *m_copy; KisAction *m_copyMerged; KisAction *m_cut; KisAction *m_paste; KisAction *m_pasteAt; KisAction *m_pasteNew; KisAction *m_cutToNewLayer; KisAction *m_selectAll; KisAction *m_deselect; KisAction *m_clear; KisAction *m_reselect; KisAction *m_invert; KisAction *m_copyToNewLayer; KisAction *m_fillForegroundColor; KisAction *m_fillBackgroundColor; KisAction *m_fillPattern; KisAction *m_fillForegroundColorOpacity; KisAction *m_fillBackgroundColorOpacity; KisAction *m_fillPatternOpacity; KisAction *m_imageResizeToSelection; KisAction *m_strokeShapes; KisAction *m_toggleDisplaySelection; KisAction *m_toggleSelectionOverlayMode; KisAction *m_strokeSelected; QList m_pluginActions; QPointer m_selectionDecoration; }; #endif // KIS_SELECTION_MANAGER_ diff --git a/libs/ui/recorder/kis_recorded_filter_action_creator.cpp b/libs/ui/recorder/kis_recorded_filter_action_creator.cpp index 60b768be53..fcdf6d4ef5 100644 --- a/libs/ui/recorder/kis_recorded_filter_action_creator.cpp +++ b/libs/ui/recorder/kis_recorded_filter_action_creator.cpp @@ -1,77 +1,77 @@ /* * Copyright (c) 2011 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_recorded_filter_action_creator.h" #include #include #include #include #include #include #include #include #include #include KisRecordedFilterActionCreator::KisRecordedFilterActionCreator(QWidget* parent , Qt::WindowFlags f) : KisRecordedActionCreator(parent, f) { m_filterModel = new KisFiltersModel(true, 0); m_filterTree = new QTreeView(this); m_filterTree->setModel(m_filterModel); m_filterTree->header()->setVisible(false); QGridLayout* layout = new QGridLayout(); setLayout(layout); layout->addWidget(m_filterTree, 0, 0, 1, 1); } KisRecordedFilterActionCreator::~KisRecordedFilterActionCreator() { delete m_filterTree; delete m_filterModel; } KisRecordedAction* KisRecordedFilterActionCreator::createAction() const { const KisFilter* filter = m_filterModel->indexToFilter(m_filterTree->currentIndex()); if(!filter) return 0; - return new KisRecordedFilterAction(filter->name(), KisNodeQueryPath::fromString(""), filter, filter->defaultConfiguration(0)); + return new KisRecordedFilterAction(filter->name(), KisNodeQueryPath::fromString(""), filter, filter->defaultConfiguration()); } KisRecordedFilterActionCreatorFactory::KisRecordedFilterActionCreatorFactory() : KisRecordedActionCreatorFactory("filter", i18nc("recorded filter action", "Apply Filter")) { } KisRecordedFilterActionCreatorFactory::~KisRecordedFilterActionCreatorFactory() { } bool KisRecordedFilterActionCreatorFactory::requireCreator() const { return true; } KisRecordedActionCreator* KisRecordedFilterActionCreatorFactory::createCreator(QWidget* parent) const { return new KisRecordedFilterActionCreator(parent); } diff --git a/libs/ui/tests/filter_stroke_test.cpp b/libs/ui/tests/filter_stroke_test.cpp index 256f47ecc9..8210ef02b8 100644 --- a/libs/ui/tests/filter_stroke_test.cpp +++ b/libs/ui/tests/filter_stroke_test.cpp @@ -1,93 +1,93 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "filter_stroke_test.h" #include #include "stroke_testing_utils.h" #include "strokes/kis_filter_stroke_strategy.h" #include "kis_resources_snapshot.h" #include "kis_image.h" #include "filter/kis_filter.h" #include "filter/kis_filter_registry.h" #include "filter/kis_filter_configuration.h" class FilterStrokeTester : public utils::StrokeTester { public: FilterStrokeTester(const QString &filterName) : StrokeTester(QString("filter_") + filterName, QSize(500, 500), ""), m_filterName(filterName) { setBaseFuzziness(5); } protected: using utils::StrokeTester::initImage; using utils::StrokeTester::addPaintingJobs; void initImage(KisImageWSP image, KisNodeSP activeNode) override { QImage src(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png"); activeNode->original()->convertFromQImage(src, 0); image->refreshGraph(); } KisStrokeStrategy* createStroke(bool indirectPainting, KisResourcesSnapshotSP resources, KisImageWSP image) override { Q_UNUSED(image); Q_UNUSED(indirectPainting); KisFilterSP filter = KisFilterRegistry::instance()->value(m_filterName); Q_ASSERT(filter); - KisFilterConfigurationSP filterConfig = filter->defaultConfiguration(0); + KisFilterConfigurationSP filterConfig = filter->defaultConfiguration(); Q_ASSERT(filterConfig); return new KisFilterStrokeStrategy(filter, KisFilterConfigurationSP(filterConfig), resources); } void addPaintingJobs(KisImageWSP image, KisResourcesSnapshotSP resources) override { Q_UNUSED(resources); image->addJob(strokeId(), new KisFilterStrokeStrategy:: Data(QRect(100,100,100,100), true)); image->addJob(strokeId(), new KisFilterStrokeStrategy:: Data(QRect(200,100,100,100), true)); image->addJob(strokeId(), new KisFilterStrokeStrategy:: Data(QRect(100,200,100,100), true)); } private: QString m_filterName; }; void FilterStrokeTest::testBlurFilter() { FilterStrokeTester tester("blur"); tester.test(); } QTEST_MAIN(FilterStrokeTest) diff --git a/libs/ui/tests/kis_recorded_action_editor_test.cpp b/libs/ui/tests/kis_recorded_action_editor_test.cpp index eaf5cde5de..3d00ce8d40 100644 --- a/libs/ui/tests/kis_recorded_action_editor_test.cpp +++ b/libs/ui/tests/kis_recorded_action_editor_test.cpp @@ -1,49 +1,49 @@ /* * Copyright (c) 2009 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_recorded_action_editor_test.h" #include #include #include #include #include #include #include #include #include void KisRecordedActionEditorTest::testFilterEditorCreation() { KisRecordedActionEditorFactoryRegistry* reg = KisRecordedActionEditorFactoryRegistry::instance(); const KisFilter* blurFilter = KisFilterRegistry::instance()->get("blur"); KisRecordedFilterAction* blurFilterAction = new KisRecordedFilterAction( - "hello", KisNodeQueryPath::fromString(""), blurFilter, blurFilter->defaultConfiguration(0)); + "hello", KisNodeQueryPath::fromString(""), blurFilter, blurFilter->defaultConfiguration()); QVERIFY(reg->hasEditor(blurFilterAction)); QVERIFY(reg->createEditor(0, blurFilterAction)); const KisFilter* invertFilter = KisFilterRegistry::instance()->get("invert"); KisRecordedFilterAction* invertFilterAction = new KisRecordedFilterAction( - "hello", KisNodeQueryPath::fromString(""), invertFilter, invertFilter->defaultConfiguration(0)); + "hello", KisNodeQueryPath::fromString(""), invertFilter, invertFilter->defaultConfiguration()); QVERIFY(reg->hasEditor(invertFilterAction)); QVERIFY(reg->createEditor(0, invertFilterAction)); } QTEST_MAIN(KisRecordedActionEditorTest) diff --git a/libs/ui/tests/util.h b/libs/ui/tests/util.h index 14745d203f..3e7d0430aa 100644 --- a/libs/ui/tests/util.h +++ b/libs/ui/tests/util.h @@ -1,234 +1,234 @@ /* * Copyright (c) 2008 Boudewijn Rempt boud@valdyas.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _UTIL_H_ #define _UTIL_H_ #include #include #include #include #include #include #include #include #include #include #include "kis_types.h" #include "filter/kis_filter_registry.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter.h" #include "KisDocument.h" #include "KisPart.h" #include "kis_image.h" #include "kis_pixel_selection.h" #include "kis_group_layer.h" #include "kis_paint_layer.h" #include "kis_clone_layer.h" #include "kis_adjustment_layer.h" #include "kis_shape_layer.h" #include "kis_filter_mask.h" #include "kis_transparency_mask.h" #include "kis_selection_mask.h" #include "kis_selection.h" #include "kis_fill_painter.h" #include "kis_shape_selection.h" #include "kis_default_bounds.h" #include "kis_transform_mask_params_interface.h" KisSelectionSP createPixelSelection(KisPaintDeviceSP paintDevice) { KisSelectionSP pixelSelection = new KisSelection(new KisSelectionDefaultBounds(paintDevice)); KisFillPainter gc(pixelSelection->pixelSelection()); gc.fillRect(10, 10, 200, 200, KoColor(gc.device()->colorSpace())); gc.fillRect(150, 150, 200, 200, KoColor(QColor(100, 100, 100, 100), gc.device()->colorSpace())); gc.end(); return pixelSelection; } KisSelectionSP createVectorSelection(KisPaintDeviceSP paintDevice, KisImageWSP image) { KisSelectionSP vectorSelection = new KisSelection(new KisSelectionDefaultBounds(paintDevice)); KoPathShape* path = new KoPathShape(); path->setShapeId(KoPathShapeId); path->moveTo(QPointF(10, 10)); path->lineTo(QPointF(10, 10) + QPointF(100, 0)); path->lineTo(QPointF(100, 100)); path->lineTo(QPointF(10, 10) + QPointF(0, 100)); path->close(); path->normalize(); KisShapeSelection* shapeSelection = new KisShapeSelection(image, vectorSelection); shapeSelection->addShape(path); vectorSelection->setShapeSelection(shapeSelection); return vectorSelection; } QTransform createTestingTransform() { return QTransform(1,2,3,4,5,6,7,8,9); } KisDocument* createCompleteDocument(bool shouldMaskToShapeLayer = false) { KisImageWSP image = new KisImage(0, 1024, 1024, KoColorSpaceRegistry::instance()->rgb8(), "test for roundtrip"); KisDocument *doc = qobject_cast(KisPart::instance()->createDocument()); doc->setCurrentImage(image); doc->documentInfo()->setAboutInfo("title", image->objectName()); KisGroupLayerSP group1 = new KisGroupLayer(image, "group1", 50); KisGroupLayerSP group2 = new KisGroupLayer(image, "group2", 100); KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paintlayer1", OPACITY_OPAQUE_U8); paintLayer1->setUserLocked(true); QBitArray channelFlags(4); channelFlags[0] = true; channelFlags[2] = true; paintLayer1->setChannelFlags(channelFlags); { KisFillPainter gc(paintLayer1->paintDevice()); gc.fillRect(10, 10, 200, 200, KoColor(Qt::red, paintLayer1->paintDevice()->colorSpace())); gc.end(); } KisPaintLayerSP paintLayer2 = new KisPaintLayer(image, "paintlayer2", OPACITY_TRANSPARENT_U8, KoColorSpaceRegistry::instance()->lab16()); paintLayer2->setVisible(false); { KisFillPainter gc(paintLayer2->paintDevice()); gc.fillRect(0, 0, 900, 1024, KoColor(QColor(10, 20, 30), paintLayer2->paintDevice()->colorSpace())); gc.end(); } KisCloneLayerSP cloneLayer1 = new KisCloneLayer(group1, image, "clonelayer1", 150); cloneLayer1->setX(100); cloneLayer1->setY(100); KisSelectionSP pixelSelection = createPixelSelection(paintLayer1->paintDevice()); - KisFilterConfigurationSP kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(group2->projection()); + KisFilterConfigurationSP kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(); Q_ASSERT(kfc); KisAdjustmentLayerSP adjustmentLayer1 = new KisAdjustmentLayer(image, "adjustmentLayer1", kfc, pixelSelection); kfc = 0; // kfc cannot be shared! KisSelectionSP vectorSelection = createVectorSelection(paintLayer2->paintDevice(), image); - kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(group2->projection()); + kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(); KisAdjustmentLayerSP adjustmentLayer2 = new KisAdjustmentLayer(image, "adjustmentLayer2", kfc, vectorSelection); kfc = 0; // kfc cannot be shared! image->addNode(paintLayer1); image->addNode(group1); image->addNode(paintLayer2, group1); image->addNode(group2); image->addNode(cloneLayer1, group2); image->addNode(adjustmentLayer1, group2); // KoShapeContainer * parentContainer = // dynamic_cast(doc->shapeForNode(group1)); KoPathShape* path = new KoPathShape(); path->setShapeId(KoPathShapeId); path->moveTo(QPointF(10, 10)); path->lineTo(QPointF(10, 10) + QPointF(100, 0)); path->lineTo(QPointF(100, 100)); path->lineTo(QPointF(10, 10) + QPointF(0, 100)); path->close(); path->normalize(); KisShapeLayerSP shapeLayer = new KisShapeLayer(doc->shapeController(), image, "shapeLayer1", 75); shapeLayer->addShape(path); image->addNode(shapeLayer, group1); image->addNode(adjustmentLayer2, group1); KisFilterMaskSP filterMask1 = new KisFilterMask(); filterMask1->setName("filterMask1"); - kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(group2->projection()); + kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(); filterMask1->setFilter(kfc); kfc = 0; // kfc cannot be shared! filterMask1->setSelection(createPixelSelection(paintLayer1->paintDevice())); image->addNode(filterMask1, paintLayer1); KisFilterMaskSP filterMask2 = new KisFilterMask(); filterMask2->setName("filterMask2"); - kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(group2->projection()); + kfc = KisFilterRegistry::instance()->get("pixelize")->defaultConfiguration(); filterMask2->setFilter(kfc); kfc = 0; // kfc cannot be shared! filterMask2->setSelection(createVectorSelection(paintLayer2->paintDevice(), image)); image->addNode(filterMask2, paintLayer2); KisTransparencyMaskSP transparencyMask1 = new KisTransparencyMask(); transparencyMask1->setName("transparencyMask1"); transparencyMask1->setSelection(createPixelSelection(paintLayer1->paintDevice())); image->addNode(transparencyMask1, group1); KisTransparencyMaskSP transparencyMask2 = new KisTransparencyMask(); transparencyMask2->setName("transparencyMask2"); transparencyMask2->setSelection(createPixelSelection(paintLayer1->paintDevice())); image->addNode(transparencyMask2, group2); KisSelectionMaskSP selectionMask1 = new KisSelectionMask(image); image->addNode(selectionMask1, paintLayer1); selectionMask1->setName("selectionMask1"); selectionMask1->setSelection(createPixelSelection(paintLayer1->paintDevice())); KisSelectionMaskSP selectionMask2 = new KisSelectionMask(image); selectionMask2->setName("selectionMask2"); selectionMask2->setSelection(createPixelSelection(paintLayer2->paintDevice())); image->addNode(selectionMask2, paintLayer2); KisTransformMaskSP transformMask = new KisTransformMask(); transformMask->setName("testTransformMask"); transformMask->setTransformParams(KisTransformMaskParamsInterfaceSP( new KisDumbTransformMaskParams(createTestingTransform()))); image->addNode(transformMask, paintLayer2); if (shouldMaskToShapeLayer) { // add all-visible transparency mask to crash a shape layer KisTransparencyMaskSP transparencyMask3 = new KisTransparencyMask(); transparencyMask3->setName("crashy-transparency-mask"); transparencyMask3->initSelection(shapeLayer); image->addNode(transparencyMask3, shapeLayer); } return doc; } KisDocument *createEmptyDocument() { KisImageWSP image = new KisImage(0, 1024, 1024, KoColorSpaceRegistry::instance()->rgb8(), "test for roundtrip"); KisDocument *doc = qobject_cast(KisPart::instance()->createDocument()); doc->setCurrentImage(image); doc->documentInfo()->setAboutInfo("title", image->objectName()); return doc; } #endif diff --git a/libs/ui/widgets/kis_filter_selector_widget.cc b/libs/ui/widgets/kis_filter_selector_widget.cc index 3cbddbd869..31450a5a36 100644 --- a/libs/ui/widgets/kis_filter_selector_widget.cc +++ b/libs/ui/widgets/kis_filter_selector_widget.cc @@ -1,319 +1,318 @@ /* * Copyright (c) 2007-2008 Cyrille Berger * Copyright (c) 2009 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_filter_selector_widget.h" #include #include #include #include #include #include #include #include "ui_wdgfilterselector.h" #include #include #include #include #include #include "kis_default_bounds.h" // From krita/ui #include "kis_bookmarked_configurations_editor.h" #include "kis_bookmarked_filter_configurations_model.h" #include "kis_filters_model.h" #include "kis_config.h" class ThumbnailBounds : public KisDefaultBounds { public: ThumbnailBounds() : KisDefaultBounds() {} ~ThumbnailBounds() override {} QRect bounds() const override { return QRect(0, 0, 100, 100); } private: Q_DISABLE_COPY(ThumbnailBounds) }; struct KisFilterSelectorWidget::Private { QWidget* currentCentralWidget; KisConfigWidget* currentFilterConfigurationWidget; KisFilterSP currentFilter; KisPaintDeviceSP paintDevice; Ui_FilterSelector uiFilterSelector; KisPaintDeviceSP thumb; KisBookmarkedFilterConfigurationsModel* currentBookmarkedFilterConfigurationsModel; KisFiltersModel* filtersModel; QGridLayout *widgetLayout; KisViewManager *view; bool showFilterGallery; }; KisFilterSelectorWidget::KisFilterSelectorWidget(QWidget* parent) : d(new Private) { Q_UNUSED(parent); setObjectName("KisFilterSelectorWidget"); d->currentCentralWidget = 0; d->currentFilterConfigurationWidget = 0; d->currentBookmarkedFilterConfigurationsModel = 0; d->currentFilter = 0; d->filtersModel = 0; d->view = 0; d->showFilterGallery = true; d->uiFilterSelector.setupUi(this); d->widgetLayout = new QGridLayout(d->uiFilterSelector.centralWidgetHolder); d->widgetLayout->setContentsMargins(0,0,0,0); d->widgetLayout->setHorizontalSpacing(0); showFilterGallery(false); connect(d->uiFilterSelector.filtersSelector, SIGNAL(clicked(const QModelIndex&)), SLOT(setFilterIndex(const QModelIndex &))); connect(d->uiFilterSelector.filtersSelector, SIGNAL(activated(const QModelIndex&)), SLOT(setFilterIndex(const QModelIndex &))); connect(d->uiFilterSelector.comboBoxPresets, SIGNAL(activated(int)), SLOT(slotBookmarkedFilterConfigurationSelected(int))); connect(d->uiFilterSelector.pushButtonEditPressets, SIGNAL(pressed()), SLOT(editConfigurations())); } KisFilterSelectorWidget::~KisFilterSelectorWidget() { delete d->filtersModel; delete d->currentBookmarkedFilterConfigurationsModel; delete d->currentCentralWidget; delete d->widgetLayout; delete d; } void KisFilterSelectorWidget::setView(KisViewManager *view) { d->view = view; } void KisFilterSelectorWidget::setPaintDevice(bool showAll, KisPaintDeviceSP _paintDevice) { if (!_paintDevice) return; if (d->filtersModel) delete d->filtersModel; d->paintDevice = _paintDevice; d->thumb = d->paintDevice->createThumbnailDevice(100, 100); d->thumb->setDefaultBounds(new ThumbnailBounds()); d->filtersModel = new KisFiltersModel(showAll, d->thumb); d->uiFilterSelector.filtersSelector->setFilterModel(d->filtersModel); d->uiFilterSelector.filtersSelector->header()->setVisible(false); KisConfig cfg; QModelIndex idx = d->filtersModel->indexForFilter(cfg.readEntry("FilterSelector/LastUsedFilter", "levels")); if (!idx.isValid()) { idx = d->filtersModel->indexForFilter("levels"); } if (isFilterGalleryVisible()) { d->uiFilterSelector.filtersSelector->activateFilter(idx); } } void KisFilterSelectorWidget::showFilterGallery(bool visible) { if (d->showFilterGallery == visible) { return; } d->showFilterGallery = visible; update(); emit sigFilterGalleryToggled(visible); emit sigSizeChanged(); } bool KisFilterSelectorWidget::isFilterGalleryVisible() const { return d->showFilterGallery; } KisFilterSP KisFilterSelectorWidget::currentFilter() const { return d->currentFilter; } void KisFilterSelectorWidget::setFilter(KisFilterSP f) { Q_ASSERT(f); Q_ASSERT(d->filtersModel); setWindowTitle(f->name()); dbgKrita << "setFilter: " << f; d->currentFilter = f; delete d->currentCentralWidget; { bool v = d->uiFilterSelector.filtersSelector->blockSignals(true); d->uiFilterSelector.filtersSelector->setCurrentIndex(d->filtersModel->indexForFilter(f->id())); d->uiFilterSelector.filtersSelector->blockSignals(v); } KisConfigWidget* widget = d->currentFilter->createConfigurationWidget(d->uiFilterSelector.centralWidgetHolder, d->paintDevice); if (!widget) { // No widget, so display a label instead d->uiFilterSelector.comboBoxPresets->setEnabled(false); d->uiFilterSelector.pushButtonEditPressets->setEnabled(false); d->currentFilterConfigurationWidget = 0; d->currentCentralWidget = new QLabel(i18n("No configuration options"), d->uiFilterSelector.centralWidgetHolder); d->uiFilterSelector.scrollArea->setMinimumSize(d->currentCentralWidget->sizeHint()); qobject_cast(d->currentCentralWidget)->setAlignment(Qt::AlignCenter); } else { d->uiFilterSelector.comboBoxPresets->setEnabled(true); d->uiFilterSelector.pushButtonEditPressets->setEnabled(true); d->currentFilterConfigurationWidget = widget; d->currentCentralWidget = widget; widget->layout()->setContentsMargins(0,0,0,0); d->currentFilterConfigurationWidget->setView(d->view); d->currentFilterConfigurationWidget->blockSignals(true); - d->currentFilterConfigurationWidget->setConfiguration( - d->currentFilter->defaultConfiguration(d->paintDevice)); + d->currentFilterConfigurationWidget->setConfiguration(d->currentFilter->defaultConfiguration()); d->currentFilterConfigurationWidget->blockSignals(false); d->uiFilterSelector.scrollArea->setContentsMargins(0,0,0,0); d->uiFilterSelector.scrollArea->setMinimumWidth(widget->sizeHint().width() + 18); connect(d->currentFilterConfigurationWidget, SIGNAL(sigConfigurationUpdated()), this, SIGNAL(configurationChanged())); } // Change the list of presets delete d->currentBookmarkedFilterConfigurationsModel; d->currentBookmarkedFilterConfigurationsModel = new KisBookmarkedFilterConfigurationsModel(d->thumb, f); d->uiFilterSelector.comboBoxPresets->setModel(d->currentBookmarkedFilterConfigurationsModel); // Add the widget to the layout d->currentCentralWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); d->widgetLayout->addWidget(d->currentCentralWidget, 0 , 0); update(); } void KisFilterSelectorWidget::setFilterIndex(const QModelIndex& idx) { if (!idx.isValid()) return; Q_ASSERT(d->filtersModel); KisFilter* filter = const_cast(d->filtersModel->indexToFilter(idx)); if (filter) { setFilter(filter); } else { if (d->currentFilter) { bool v = d->uiFilterSelector.filtersSelector->blockSignals(true); QModelIndex idx = d->filtersModel->indexForFilter(d->currentFilter->id()); d->uiFilterSelector.filtersSelector->setCurrentIndex(idx); d->uiFilterSelector.filtersSelector->scrollTo(idx); d->uiFilterSelector.filtersSelector->blockSignals(v); } } KisConfig cfg; cfg.writeEntry("FilterSelector/LastUsedFilter", d->currentFilter->id()); emit(configurationChanged()); } void KisFilterSelectorWidget::slotBookmarkedFilterConfigurationSelected(int index) { if (d->currentFilterConfigurationWidget) { QModelIndex modelIndex = d->currentBookmarkedFilterConfigurationsModel->index(index, 0); KisFilterConfigurationSP config = d->currentBookmarkedFilterConfigurationsModel->configuration(modelIndex); d->currentFilterConfigurationWidget->setConfiguration(config); } } void KisFilterSelectorWidget::editConfigurations() { KisSerializableConfigurationSP config = d->currentFilterConfigurationWidget ? d->currentFilterConfigurationWidget->configuration() : 0; KisBookmarkedConfigurationsEditor editor(this, d->currentBookmarkedFilterConfigurationsModel, config); editor.exec(); } void KisFilterSelectorWidget::update() { d->uiFilterSelector.filtersSelector->setVisible(d->showFilterGallery); if (d->showFilterGallery) { setMinimumWidth(qMax(sizeHint().width(), 700)); d->uiFilterSelector.scrollArea->setMinimumHeight(400); setMinimumHeight(d->uiFilterSelector.widget->sizeHint().height()); if (d->currentFilter) { bool v = d->uiFilterSelector.filtersSelector->blockSignals(true); d->uiFilterSelector.filtersSelector->setCurrentIndex(d->filtersModel->indexForFilter(d->currentFilter->id())); d->uiFilterSelector.filtersSelector->blockSignals(v); } } else { if (d->currentCentralWidget) { d->uiFilterSelector.scrollArea->setMinimumHeight(qMin(400, d->currentCentralWidget->sizeHint().height())); } setMinimumSize(d->uiFilterSelector.widget->sizeHint()); } } KisFilterConfigurationSP KisFilterSelectorWidget::configuration() { if (d->currentFilterConfigurationWidget) { KisFilterConfigurationSP config = dynamic_cast(d->currentFilterConfigurationWidget->configuration().data()); if (config) { return config; } } else if (d->currentFilter) { - return d->currentFilter->defaultConfiguration(d->paintDevice); + return d->currentFilter->defaultConfiguration(); } return 0; } void KisFilterTree::setFilterModel(QAbstractItemModel *model) { m_model = model; } void KisFilterTree::activateFilter(QModelIndex idx) { setModel(m_model); selectionModel()->select(idx, QItemSelectionModel::SelectCurrent); expand(idx); scrollTo(idx); emit activated(idx); } void KisFilterSelectorWidget::setVisible(bool visible) { QWidget::setVisible(visible); if (visible) { update(); } } diff --git a/libs/ui/widgets/kis_wdg_generator.cpp b/libs/ui/widgets/kis_wdg_generator.cpp index b52d8c9cd3..8dc3da51db 100644 --- a/libs/ui/widgets/kis_wdg_generator.cpp +++ b/libs/ui/widgets/kis_wdg_generator.cpp @@ -1,164 +1,164 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "widgets/kis_wdg_generator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_wdggenerators.h" class KisGeneratorItem : public QListWidgetItem { public: KisGeneratorItem(const QString & text, QListWidget * parent = 0, int type = Type) : QListWidgetItem(text, parent, type) { } KisGeneratorSP generator; }; struct KisWdgGenerator::Private { public: Private() : centralWidget(0), view(0) { } QWidget * centralWidget; // Active generator settings widget KisGeneratorSP currentGenerator; Ui_WdgGenerators uiWdgGenerators; KisPaintDeviceSP dev; QGridLayout *widgetLayout; KisViewManager *view; }; KisWdgGenerator::KisWdgGenerator(QWidget * parent) : QWidget(parent) , d(new Private()) { KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8(0)); } KisWdgGenerator::~KisWdgGenerator() { delete d; } void KisWdgGenerator::initialize(KisViewManager *view) { d->view = view; d->uiWdgGenerators.setupUi(this); d->widgetLayout = new QGridLayout(d->uiWdgGenerators.centralWidgetHolder); QList generators = KisGeneratorRegistry::instance()->values(); Q_FOREACH (const KisGeneratorSP generator, generators) { Q_ASSERT(generator); KisGeneratorItem * item = new KisGeneratorItem(generator->name(), d->uiWdgGenerators.lstGenerators, QListWidgetItem::UserType + 1); item->generator = generator; } connect(d->uiWdgGenerators.lstGenerators, SIGNAL(currentRowChanged(int)), this, SLOT(slotGeneratorActivated(int))); if (d->uiWdgGenerators.lstGenerators->count() > 0) { d->uiWdgGenerators.lstGenerators->setCurrentRow(0); } } void KisWdgGenerator::setConfiguration(const KisFilterConfigurationSP config) { for (int i = 0; i < d->uiWdgGenerators.lstGenerators->count(); ++i) { KisGeneratorItem * item = static_cast(d->uiWdgGenerators.lstGenerators->item(i)); if (item->generator->id() == config->name()) { // match! slotGeneratorActivated(i); d->uiWdgGenerators.lstGenerators->setCurrentRow(i); KisConfigWidget * wdg = dynamic_cast(d->centralWidget); if (wdg) { wdg->setConfiguration(config); } return; } } } KisFilterConfigurationSP KisWdgGenerator::configuration() { KisConfigWidget * wdg = dynamic_cast(d->centralWidget); if (wdg) { KisFilterConfigurationSP config = dynamic_cast(wdg->configuration().data()); if (config) { return config; } } else { - return d->currentGenerator->defaultConfiguration(0); + return d->currentGenerator->defaultConfiguration(); } return 0; } void KisWdgGenerator::slotGeneratorActivated(int row) { KisGeneratorItem *item = dynamic_cast(d->uiWdgGenerators.lstGenerators->item(row)); if (!item) { d->centralWidget = new QLabel(i18n("No configuration options."), d->uiWdgGenerators.centralWidgetHolder); } else { d->currentGenerator = item->generator; delete d->centralWidget; KisConfigWidget* widget = d->currentGenerator->createConfigurationWidget(d->uiWdgGenerators.centralWidgetHolder, d->dev); if (!widget) { // No widget, so display a label instead d->centralWidget = new QLabel(i18n("No configuration options."), d->uiWdgGenerators.centralWidgetHolder); } else { d->centralWidget = widget; widget->setView(d->view); - widget->setConfiguration(d->currentGenerator->defaultConfiguration(d->dev)); + widget->setConfiguration(d->currentGenerator->defaultConfiguration()); } } d->widgetLayout->addWidget(d->centralWidget, 0 , 0); d->uiWdgGenerators.centralWidgetHolder->setMinimumSize(d->centralWidget->minimumSize()); } diff --git a/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt b/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt index 18de88fc76..62da3c35dc 100644 --- a/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt +++ b/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt @@ -1,91 +1,92 @@ # Copyright (C) 2012, 2013 Shaheed Haque # Copyright (C) 2013 Alex Turbov # Copyright (C) 2014-2016 Boudewijn Rempt # # 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. # # 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. include(CMakeParseArguments) # # Simple helper function to install plugin and related files # having only a name of the plugin... # (just to reduce syntactic noise when a lot of plugins get installed) # function(install_pykrita_plugin name) set(_options) set(_one_value_args) set(_multi_value_args PATTERNS FILE) cmake_parse_arguments(install_pykrita_plugin "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN}) if(NOT name) message(FATAL_ERROR "Plugin filename is not given") endif() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py) install(FILES kritapykrita_${name}.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita) foreach(_f ${name}.py ${name}.ui ${install_pykrita_plugin_FILE}) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_f}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${_f} DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita) endif() endforeach() elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${name}) install(FILES ${name}/kritapykrita_${name}.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita) install( DIRECTORY ${name} DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita FILES_MATCHING PATTERN "*.py" PATTERN "*.ui" PATTERN "__pycache__*" EXCLUDE ) # TODO Is there any way to form a long PATTERN options string # and use it in a single install() call? # NOTE Install specified patterns one-by-one... foreach(_pattern ${install_pykrita_plugin_PATTERNS}) install( DIRECTORY ${name} DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita FILES_MATCHING PATTERN "${_pattern}" PATTERN "__pycache__*" EXCLUDE ) endforeach() else() message(FATAL_ERROR "Do not know what to do with ${name}") endif() endfunction() install_pykrita_plugin(hello) install_pykrita_plugin(assignprofiledialog) install_pykrita_plugin(scripter) +install_pykrita_plugin(highpass) # if(PYTHON_VERSION_MAJOR VERSION_EQUAL 3) # install_pykrita_plugin(cmake_utils) # install_pykrita_plugin(js_utils PATTERNS "*.json") # install_pykrita_plugin(expand PATTERNS "*.expand" "templates/*.tpl") # endif() install( DIRECTORY libkritapykrita DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita FILES_MATCHING PATTERN "*.py" PATTERN "__pycache__*" EXCLUDE ) diff --git a/plugins/extensions/pykrita/plugin/plugins/assignprofiledialog/assignprofiledialog.py b/plugins/extensions/pykrita/plugin/plugins/assignprofiledialog/assignprofiledialog.py index 512f7a49cb..6aa76e8810 100644 --- a/plugins/extensions/pykrita/plugin/plugins/assignprofiledialog/assignprofiledialog.py +++ b/plugins/extensions/pykrita/plugin/plugins/assignprofiledialog/assignprofiledialog.py @@ -1,46 +1,44 @@ import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import * from krita import * class AssignProfileDialog(ViewExtension): def __init__(self, parent): super().__init__(parent) def assignProfile(self): doc = Application.activeDocument() if doc == None: QMessageBox.information(Application.activeWindow().qwindow(), "Assign Profile", "There is no active document.") return self.dialog = QDialog(Application.activeWindow().qwindow()) - self.dialog.setWindowModality(Qt.NonModal) - + self.cmbProfile = QComboBox(self.dialog) - for profile in sorted(Application.profiles(doc.colorModel(), doc.colorDepth())): self.cmbProfile.addItem(profile) vbox = QVBoxLayout(self.dialog) vbox.addWidget(self.cmbProfile) self.buttonBox = QDialogButtonBox(self.dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.accepted.connect(self.dialog.accept) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.dialog.reject) vbox.addWidget(self.buttonBox) self.dialog.show() self.dialog.activateWindow() - self.dialog.exec() + self.dialog.exec_() def accept(self): doc = Application.activeDocument() doc.setColorProfile(self.cmbProfile.currentText()) def setup(self): action = Application.createAction("Assign Profile to Image") action.triggered.connect(self.assignProfile) Scripter.addViewExtension(AssignProfileDialog(Application)) diff --git a/plugins/extensions/pykrita/plugin/plugins/highpass/__init__.py b/plugins/extensions/pykrita/plugin/plugins/highpass/__init__.py new file mode 100644 index 0000000000..f1ccabc909 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/highpass/__init__.py @@ -0,0 +1,2 @@ +# let's make a module +from .highpass import * diff --git a/plugins/extensions/pykrita/plugin/plugins/highpass/high-pass.scm b/plugins/extensions/pykrita/plugin/plugins/highpass/high-pass.scm new file mode 100644 index 0000000000..94f6c3c397 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/highpass/high-pass.scm @@ -0,0 +1,176 @@ +;high-pass.scm +; by Rob Antonishen +; http://ffaat.pointclark.net + +; Version 1.2 (20120427) + +; Description +; +; This implements a highpass filter using the blur and invert method +; parameters are blur radius, a preserve colour toggle, and whether to keep the original layer +; +; Changes: +; v1.1 fixes "bug" created by bug fix for gimp 2.6.9 in gimp-histogram +; v1.2 changed to a different layer blend mode (thanks Blacklemon67) that +; has less histogram banding, by eliminating the need for the contrast boost. +; + +; License: +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; The GNU Public License is available at +; http://www.gnu.org/copyleft/gpl.html + +(define (high-pass img inLayer inRadius inMode inKeepOrig) + (let* + ( + (blur-layer 0) + (blur-layer2 0) + (working-layer 0) + (colours-layer 0) + (colours-layer2 0) + (orig-name (car (gimp-drawable-get-name inLayer))) + ) + ; it begins here + (gimp-context-push) + (gimp-image-undo-group-start img) + + ;if keep original selected, make a working copy + (if (= inKeepOrig TRUE) + (begin + (set! working-layer (car (gimp-layer-copy inLayer FALSE))) + (gimp-image-add-layer img working-layer -1) + (gimp-drawable-set-name working-layer "working") + ) + (set! working-layer inLayer) ;else + ) + + (gimp-image-set-active-layer img working-layer) + + ;if keeping colours + (if (or (= inMode 1) (= inMode 3)) + (begin + (set! colours-layer (car (gimp-layer-copy inLayer FALSE))) + (gimp-image-add-layer img colours-layer -1) + (gimp-image-lower-layer img colours-layer) + (gimp-drawable-set-name colours-layer "colours") + (gimp-image-set-active-layer img working-layer) + ) + ) + + ;if Greyscale, desaturate + (if (or (= inMode 2) (= inMode 3)) + (gimp-desaturate working-layer) + ) + + ;Duplicate on top and blur + (set! blur-layer (car (gimp-layer-copy working-layer FALSE))) + (gimp-image-add-layer img blur-layer -1) + (gimp-drawable-set-name blur-layer "blur") + + ;blur + (plug-in-gauss 1 img blur-layer inRadius inRadius 1) + + (if (<= inMode 3) + (begin + ;v1.2 using grain extract... + (gimp-layer-set-mode blur-layer GRAIN-EXTRACT-MODE) + (set! working-layer (car (gimp-image-merge-down img blur-layer 0))) + + ; if preserve chroma, change set the mode to value and merge down with the layer we kept earlier. + (if (= inMode 3) + (begin + (gimp-layer-set-mode working-layer VALUE-MODE) + (set! working-layer (car (gimp-image-merge-down img working-layer 0))) + ) + ) + + ; if preserve DC, change set the mode to overlay and merge down with the average colour of the layer we kept earlier. + (if (= inMode 1) + (begin + (gimp-context-set-foreground (list + (car (gimp-histogram colours-layer HISTOGRAM-RED 0 255)) + (car (gimp-histogram colours-layer HISTOGRAM-GREEN 0 255)) + (car (gimp-histogram colours-layer HISTOGRAM-BLUE 0 255))) + ) + (gimp-drawable-fill colours-layer FOREGROUND-FILL) + (gimp-layer-set-mode working-layer OVERLAY-MODE) + (set! working-layer (car (gimp-image-merge-down img working-layer 0))) + ) + ) + ) + (begin ;else 4=redrobes method + + (gimp-image-set-active-layer img blur-layer) ;top layer + + ;get the average colour of the input layer + (set! colours-layer (car (gimp-layer-copy inLayer FALSE))) + (gimp-image-add-layer img colours-layer -1) + (gimp-drawable-set-name colours-layer "colours") + + (gimp-context-set-foreground (list + (car (gimp-histogram colours-layer HISTOGRAM-RED 0 255)) + (car (gimp-histogram colours-layer HISTOGRAM-GREEN 0 255)) + (car (gimp-histogram colours-layer HISTOGRAM-BLUE 0 255))) + ) + (gimp-drawable-fill colours-layer FOREGROUND-FILL) + (gimp-image-set-active-layer img colours-layer) + + ;copy the solid colour layer + (set! colours-layer2 (car (gimp-layer-copy colours-layer FALSE))) + (gimp-image-add-layer img colours-layer2 -1) + (gimp-layer-set-mode colours-layer SUBTRACT-MODE) + (gimp-image-set-active-layer img colours-layer2) + + ;copy the blurred layer + (set! blur-layer2 (car (gimp-layer-copy blur-layer FALSE))) + (gimp-image-add-layer img blur-layer2 -1) + (gimp-layer-set-mode blur-layer2 SUBTRACT-MODE) + + (set! blur-layer (car (gimp-image-merge-down img colours-layer 0))) + (set! blur-layer2 (car (gimp-image-merge-down img blur-layer2 0))) + + (gimp-layer-set-mode blur-layer SUBTRACT-MODE) + (gimp-layer-set-mode blur-layer2 ADDITION-MODE) + + (set! working-layer (car (gimp-image-merge-down img blur-layer 0))) + (set! working-layer (car (gimp-image-merge-down img blur-layer2 0))) + + ) + ) + + (if (= inKeepOrig TRUE) + (gimp-drawable-set-name working-layer (string-append orig-name " high pass")) + (gimp-drawable-set-name working-layer orig-name) + ) + + ;done + (gimp-progress-end) + (gimp-image-undo-group-end img) + (gimp-displays-flush) + (gimp-context-pop) + ) +) + +(script-fu-register "high-pass" + "/Filters/Generic/_High Pass Filter" + "Basic High Pass Filter." + "Rob Antonishen" + "Rob Antonishen" + "April 2012" + "RGB* GRAY*" + SF-IMAGE "image" 0 + SF-DRAWABLE "drawable" 0 + SF-ADJUSTMENT "Filter Radius" '(10 2 200 1 10 0 0) + SF-OPTION "Mode" '("Colour" "Preserve DC" "Greyscale" "Greyscale, Apply Chroma" "Redrobes") + SF-TOGGLE "Keep Original Layer?" TRUE +) \ No newline at end of file diff --git a/plugins/extensions/pykrita/plugin/plugins/highpass/highpass.py b/plugins/extensions/pykrita/plugin/plugins/highpass/highpass.py new file mode 100644 index 0000000000..5cbe641ea5 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/highpass/highpass.py @@ -0,0 +1,117 @@ +import sys +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * +from krita import * + +class HighpassViewExtension(ViewExtension): + + def __init__(self, parent): + super().__init__(parent) + + def setup(self): + action = Application.createAction("High Pass") + action.triggered.connect(self.showDialog) + + def showDialog(self): + doc = Application.activeDocument() + if doc == None: + QMessageBox.information(Application.activeWindow().qwindow(), "Highpass Filter", "There is no active image.") + return + + self.dialog = QDialog(Application.activeWindow().qwindow()) + + self.intRadius = QSpinBox() + self.intRadius.setValue(10) + self.intRadius.setRange(2, 200) + + self.cmbMode = QComboBox() + self.cmbMode.addItems(["Color", "Preserve DC", "Greyscale", "Greyscale, Apply Chroma", "Redrobes"]) + self.keepOriginal = QCheckBox("Keep Original Layer"); + self.keepOriginal.setChecked(True) + form = QFormLayout() + form.addRow("Filter Radius", self.intRadius) + form.addRow("Mode", self.cmbMode) + form.addRow("", self.keepOriginal) + + self.buttonBox = QDialogButtonBox(self.dialog) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.buttonBox.accepted.connect(self.dialog.accept) + self.buttonBox.accepted.connect(self.highpass) + self.buttonBox.rejected.connect(self.dialog.reject) + + vbox = QVBoxLayout(self.dialog) + vbox.addLayout(form) + vbox.addWidget(self.buttonBox) + + self.dialog.show() + self.dialog.activateWindow() + self.dialog.exec_() + + def highpass(self): + # XXX: Start undo macro + image = Application.activeDocument() + original = image.activeNode() + working_layer = original + + # We can only highpass on paint layers + if self.keepOriginal.isChecked() or original.type() != "paintlayer": + working_layer = image.createNode("working", "paintlayer") + working_layer.setColorSpace(original.colorModel(), original.colorSpace(), original.profile()) + working_layer.writeBytes(original.readBytes(0, 0, image.width(), image.height()), + 0, 0, image.width(), image.height()) + original.parentNode().addChildNode(working_layer, original) # XXX: Unimplemented + + image.setActiveNode(working_layer) + colors_layer = None; + + # if keeping colors + if self.cmbMode.currentIndex() == 1 || self.cmbMode.currentIndex() == 3: + colors_layer = working_layer.duplicate() # XXX: Unimplemented + colors_layer.setName("colors") + original.parentNode().addChildNode(working_layer, colors_layer) # XXX: Unimplemented + + # if greyscale, desature + if (self.cmbMode.currentIndex() == 2 || self.cmbMode.currentIndex() == 3): + filter = Application.filter("desaturate") + filter.apply(working_layer, 0, 0, image.width(), image.height()) + + # Duplicate on top and blur + blur_layer = working_layer.duplicate() + blur_layer.setName("blur") + original.parentNode().addChildNode(blur_layer, working_layer) # XXX: Unimplemented + + # blur + filter = Application.filter("gaussian blur") + filter_configuration = filter.configuration() + filter_configuration.setProperty("horizRadius", self.intRadius.value()) + filter_configuration.setProperty("vertRadius", self.intRadius.value()) + filter_configuration.setProperty("lockAspect", true) + filter.setConfiguration(filter_configuration) + filter.apply(blur_layer, 0, 0, image.width(), image.height()) + + + if self.cmbMode.currentIndex() <= 3: + blur_layer.setBlendingMode("grain_extract") + working_layer = image.mergeDown(blur_layer) + + # if preserve chroma, change set the mode to value and merge down with the layer we kept earlier. + if self.cmbMode.currentIndex() == 3: + working_layer.setBlendingMode("value") + working_layer = image.mergeDown(working_layer) + + # if preserve DC, change set the mode to overlay and merge down with the average colour of the layer we kept earlier. + if self.cmbMode.currentIndex() == 1: + # get the average color of the entire image + # clear the colors layer to the given color + working_layer = image.mergeDown(working_layer) + + else: # Mode == 4, RedRobes + image.setActiveNode(blur_layer) + # Get the average color of the input layer + # copy the solid colour layer + # copy the blurred layer + # XXX: End undo macro + +Scripter.addViewExtension(HighpassViewExtension(Krita.instance())) + diff --git a/plugins/extensions/pykrita/plugin/plugins/highpass/kritapykrita_highpass.desktop b/plugins/extensions/pykrita/plugin/plugins/highpass/kritapykrita_highpass.desktop new file mode 100644 index 0000000000..34d9564a12 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/highpass/kritapykrita_highpass.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Service +ServiceTypes=Krita/PythonPlugin +X-KDE-Library=highpass +X-Python-2-Compatible=false +Name=Highpass Filter +Comment=Highpass Filter, based on http://registry.gimp.org/node/7385 diff --git a/plugins/extensions/pykrita/sip/krita/Document.sip b/plugins/extensions/pykrita/sip/krita/Document.sip index 73c4b92742..92b9f8a3b9 100644 --- a/plugins/extensions/pykrita/sip/krita/Document.sip +++ b/plugins/extensions/pykrita/sip/krita/Document.sip @@ -1,51 +1,52 @@ class Document : QObject /NoDefaultCtors/ { %TypeHeaderCode #include "Document.h" %End Document(const Document & __0); public Q_SLOTS: Node * activeNode() const; void setActiveNode(Node* value); bool batchmode() const; void setBatchmode(bool value); QString colorDepth() const; QString colorModel() const; QString colorProfile() const; bool setColorProfile(const QString &colorProfile); void setColorSpace(const QString &value, const QString &colorDepth, const QString &colorProfile); QString documentInfo() const; void setDocumentInfo(const QString &document); QString fileName() const; void setFileName(QString value); int height() const; void setHeight(int value); QString name() const; void setName(QString value); int resolution() const; void setResolution(int value); Node * rootNode() const; Selection * selection() const; void setSelection(Selection* value); int width() const; void setWidth(int value); double xRes() const; void setXRes(double xRes) const; double yRes() const; void setyRes(double yRes) const; QByteArray pixelData(int x, int y, int w, int h) const; bool close(); void crop(int x, int y, int w, int h); bool exportImage(const QString &filename, const InfoObject & exportConfiguration); void flatten(); void resizeImage(int w, int h); bool save(); bool saveAs(const QString & filename); void openView(); - Node * createNode(const QString & name, const QString & nodeType); + Node *createNode(const QString & name, const QString & nodeType); + Node *mergeDown(Node *node); Q_SIGNALS: void nodeCreated(Node *node); private: }; diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip index 71e0e6769a..c79aa07cbf 100644 --- a/plugins/extensions/pykrita/sip/krita/Node.sip +++ b/plugins/extensions/pykrita/sip/krita/Node.sip @@ -1,59 +1,58 @@ class Node : QObject { %TypeHeaderCode #include "Node.h" %End Node(const Node & __0); public: virtual ~Node(); public Q_SLOTS: bool alphaLocked() const; void setAlphaLocked(bool value); QString blendingMode() const; void setBlendingMode(QString value); QList channels() const; QList childNodes() const; void setChildNodes(QList value); QString colorDepth() const; QString colorLabel() const; void setColorLabel(QString value); QString colorModel() const; QString colorProfile() const; void setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); bool inheritAlpha() const; void setInheritAlpha(bool value); bool locked() const; void setLocked(bool value); QString name() const; void setName(QString value); int opacity() const; void setOpacity(int value); Node * parentNode() const; void setParentNode(Node* value); QString type() const; void setType(QString value); bool visible() const; void setVisible(bool value); InfoObject * metaDataInfo() const; void setMetaDataInfo(InfoObject* value); Generator * generator() const; void setGenerator(Generator* value); Filter * filter() const; void setFilter(Filter* value); Transformation * transformation() const; void setTransformation(Transformation* value); - Selection * selection() const; - void setSelection(Selection* value); QString fileName() const; void setFileName(QString value); QByteArray pixelData(int x, int y, int w, int h) const; + QByteArray projectionPixelData(int x, int y, int w, int h) const; void setPixelData(QByteArray value, int x, int y, int w, int h); QRect bounds() const; void move(int x, int y); void moveToParent(Node* parent); void remove(); - Node * duplicate(); + Node *duplicate(); void save(const QString &filename, double xRes, double yRes); Q_SIGNALS: private: }; diff --git a/plugins/extensions/pykrita/sip/krita/Selection.sip b/plugins/extensions/pykrita/sip/krita/Selection.sip index 8927a8370d..c7ca1732a5 100644 --- a/plugins/extensions/pykrita/sip/krita/Selection.sip +++ b/plugins/extensions/pykrita/sip/krita/Selection.sip @@ -1,37 +1,38 @@ class Selection : QObject { %TypeHeaderCode #include "Selection.h" %End Selection(const Selection & __0); public: Selection(QObject* parent /TransferThis/ = 0); virtual ~Selection(); public Q_SLOTS: - int width() const; int height() const; int x() const; int y() const; void move(int x, int y); - void clear(); void contract(int value); void cut(Node *node); void paste(Node *source, Node*destination); - void deselect(); - void expand(int value); - void feather(int value); - void fill(Node* node); - void grow(int value); + void erode(); + void dilate(); + void border(int xRadius, int yRadius); + void feather(int radius); + void grow(int xradius, int yradius); + void shrink(int xRadius, int yRadius, bool edgeLock); + void smooth(); void invert(); void resize(int w, int h); - void rotate(int degrees); void select(int x, int y, int w, int h, int value); - void selectAll(Node* node); + void selectAll(Node* node, int value); + void replace(Selection *selection); + void add(Selection *selection); + void subtract(Selection *selection); + void intersect(Selection *selection); QByteArray pixelData(int x, int y, int w, int h) const; void setPixelData(QByteArray value, int x, int y, int w, int h); - -Q_SIGNALS: private: }; diff --git a/plugins/filters/blur/kis_blur_filter.cpp b/plugins/filters/blur/kis_blur_filter.cpp index 7511a22ce2..46b62dbe0d 100644 --- a/plugins/filters/blur/kis_blur_filter.cpp +++ b/plugins/filters/blur/kis_blur_filter.cpp @@ -1,138 +1,138 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "kis_blur_filter.h" #include #include #include #include "kis_wdg_blur.h" #include "ui_wdgblur.h" #include #include #include #include #include "kis_mask_generator.h" #include "kis_lod_transform.h" KisBlurFilter::KisBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgBlur(parent); } -KisFilterConfigurationSP KisBlurFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("halfWidth", 5); config->setProperty("halfHeight", 5); config->setProperty("rotate", 0); config->setProperty("strength", 0); config->setProperty("shape", 0); return config; } void KisBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; const uint halfWidth = t.scale((config->getProperty("halfWidth", value)) ? value.toUInt() : 5); const uint halfHeight = t.scale((config->getProperty("halfHeight", value)) ? value.toUInt() : 5); int shape = (config->getProperty("shape", value)) ? value.toInt() : 0; uint width = 2 * halfWidth + 1; uint height = 2 * halfHeight + 1; float aspectRatio = (float) width / height; int rotate = (config->getProperty("rotate", value)) ? value.toInt() : 0; int strength = 100 - (config->getProperty("strength", value) ? value.toUInt() : 0); int hFade = (halfWidth * strength) / 100; int vFade = (halfHeight * strength) / 100; KisMaskGenerator* kas; dbgKrita << width << "" << height << "" << hFade << "" << vFade; switch (shape) { case 1: kas = new KisRectangleMaskGenerator(width, aspectRatio, hFade, vFade, 2, true); break; case 0: default: kas = new KisCircleMaskGenerator(width, aspectRatio, hFade, vFade, 2, true); break; } QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas, rotate * M_PI / 180.0); delete kas; KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } QRect KisBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth, -halfHeight, halfWidth, halfHeight); } diff --git a/plugins/filters/blur/kis_blur_filter.h b/plugins/filters/blur/kis_blur_filter.h index 8fcdf9823e..87e48eba15 100644 --- a/plugins/filters/blur/kis_blur_filter.h +++ b/plugins/filters/blur/kis_blur_filter.h @@ -1,48 +1,48 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BLUR_FILTER_H #define KIS_BLUR_FILTER_H #include "filter/kis_filter.h" class KisBlurFilter : public KisFilter { public: KisBlurFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("blur", i18n("Blur")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; QRect neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; QRect changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; }; #endif diff --git a/plugins/filters/blur/kis_gaussian_blur_filter.cpp b/plugins/filters/blur/kis_gaussian_blur_filter.cpp index 47a59b4caf..40450579d5 100644 --- a/plugins/filters/blur/kis_gaussian_blur_filter.cpp +++ b/plugins/filters/blur/kis_gaussian_blur_filter.cpp @@ -1,122 +1,122 @@ /* * This file is part of Krita * * Copyright (c) 2009 Edward Apap * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_gaussian_blur_filter.h" #include "kis_wdg_gaussian_blur.h" #include #include #include #include #include "ui_wdg_gaussian_blur.h" #include #include #include #include #include "kis_lod_transform.h" #include KisGaussianBlurFilter::KisGaussianBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Gaussian Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisGaussianBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgGaussianBlur(parent); } -KisFilterConfigurationSP KisGaussianBlurFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisGaussianBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("horizRadius", 5); config->setProperty("vertRadius", 5); config->setProperty("lockAspect", true); return config; } void KisGaussianBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; config->getProperty("horizRadius", value); float horizontalRadius = t.scale(value.toFloat()); config->getProperty("vertRadius", value); float verticalRadius = t.scale(value.toFloat()); QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } KisGaussianKernel::applyGaussian(device, rect, horizontalRadius, verticalRadius, channelFlags, progressUpdater); } QRect KisGaussianBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; /** * NOTE: integer devision by two is done on purpose, * because the kernel size is always odd */ const int halfWidth = _config->getProperty("horizRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisGaussianBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = _config->getProperty("horizRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted( -halfWidth, -halfHeight, halfWidth, halfHeight); } diff --git a/plugins/filters/blur/kis_gaussian_blur_filter.h b/plugins/filters/blur/kis_gaussian_blur_filter.h index cb8349860f..eb5e18da39 100644 --- a/plugins/filters/blur/kis_gaussian_blur_filter.h +++ b/plugins/filters/blur/kis_gaussian_blur_filter.h @@ -1,50 +1,50 @@ /* This file is part of Krita * * Copyright (c) 2009 Edward Apap * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_GAUSSIAN_BLUR_FILTER_H #define KIS_GAUSSIAN_BLUR_FILTER_H #include "filter/kis_filter.h" #include "ui_wdg_gaussian_blur.h" #include class KisGaussianBlurFilter : public KisFilter { public: KisGaussianBlurFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("gaussian blur", i18n("Gaussian Blur")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; QRect neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; QRect changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; }; #endif diff --git a/plugins/filters/blur/kis_lens_blur_filter.cpp b/plugins/filters/blur/kis_lens_blur_filter.cpp index a1bc478869..01c42c5f01 100644 --- a/plugins/filters/blur/kis_lens_blur_filter.cpp +++ b/plugins/filters/blur/kis_lens_blur_filter.cpp @@ -1,204 +1,204 @@ /* * This file is part of Krita * * Copyright (c) 2010 Edward Apap * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_lens_blur_filter.h" #include "kis_wdg_lens_blur.h" #include #include #include #include "ui_wdg_lens_blur.h" #include #include #include #include #include "kis_lod_transform.h" #include #include KisLensBlurFilter::KisLensBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Lens Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisLensBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgLensBlur(parent); } QSize KisLensBlurFilter::getKernelHalfSize(const KisFilterConfigurationSP config, int lod) { QPolygonF iris = getIrisPolygon(config, lod); QRect rect = iris.boundingRect().toAlignedRect(); int w = std::ceil(qreal(rect.width()) / 2.0); int h = std::ceil(qreal(rect.height()) / 2.0); return QSize(w, h); } -KisFilterConfigurationSP KisLensBlurFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisLensBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("irisShape", "Pentagon (5)"); config->setProperty("irisRadius", 5); config->setProperty("irisRotation", 0); QSize halfSize = getKernelHalfSize(config, 0); config->setProperty("halfWidth", halfSize.width()); config->setProperty("halfHeight", halfSize.height()); return config; } QPolygonF KisLensBlurFilter::getIrisPolygon(const KisFilterConfigurationSP config, int lod) { KIS_ASSERT_RECOVER(config) { return QPolygonF(); } KisLodTransformScalar t(lod); QVariant value; config->getProperty("irisShape", value); QString irisShape = value.toString(); config->getProperty("irisRadius", value); uint irisRadius = t.scale(value.toUInt()); config->getProperty("irisRotation", value); uint irisRotation = value.toUInt(); if (irisRadius < 1) return QPolygon(); QPolygonF irisShapePoly; int sides = 1; qreal angle = 0; if (irisShape == "Triangle") sides = 3; else if (irisShape == "Quadrilateral (4)") sides = 4; else if (irisShape == "Pentagon (5)") sides = 5; else if (irisShape == "Hexagon (6)") sides = 6; else if (irisShape == "Heptagon (7)") sides = 7; else if (irisShape == "Octagon (8)") sides = 8; else return QPolygonF(); for (int i = 0; i < sides; ++i) { irisShapePoly << QPointF(0.5 * cos(angle), 0.5 * sin(angle)); angle += 2 * M_PI / sides; } QTransform transform; transform.rotate(irisRotation); transform.scale(irisRadius * 2, irisRadius * 2); QPolygonF transformedIris = transform.map(irisShapePoly); return transformedIris; } void KisLensBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } const int lod = device->defaultBounds()->currentLevelOfDetail(); QPolygonF transformedIris = getIrisPolygon(config, lod); if (transformedIris.isEmpty()) return; QRectF boundingRect = transformedIris.boundingRect(); int kernelWidth = boundingRect.toAlignedRect().width(); int kernelHeight = boundingRect.toAlignedRect().height(); QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32); kernelRepresentation.fill(0); QPainter imagePainter(&kernelRepresentation); imagePainter.setRenderHint(QPainter::Antialiasing); imagePainter.setBrush(QColor::fromRgb(255, 255, 255)); QTransform offsetTransform; offsetTransform.translate(-boundingRect.x(), -boundingRect.y()); imagePainter.setTransform(offsetTransform); imagePainter.drawPolygon(transformedIris, Qt::WindingFill); // construct kernel from image Eigen::Matrix irisKernel(kernelHeight, kernelWidth); for (int j = 0; j < kernelHeight; ++j) { for (int i = 0; i < kernelWidth; ++i) { irisKernel(j, i) = qRed(kernelRepresentation.pixel(i, j)); } } // apply convolution KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(irisKernel, 0, irisKernel.sum()); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } QRect KisLensBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisLensBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth, -halfHeight, halfWidth, halfHeight); } diff --git a/plugins/filters/blur/kis_lens_blur_filter.h b/plugins/filters/blur/kis_lens_blur_filter.h index 1f66559fa0..11a06fe7e4 100644 --- a/plugins/filters/blur/kis_lens_blur_filter.h +++ b/plugins/filters/blur/kis_lens_blur_filter.h @@ -1,59 +1,59 @@ /* * This file is part of Krita * * Copyright (c) 2010 Edward Apap * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LENS_BLUR_FILTER_H #define KIS_LENS_BLUR_FILTER_H #include "filter/kis_filter.h" #include "ui_wdg_lens_blur.h" #include class KisLensBlurFilter : public KisFilter { public: KisLensBlurFilter(); public: void processImpl(KisPaintDeviceSP src, const QRect& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("lens blur", i18n("Lens Blur")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; static QSize getKernelHalfSize(const KisFilterConfigurationSP config, int lod); QRect neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; QRect changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; public: KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; private: static QPolygonF getIrisPolygon(const KisFilterConfigurationSP config, int lod); }; #endif diff --git a/plugins/filters/blur/kis_motion_blur_filter.cpp b/plugins/filters/blur/kis_motion_blur_filter.cpp index b691615361..690d5495f2 100644 --- a/plugins/filters/blur/kis_motion_blur_filter.cpp +++ b/plugins/filters/blur/kis_motion_blur_filter.cpp @@ -1,166 +1,166 @@ /* * This file is part of Krita * * Copyright (c) 2010 Edward Apap * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_motion_blur_filter.h" #include "kis_wdg_motion_blur.h" #include #include #include #include "ui_wdg_motion_blur.h" #include #include #include #include #include "kis_lod_transform.h" #include #include KisMotionBlurFilter::KisMotionBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Motion Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisMotionBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgMotionBlur(parent); } -KisFilterConfigurationSP KisMotionBlurFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisMotionBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("blurAngle", 0); config->setProperty("blurLength", 5); return config; } void KisMotionBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); QVariant value; config->getProperty("blurAngle", value); uint blurAngle = value.toUInt(); KisLodTransformScalar t(device); config->getProperty("blurLength", value); uint blurLength = t.scale(value.toUInt()); if (blurLength == 0) return; QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } // convert angle to radians qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; // construct image qreal halfWidth = blurLength / 2.0 * cos(angleRadians); qreal halfHeight = blurLength / 2.0 * sin(angleRadians); int kernelWidth = ceil(fabs(halfWidth)) * 2; int kernelHeight = ceil(fabs(halfHeight)) * 2; // check for zero dimensions (vertical/horizontal motion vectors) kernelWidth = (kernelWidth == 0) ? 1 : kernelWidth; kernelHeight = (kernelHeight == 0) ? 1 : kernelHeight; QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32); kernelRepresentation.fill(0); QPainter imagePainter(&kernelRepresentation); imagePainter.setRenderHint(QPainter::Antialiasing); imagePainter.setPen(QPen(QColor::fromRgb(255, 255, 255), 1.0)); imagePainter.drawLine(QPointF(kernelWidth / 2 - halfWidth, kernelHeight / 2 + halfHeight), QPointF(kernelWidth / 2 + halfWidth, kernelHeight / 2 - halfHeight)); // construct kernel from image Eigen::Matrix motionBlurKernel(kernelHeight, kernelWidth); for (int j = 0; j < kernelHeight; ++j) { for (int i = 0; i < kernelWidth; ++i) { motionBlurKernel(j, i) = qRed(kernelRepresentation.pixel(i, j)); } } // apply convolution KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(motionBlurKernel, 0, motionBlurKernel.sum()); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } QRect KisMotionBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; uint blurAngle = _config->getProperty("blurAngle", value) ? value.toUInt() : 0; uint blurLength = t.scale(_config->getProperty("blurLength", value) ? value.toUInt() : 5); qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; const int halfWidth = ceil(fabs(blurLength / 2.0 * cos(angleRadians))); const int halfHeight = ceil(fabs(blurLength / 2.0 * cos(angleRadians))); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisMotionBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; uint blurAngle = _config->getProperty("blurAngle", value) ? value.toUInt() : 0; uint blurLength = t.scale(_config->getProperty("blurLength", value) ? value.toUInt() : 5); qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; const int halfWidth = ceil(fabs(blurLength * cos(angleRadians))); const int halfHeight = ceil(fabs(blurLength * cos(angleRadians))); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } diff --git a/plugins/filters/blur/kis_motion_blur_filter.h b/plugins/filters/blur/kis_motion_blur_filter.h index 5a1c4e238b..940c469c10 100644 --- a/plugins/filters/blur/kis_motion_blur_filter.h +++ b/plugins/filters/blur/kis_motion_blur_filter.h @@ -1,52 +1,52 @@ /* * This file is part of Krita * * Copyright (c) 2010 Edward Apap * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_MOTION_BLUR_FILTER_H #define KIS_MOTION_BLUR_FILTER_H #include "filter/kis_filter.h" #include "ui_wdg_motion_blur.h" #include class KisMotionBlurFilter : public KisFilter { public: KisMotionBlurFilter(); public: void processImpl(KisPaintDeviceSP src, const QRect& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("motion blur", i18n("Motion Blur")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; QRect neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; QRect changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; }; #endif diff --git a/plugins/filters/colors/kis_color_to_alpha.cpp b/plugins/filters/colors/kis_color_to_alpha.cpp index dd2ffba258..fb48d46ade 100644 --- a/plugins/filters/colors/kis_color_to_alpha.cpp +++ b/plugins/filters/colors/kis_color_to_alpha.cpp @@ -1,191 +1,191 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_color_to_alpha.h" #include #include #include #include #include "kis_progress_update_helper.h" #include #include #include #include #include "ui_wdgcolortoalphabase.h" #include "kis_wdg_color_to_alpha.h" #include KisFilterColorToAlpha::KisFilterColorToAlpha() : KisFilter(id(), categoryColors(), i18n("&Color to Alpha...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisFilterColorToAlpha::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgColorToAlpha(parent); } -KisFilterConfigurationSP KisFilterColorToAlpha::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterColorToAlpha::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("colortoalpha", 1); config->setProperty("targetcolor", QColor(255, 255, 255)); config->setProperty("threshold", 100); return config; } template inline void inverseOver(const int numChannels, const int *channelIndex, channel_type *dst, const channel_type *baseColor, qreal dstOpacity) { for (int i = 0; i < numChannels; i++) { const int idx = channelIndex[i]; dst[idx] = KoColorSpaceMaths::clamp( (static_cast(dst[idx]) - baseColor[idx]) / dstOpacity + baseColor[idx]); } } template void applyToIterator(const int numChannels, const int *channelIndex, KisSequentialIterator &it, KoColor baseColor, int threshold, const KoColorSpace *cs, KisProgressUpdateHelper &progressHelper) { qreal thresholdF = threshold; quint8 *baseColorData_uint8 = baseColor.data(); channel_type *baseColorData = reinterpret_cast(baseColorData_uint8); do { channel_type *dst = reinterpret_cast(it.rawData()); quint8 *dst_uint8 = it.rawData(); quint8 diff = cs->difference(baseColorData_uint8, dst_uint8); qreal newOpacity = diff >= threshold ? 1.0 : diff / thresholdF; if(newOpacity < cs->opacityF(dst_uint8)) { cs->setOpacity(dst_uint8, newOpacity, 1); } inverseOver(numChannels, channelIndex, dst, baseColorData, newOpacity); progressHelper.step(); } while(it.nextPixel()); } void KisFilterColorToAlpha::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration("colortoalpha", 1); QVariant value; QColor cTA = (config->getProperty("targetcolor", value)) ? value.value() : QColor(255, 255, 255); int threshold = (config->getProperty("threshold", value)) ? value.toInt() : 1; const KoColorSpace * cs = device->colorSpace(); KisProgressUpdateHelper progressHelper(progressUpdater, 100, rect.width() * rect.height()); KisSequentialIterator it(device, rect); KoColor baseColor(cTA, cs); QVector channelIndex; KoChannelInfo::enumChannelValueType valueType = KoChannelInfo::OTHER; QList channels = cs->channels(); for (int i = 0; i < channels.size(); i++) { const KoChannelInfo *info = channels[i]; if (info->channelType() != KoChannelInfo::COLOR) continue; KoChannelInfo::enumChannelValueType currentValueType = info->channelValueType(); if (valueType != KoChannelInfo::OTHER && valueType != currentValueType) { warnKrita << "Cannot apply a Color-to-Alpha filter to a heterogeneous colorspace"; return; } else { valueType = currentValueType; } channelIndex.append(i); } switch (valueType) { case KoChannelInfo::UINT8: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs, progressHelper); break; case KoChannelInfo::UINT16: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs, progressHelper); break; case KoChannelInfo::UINT32: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs, progressHelper); break; case KoChannelInfo::FLOAT32: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs, progressHelper); break; case KoChannelInfo::FLOAT64: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs, progressHelper); break; case KoChannelInfo::FLOAT16: #include #ifdef HAVE_OPENEXR #include applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs, progressHelper); break; #endif case KoChannelInfo::INT8: /* !UNSUPPORTED! */ case KoChannelInfo::INT16: /* !UNSUPPORTED! */ case KoChannelInfo::OTHER: warnKrita << "Color To Alpha: Unsupported channel type:" << valueType; } } diff --git a/plugins/filters/colors/kis_color_to_alpha.h b/plugins/filters/colors/kis_color_to_alpha.h index 0fffc0d18c..01a8e21b99 100644 --- a/plugins/filters/colors/kis_color_to_alpha.h +++ b/plugins/filters/colors/kis_color_to_alpha.h @@ -1,49 +1,49 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_COLOR_TO_ALPHA_H_ #define KIS_COLOR_TO_ALPHA_H_ #include "filter/kis_filter.h" class KisFilterColorToAlpha : public KisFilter { public: KisFilterColorToAlpha(); void processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("colortoalpha", i18n("Color to Alpha")); } public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP dev) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; #endif diff --git a/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cpp b/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cpp index 2401b0dce6..d6c6d04a1a 100644 --- a/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cpp +++ b/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cpp @@ -1,302 +1,302 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * Copyright (c) 2005 C. Boemann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_brightness_contrast_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "KoBasicHistogramProducers.h" #include "KoColorSpace.h" #include "KoColorTransformation.h" #include "KoCompositeOp.h" #include #include "kis_config_widget.h" #include "kis_bookmarked_configuration_manager.h" #include "kis_paint_device.h" #include "widgets/kis_curve_widget.h" #include "kis_histogram.h" #include "kis_painter.h" #include #include #include KisBrightnessContrastFilterConfiguration::KisBrightnessContrastFilterConfiguration() : KisColorTransformationConfiguration("brightnesscontrast", 1) { } KisBrightnessContrastFilterConfiguration::~KisBrightnessContrastFilterConfiguration() { } void KisBrightnessContrastFilterConfiguration::fromLegacyXML(const QDomElement& root) { fromXML(root); } void KisBrightnessContrastFilterConfiguration::updateTransfer() { m_transfer = m_curve.uint16Transfer(); } void KisBrightnessContrastFilterConfiguration::setCurve(const KisCubicCurve &curve) { m_curve = curve; updateTransfer(); } const QVector& KisBrightnessContrastFilterConfiguration::transfer() const { return m_transfer; } const KisCubicCurve& KisBrightnessContrastFilterConfiguration::curve() const { return m_curve; } void KisBrightnessContrastFilterConfiguration::fromXML(const QDomElement& root) { KisCubicCurve curve; int version; version = root.attribute("version").toInt(); QDomElement e = root.firstChild().toElement(); QString attributeName; while (!e.isNull()) { if ((attributeName = e.attribute("name")) != "nTransfers") { QRegExp rx("curve(\\d+)"); if (rx.indexIn(attributeName, 0) != -1) { quint16 index = rx.cap(1).toUShort(); if (index == 0 && !e.text().isEmpty()) { /** * We are going to use first curve only */ curve.fromString(e.text()); } } } e = e.nextSiblingElement(); } setVersion(version); setCurve(curve); } /** * Inherited from KisPropertiesConfiguration */ //void KisPerChannelFilterConfiguration::fromXML(const QString& s) void KisBrightnessContrastFilterConfiguration::toXML(QDomDocument& doc, QDomElement& root) const { /** * * 1 * 0,0;0.5,0.5;1,1; * */ /* This is a constant for Brightness/Contranst filter */ const qint32 numTransfers = 1; root.setAttribute("version", version()); QDomElement t = doc.createElement("param"); QDomText text = doc.createTextNode(QString::number(numTransfers)); t.setAttribute("name", "nTransfers"); t.appendChild(text); root.appendChild(t); t = doc.createElement("param"); t.setAttribute("name", "curve0"); text = doc.createTextNode(m_curve.toString()); t.appendChild(text); root.appendChild(t); } /** * Inherited from KisPropertiesConfiguration */ //QString KisPerChannelFilterConfiguration::toXML() KisBrightnessContrastFilter::KisBrightnessContrastFilter() : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Brightness/Contrast curve...")) { setSupportsPainting(false); setColorSpaceIndependence(TO_LAB16); } KisConfigWidget * KisBrightnessContrastFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisBrightnessContrastConfigWidget(parent, dev); } -KisFilterConfigurationSP KisBrightnessContrastFilter::factoryConfiguration(const KisPaintDeviceSP) +KisFilterConfigurationSP KisBrightnessContrastFilter::factoryConfiguration() const { return new KisBrightnessContrastFilterConfiguration(); } KoColorTransformation* KisBrightnessContrastFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { const KisBrightnessContrastFilterConfiguration* configBC = dynamic_cast(config.data()); if (!configBC) return 0; KoColorTransformation * adjustment = cs->createBrightnessContrastAdjustment(configBC->transfer().constData()); return adjustment; } KisBrightnessContrastConfigWidget::KisBrightnessContrastConfigWidget(QWidget * parent, KisPaintDeviceSP dev, Qt::WFlags f) : KisConfigWidget(parent, f) { int i; int height; m_page = new WdgBrightnessContrast(this); QHBoxLayout * l = new QHBoxLayout(this); Q_CHECK_PTR(l); //Hide these buttons and labels as they are not implemented in 1.5 m_page->pb_more_contrast->hide(); m_page->pb_less_contrast->hide(); m_page->pb_more_brightness->hide(); m_page->pb_less_brightness->hide(); m_page->textLabelBrightness->hide(); m_page->textLabelContrast->hide(); l->addWidget(m_page, 1, Qt::AlignTop); l->setContentsMargins(0,0,0,0); height = 256; connect(m_page->curveWidget, SIGNAL(modified()), SIGNAL(sigConfigurationItemChanged())); // Create the horizontal gradient label QPixmap hgradientpix(256, 1); QPainter hgp(&hgradientpix); hgp.setPen(QPen(QColor(0, 0, 0), 1, Qt::SolidLine)); for (i = 0; i < 256; ++i) { hgp.setPen(QColor(i, i, i)); hgp.drawPoint(i, 0); } m_page->hgradient->setPixmap(hgradientpix); // Create the vertical gradient label QPixmap vgradientpix(1, 256); QPainter vgp(&vgradientpix); vgp.setPen(QPen(QColor(0, 0, 0), 1, Qt::SolidLine)); for (i = 0; i < 256; ++i) { vgp.setPen(QColor(i, i, i)); vgp.drawPoint(0, 255 - i); } m_page->vgradient->setPixmap(vgradientpix); KoHistogramProducer *producer = new KoGenericLabHistogramProducer(); KisHistogram histogram(dev, dev->exactBounds(), producer, LINEAR); QPalette appPalette = QApplication::palette(); QPixmap pix(256, height); pix.fill(QColor(appPalette.color(QPalette::Base))); QPainter p(&pix); p.setPen(QPen(Qt::gray, 1, Qt::SolidLine)); double highest = (double)histogram.calculations().getHighest(); qint32 bins = histogram.producer()->numberOfBins(); if (histogram.getHistogramType() == LINEAR) { double factor = (double)height / highest; for (i = 0; i < bins; ++i) { p.drawLine(i, height, i, height - int(histogram.getValue(i) * factor)); } } else { double factor = (double)height / (double)log(highest); for (i = 0; i < bins; ++i) { p.drawLine(i, height, i, height - int(log((double)histogram.getValue(i)) * factor)); } } m_page->curveWidget->setPixmap(pix); m_page->curveWidget->setBasePixmap(pix); } KisBrightnessContrastConfigWidget::~KisBrightnessContrastConfigWidget() { KoToolManager::instance()->switchBackRequested(); delete m_page; } KisPropertiesConfigurationSP KisBrightnessContrastConfigWidget::configuration() const { KisBrightnessContrastFilterConfiguration * cfg = new KisBrightnessContrastFilterConfiguration(); cfg->setCurve(m_page->curveWidget->curve()); return cfg; } void KisBrightnessContrastConfigWidget::slotDrawLine(const KoColor &color) { QColor colorNew = color.toQColor(); int i = (colorNew.red() + colorNew.green() + colorNew.blue())/3 ; QPixmap pix = m_page->curveWidget->getBasePixmap(); QPainter p(&pix); p.setPen(QPen(Qt::black, 1, Qt::SolidLine)); p.drawLine(i,0,i,255); QString label = "x:"; label.insert(2,QString(QString::number(i))); p.drawText(i,250,label); m_page->curveWidget->setPixmap(pix); } void KisBrightnessContrastConfigWidget::setView(KisViewManager *view) { connect(view->resourceProvider(), SIGNAL(sigFGColorChanged(const KoColor&)), this, SLOT(slotDrawLine(const KoColor&))); KoToolManager::instance()->switchToolTemporaryRequested("KritaSelected/KisToolColorPicker"); } void KisBrightnessContrastConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { const KisBrightnessContrastFilterConfiguration * cfg = dynamic_cast(config.data()); Q_ASSERT(cfg); m_page->curveWidget->setCurve(cfg->curve()); } diff --git a/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h b/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h index 6a0f8a9739..1a4508ba1d 100644 --- a/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h +++ b/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h @@ -1,116 +1,116 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_BRIGHTNESS_CONTRAST_FILTER_H_ #define _KIS_BRIGHTNESS_CONTRAST_FILTER_H_ #include #include "filter/kis_color_transformation_filter.h" #include "kis_config_widget.h" #include "ui_wdg_brightness_contrast.h" #include #include #include #include #include class QWidget; class KoColorTransformation; class WdgBrightnessContrast : public QWidget, public Ui::WdgBrightnessContrast { Q_OBJECT public: WdgBrightnessContrast(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class KisBrightnessContrastFilterConfiguration : public KisColorTransformationConfiguration { public: using KisFilterConfiguration::fromXML; using KisFilterConfiguration::toXML; using KisFilterConfiguration::fromLegacyXML; virtual void fromLegacyXML(const QDomElement& root); virtual void fromXML(const QDomElement& e); virtual void toXML(QDomDocument& doc, QDomElement& root) const; KisBrightnessContrastFilterConfiguration(); virtual ~KisBrightnessContrastFilterConfiguration(); virtual void setCurve(const KisCubicCurve &curve); const QVector& transfer() const; virtual const KisCubicCurve& curve() const; private: void updateTransfer(); private: KisCubicCurve m_curve; QVector m_transfer; }; /** * This class affect Intensity Y of the image */ class KisBrightnessContrastFilter : public KisColorTransformationFilter { public: KisBrightnessContrastFilter(); public: virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; static inline KoID id() { return KoID("brightnesscontrast", i18n("Brightness / Contrast")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; class KisBrightnessContrastConfigWidget : public KisConfigWidget { Q_OBJECT public: KisBrightnessContrastConfigWidget(QWidget * parent, KisPaintDeviceSP dev, Qt::WFlags f = 0); virtual ~KisBrightnessContrastConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; virtual void setConfiguration(const KisPropertiesConfigurationSP config); WdgBrightnessContrast * m_page; void setView(KisViewManager *view); public Q_SLOTS: void slotDrawLine(const KoColor &color); }; #endif diff --git a/plugins/filters/colorsfilters/kis_color_balance_filter.cpp b/plugins/filters/colorsfilters/kis_color_balance_filter.cpp index 58e21f2430..c4e856eb7d 100644 --- a/plugins/filters/colorsfilters/kis_color_balance_filter.cpp +++ b/plugins/filters/colorsfilters/kis_color_balance_filter.cpp @@ -1,205 +1,205 @@ /* * Copyright (c) 2013 Sahil Nagpal * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_color_balance_filter.h" #include "filter/kis_color_transformation_configuration.h" #include "kis_selection.h" #include "kis_paint_device.h" #include "kis_processing_information.h" KisColorBalanceFilter::KisColorBalanceFilter() : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Color Balance...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); setSupportsPainting(true); } KisConfigWidget * KisColorBalanceFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisColorBalanceConfigWidget(parent); } KoColorTransformation * KisColorBalanceFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; if (config) { params["cyan_red_midtones"] = config->getInt("cyan_red_midtones", 0) * 0.01; params["magenta_green_midtones"] = config->getInt("magenta_green_midtones", 0) * 0.01; params["yellow_blue_midtones"] = config->getInt("yellow_blue_midtones", 0) * 0.01; params["cyan_red_shadows"] = config->getInt("cyan_red_shadows", 0) * 0.01; params["magenta_green_shadows"] = config->getInt("magenta_green_shadows", 0) * 0.01; params["yellow_blue_shadows"] = config->getInt("yellow_blue_shadows", 0) * 0.01; params["cyan_red_highlights"] = config->getInt("cyan_red_highlights", 0) * 0.01; params["magenta_green_highlights"] = config->getInt("magenta_green_highlights", 0) * 0.01; params["yellow_blue_highlights"] = config->getInt("yellow_blue_highlights", 0) * 0.01; params["preserve_luminosity"] = config->getBool("preserve_luminosity", true); } return cs->createColorTransformation("ColorBalance" , params); } -KisFilterConfigurationSP KisColorBalanceFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisColorBalanceFilter::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); config->setProperty("cyan_red_midtones", 0); config->setProperty("yellow_green_midtones", 0); config->setProperty("magenta_blue_midtones", 0); config->setProperty("cyan_red_shadows", 0); config->setProperty("yellow_green_shadows", 0); config->setProperty("magenta_blue_shadows", 0); config->setProperty("cyan_red_highlights", 0); config->setProperty("yellow_green_highlights", 0); config->setProperty("magenta_blue_highlights", 0); config->setProperty("preserve_luminosity", true); return config; } KisColorBalanceConfigWidget::KisColorBalanceConfigWidget(QWidget* parent) : KisConfigWidget(parent) { m_page = new Ui_Form(); m_page->setupUi(this); m_page->cyanRedShadowsSlider->setMaximum(100); m_page->cyanRedShadowsSlider->setMinimum(-100); m_page->yellowBlueShadowsSlider->setMaximum(100); m_page->yellowBlueShadowsSlider->setMinimum(-100); m_page->magentaGreenShadowsSlider->setMaximum(100); m_page->magentaGreenShadowsSlider->setMinimum(-100); m_page->cyanRedMidtonesSlider->setMaximum(100); m_page->cyanRedMidtonesSlider->setMinimum(-100); m_page->yellowBlueMidtonesSlider->setMaximum(100); m_page->yellowBlueMidtonesSlider->setMinimum(-100); m_page->magentaGreenMidtonesSlider->setMaximum(100); m_page->magentaGreenMidtonesSlider->setMinimum(-100); m_page->cyanRedHighlightsSlider->setMaximum(100); m_page->cyanRedHighlightsSlider->setMinimum(-100); m_page->yellowBlueHighlightsSlider->setMaximum(100); m_page->yellowBlueHighlightsSlider->setMinimum(-100); m_page->magentaGreenHighlightsSlider->setMaximum(100); m_page->magentaGreenHighlightsSlider->setMinimum(-100); connect(m_page->cyanRedShadowsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->magentaGreenShadowsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->yellowBlueShadowsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->cyanRedMidtonesSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->magentaGreenMidtonesSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->yellowBlueMidtonesSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->cyanRedHighlightsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->magentaGreenHighlightsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->yellowBlueHighlightsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->chkPreserveLuminosity, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->pushResetShadows, SIGNAL(clicked()), SLOT(slotShadowsClear())); connect(m_page->pushResetMidtones, SIGNAL(clicked()), SLOT(slotMidtonesClear())); connect(m_page->pushResetHighlights, SIGNAL(clicked()), SLOT(slotHighlightsClear())); m_page->cyanRedShadowsSpinbox->setMaximum(100); m_page->cyanRedShadowsSpinbox->setMinimum(-100); m_page->yellowBlueShadowsSpinbox->setMaximum(100); m_page->yellowBlueShadowsSpinbox->setMinimum(-100); m_page->magentaGreenShadowsSpinbox->setMaximum(100); m_page->magentaGreenShadowsSpinbox->setMinimum(-100); m_page->cyanRedMidtonesSpinbox->setMaximum(100); m_page->cyanRedMidtonesSpinbox->setMinimum(-100); m_page->yellowBlueMidtonesSpinbox->setMaximum(100); m_page->yellowBlueMidtonesSpinbox->setMinimum(-100); m_page->magentaGreenMidtonesSpinbox->setMaximum(100); m_page->magentaGreenMidtonesSpinbox->setMinimum(-100); m_page->cyanRedHighlightsSpinbox->setMaximum(100); m_page->cyanRedHighlightsSpinbox->setMinimum(-100); m_page->yellowBlueHighlightsSpinbox->setMaximum(100); m_page->yellowBlueHighlightsSpinbox->setMinimum(-100); m_page->magentaGreenHighlightsSpinbox->setMaximum(100); m_page->magentaGreenHighlightsSpinbox->setMinimum(-100); } KisColorBalanceConfigWidget::~KisColorBalanceConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisColorBalanceConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(KisColorBalanceFilter::id().id(), 0); c->setProperty("cyan_red_shadows", m_page->cyanRedShadowsSlider->value()); c->setProperty("magenta_green_shadows", m_page->magentaGreenShadowsSlider->value()); c->setProperty("yellow_blue_shadows", m_page->yellowBlueShadowsSlider->value()); c->setProperty("cyan_red_midtones", m_page->cyanRedMidtonesSlider->value()); c->setProperty("magenta_green_midtones", m_page->magentaGreenMidtonesSlider->value()); c->setProperty("yellow_blue_midtones", m_page->yellowBlueMidtonesSlider->value()); c->setProperty("cyan_red_highlights", m_page->cyanRedHighlightsSlider->value()); c->setProperty("magenta_green_highlights", m_page->magentaGreenHighlightsSlider->value()); c->setProperty("yellow_blue_highlights", m_page->yellowBlueHighlightsSlider->value()); c->setProperty("preserve_luminosity", m_page->chkPreserveLuminosity->isChecked()); return c; } void KisColorBalanceConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { m_page->cyanRedMidtonesSlider->setValue( config->getDouble("cyan_red_midtones", 0)); m_page->magentaGreenMidtonesSlider->setValue( config->getDouble("magenta_green_midtones", 0)); m_page->yellowBlueMidtonesSlider->setValue( config->getDouble("yellow_blue_midtones", 0)); m_page->cyanRedShadowsSlider->setValue( config->getDouble("cyan_red_shadows", 0)); m_page->magentaGreenShadowsSlider->setValue( config->getDouble("magenta_green_shadows", 0)); m_page->yellowBlueShadowsSlider->setValue( config->getDouble("yellow_blue_shadows", 0)); m_page->cyanRedHighlightsSlider->setValue( config->getDouble("cyan_red_highlights", 0)); m_page->magentaGreenHighlightsSlider->setValue( config->getDouble("magenta_green_highlights", 0)); m_page->yellowBlueHighlightsSlider->setValue( config->getDouble("yellow_blue_highlights", 0)); m_page->chkPreserveLuminosity->setChecked(config->getBool("preserve_luminosity", true)); } void KisColorBalanceConfigWidget::slotMidtonesClear() { m_page->cyanRedMidtonesSlider->setValue(0); m_page->magentaGreenMidtonesSlider->setValue(0); m_page->yellowBlueMidtonesSlider->setValue(0); } void KisColorBalanceConfigWidget::slotHighlightsClear() { m_page->cyanRedHighlightsSlider->setValue(0); m_page->magentaGreenHighlightsSlider->setValue(0); m_page->yellowBlueHighlightsSlider->setValue(0); } void KisColorBalanceConfigWidget::slotShadowsClear() { m_page->cyanRedShadowsSlider->setValue(0); m_page->magentaGreenShadowsSlider->setValue(0); m_page->yellowBlueShadowsSlider->setValue(0); } diff --git a/plugins/filters/colorsfilters/kis_color_balance_filter.h b/plugins/filters/colorsfilters/kis_color_balance_filter.h index d02d3dbb69..d7303e3ef5 100644 --- a/plugins/filters/colorsfilters/kis_color_balance_filter.h +++ b/plugins/filters/colorsfilters/kis_color_balance_filter.h @@ -1,80 +1,80 @@ /* * Copyright (c) 2013 Sahil Nagpal * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KIS_COLOR_BALANCE_FILTER_H_ #define _KIS_COLOR_BALANCE_FILTER_H_ #include #include "filter/kis_filter.h" #include "kis_config_widget.h" #include "ui_wdg_color_balance.h" #include "filter/kis_color_transformation_filter.h" class QWidget; class KoColorTransformation; class KisColorBalanceFilter : public KisColorTransformationFilter { public: KisColorBalanceFilter(); public: enum Type { SHADOWS, MIDTONES, HIGHLIGHTS }; public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; static inline KoID id() { return KoID("colorbalance", i18n("Color Balance")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; class KisColorBalanceConfigWidget : public KisConfigWidget { Q_OBJECT public: KisColorBalanceConfigWidget(QWidget * parent); virtual ~KisColorBalanceConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; virtual void setConfiguration(const KisPropertiesConfigurationSP config); Ui_Form * m_page; QString m_id; public Q_SLOTS: void slotShadowsClear(); void slotMidtonesClear(); void slotHighlightsClear(); }; #endif diff --git a/plugins/filters/colorsfilters/kis_desaturate_filter.cpp b/plugins/filters/colorsfilters/kis_desaturate_filter.cpp index bf4e7b9d5f..30a48acdbf 100644 --- a/plugins/filters/colorsfilters/kis_desaturate_filter.cpp +++ b/plugins/filters/colorsfilters/kis_desaturate_filter.cpp @@ -1,121 +1,121 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_desaturate_filter.h" #include #include #include #include #include #include #include #include #include #include "KoBasicHistogramProducers.h" #include #include #include #include #include #include #include #include #include #include #include #include "filter/kis_filter_registry.h" #include #include #include #include KisDesaturateFilter::KisDesaturateFilter() : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Desaturate...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_U)); setSupportsPainting(true); } KisDesaturateFilter::~KisDesaturateFilter() { } KisConfigWidget *KisDesaturateFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisDesaturateConfigWidget(parent); } KoColorTransformation* KisDesaturateFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; if (config) { params["type"] = config->getInt("type", 0); } return cs->createColorTransformation("desaturate_adjustment", params); } -KisFilterConfigurationSP KisDesaturateFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisDesaturateFilter::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 1); config->setProperty("type", 0); return config; } KisDesaturateConfigWidget::KisDesaturateConfigWidget(QWidget * parent, Qt::WFlags f) : KisConfigWidget(parent, f) { m_page = new Ui_WdgDesaturate(); m_page->setupUi(this); m_group = new QButtonGroup(this); m_group->addButton(m_page->radioLightness, 0); m_group->addButton(m_page->radioLuminosityBT709, 1); m_group->addButton(m_page->radioLuminosityBT601, 2); m_group->addButton(m_page->radioAverage, 3); m_group->addButton(m_page->radioMin, 4); m_group->addButton(m_page->radioMax, 5); m_group->setExclusive(true); connect(m_group, SIGNAL(buttonClicked(int)), SIGNAL(sigConfigurationItemChanged())); } KisDesaturateConfigWidget::~KisDesaturateConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisDesaturateConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(KisDesaturateFilter::id().id(), 0); c->setProperty("type", m_group->checkedId()); return c; } void KisDesaturateConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { m_group->button(config->getInt("type", 0))->setChecked(true); emit sigConfigurationItemChanged(); } diff --git a/plugins/filters/colorsfilters/kis_desaturate_filter.h b/plugins/filters/colorsfilters/kis_desaturate_filter.h index 9095dacf52..874bf29980 100644 --- a/plugins/filters/colorsfilters/kis_desaturate_filter.h +++ b/plugins/filters/colorsfilters/kis_desaturate_filter.h @@ -1,70 +1,70 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_DESATURATE_FILTER_H #define KIS_DESATURATE_FILTER_H #include #include #include #include #include "ui_wdg_desaturate.h" class KoColorSpace; class KoColorTransformation; class KisDesaturateFilter : public KisColorTransformationFilter { public: KisDesaturateFilter(); ~KisDesaturateFilter(); public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; static inline KoID id() { return KoID("desaturate", i18n("Desaturate")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; class KisDesaturateConfigWidget : public KisConfigWidget { Q_OBJECT public: KisDesaturateConfigWidget(QWidget * parent, Qt::WFlags f = 0); virtual ~KisDesaturateConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; virtual void setConfiguration(const KisPropertiesConfigurationSP config); Ui_WdgDesaturate *m_page; QButtonGroup *m_group; }; #endif diff --git a/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp b/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp index 4854ec254c..66e11a2755 100644 --- a/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp +++ b/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp @@ -1,190 +1,190 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_hsv_adjustment_filter.h" #include #include #include #include #include namespace { struct SliderConfig { QString m_text; int m_minimum; int m_maximum; inline void apply(QSpinBox* spinBox, QSlider* slider, QLabel* label) const { label->setText(m_text); slider->setMinimum(m_minimum); slider->setMaximum(m_maximum); spinBox->setMinimum(m_minimum); spinBox->setMaximum(m_maximum); int sliderValue = slider->value(); if (sliderValue < m_minimum || sliderValue > m_maximum) { slider->setValue((m_minimum + m_maximum) / 2); } } inline double normalize(int value) const { return (double)value / (double)m_maximum; } }; struct WidgetSlidersConfig { SliderConfig m_sliders[3]; }; #define PERCENT_FIELD_REL(x) {x, -100, 100} #define PERCENT_FIELD_ABS(x) {x, 0, 100} #define DEGREES_FIELD_REL(x) {x, -180, 180} #define DEGREES_FIELD_ABS(x) {x, 0, 360} #define HSX_CONFIGS(x) { \ { {DEGREES_FIELD_REL(i18n("Hue:")), PERCENT_FIELD_REL(i18n("Saturation:")), PERCENT_FIELD_REL(x)} }, \ { {DEGREES_FIELD_ABS(i18n("Hue:")), PERCENT_FIELD_ABS(i18n("Saturation:")), PERCENT_FIELD_REL(x)} } \ } const WidgetSlidersConfig WIDGET_CONFIGS[][2] = { // Hue/Saturation/Value HSX_CONFIGS(i18n("Value:")), // Hue/Saturation/Lightness HSX_CONFIGS(i18n("Lightness:")), // Hue/Saturation/Intensity HSX_CONFIGS(i18n("Intensity:")), // Hue/Saturation/Luminosity HSX_CONFIGS(i18n("Luma:")), // Blue Chroma/Red Chroma/Luma {{ {PERCENT_FIELD_REL(i18n("Yellow-Blue:")), PERCENT_FIELD_REL(i18n("Green-Red:")), PERCENT_FIELD_REL(i18n("Luma:"))} }, { {PERCENT_FIELD_ABS(i18n("Yellow-Blue:")), PERCENT_FIELD_ABS(i18n("Green-Red:")), PERCENT_FIELD_REL(i18n("Luma:"))} }} }; inline const WidgetSlidersConfig& getCurrentWidgetConfig(int type, bool colorize) { return WIDGET_CONFIGS[type][colorize ? 1 : 0]; } } KisHSVAdjustmentFilter::KisHSVAdjustmentFilter() : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&HSV Adjustment...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); setSupportsPainting(true); } KisConfigWidget * KisHSVAdjustmentFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisHSVConfigWidget(parent); } KoColorTransformation* KisHSVAdjustmentFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; if (config) { int type = config->getInt("type", 1); bool colorize = config->getBool("colorize", false); const WidgetSlidersConfig& widgetConfig = getCurrentWidgetConfig(type, colorize); params["h"] = widgetConfig.m_sliders[0].normalize(config->getInt("h", 0)); params["s"] = widgetConfig.m_sliders[1].normalize(config->getInt("s", 0)); params["v"] = widgetConfig.m_sliders[2].normalize(config->getInt("v", 0)); params["type"] = type; params["colorize"] = colorize; params["lumaRed"] = cs->lumaCoefficients()[0]; params["lumaGreen"] = cs->lumaCoefficients()[1]; params["lumaBlue"] = cs->lumaCoefficients()[2]; } return cs->createColorTransformation("hsv_adjustment", params); } -KisFilterConfigurationSP KisHSVAdjustmentFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisHSVAdjustmentFilter::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 1); config->setProperty("h", 0); config->setProperty("s", 0); config->setProperty("v", 0); config->setProperty("type", 1); config->setProperty("colorize", false); return config; } KisHSVConfigWidget::KisHSVConfigWidget(QWidget * parent, Qt::WFlags f) : KisConfigWidget(parent, f) { m_page = new Ui_WdgHSVAdjustment(); m_page->setupUi(this); connect(m_page->cmbType, SIGNAL(activated(int)), this, SLOT(configureSliderLimitsAndLabels())); connect(m_page->chkColorize, SIGNAL(toggled(bool)), this, SLOT(configureSliderLimitsAndLabels())); // connect horizontal sliders connect(m_page->hueSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->saturationSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->valueSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->hueSpinBox, SIGNAL(valueChanged(int)), m_page->hueSlider, SLOT(setValue(int))); connect(m_page->saturationSpinBox, SIGNAL(valueChanged(int)), m_page->saturationSlider, SLOT(setValue(int))); connect(m_page->valueSpinBox, SIGNAL(valueChanged(int)), m_page->valueSlider, SLOT(setValue(int))); connect(m_page->hueSlider, SIGNAL(valueChanged(int)), m_page->hueSpinBox, SLOT(setValue(int))); connect(m_page->saturationSlider, SIGNAL(valueChanged(int)), m_page->saturationSpinBox, SLOT(setValue(int))); connect(m_page->valueSlider, SIGNAL(valueChanged(int)), m_page->valueSpinBox, SLOT(setValue(int))); } KisHSVConfigWidget::~KisHSVConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisHSVConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(KisHSVAdjustmentFilter::id().id(), 0); c->setProperty("h", m_page->hueSlider->value()); c->setProperty("s", m_page->saturationSlider->value()); c->setProperty("v", m_page->valueSlider->value()); c->setProperty("type", m_page->cmbType->currentIndex()); c->setProperty("colorize", m_page->chkColorize->isChecked()); return c; } void KisHSVConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { m_page->cmbType->setCurrentIndex(config->getInt("type", 1)); m_page->chkColorize->setChecked(config->getBool("colorize", false)); m_page->hueSlider->setValue(config->getInt("h", 0)); m_page->saturationSlider->setValue(config->getInt("s", 0)); m_page->valueSlider->setValue(config->getInt("v", 0)); configureSliderLimitsAndLabels(); } void KisHSVConfigWidget::configureSliderLimitsAndLabels() { const WidgetSlidersConfig& widget = getCurrentWidgetConfig(m_page->cmbType->currentIndex(), m_page->chkColorize->isChecked()); widget.m_sliders[0].apply(m_page->hueSpinBox, m_page->hueSlider, m_page->label); widget.m_sliders[1].apply(m_page->saturationSpinBox, m_page->saturationSlider, m_page->label_2); widget.m_sliders[2].apply(m_page->valueSpinBox, m_page->valueSlider, m_page->label_3); emit sigConfigurationItemChanged(); } diff --git a/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.h b/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.h index 678779c5c8..934cbb9f15 100644 --- a/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.h +++ b/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.h @@ -1,77 +1,77 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KIS_HSV_ADJUSTMENT_FILTER_H_ #define _KIS_HSV_ADJUSTMENT_FILTER_H_ #include #include "filter/kis_filter.h" #include "kis_config_widget.h" #include "ui_wdg_hsv_adjustment.h" #include "filter/kis_color_transformation_filter.h" class QWidget; class KoColorTransformation; /** * This class affect Intensity Y of the image */ class KisHSVAdjustmentFilter : public KisColorTransformationFilter { public: KisHSVAdjustmentFilter(); public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; static inline KoID id() { return KoID("hsvadjustment", i18n("HSV/HSL Adjustment")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; class KisHSVConfigWidget : public KisConfigWidget { Q_OBJECT public: KisHSVConfigWidget(QWidget * parent, Qt::WFlags f = 0); virtual ~KisHSVConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; virtual void setConfiguration(const KisPropertiesConfigurationSP config); Ui_WdgHSVAdjustment * m_page; private Q_SLOTS: void configureSliderLimitsAndLabels(); }; #endif diff --git a/plugins/filters/colorsfilters/kis_perchannel_filter.cpp b/plugins/filters/colorsfilters/kis_perchannel_filter.cpp index 3c3cce30d8..5d92ce494a 100644 --- a/plugins/filters/colorsfilters/kis_perchannel_filter.cpp +++ b/plugins/filters/colorsfilters/kis_perchannel_filter.cpp @@ -1,598 +1,598 @@ /* * This file is part of Krita * * Copyright (c) 2005 C. Boemann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_perchannel_filter.h" #include #include #include #include #include #include #include #include #include "KoChannelInfo.h" #include "KoBasicHistogramProducers.h" #include "KoColorModelStandardIds.h" #include "KoColorSpace.h" #include "KoColorTransformation.h" #include "KoCompositeColorTransformation.h" #include "KoCompositeOp.h" #include "KoID.h" #include "kis_signals_blocker.h" #include "kis_bookmarked_configuration_manager.h" #include "kis_config_widget.h" #include #include #include #include #include "kis_histogram.h" #include "kis_painter.h" #include "widgets/kis_curve_widget.h" QVector getVirtualChannels(const KoColorSpace *cs) { const bool supportsLightness = cs->colorModelId() != LABAColorModelID && cs->colorModelId() != GrayAColorModelID && cs->colorModelId() != GrayColorModelID && cs->colorModelId() != AlphaColorModelID; QVector vchannels; QList sortedChannels = KoChannelInfo::displayOrderSorted(cs->channels()); if (supportsLightness) { vchannels << VirtualChannelInfo(VirtualChannelInfo::ALL_COLORS, -1, 0, cs); } Q_FOREACH (KoChannelInfo *channel, sortedChannels) { int pixelIndex = KoChannelInfo::displayPositionToChannelIndex(channel->displayPosition(), sortedChannels); vchannels << VirtualChannelInfo(VirtualChannelInfo::REAL, pixelIndex, channel, cs); } if (supportsLightness) { vchannels << VirtualChannelInfo(VirtualChannelInfo::LIGHTNESS, -1, 0, cs); } return vchannels; } KisPerChannelConfigWidget::KisPerChannelConfigWidget(QWidget * parent, KisPaintDeviceSP dev, Qt::WFlags f) : KisConfigWidget(parent, f), m_histogram(0) { Q_ASSERT(dev); m_page = new WdgPerChannel(this); QHBoxLayout * layout = new QHBoxLayout(this); Q_CHECK_PTR(layout); layout->setContentsMargins(0,0,0,0); layout->addWidget(m_page); m_dev = dev; m_activeVChannel = 0; const KoColorSpace *targetColorSpace = dev->compositionSourceColorSpace(); // fill in the channel chooser, in the display order, but store the pixel index as well. m_virtualChannels = getVirtualChannels(targetColorSpace); const int virtualChannelCount = m_virtualChannels.size(); KisPerChannelFilterConfiguration::initDefaultCurves(m_curves, virtualChannelCount); for (int i = 0; i < virtualChannelCount; i++) { const VirtualChannelInfo &info = m_virtualChannels[i]; m_page->cmbChannel->addItem(info.name(), info.pixelIndex()); m_curves[i].setName(info.name()); } connect(m_page->cmbChannel, SIGNAL(activated(int)), this, SLOT(setActiveChannel(int))); // create the horizontal and vertical gradient labels m_page->hgradient->setPixmap(createGradient(Qt::Horizontal)); m_page->vgradient->setPixmap(createGradient(Qt::Vertical)); // init histogram calculator QList keys = KoHistogramProducerFactoryRegistry::instance()->keysCompatibleWith(targetColorSpace); if(keys.size() > 0) { KoHistogramProducerFactory *hpf; hpf = KoHistogramProducerFactoryRegistry::instance()->get(keys.at(0)); m_histogram = new KisHistogram(m_dev, m_dev->exactBounds(), hpf->generate(), LINEAR); } connect(m_page->curveWidget, SIGNAL(modified()), this, SIGNAL(sigConfigurationItemChanged())); m_page->curveWidget->setupInOutControls(m_page->intIn, m_page->intOut, 0, 100); { KisSignalsBlocker b(m_page->curveWidget); m_page->curveWidget->setCurve(m_curves[0]); setActiveChannel(0); } } KisPerChannelConfigWidget::~KisPerChannelConfigWidget() { delete m_histogram; } inline QPixmap KisPerChannelConfigWidget::createGradient(Qt::Orientation orient /*, int invert (not used yet) */) { int width; int height; int *i, inc, col; int x = 0, y = 0; if (orient == Qt::Horizontal) { i = &x; inc = 1; col = 0; width = 256; height = 1; } else { i = &y; inc = -1; col = 255; width = 1; height = 256; } QPixmap gradientpix(width, height); QPainter p(&gradientpix); p.setPen(QPen(QColor(0, 0, 0), 1, Qt::SolidLine)); for (; *i < 256; (*i)++, col += inc) { p.setPen(QColor(col, col, col)); p.drawPoint(x, y); } return gradientpix; } inline QPixmap KisPerChannelConfigWidget::getHistogram() { int i; int height = 256; QPixmap pix(256, height); QPalette appPalette = QApplication::palette(); pix.fill(QColor(appPalette.color(QPalette::Base))); QPainter p(&pix); p.setPen(QColor(appPalette.color(QPalette::Text))); p.save(); p.setOpacity(0.2); const VirtualChannelInfo &info = m_virtualChannels[m_activeVChannel]; if (m_histogram && info.type() == VirtualChannelInfo::REAL) { m_histogram->setChannel(info.pixelIndex()); double highest = (double)m_histogram->calculations().getHighest(); qint32 bins = m_histogram->producer()->numberOfBins(); if (m_histogram->getHistogramType() == LINEAR) { double factor = (double)height / highest; for (i = 0; i < bins; ++i) { p.drawLine(i, height, i, height - int(m_histogram->getValue(i) * factor)); } } else { double factor = (double)height / (double)log(highest); for (i = 0; i < bins; ++i) { p.drawLine(i, height, i, height - int(log((double)m_histogram->getValue(i)) * factor)); } } } p.restore(); return pix; } #define BITS_PER_BYTE 8 #define pwr2(p) (1<curveWidget->curve(); m_activeVChannel = ch; m_page->curveWidget->setCurve(m_curves[m_activeVChannel]); m_page->curveWidget->setPixmap(getHistogram()); m_page->cmbChannel->setCurrentIndex(m_activeVChannel); // Getting range accepted by channel VirtualChannelInfo ¤tVChannel = m_virtualChannels[m_activeVChannel]; KoChannelInfo::enumChannelValueType valueType = currentVChannel.valueType(); int order = BITS_PER_BYTE * currentVChannel.channelSize(); int maxValue = pwr2(order); int min; int max; m_page->curveWidget->dropInOutControls(); switch (valueType) { case KoChannelInfo::UINT8: case KoChannelInfo::UINT16: case KoChannelInfo::UINT32: m_shift = 0; m_scale = double(maxValue); min = 0; max = maxValue - 1; break; case KoChannelInfo::INT8: case KoChannelInfo::INT16: m_shift = 0.5; m_scale = double(maxValue); min = -maxValue / 2; max = maxValue / 2 - 1; break; case KoChannelInfo::FLOAT16: case KoChannelInfo::FLOAT32: case KoChannelInfo::FLOAT64: default: m_shift = 0; m_scale = 100.0; //Hack Alert: should be changed to float min = 0; max = 100; break; } m_page->curveWidget->setupInOutControls(m_page->intIn, m_page->intOut, min, max); } KisPropertiesConfigurationSP KisPerChannelConfigWidget::configuration() const { int numChannels = m_virtualChannels.size(); KisPropertiesConfigurationSP cfg = new KisPerChannelFilterConfiguration(numChannels); KIS_ASSERT_RECOVER(m_activeVChannel < m_curves.size()) { return cfg; } m_curves[m_activeVChannel] = m_page->curveWidget->curve(); static_cast(cfg.data())->setCurves(m_curves); return cfg; } void KisPerChannelConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { const KisPerChannelFilterConfiguration * cfg = dynamic_cast(config.data()); if (!cfg) return; if (cfg->curves().size() == 0) { /** * HACK ALERT: our configuration factory generates * default configuration with nTransfers==0. * Catching it here. Just reset all the transfers. */ const int virtualChannelCount = m_virtualChannels.size(); KisPerChannelFilterConfiguration::initDefaultCurves(m_curves, virtualChannelCount); for (int i = 0; i < virtualChannelCount; i++) { const VirtualChannelInfo &info = m_virtualChannels[i]; m_curves[i].setName(info.name()); } } else if (cfg->curves().size() != int(m_virtualChannels.size())) { warnKrita << "WARNING: trying to load a curve with incorrect number of channels!"; warnKrita << "WARNING: expected:" << m_virtualChannels.size(); warnKrita << "WARNING: got:" << cfg->curves().size(); return; } else { for (int ch = 0; ch < cfg->curves().size(); ch++) m_curves[ch] = cfg->curves()[ch]; } // HACK: we save the previous curve in setActiveChannel, so just copy it m_page->curveWidget->setCurve(m_curves[m_activeVChannel]); setActiveChannel(0); } KisPerChannelFilterConfiguration::KisPerChannelFilterConfiguration(int nCh) : KisColorTransformationConfiguration("perchannel", 1) { initDefaultCurves(m_curves, nCh); updateTransfers(); } KisPerChannelFilterConfiguration::~KisPerChannelFilterConfiguration() { } bool KisPerChannelFilterConfiguration::isCompatible(const KisPaintDeviceSP dev) const { return (int)dev->compositionSourceColorSpace()->channelCount() == m_curves.size(); } void KisPerChannelFilterConfiguration::setCurves(QList &curves) { m_curves.clear(); m_curves = curves; updateTransfers(); } void KisPerChannelFilterConfiguration::initDefaultCurves(QList &curves, int nCh) { curves.clear(); for (int i = 0; i < nCh; i++) { curves.append(KisCubicCurve()); } } void KisPerChannelFilterConfiguration::updateTransfers() { m_transfers.resize(m_curves.size()); for (int i = 0; i < m_curves.size(); i++) { m_transfers[i] = m_curves[i].uint16Transfer(); } } const QVector >& KisPerChannelFilterConfiguration::transfers() const { return m_transfers; } const QList& KisPerChannelFilterConfiguration::curves() const { return m_curves; } void KisPerChannelFilterConfiguration::fromLegacyXML(const QDomElement& root) { fromXML(root); } void KisPerChannelFilterConfiguration::fromXML(const QDomElement& root) { QList curves; quint16 numTransfers = 0; int version; version = root.attribute("version").toInt(); QDomElement e = root.firstChild().toElement(); QString attributeName; KisCubicCurve curve; quint16 index; while (!e.isNull()) { if ((attributeName = e.attribute("name")) == "nTransfers") { numTransfers = e.text().toUShort(); } else { QRegExp rx("curve(\\d+)"); if (rx.indexIn(attributeName, 0) != -1) { index = rx.cap(1).toUShort(); index = qMin(index, quint16(curves.count())); if (!e.text().isEmpty()) { curve.fromString(e.text()); } curves.insert(index, curve); } } e = e.nextSiblingElement(); } if (!numTransfers) return; setVersion(version); setCurves(curves); } /** * Inherited from KisPropertiesConfiguration */ //void KisPerChannelFilterConfiguration::fromXML(const QString& s) void addParamNode(QDomDocument& doc, QDomElement& root, const QString &name, const QString &value) { QDomText text = doc.createTextNode(value); QDomElement t = doc.createElement("param"); t.setAttribute("name", name); t.appendChild(text); root.appendChild(t); } void KisPerChannelFilterConfiguration::toXML(QDomDocument& doc, QDomElement& root) const { /** * * 3 * 0,0;0.5,0.5;1,1; * 0,0;1,1; * 0,0;1,1; * */ root.setAttribute("version", version()); QDomText text; QDomElement t; addParamNode(doc, root, "nTransfers", QString::number(m_curves.size())); KisCubicCurve curve; QString paramName; for (int i = 0; i < m_curves.size(); ++i) { QString name = QLatin1String("curve") + QString::number(i); QString value = m_curves[i].toString(); addParamNode(doc, root, name, value); } } /** * Inherited from KisPropertiesConfiguration */ //QString KisPerChannelFilterConfiguration::toXML() KisPerChannelFilter::KisPerChannelFilter() : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Color Adjustment curves...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); setSupportsPainting(true); setColorSpaceIndependence(TO_LAB16); } KisConfigWidget * KisPerChannelFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisPerChannelConfigWidget(parent, dev); } -KisFilterConfigurationSP KisPerChannelFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisPerChannelFilter::factoryConfiguration() const { return new KisPerChannelFilterConfiguration(0); } KoColorTransformation* KisPerChannelFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { const KisPerChannelFilterConfiguration* configBC = dynamic_cast(config.data()); // Somehow, this shouldn't happen Q_ASSERT(configBC); const QVector > &originalTransfers = configBC->transfers(); const QList &originalCurves = configBC->curves(); /** * TODO: What about the order of channels? (DK) * * Virtual channels are sorted in display order, does Lcms accepts * transforms in display order? Why on Earth it works?! Is it * documented anywhere? */ const QVector virtualChannels = getVirtualChannels(cs); if (originalTransfers.size() != int(virtualChannels.size())) { // We got an illegal number of colorchannels :( return 0; } bool colorsNull = true; bool lightnessNull = true; bool allColorsNull = true; int alphaIndexInReal = -1; QVector > realTransfers; QVector lightnessTransfer; QVector allColorsTransfer; for (int i = 0; i < virtualChannels.size(); i++) { if (virtualChannels[i].type() == VirtualChannelInfo::REAL) { realTransfers << originalTransfers[i]; if (virtualChannels[i].isAlpha()) { alphaIndexInReal = realTransfers.size() - 1; } if (colorsNull && !originalCurves[i].isNull()) { colorsNull = false; } } else if (virtualChannels[i].type() == VirtualChannelInfo::LIGHTNESS) { KIS_ASSERT_RECOVER_NOOP(lightnessTransfer.isEmpty()); lightnessTransfer = originalTransfers[i]; if (lightnessNull && !originalCurves[i].isNull()) { lightnessNull = false; } } else if (virtualChannels[i].type() == VirtualChannelInfo::ALL_COLORS) { KIS_ASSERT_RECOVER_NOOP(allColorsTransfer.isEmpty()); allColorsTransfer = originalTransfers[i]; if (allColorsNull && !originalCurves[i].isNull()) { allColorsNull = false; } } } KoColorTransformation *lightnessTransform = 0; KoColorTransformation *allColorsTransform = 0; KoColorTransformation *colorTransform = 0; if (!colorsNull) { const quint16** transfers = new const quint16*[realTransfers.size()]; for(int i = 0; i < realTransfers.size(); ++i) { transfers[i] = realTransfers[i].constData(); /** * createPerChannelAdjustment() expects alpha channel to * be the last channel in the list, so just it here */ KIS_ASSERT_RECOVER_NOOP(i != alphaIndexInReal || alphaIndexInReal == (realTransfers.size() - 1)); } colorTransform = cs->createPerChannelAdjustment(transfers); delete [] transfers; } if (!lightnessNull) { lightnessTransform = cs->createBrightnessContrastAdjustment(lightnessTransfer.constData()); } if (!allColorsNull) { const quint16** allColorsTransfers = new const quint16*[realTransfers.size()]; for(int i = 0; i < realTransfers.size(); ++i) { allColorsTransfers[i] = (i != alphaIndexInReal) ? allColorsTransfer.constData() : 0; /** * createPerChannelAdjustment() expects alpha channel to * be the last channel in the list, so just it here */ KIS_ASSERT_RECOVER_NOOP(i != alphaIndexInReal || alphaIndexInReal == (realTransfers.size() - 1)); } allColorsTransform = cs->createPerChannelAdjustment(allColorsTransfers); delete[] allColorsTransfers; } QVector allTransforms; allTransforms << colorTransform; allTransforms << allColorsTransform; allTransforms << lightnessTransform; return KoCompositeColorTransformation::createOptimizedCompositeTransform(allTransforms); } bool KisPerChannelFilter::needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const { Q_UNUSED(config); return cs->colorModelId() == AlphaColorModelID; } diff --git a/plugins/filters/colorsfilters/kis_perchannel_filter.h b/plugins/filters/colorsfilters/kis_perchannel_filter.h index ce272ead29..566734bd60 100644 --- a/plugins/filters/colorsfilters/kis_perchannel_filter.h +++ b/plugins/filters/colorsfilters/kis_perchannel_filter.h @@ -1,135 +1,135 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_PERCHANNEL_FILTER_H_ #define _KIS_PERCHANNEL_FILTER_H_ #include #include #include #include #include #include #include "ui_wdg_perchannel.h" #include "virtual_channel_info.h" class WdgPerChannel : public QWidget, public Ui::WdgPerChannel { Q_OBJECT public: WdgPerChannel(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class KisPerChannelFilterConfiguration : public KisColorTransformationConfiguration { public: KisPerChannelFilterConfiguration(int n); ~KisPerChannelFilterConfiguration(); using KisFilterConfiguration::fromXML; using KisFilterConfiguration::toXML; using KisFilterConfiguration::fromLegacyXML; virtual void fromLegacyXML(const QDomElement& root); virtual void fromXML(const QDomElement& e); virtual void toXML(QDomDocument& doc, QDomElement& root) const; virtual void setCurves(QList &curves); static inline void initDefaultCurves(QList &curves, int nCh); bool isCompatible(const KisPaintDeviceSP) const; const QVector >& transfers() const; virtual const QList& curves() const; private: QList m_curves; private: void updateTransfers(); private: QVector > m_transfers; }; /** * This class is generic for filters that affect channel separately */ class KisPerChannelFilter : public KisColorTransformationFilter { public: KisPerChannelFilter(); public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; virtual bool needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const; static inline KoID id() { return KoID("perchannel", i18n("Color Adjustment")); } private: }; class KisPerChannelConfigWidget : public KisConfigWidget { Q_OBJECT public: KisPerChannelConfigWidget(QWidget * parent, KisPaintDeviceSP dev, Qt::WFlags f = 0); virtual ~KisPerChannelConfigWidget(); virtual void setConfiguration(const KisPropertiesConfigurationSP config); virtual KisPropertiesConfigurationSP configuration() const; private Q_SLOTS: virtual void setActiveChannel(int ch); private: QVector m_virtualChannels; int m_activeVChannel; // private routines inline QPixmap getHistogram(); inline QPixmap createGradient(Qt::Orientation orient /*, int invert (not used now) */); // members WdgPerChannel * m_page; KisPaintDeviceSP m_dev; KisHistogram *m_histogram; mutable QList m_curves; // scales for displaying color numbers double m_scale; double m_shift; }; #endif diff --git a/plugins/filters/embossfilter/kis_emboss_filter.cpp b/plugins/filters/embossfilter/kis_emboss_filter.cpp index 64981dae47..0eed8d49ea 100644 --- a/plugins/filters/embossfilter/kis_emboss_filter.cpp +++ b/plugins/filters/embossfilter/kis_emboss_filter.cpp @@ -1,163 +1,163 @@ /* * This file is part of Krita * * Copyright (c) 2004 Michael Thaler * * ported from digikam, Copyrighted 2004 Gilles Caulier, * Original Emboss algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_emboss_filter.h" #include #include #include #include #include #include #include #include "KoIntegerMaths.h" #include #include #include #include #include #include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" #include KisEmbossFilter::KisEmbossFilter() : KisFilter(id(), categoryEmboss(), i18n("&Emboss with Variable Depth...")) { setSupportsPainting(false); setColorSpaceIndependence(TO_RGBA8); setSupportsThreading(false); setSupportsAdjustmentLayers(false); } -KisFilterConfigurationSP KisEmbossFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisEmbossFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 0); config->setProperty("depth", 30); return config; } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the Emboss effect * * data => The image data in RGBA mode. * Width => Width of image. * Height => Height of image. * d => Emboss value * * Theory => This is an amazing effect. And the theory is very simple to * understand. You get the diference between the colors and * increase it. After this, get the gray tone */ void KisEmbossFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); //read the filter configuration values from the KisFilterConfiguration object quint32 embossdepth = config ? config->getInt("depth", 30) : 30; //the actual filter function from digikam. It needs a pointer to a quint8 array //with the actual pixel data. float Depth = embossdepth / 10.0; int R = 0, G = 0, B = 0; uchar Gray = 0; int Width = applyRect.width(); int Height = applyRect.height(); if (progressUpdater) { progressUpdater->setRange(0, Height); } KisSequentialIterator it(device, applyRect); QColor color1; QColor color2; KisRandomConstAccessorSP acc = device->createRandomAccessorNG(srcTopLeft.x(), srcTopLeft.y()); do { // XXX: COLORSPACE_INDEPENDENCE or at least work IN RGB16A device->colorSpace()->toQColor(it.oldRawData(), &color1); acc->moveTo(srcTopLeft.x() + it.x() + Lim_Max(it.x(), 1, Width), srcTopLeft.y() + it.y() + Lim_Max(it.y(), 1, Height)); device->colorSpace()->toQColor(acc->oldRawData(), &color2); R = abs((int)((color1.red() - color2.red()) * Depth + (quint8_MAX / 2))); G = abs((int)((color1.green() - color2.green()) * Depth + (quint8_MAX / 2))); B = abs((int)((color1.blue() - color2.blue()) * Depth + (quint8_MAX / 2))); Gray = CLAMP((R + G + B) / 3, 0, quint8_MAX); device->colorSpace()->fromQColor(QColor(Gray, Gray, Gray, color1.alpha()), it.rawData()); if (progressUpdater) { progressUpdater->setValue(it.y()); if(progressUpdater->interrupted()) return; } } while(it.nextPixel()); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* This function limits the max and min values * defined by the developer * * Now => Original value * Up => Increments * Max => Maximum value * * Theory => This function is used in some functions to limit the * "for step". E.g. I have a picture with 309 pixels (width), and * my "for step" is 5. All the code go alright until reachs the * w = 305, because in the next step w will go to 310, but we want * to analize all the pixels. So, this function will reduce the * "for step", when necessary, until reach the last possible value */ int KisEmbossFilter::Lim_Max(int Now, int Up, int Max) const { --Max; while (Now > Max - Up) --Up; return (Up); } KisConfigWidget * KisEmbossFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(10, 300, 30, i18n("Depth"), "depth")); KisConfigWidget * w = new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); Q_CHECK_PTR(w); return w; } diff --git a/plugins/filters/embossfilter/kis_emboss_filter.h b/plugins/filters/embossfilter/kis_emboss_filter.h index 2744d2812f..e441ea3093 100644 --- a/plugins/filters/embossfilter/kis_emboss_filter.h +++ b/plugins/filters/embossfilter/kis_emboss_filter.h @@ -1,51 +1,51 @@ /* * This file is part of the KDE project * * Copyright (c) Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_EMBOSS_FILTER_H_ #define _KIS_EMBOSS_FILTER_H_ #include "filter/kis_filter.h" #include "kis_config_widget.h" class KisEmbossFilter : public KisFilter { public: KisEmbossFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("emboss", i18n("Emboss with Variable Depth")); } public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; protected: - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; private: inline int Lim_Max(int Now, int Up, int Max) const; }; #endif diff --git a/plugins/filters/fastcolortransfer/fastcolortransfer.cpp b/plugins/filters/fastcolortransfer/fastcolortransfer.cpp index 558bb8522f..df9b683354 100644 --- a/plugins/filters/fastcolortransfer/fastcolortransfer.cpp +++ b/plugins/filters/fastcolortransfer/fastcolortransfer.cpp @@ -1,175 +1,175 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "fastcolortransfer.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_fastcolortransfer.h" #include "ui_wdgfastcolortransfer.h" #include K_PLUGIN_FACTORY_WITH_JSON(KritaFastColorTransferFactory, "kritafastcolortransfer.json", registerPlugin();) FastColorTransferPlugin::FastColorTransferPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterFastColorTransfer()); } FastColorTransferPlugin::~FastColorTransferPlugin() { } KisFilterFastColorTransfer::KisFilterFastColorTransfer() : KisFilter(id(), categoryColors(), i18n("&Color Transfer...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsThreading(false); setSupportsPainting(false); setSupportsAdjustmentLayers(false); } KisConfigWidget * KisFilterFastColorTransfer::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgFastColorTransfer(parent); } -KisFilterConfigurationSP KisFilterFastColorTransfer::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterFastColorTransfer::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); - config->setProperty("filename", ""); // TODO: put an exemple image in share/krita, like a sunset that what's give the best results + config->setProperty("filename", ""); return config; } #define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x))) void KisFilterFastColorTransfer::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const { Q_ASSERT(device != 0); dbgPlugins << "Start transferring color"; // Convert ref and src to LAB const KoColorSpace* labCS = KoColorSpaceRegistry::instance()->lab16(); if (!labCS) { dbgPlugins << "The LAB colorspace is not available."; return; } dbgPlugins << "convert a copy of src to lab"; const KoColorSpace* oldCS = device->colorSpace(); KisPaintDeviceSP srcLAB = new KisPaintDevice(*device.data()); dbgPlugins << "srcLab : " << srcLAB->extent(); KUndo2Command* cmd = srcLAB->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); delete cmd; if (progressUpdater) { progressUpdater->setRange(0, 2 * applyRect.width() * applyRect.height()); } int count = 0; // Compute the means and sigmas of src dbgPlugins << "Compute the means and sigmas of src"; double meanL_src = 0., meanA_src = 0., meanB_src = 0.; double sigmaL_src = 0., sigmaA_src = 0., sigmaB_src = 0.; KisSequentialConstIterator srcIt(srcLAB, applyRect); do { const quint16* data = reinterpret_cast(srcIt.oldRawData()); quint32 L = data[0]; quint32 A = data[1]; quint32 B = data[2]; meanL_src += L; meanA_src += A; meanB_src += B; sigmaL_src += L * L; sigmaA_src += A * A; sigmaB_src += B * B; if (progressUpdater) progressUpdater->setValue(++count); } while (srcIt.nextPixel() && !(progressUpdater && progressUpdater->interrupted())); double totalSize = 1. / (applyRect.width() * applyRect.height()); meanL_src *= totalSize; meanA_src *= totalSize; meanB_src *= totalSize; sigmaL_src *= totalSize; sigmaA_src *= totalSize; sigmaB_src *= totalSize; dbgPlugins << totalSize << "" << meanL_src << "" << meanA_src << "" << meanB_src << "" << sigmaL_src << "" << sigmaA_src << "" << sigmaB_src; double meanL_ref = config->getDouble("meanL"); double meanA_ref = config->getDouble("meanA"); double meanB_ref = config->getDouble("meanB"); double sigmaL_ref = config->getDouble("sigmaL"); double sigmaA_ref = config->getDouble("sigmaA"); double sigmaB_ref = config->getDouble("sigmaB"); // Transfer colors dbgPlugins << "Transfer colors"; { double coefL = sqrt((sigmaL_ref - meanL_ref * meanL_ref) / (sigmaL_src - meanL_src * meanL_src)); double coefA = sqrt((sigmaA_ref - meanA_ref * meanA_ref) / (sigmaA_src - meanA_src * meanA_src)); double coefB = sqrt((sigmaB_ref - meanB_ref * meanB_ref) / (sigmaB_src - meanB_src * meanB_src)); KisHLineConstIteratorSP srcLABIt = srcLAB->createHLineConstIteratorNG(applyRect.x(), applyRect.y(), applyRect.width()); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(applyRect.x(), applyRect.y(), applyRect.width()); quint16 labPixel[4]; for (int y = 0; y < applyRect.height() && !(progressUpdater && progressUpdater->interrupted()); ++y) { do { const quint16* data = reinterpret_cast(srcLABIt->oldRawData()); labPixel[0] = (quint16)CLAMP(((double)data[0] - meanL_src) * coefL + meanL_ref, 0., 65535.); labPixel[1] = (quint16)CLAMP(((double)data[1] - meanA_src) * coefA + meanA_ref, 0., 65535.); labPixel[2] = (quint16)CLAMP(((double)data[2] - meanB_src) * coefB + meanB_ref, 0., 65535.); labPixel[3] = data[3]; oldCS->fromLabA16(reinterpret_cast(labPixel), dstIt->rawData(), 1); if (progressUpdater) progressUpdater->setValue(++count); srcLABIt->nextPixel(); } while(dstIt->nextPixel()); dstIt->nextRow(); srcLABIt->nextRow(); } } } #include "fastcolortransfer.moc" diff --git a/plugins/filters/fastcolortransfer/fastcolortransfer.h b/plugins/filters/fastcolortransfer/fastcolortransfer.h index f906fe66be..592e1d4e31 100644 --- a/plugins/filters/fastcolortransfer/fastcolortransfer.h +++ b/plugins/filters/fastcolortransfer/fastcolortransfer.h @@ -1,55 +1,55 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef COLORTRANSFER_H #define COLORTRANSFER_H #include #include #include class FastColorTransferPlugin : public QObject { Q_OBJECT public: FastColorTransferPlugin(QObject *parent, const QVariantList &); virtual ~FastColorTransferPlugin(); }; class KisFilterFastColorTransfer : public KisFilter { public: KisFilterFastColorTransfer(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const; static inline KoID id() { return KoID("colortransfer", i18n("Color Transfer")); } public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; #endif diff --git a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp index 06b10db86e..11e713d4bc 100644 --- a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp +++ b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp @@ -1,99 +1,99 @@ /* * This file is part of the KDE project * * Copyright (c) 2016 Spencer Brown * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "krita_filter_gradient_map.h" #include #include #include #include #include #include "kis_config_widget.h" #include #include #include #include #include "gradientmap.h" #include KritaFilterGradientMap::KritaFilterGradientMap() : KisFilter(id(), categoryMap(), i18n("&Gradient Map")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); setSupportsLevelOfDetail(true); setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsThreading(true); } void KritaFilterGradientMap::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.height() * applyRect.width()); } KoAbstractGradient *gradient = KoResourceServerProvider::instance()->gradientServer(false)->resourceByName(config->getString("gradientName")); KoColorSet *gradientCache = new KoColorSet(); for (int i=0; i<256; i++) { KoColor gc; gradient->colorAt(gc, ((qreal)i/255.0)); KoColorSetEntry col; col.color = gc; gradientCache->add(col); } KoColor outColor(Qt::white, device->colorSpace()); KisSequentialIterator it(device, applyRect); int p = 0; quint8 grey; const int pixelSize = device->colorSpace()->pixelSize(); do { grey = device->colorSpace()->intensity8(it.oldRawData()); outColor = gradientCache->getColor((quint32)grey).color; outColor.setOpacity(qMin(KoColor(it.oldRawData(), device->colorSpace()).opacityF(), outColor.opacityF())); outColor.convertTo(device->colorSpace()); memcpy(it.rawData(), outColor.data(), pixelSize); if (progressUpdater) progressUpdater->setValue(p++); } while (it.nextPixel()); } -KisFilterConfigurationSP KritaFilterGradientMap::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KritaFilterGradientMap::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("gradientmap", 1); KoAbstractGradient *gradient = KoResourceServerProvider::instance()->gradientServer(false)->resources().first(); config->setProperty("gradientName", gradient->name()); return config; } KisConfigWidget * KritaFilterGradientMap::createConfigurationWidget(QWidget * parent, const KisPaintDeviceSP dev) const { return new KritaGradientMapConfigWidget(parent, dev); } diff --git a/plugins/filters/gradientmap/krita_filter_gradient_map.h b/plugins/filters/gradientmap/krita_filter_gradient_map.h index 6d805da010..4a3303175c 100644 --- a/plugins/filters/gradientmap/krita_filter_gradient_map.h +++ b/plugins/filters/gradientmap/krita_filter_gradient_map.h @@ -1,52 +1,52 @@ /* * This file is part of Krita * * Copyright (c) 2016 Spencer Brown * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_GRADIENT_MAP_H #define KIS_GRADIENT_MAP_H #include #include #include #include #include #include #include class KritaFilterGradientMap : public KisFilter { public: KritaFilterGradientMap(); public: static inline KoID id() { return KoID("gradientmap", i18n("Gradient Map")); } virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget* createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; #endif diff --git a/plugins/filters/halftone/kis_halftone_filter.cpp b/plugins/filters/halftone/kis_halftone_filter.cpp index c5782dde34..9c8c9db5ea 100644 --- a/plugins/filters/halftone/kis_halftone_filter.cpp +++ b/plugins/filters/halftone/kis_halftone_filter.cpp @@ -1,271 +1,269 @@ /* * This file is part of Krita * * Copyright (c) 2016 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "kis_filter_configuration.h" #include #include #include #include #include #include #include #include "kis_halftone_filter.h" K_PLUGIN_FACTORY_WITH_JSON(KritaHalftoneFactory, "kritahalftone.json", registerPlugin();) KritaHalftone::KritaHalftone(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisHalftoneFilter()); } KritaHalftone::~KritaHalftone() { } KisHalftoneFilter::KisHalftoneFilter() : KisFilter(id(), categoryArtistic(), i18n("&Halftone...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(false); setShowConfigurationWidget(true); setSupportsLevelOfDetail(false); setSupportsAdjustmentLayers(false); setSupportsThreading(false); } //I am pretty terrible at trigionometry, hence all the comments. void KisHalftoneFilter::processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { qreal cellSize = (qreal)config->getInt("cellSize", 8); qreal angle = fmod((qreal)config->getInt("patternAngle", 45), 90.0); KoColor foregroundC(Qt::black, device->colorSpace()); foregroundC.fromKoColor(config->getColor("foreGroundColor", KoColor(Qt::black, device->colorSpace()) ) ); KoColor backgroundC(Qt::white, device->colorSpace()); backgroundC.fromKoColor(config->getColor("backGroundColor", KoColor(Qt::white, device->colorSpace()) ) ); //First calculate the full diameter, using pythagoras theorem. qreal diameter = qSqrt((cellSize*cellSize)*2); qreal cellSpacingH = cellSize; qreal cellSpacingV = cellSize; qreal cellOffsetV = 0; if (angle>0.0){ //2/3=0.6 sin=o/h //0.6*3=2 sin*h=o //2/0.6=3 o/sin=h qreal angleRad = qDegreesToRadians(angle); //Horizontal cellspacing is the hypotenuse of the Angle and the cellSize(opposite). cellSpacingH = cellSize/qSin(angleRad); //Vertical cellspacing is the opposite of the Angle and the cellSize(hypotenuse). cellSpacingV = cellSize*qSin(angleRad); //cellSpacingoffset is the oppose of the (90-angle) and the vertical cellspacing(adjectant) toa t=o/a, t*a=o. cellOffsetV = qTan(qDegreesToRadians(90-angle))*cellSpacingV; } QPolygonF gridPoints; QRect totalRect(QPoint(0,0), applyRect.bottomRight()); if (gridPoints.size()<1) { int rows = (totalRect.height()/cellSpacingV)+3; for (int r=0; rexactBounds(); if (progressUpdater) { progressUpdater->setRange(0, (applyRect.height()/cellSpacingV+3)*(applyRect.width()/cellSpacingH+3)); } KisRandomConstAccessorSP itterator = device->createRandomConstAccessorNG( 0, 0); //itterator->numContiguousColumns(qCeil(cellSize)); //itterator->numContiguousRows(qCeil(cellSize)); KisPainter painter(device); painter.setCompositeOp(device->colorSpace()->compositeOp(COMPOSITE_OVER)); KisPaintDeviceSP dab = device->createCompositionSourceDevice(); KisPainter dbPainter(dab); KisSelectionSP alpha = new KisSelection(); alpha->pixelSelection()->copyAlphaFrom(device, applyRect); device->fill(applyRect, backgroundC); dbPainter.setAntiAliasPolygonFill(config->getBool("antiAliasing", true)); dbPainter.setPaintColor(foregroundC); dbPainter.setFillStyle(KisPainter::FillStyleForegroundColor); dbPainter.setCompositeOp(device->colorSpace()->compositeOp(COMPOSITE_OVER)); quint8 eightbit = 255; if (config->getBool("invert", false)) { eightbit = 0; } QRect cellRect(applyRect.topLeft()-QPoint(qFloor(cellSpacingH), qFloor(qMax(cellSpacingV, diameter))), applyRect.bottomRight()+QPoint(qCeil(cellSpacingH), qCeil(qMax(cellSpacingV, diameter)))); for (int i=0; imoveTo(center.x(), center.y()); quint8 intensity = device->colorSpace()->intensity8(itterator->oldRawData()); qreal size = diameter*((qAbs(intensity-eightbit))/255.0); QPoint sPoint(qMax(qFloor(samplePoint.x()), applyRect.left()), qMax(qFloor(samplePoint.y()), applyRect.top())); dbPainter.bitBlt(0, 0, device, sPoint.x(), sPoint.y(), diameter, diameter); dbPainter.paintEllipse((samplePoint.x()-qFloor(samplePoint.x()))+qCeil(size)-size, (samplePoint.y()-qFloor(samplePoint.y()))+qCeil(size)-size, size, size); dab->crop(qAbs(qMin(0, xdifference)), qAbs(qMin(0, ydifference)), diameter, diameter); //we only want to paint the bits actually in the apply rect...) painter.bitBlt(sPoint, dab, dab->exactBounds()); if (progressUpdater) { progressUpdater->setValue(i); } } } alpha->pixelSelection()->invert(); device->clearSelection(alpha); } -KisFilterConfigurationSP KisHalftoneFilter::factoryConfiguration(const KisPaintDeviceSP dev) const +KisFilterConfigurationSP KisHalftoneFilter::factoryConfiguration() const { - Q_UNUSED(dev); - KisFilterConfigurationSP config = new KisFilterConfiguration("halftone", 1); config->setProperty("cellSize", 8.0); config->setProperty("patternAngle", 45.0); QVariant v; KoColor black; black.fromQColor(QColor(Qt::black)); v.setValue(black); config->setProperty("foreGroundColor", v); KoColor white; white.fromQColor(QColor(Qt::white)); v.setValue(white); config->setProperty("backGroundColor", v); config->setProperty("antiAliasing", true); config->setProperty("invert", false); return config; } KisConfigWidget *KisHalftoneFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisHalftoneConfigWidget(parent, dev); } //----------config---------// KisHalftoneConfigWidget::KisHalftoneConfigWidget(QWidget *parent, KisPaintDeviceSP dev) : KisConfigWidget(parent) { Q_ASSERT(dev); m_page.setupUi(this); KoColor white(Qt::white, dev->colorSpace()); KoColor black(Qt::black, dev->colorSpace()); m_page.bnforeground->setColor(white); m_page.bnbackground->setColor(black); m_page.bnforeground->setDefaultColor(white); m_page.bnbackground->setDefaultColor(black); m_page.sld_cellSize->setRange(3, 90); connect(m_page.sld_cellSize, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); connect(m_page.dial_angle, SIGNAL(valueChanged(int)), m_page.spb_angle, SLOT(setValue(int))); connect(m_page.dial_angle, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); connect(m_page.spb_angle, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); connect(m_page.bnforeground, SIGNAL(changed(KoColor)), SLOT(slotConfigChanged())); connect(m_page.bnbackground, SIGNAL(changed(KoColor)), SLOT(slotConfigChanged())); connect(m_page.ckbAntialiasing, SIGNAL(toggled(bool)), SLOT(slotConfigChanged())); connect(m_page.ckbInvert, SIGNAL(toggled(bool)), SLOT(slotConfigChanged())); } KisHalftoneConfigWidget::~KisHalftoneConfigWidget() { } KisPropertiesConfigurationSP KisHalftoneConfigWidget::configuration() const { KisFilterConfiguration *config = new KisFilterConfiguration("halftone", 1); config->setProperty("cellSize", m_page.sld_cellSize->value()); config->setProperty("patternAngle", m_page.spb_angle->value()); QVariant v; v.setValue(m_page.bnforeground->color()); config->setProperty("foreGroundColor", v); v.setValue(m_page.bnbackground->color()); config->setProperty("backGroundColor", v); config->setProperty("antiAliasing", m_page.ckbAntialiasing->isChecked()); config->setProperty("invert", m_page.ckbInvert->isChecked()); return config; } void KisHalftoneConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { QVariant value; if (config->getProperty("cellSize", value)) { m_page.sld_cellSize->setValue(value.toUInt()); } if (config->getProperty("patternAngle", value)) { m_page.dial_angle->setValue(value.toUInt()); m_page.spb_angle->setValue(value.toUInt()); } if (config->getProperty("antiAliasing", value)) { m_page.ckbAntialiasing->setChecked(value.toBool()); } if (config->getProperty("invert", value)) { m_page.ckbInvert->setChecked(value.toBool()); } m_page.bnforeground->setColor(config->getColor("foreGroundColor",m_page.bnforeground->defaultColor())); m_page.bnbackground->setColor(config->getColor("backGroundColor",m_page.bnbackground->defaultColor())); } #include "kis_halftone_filter.moc" diff --git a/plugins/filters/halftone/kis_halftone_filter.h b/plugins/filters/halftone/kis_halftone_filter.h index bcdb18e4b4..6c44db621a 100644 --- a/plugins/filters/halftone/kis_halftone_filter.h +++ b/plugins/filters/halftone/kis_halftone_filter.h @@ -1,101 +1,101 @@ /* * This file is part of Krita * * Copyright (c) 2016 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISHALFTONEFILTER_H #define KISHALFTONEFILTER_H #include #include #include #include #include "ui_wdg_halftone_filter.h" class WdgHalftone; class KritaHalftone : public QObject { Q_OBJECT public: KritaHalftone(QObject *parent, const QVariantList &); virtual ~KritaHalftone(); }; /** * @brief The kisHalftoneFilter class * This filter will allow the user to input an image and have it be approximated with * a halftone pattern. https://en.wikipedia.org/wiki/Halftone * * The primary usecase of such a filter is for specialised printing techniques, but for * many people the half-tone pattern also serves as a neutral pattern that is more pleasant * than plain flat look. The half tone in this case also becomes a stylistic technique. * * Based on that, there's a few ways a user could want to use this techique: * 1. Per-component. Per patch, each component will have a halftone approximated. * 2. Intensity only. The relative luminosity of the patch is determined and will be used * for the approximation, resulting in a black/white pattern. * 3. Intensity and then two colors mapped to the black/white pattern. * * On top of that, the pattern can be rotated, the shape can be chosen, and the user will want to * decide whether or not to use antialiasing(as printers themselves give * inefficient results with anti-aliasing). * * As of currently, 2 and 3 can be done. 1 is not impossible to code with some creative usage of composite * modes, but might be a little slow. */ class KisHalftoneFilter : public KisFilter { public: KisHalftoneFilter(); static inline KoID id() { return KoID("halftone", i18n("Halftone")); } virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP dev) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget *createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const; private: QPolygonF m_gridPoints; }; class KisHalftoneConfigWidget : public KisConfigWidget { Q_OBJECT public: KisHalftoneConfigWidget(QWidget *parent, KisPaintDeviceSP dev); virtual ~KisHalftoneConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; void setConfiguration(const KisPropertiesConfigurationSP config); Ui::WdgHalftone m_page; }; #endif // KISHALFTONEFILTER_H diff --git a/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp b/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp index 0d6dde31d6..86b1e2e7ee 100644 --- a/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp +++ b/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp @@ -1,129 +1,129 @@ /* * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "kis_simple_noise_reducer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include KisSimpleNoiseReducer::KisSimpleNoiseReducer() : KisFilter(id(), categoryEnhance(), i18n("&Gaussian Noise Reduction...")) { setSupportsPainting(false); } KisSimpleNoiseReducer::~KisSimpleNoiseReducer() { } KisConfigWidget * KisSimpleNoiseReducer::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(0, 255, 15, i18n("Threshold"), "threshold")); param.push_back(KisIntegerWidgetParam(0, 10, 1, i18n("Window size"), "windowsize")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } -KisFilterConfigurationSP KisSimpleNoiseReducer::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisSimpleNoiseReducer::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 0); config->setProperty("threshold", 15); config->setProperty("windowsize", 1); return config; } inline int ABS(int v) { if (v < 0) return -v; return v; } void KisSimpleNoiseReducer::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); int threshold, windowsize; - KisFilterConfigurationSP config = _config ? _config : defaultConfiguration(device); + KisFilterConfigurationSP config = _config ? _config : defaultConfiguration(); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; threshold = config->getInt("threshold", 15); windowsize = config->getInt("windowsize", 1); const KoColorSpace* cs = device->colorSpace(); // Compute the blur mask KisCircleMaskGenerator* kas = new KisCircleMaskGenerator(2*windowsize + 1, 1, windowsize, windowsize, 2, true); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas); delete kas; KisPaintDeviceSP interm = new KisPaintDevice(*device); // TODO no need for a full copy and then a transaction KisConvolutionPainter painter(interm); painter.beginTransaction(); painter.applyMatrix(kernel, interm, srcTopLeft, srcTopLeft, applyRect.size(), BORDER_REPEAT); painter.deleteTransaction(); if (progressUpdater && progressUpdater->interrupted()) { return; } KisHLineIteratorSP dstIt = device->createHLineIteratorNG(srcTopLeft.x(), srcTopLeft.y(), applyRect.width()); KisHLineConstIteratorSP intermIt = interm->createHLineConstIteratorNG(srcTopLeft.x(), srcTopLeft.y(), applyRect.width()); for (int j = 0; j < applyRect.height() && !(progressUpdater && progressUpdater->interrupted()); j++) { do { quint8 diff = cs->difference(dstIt->oldRawData(), intermIt->oldRawData()); if (diff > threshold) { memcpy(dstIt->rawData(), intermIt->oldRawData(), cs->pixelSize()); } if (progressUpdater) progressUpdater->setValue(++count); intermIt->nextPixel(); } while (dstIt->nextPixel() && !(progressUpdater && progressUpdater->interrupted())); dstIt->nextRow(); intermIt->nextRow(); } } diff --git a/plugins/filters/imageenhancement/kis_simple_noise_reducer.h b/plugins/filters/imageenhancement/kis_simple_noise_reducer.h index 94899b488c..a78ca45075 100644 --- a/plugins/filters/imageenhancement/kis_simple_noise_reducer.h +++ b/plugins/filters/imageenhancement/kis_simple_noise_reducer.h @@ -1,48 +1,48 @@ /* a * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISSIMPLENOISEREDUCER_H #define KISSIMPLENOISEREDUCER_H #include #include "kis_config_widget.h" /** @author Cyrille Berger */ class KisSimpleNoiseReducer : public KisFilter { public: KisSimpleNoiseReducer(); ~KisSimpleNoiseReducer(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; static inline KoID id() { return KoID("gaussiannoisereducer", i18n("Gaussian Noise Reducer")); } protected: - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; #endif diff --git a/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp b/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp index d09b3b7f8e..8a425011da 100644 --- a/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp +++ b/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp @@ -1,127 +1,127 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_wavelet_noise_reduction.h" #include #include #include #include #include #include #include #include #include KisWaveletNoiseReduction::KisWaveletNoiseReduction() : KisFilter(id(), categoryEnhance(), i18n("&Wavelet Noise Reducer...")) { setSupportsPainting(false); setSupportsThreading(false); } KisWaveletNoiseReduction::~KisWaveletNoiseReduction() { } KisConfigWidget * KisWaveletNoiseReduction::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisDoubleWidgetParam param; param.push_back(KisDoubleWidgetParam(0.0, 256.0, BEST_WAVELET_THRESHOLD_VALUE, i18n("Threshold"), "threshold")); return new KisMultiDoubleFilterWidget(id().id(), parent, id().id(), param); } -KisFilterConfigurationSP KisWaveletNoiseReduction::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisWaveletNoiseReduction::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 0); config->setProperty("threshold", BEST_WAVELET_THRESHOLD_VALUE); return config; } void KisWaveletNoiseReduction::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { Q_ASSERT(device); // TODO take selections into account float threshold; - KisFilterConfigurationSP config = _config ? _config : defaultConfiguration(device); + KisFilterConfigurationSP config = _config ? _config : defaultConfiguration(); threshold = config->getDouble("threshold", BEST_WAVELET_THRESHOLD_VALUE); qint32 depth = device->colorSpace()->colorChannelCount(); int size; int maxrectsize = qMax(applyRect.width(), applyRect.height()); for (size = 2; size < maxrectsize; size *= 2) ; KisMathToolbox mathToolbox; if (progressUpdater) { progressUpdater->setRange(0, mathToolbox.fastWaveletTotalSteps(applyRect) * 2 + size*size*depth); } int count = 0; // dbgFilters << size <<"" << maxrectsize <<"" << srcTopLeft.x() <<"" << srcTopLeft.y(); // dbgFilters <<"Transforming..."; KisMathToolbox::KisWavelet* buff = 0; KisMathToolbox::KisWavelet* wav = 0; try { buff = mathToolbox.initWavelet(device, applyRect); } catch (std::bad_alloc) { if (buff) delete buff; return; } try { wav = mathToolbox.fastWaveletTransformation(device, applyRect, buff); } catch (std::bad_alloc) { if (wav) delete wav; return; } // dbgFilters <<"Thresholding..."; float* fin = wav->coeffs + wav->depth * wav->size * wav->size; for (float* it = wav->coeffs + wav->depth; it < fin; it++) { if (*it > threshold) { *it -= threshold; } else if (*it < -threshold) { *it += threshold; } else { *it = 0.; } if (progressUpdater) progressUpdater->setValue(++count); } // dbgFilters <<"Untransforming..."; mathToolbox.fastWaveletUntransformation(device, applyRect, wav, buff); delete wav; delete buff; } diff --git a/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h b/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h index 99858e2dfd..e6cbc43854 100644 --- a/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h +++ b/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h @@ -1,57 +1,57 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_WAVELET_NOISE_REDUCTION_H #define KIS_WAVELET_NOISE_REDUCTION_H #include #include #define BEST_WAVELET_THRESHOLD_VALUE 7.0 /** @author Cyrille Berger */ class KisWaveletNoiseReduction : public KisFilter { public: KisWaveletNoiseReduction(); ~KisWaveletNoiseReduction(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; static inline KoID id() { return KoID("waveletnoisereducer", i18n("Wavelet Noise Reducer")); } private: - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; #endif diff --git a/plugins/filters/indexcolors/indexcolors.cpp b/plugins/filters/indexcolors/indexcolors.cpp index 3e4aca223e..8754592529 100644 --- a/plugins/filters/indexcolors/indexcolors.cpp +++ b/plugins/filters/indexcolors/indexcolors.cpp @@ -1,144 +1,144 @@ /* * Copyright 2014 Manuel Riecke * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #include "indexcolors.h" #include #include #include #include #include #include #include #include "kiswdgindexcolors.h" #include "palettegeneratorconfig.h" K_PLUGIN_FACTORY_WITH_JSON(IndexColorsFactory, "kritaindexcolors.json", registerPlugin();) IndexColors::IndexColors(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterIndexColors())); } IndexColors::~IndexColors() { } KisFilterIndexColors::KisFilterIndexColors() : KisColorTransformationFilter(id(), categoryArtistic(), i18n("&Index Colors...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); // Technically it is TO_LAB16 but that would only display a warning we don't want // This filter will always degrade the color space, that is it's purpose setSupportsPainting(true); setShowConfigurationWidget(true); } KoColorTransformation* KisFilterIndexColors::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { IndexColorPalette pal; PaletteGeneratorConfig palCfg; palCfg.fromByteArray(config->getProperty("paletteGen").toByteArray()); pal = palCfg.generate(); if(config->getBool("reduceColorsEnabled")) { int maxClrs = config->getInt("colorLimit"); while(pal.numColors() > maxClrs) pal.mergeMostReduantColors(); } pal.similarityFactors.L = config->getFloat("LFactor"); pal.similarityFactors.a = config->getFloat("aFactor"); pal.similarityFactors.b = config->getFloat("bFactor"); return new KisIndexColorTransformation(pal, cs, config->getInt("alphaSteps")); } KisConfigWidget* KisFilterIndexColors::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); KisWdgIndexColors* w = new KisWdgIndexColors(parent); w->setup( QStringList() << i18nc("Color palette shade", "Bright") << i18nc("Color palette shade", "Light") << i18nc("Color palette shade", "Base") << i18nc("Color palette shade", "Shadow") , 4 ); return w; } -KisFilterConfigurationSP KisFilterIndexColors::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterIndexColors::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); PaletteGeneratorConfig palCfg; // Default constructor is factory config config->setProperty("paletteGen", palCfg.toByteArray()); config->setProperty("LFactor", 1.f); config->setProperty("aFactor", 1.f); config->setProperty("bFactor", 1.f); config->setProperty("reduceColorsEnabled", false); config->setProperty("colorLimit", 32); config->setProperty("alphaSteps", 1); return config; } KisIndexColorTransformation::KisIndexColorTransformation(IndexColorPalette palette, const KoColorSpace* cs, int alphaSteps) : m_colorSpace(cs), m_psize(cs->pixelSize()) { m_palette = palette; static const qreal max = KoColorSpaceMathsTraits::max; if(alphaSteps > 0) { m_alphaStep = max / alphaSteps; m_alphaHalfStep = m_alphaStep / 2; } else { m_alphaStep = 0; m_alphaHalfStep = 0; } } void KisIndexColorTransformation::transform(const quint8* src, quint8* dst, qint32 nPixels) const { union { quint16 laba[4]; LabColor lab; } clr; while (nPixels--) { m_colorSpace->toLabA16(src, reinterpret_cast(clr.laba), 1); clr.lab = m_palette.getNearestIndex(clr.lab); if(m_alphaStep) { quint16 amod = clr.laba[3] % m_alphaStep; clr.laba[3] = clr.laba[3] + (amod > m_alphaHalfStep ? m_alphaStep - amod : -amod); } m_colorSpace->fromLabA16(reinterpret_cast(clr.laba), dst, 1); src += m_psize; dst += m_psize; } } -#include "indexcolors.moc" \ No newline at end of file +#include "indexcolors.moc" diff --git a/plugins/filters/indexcolors/indexcolors.h b/plugins/filters/indexcolors/indexcolors.h index 7bbe1bfb75..943fe0d5be 100644 --- a/plugins/filters/indexcolors/indexcolors.h +++ b/plugins/filters/indexcolors/indexcolors.h @@ -1,69 +1,69 @@ /* * Copyright 2014 Manuel Riecke * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #ifndef INDEXCOLORS_H #define INDEXCOLORS_H #include #include #include "filter/kis_color_transformation_filter.h" #include "kis_config_widget.h" #include #include "indexcolorpalette.h" class IndexColors : public QObject { Q_OBJECT public: IndexColors(QObject *parent, const QVariantList &); virtual ~IndexColors(); }; class KisFilterIndexColors : public KisColorTransformationFilter { public: KisFilterIndexColors(); public: virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; virtual KisConfigWidget* createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; static inline KoID id() { return KoID("indexcolors", i18n("Index Colors")); } protected: - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; class KisIndexColorTransformation : public KoColorTransformation { public: KisIndexColorTransformation(IndexColorPalette palette, const KoColorSpace* cs, int alphaSteps); virtual void transform(const quint8* src, quint8* dst, qint32 nPixels) const; private: const KoColorSpace* m_colorSpace; quint32 m_psize; IndexColorPalette m_palette; quint16 m_alphaStep; quint16 m_alphaHalfStep; }; #endif diff --git a/plugins/filters/levelfilter/kis_level_filter.h b/plugins/filters/levelfilter/kis_level_filter.h index 114c074033..d0fe6cf42c 100644 --- a/plugins/filters/levelfilter/kis_level_filter.h +++ b/plugins/filters/levelfilter/kis_level_filter.h @@ -1,84 +1,84 @@ /* * This file is part of Krita * * Copyright (c) 2006 Frederic Coiffier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_LEVEL_FILTER_H_ #define _KIS_LEVEL_FILTER_H_ #include "filter/kis_color_transformation_filter.h" #include "kis_config_widget.h" #include "ui_wdg_level.h" class WdgLevel; class QWidget; class KisHistogram; /** * This class affect Intensity Y of the image */ class KisLevelFilter : public KisColorTransformationFilter { public: KisLevelFilter(); ~KisLevelFilter(); public: -// virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; +// virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; static inline KoID id() { return KoID("levels", i18n("Levels")); } }; class KisLevelConfigWidget : public KisConfigWidget { Q_OBJECT public: KisLevelConfigWidget(QWidget * parent, KisPaintDeviceSP dev); virtual ~KisLevelConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; void setConfiguration(const KisPropertiesConfigurationSP config); Ui::WdgLevel m_page; protected Q_SLOTS: void slotDrawHistogram(bool logarithmic = false); void slotModifyInBlackLimit(int); void slotModifyInWhiteLimit(int); void slotModifyOutBlackLimit(int); void slotModifyOutWhiteLimit(int); void slotAutoLevel(void); protected: QScopedPointer m_histogram; bool m_histlog; }; #endif diff --git a/plugins/filters/noisefilter/noisefilter.cpp b/plugins/filters/noisefilter/noisefilter.cpp index 008db81482..c3e192b31d 100644 --- a/plugins/filters/noisefilter/noisefilter.cpp +++ b/plugins/filters/noisefilter/noisefilter.cpp @@ -1,154 +1,154 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "noisefilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_noise.h" #include "ui_wdgnoiseoptions.h" #include K_PLUGIN_FACTORY_WITH_JSON(KritaNoiseFilterFactory, "kritanoisefilter.json", registerPlugin();) KritaNoiseFilter::KritaNoiseFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterNoise()); } KritaNoiseFilter::~KritaNoiseFilter() { } KisFilterNoise::KisFilterNoise() : KisFilter(id(), categoryOther(), i18n("&Random Noise...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } -KisFilterConfigurationSP KisFilterNoise::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterNoise::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("noise", 1); config->setProperty("level", 50); config->setProperty("opacity", 100); config->setProperty("seedThreshold", rand()); config->setProperty("seedRed", rand()); config->setProperty("seedGreen", rand()); config->setProperty("seedBlue", rand()); return config; } KisConfigWidget * KisFilterNoise::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgNoise((KisFilter*)this, (QWidget*)parent); } void KisFilterNoise::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; KisSequentialIterator it(device, applyRect); quint8* interm = new quint8[cs->pixelSize()]; double threshold = (100.0 - level) * 0.01; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; pixels[0] = interm; KoMixColorsOp * mixOp = cs->mixColorsOp(); int seedThreshold = rand(); int seedRed = rand(); int seedGreen = rand(); int seedBlue = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedRed = config->getInt("seedRed", seedRed); seedGreen = config->getInt("seedGreen", seedGreen); seedBlue = config->getInt("seedBlue", seedBlue); } KisRandomGenerator randt(seedThreshold); KisRandomGenerator randr(seedRed); KisRandomGenerator randg(seedGreen); KisRandomGenerator randb(seedBlue); do { if (randt.doubleRandomAt(it.x(), it.y()) > threshold) { // XXX: Added static_cast to get rid of warnings QColor c = qRgb(static_cast((double)randr.doubleRandomAt(it.x(), it.y()) * 255), static_cast((double)randg.doubleRandomAt(it.x(), it.y()) * 255), static_cast((double)randb.doubleRandomAt(it.x(), it.y()) * 255)); cs->fromQColor(c, interm, 0); pixels[1] = it.oldRawData(); mixOp->mixColors(pixels, weights, 2, it.rawData()); } if (progressUpdater) progressUpdater->setValue(++count); } while (it.nextPixel() && !(progressUpdater && progressUpdater->interrupted())); delete [] interm; } #include "noisefilter.moc" diff --git a/plugins/filters/noisefilter/noisefilter.h b/plugins/filters/noisefilter/noisefilter.h index dfd0570b9a..6f3f36b088 100644 --- a/plugins/filters/noisefilter/noisefilter.h +++ b/plugins/filters/noisefilter/noisefilter.h @@ -1,56 +1,56 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef NOISEFILTER_H #define NOISEFILTER_H #include #include #include "filter/kis_filter.h" class KisConfigWidget; class KritaNoiseFilter : public QObject { Q_OBJECT public: KritaNoiseFilter(QObject *parent, const QVariantList &); virtual ~KritaNoiseFilter(); }; class KisFilterNoise : public KisFilter { public: KisFilterNoise(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("noise", i18n("Noise")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; #endif diff --git a/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp b/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp index 9b3b165b92..cb4e9eb8de 100644 --- a/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp +++ b/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp @@ -1,220 +1,220 @@ /* * This file is part of Krita * * Copyright (c) 2004 Michael Thaler * Copyright (c) 2008 Cyrille Berger * * ported from digikam, Copyrighted by Gilles Caulier, * Original Oilpaint algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_oilpaint_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" KisOilPaintFilter::KisOilPaintFilter() : KisFilter(id(), KisFilter::categoryArtistic(), i18n("&Oilpaint...")) { setSupportsPainting(true); setSupportsThreading(false); setSupportsAdjustmentLayers(true); } void KisOilPaintFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(!device.isNull()); qint32 width = applyRect.width(); qint32 height = applyRect.height(); //read the filter configuration values from the KisFilterConfiguration object quint32 brushSize = config ? config->getInt("brushSize", 1) : 1; quint32 smooth = config ? config->getInt("smooth", 30) : 30; OilPaint(device, device, srcTopLeft, applyRect.topLeft(), width, height, brushSize, smooth, progressUpdater); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the OilPaint effect. * * data => The image data in RGBA mode. * w => Width of image. * h => Height of image. * BrushSize => Brush size. * Smoothness => Smooth value. * * Theory => Using MostFrequentColor function we take the main color in * a matrix and simply write at the original position. */ void KisOilPaintFilter::OilPaint(const KisPaintDeviceSP src, KisPaintDeviceSP dst, const QPoint& srcTopLeft, const QPoint& dstTopLeft, int w, int h, int BrushSize, int Smoothness, KoUpdater* progressUpdater) const { if (progressUpdater) { progressUpdater->setRange(0, w * h); } QRect bounds(srcTopLeft.x(), srcTopLeft.y(), w, h); KisHLineConstIteratorSP it = src->createHLineConstIteratorNG(srcTopLeft.x(), srcTopLeft.y(), w); KisHLineIteratorSP dstIt = dst->createHLineIteratorNG(dstTopLeft.x(), dstTopLeft.y(), w); int progress = 0; for (qint32 yOffset = 0; yOffset < h; yOffset++) { do { //&& !cancelRequested()) { MostFrequentColor(src, dstIt->rawData(), bounds, it->x(), it->y(), BrushSize, Smoothness); } while (it->nextPixel() && dstIt->nextPixel()); it->nextRow(); dstIt->nextRow(); if (progressUpdater) progressUpdater->setValue(progress += w); } } // This method has been ported from Pieter Z. Voloshyn's algorithm code in Digikam. /* Function to determine the most frequent color in a matrix * * Bits => Bits array * Width => Image width * Height => Image height * X => Position horizontal * Y => Position vertical * Radius => Is the radius of the matrix to be analyzed * Intensity => Intensity to calculate * * Theory => This function creates a matrix with the analyzed pixel in * the center of this matrix and find the most frequenty color */ void KisOilPaintFilter::MostFrequentColor(KisPaintDeviceSP src, quint8* dst, const QRect& bounds, int X, int Y, int Radius, int Intensity) const { uint I; double Scale = Intensity / 255.0; // Alloc some arrays to be used uchar *IntensityCount = new uchar[(Intensity + 1) * sizeof(uchar)]; const KoColorSpace* cs = src->colorSpace(); QVector channel(cs->channelCount()); QVector* AverageChannels = new QVector[(Intensity + 1)]; // Erase the array memset(IntensityCount, 0, (Intensity + 1) * sizeof(uchar)); int startx = qMax(X - Radius, bounds.left()); int starty = qMax(Y - Radius, bounds.top()); int width = (2 * Radius) + 1; if ((startx + width - 1) > bounds.right()) width = bounds.right() - startx + 1; Q_ASSERT((startx + width - 1) <= bounds.right()); int height = (2 * Radius) + 1; if ((starty + height) > bounds.bottom()) height = bounds.bottom() - starty + 1; Q_ASSERT((starty + height - 1) <= bounds.bottom()); KisSequentialConstIterator srcIt(src, QRect(startx, starty, width, height)); do { cs->normalisedChannelsValue(srcIt.rawDataConst(), channel); I = (uint)(cs->intensity8(srcIt.rawDataConst()) * Scale); IntensityCount[I]++; if (IntensityCount[I] == 1) { AverageChannels[I] = channel; } else { for (int i = 0; i < channel.size(); i++) { AverageChannels[I][i] += channel[i]; } } } while (srcIt.nextPixel()); I = 0; int MaxInstance = 0; for (int i = 0 ; i <= Intensity ; ++i) { if (IntensityCount[i] > MaxInstance) { I = i; MaxInstance = IntensityCount[i]; } } if (MaxInstance != 0) { channel = AverageChannels[I]; for (int i = 0; i < channel.size(); i++) { channel[i] /= MaxInstance; } cs->fromNormalisedChannelsValue(dst, channel); } else { memset(dst, 0, cs->pixelSize()); cs->setOpacity(dst, OPACITY_OPAQUE_U8, 1); } delete [] IntensityCount; // free all the arrays delete [] AverageChannels; } KisConfigWidget * KisOilPaintFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(1, 5, 1, i18n("Brush size"), "brushSize")); param.push_back(KisIntegerWidgetParam(10, 255, 30, i18nc("smooth out the painting strokes the filter creates", "Smooth"), "smooth")); KisMultiIntegerFilterWidget * w = new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); - w->setConfiguration(factoryConfiguration(0)); + w->setConfiguration(factoryConfiguration()); return w; } -KisFilterConfigurationSP KisOilPaintFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisOilPaintFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("oilpaint", 1); config->setProperty("brushSize", 1); config->setProperty("smooth", 30); return config; } diff --git a/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h b/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h index 570a7730fd..846ebdeaa0 100644 --- a/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h +++ b/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h @@ -1,51 +1,51 @@ /* * This file is part of the KDE project * * Copyright (c) Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_OILPAINT_FILTER_H_ #define _KIS_OILPAINT_FILTER_H_ #include "filter/kis_filter.h" #include "kis_config_widget.h" class KisOilPaintFilter : public KisFilter { public: KisOilPaintFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("oilpaint", i18n("Oilpaint")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; private: void OilPaint(const KisPaintDeviceSP src, KisPaintDeviceSP dst, const QPoint& srcTopLeft, const QPoint& dstTopLeft, int w, int h, int BrushSize, int Smoothness, KoUpdater* progressUpdater) const; void MostFrequentColor(KisPaintDeviceSP src, quint8* dst, const QRect& bounds, int X, int Y, int Radius, int Intensity) const; }; #endif diff --git a/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp b/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp index a34b1b7e8e..4b7695d962 100644 --- a/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp +++ b/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp @@ -1,238 +1,238 @@ /* * Copyright (c) 2010-2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_phong_bumpmap_filter.h" #include "kis_phong_bumpmap_config_widget.h" #include "phong_pixel_processor.h" #include "kis_debug.h" #include "kis_paint_device.h" #include "kis_config_widget.h" #include "KoUpdater.h" #include "kis_math_toolbox.h" #include "KoColorSpaceRegistry.h" #include #include #include "kis_iterator_ng.h" #include "kundo2command.h" #include "kis_painter.h" KisFilterPhongBumpmap::KisFilterPhongBumpmap() : KisFilter(KoID("phongbumpmap" , i18n("PhongBumpmap")), KisFilter::categoryMap(), i18n("&PhongBumpmap...")) { setColorSpaceIndependence(TO_LAB16); setSupportsPainting(true); setSupportsLevelOfDetail(true); } void KisFilterPhongBumpmap::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater ) const { if (!config) return; if (progressUpdater) progressUpdater->setProgress(0); QString userChosenHeightChannel = config->getString(PHONG_HEIGHT_CHANNEL, "FAIL"); bool m_usenormalmap = config->getBool(USE_NORMALMAP_IS_ENABLED); if (userChosenHeightChannel == "FAIL") { qDebug("FIX YOUR FILTER"); return; } KoChannelInfo *m_heightChannel = 0; Q_FOREACH (KoChannelInfo* channel, device->colorSpace()->channels()) { if (userChosenHeightChannel == channel->name()) { m_heightChannel = channel; } } if (!m_heightChannel) { m_heightChannel = device->colorSpace()->channels().first(); } KIS_ASSERT_RECOVER_RETURN(m_heightChannel); QRect inputArea = applyRect; QRect outputArea = applyRect; if (m_usenormalmap==false) { inputArea.adjust(-1, -1, 1, 1); } quint32 posup; quint32 posdown; quint32 posleft; quint32 posright; QColor I; //Reflected light if (progressUpdater) progressUpdater->setProgress(1); //======Preparation paraphlenalia======= //Hardcoded facts about Phong Bumpmap: it _will_ generate an RGBA16 bumpmap const quint8 BYTE_DEPTH_OF_BUMPMAP = 2; // 16 bits per channel const quint8 CHANNEL_COUNT_OF_BUMPMAP = 4; // RGBA const quint32 pixelsOfInputArea = abs(inputArea.width() * inputArea.height()); const quint32 pixelsOfOutputArea = abs(outputArea.width() * outputArea.height()); const quint8 pixelSize = BYTE_DEPTH_OF_BUMPMAP * CHANNEL_COUNT_OF_BUMPMAP; const quint32 bytesToFillBumpmapArea = pixelsOfOutputArea * pixelSize; QVector bumpmap(bytesToFillBumpmapArea); quint8 *bumpmapDataPointer = bumpmap.data(); quint32 ki = KoChannelInfo::displayPositionToChannelIndex(m_heightChannel->displayPosition(), device->colorSpace()->channels()); PhongPixelProcessor tileRenderer(pixelsOfInputArea, config); if (progressUpdater) progressUpdater->setProgress(2); //===============RENDER================= QVector toDoubleFuncPtr(device->colorSpace()->channels().count()); KisMathToolbox mathToolbox; if (!mathToolbox.getToDoubleChannelPtr(device->colorSpace()->channels(), toDoubleFuncPtr)) { return; } KisHLineConstIteratorSP iterator; quint32 curPixel = 0; iterator = device->createHLineConstIteratorNG(inputArea.x(), inputArea.y(), inputArea.width() ); if (m_usenormalmap==false) { for (qint32 srcRow = 0; srcRow < inputArea.height(); ++srcRow) { do { const quint8 *data = iterator->oldRawData(); tileRenderer.realheightmap[curPixel] = toDoubleFuncPtr[ki](data, device->colorSpace()->channels()[ki]->pos()); curPixel++; } while (iterator->nextPixel()); iterator->nextRow(); } if (progressUpdater) progressUpdater->setProgress(50); const int tileHeightMinus1 = inputArea.height() - 1; const int tileWidthMinus1 = inputArea.width() - 1; // Foreach INNER pixel in tile for (int y = 1; y < tileHeightMinus1; ++y) { for (int x = 1; x < tileWidthMinus1; ++x) { posup = (y + 1) * inputArea.width() + x; posdown = (y - 1) * inputArea.width() + x; posleft = y * inputArea.width() + x - 1; posright = y * inputArea.width() + x + 1; memcpy(bumpmapDataPointer, tileRenderer.IlluminatePixelFromHeightmap(posup, posdown, posleft, posright).data(), pixelSize); bumpmapDataPointer += pixelSize; } } } else { for (qint32 srcRow = 0; srcRow < inputArea.height(); ++srcRow) { do { const quint8 *data = iterator->oldRawData(); tileRenderer.realheightmap[curPixel] = toDoubleFuncPtr[ki](data, device->colorSpace()->channels()[ki]->pos()); QVector current_pixel_values(4); device->colorSpace()->normalisedChannelsValue(data, current_pixel_values ); //dbgKrita<< "Vector:" << current_pixel_values[2] << "," << current_pixel_values[1] << "," << current_pixel_values[0]; memcpy(bumpmapDataPointer, tileRenderer.IlluminatePixelFromNormalmap(current_pixel_values[2], current_pixel_values[1], current_pixel_values[0]).data(), pixelSize); curPixel++; //pointer that crashes here, but not in the other if statement. bumpmapDataPointer += pixelSize; } while (iterator->nextPixel()); iterator->nextRow(); } } if (progressUpdater) progressUpdater->setProgress(90); KisPaintDeviceSP bumpmapPaintDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb16()); bumpmapPaintDevice->writeBytes(bumpmap.data(), outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height()); KUndo2Command *leaker = bumpmapPaintDevice->convertTo(device->colorSpace(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); KisPainter copier(device); copier.bitBlt(outputArea.x(), outputArea.y(), bumpmapPaintDevice, outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height()); //device->prepareClone(bumpmapPaintDevice); //device->makeCloneFrom(bumpmapPaintDevice, bumpmapPaintDevice->extent()); // THIS COULD BE BUG GY delete leaker; if (progressUpdater) progressUpdater->setProgress(100); } -KisFilterConfigurationSP KisFilterPhongBumpmap::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterPhongBumpmap::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id(), 2); config->setProperty(PHONG_AMBIENT_REFLECTIVITY, 0.2); config->setProperty(PHONG_DIFFUSE_REFLECTIVITY, 0.5); config->setProperty(PHONG_SPECULAR_REFLECTIVITY, 0.3); config->setProperty(PHONG_SHINYNESS_EXPONENT, 2); config->setProperty(USE_NORMALMAP_IS_ENABLED, false); config->setProperty(PHONG_DIFFUSE_REFLECTIVITY_IS_ENABLED, true); config->setProperty(PHONG_SPECULAR_REFLECTIVITY_IS_ENABLED, true); // Indexes are off by 1 simply because arrays start at 0 and the GUI naming scheme started at 1 config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[0], true); config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[1], true); config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[2], false); config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[3], false); config->setProperty(PHONG_ILLUMINANT_COLOR[0], QColor(255, 255, 0)); config->setProperty(PHONG_ILLUMINANT_COLOR[1], QColor(255, 0, 0)); config->setProperty(PHONG_ILLUMINANT_COLOR[2], QColor(0, 0, 255)); config->setProperty(PHONG_ILLUMINANT_COLOR[3], QColor(0, 255, 0)); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[0], 50); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[1], 100); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[2], 150); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[3], 200); config->setProperty(PHONG_ILLUMINANT_INCLINATION[0], 25); config->setProperty(PHONG_ILLUMINANT_INCLINATION[1], 20); config->setProperty(PHONG_ILLUMINANT_INCLINATION[2], 30); config->setProperty(PHONG_ILLUMINANT_INCLINATION[3], 40); return config; } QRect KisFilterPhongBumpmap::neededRect(const QRect &rect, const KisFilterConfigurationSP /*config*/, int /*lod*/) const { return rect.adjusted(-1, -1, 1, 1); } QRect KisFilterPhongBumpmap::changedRect(const QRect &rect, const KisFilterConfigurationSP /*config*/, int /*lod*/) const { return rect; } KisConfigWidget *KisFilterPhongBumpmap::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { KisPhongBumpmapConfigWidget *w = new KisPhongBumpmapConfigWidget(dev, parent); return w; } diff --git a/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.h b/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.h index 2c8abbc945..a2789db634 100644 --- a/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.h +++ b/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.h @@ -1,54 +1,54 @@ /* * Copyright (c) 2010 Dmitry Kazakov * Copyright (c) 2010-2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PHONG_BUMPMAP_FILTER_H #define KIS_PHONG_BUMPMAP_FILTER_H #include #include /** * This class is an implementation of the phong illumination model. * It uses a heightmap as an input mesh (normally taken from 1 * channel of a colorspace) to achieve a bumpmapping effect with * multiple illumination sources. */ class KisFilterPhongBumpmap : public KisFilter { public: KisFilterPhongBumpmap(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater ) const; QRect neededRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const; QRect changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const; virtual KisConfigWidget *createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; private: //bool m_usenormalmap; }; #endif //KIS_PHONG_BUMPMAP_FILTER_H diff --git a/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp b/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp index e6dff618e8..f913f49357 100644 --- a/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp +++ b/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp @@ -1,142 +1,142 @@ /* * This file is part of Krita * * Copyright (c) 2005 Michael Thaler * * ported from Gimp, Copyright (C) 1997 Eiichi Takamori * original pixelize.c for GIMP 0.54 by Tracy Scott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_pixelize_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" #include KisPixelizeFilter::KisPixelizeFilter() : KisFilter(id(), KisFilter::categoryArtistic(), i18n("&Pixelize...")) { setSupportsPainting(true); setSupportsThreading(false); setSupportsAdjustmentLayers(false); } void KisPixelizeFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); qint32 width = applyRect.width(); qint32 height = applyRect.height(); //read the filter configuration values from the KisFilterConfiguration object quint32 pixelWidth = config ? config->getInt("pixelWidth", 10) : 10; quint32 pixelHeight = config ? config->getInt("pixelHeight", 10) : 10; if (pixelWidth == 0) pixelWidth = 1; if (pixelHeight == 0) pixelHeight = 1; qint32 pixelSize = device->pixelSize(); QVector average(pixelSize); qint32 count; if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } qint32 numberOfPixelsProcessed = 0; for (qint32 y = 0; y < height; y += pixelHeight - (y % pixelHeight)) { qint32 h = pixelHeight; h = qMin(h, height - y); for (qint32 x = 0; x < width; x += pixelWidth - (x % pixelWidth)) { qint32 w = pixelWidth; w = qMin(w, width - x); average.fill(0, pixelSize); count = 0; //read KisSequentialConstIterator srcIt(device, QRect(srcTopLeft.x() + x, srcTopLeft.y() + y, w, h)); do { for (qint32 i = 0; i < pixelSize; i++) { average[i] += srcIt.oldRawData()[i]; } count++; } while (srcIt.nextPixel()); //average if (count > 0) { for (qint32 i = 0; i < pixelSize; i++) average[i] /= count; } //write KisSequentialIterator dstIt(device, QRect(srcTopLeft.x() + x, srcTopLeft.y() + y, w, h)); do { for (int i = 0; i < pixelSize; i++) { dstIt.rawData()[i] = average[i]; } } while (dstIt.nextPixel()); if (progressUpdater) progressUpdater->setValue(++numberOfPixelsProcessed); } } } KisConfigWidget * KisPixelizeFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 512, 10, i18n("Pixel width"), "pixelWidth")); param.push_back(KisIntegerWidgetParam(2, 512, 10, i18n("Pixel height"), "pixelHeight")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } -KisFilterConfigurationSP KisPixelizeFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisPixelizeFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("pixelize", 1); config->setProperty("pixelWidth", 10); config->setProperty("pixelHeight", 10); return config; } diff --git a/plugins/filters/pixelizefilter/kis_pixelize_filter.h b/plugins/filters/pixelizefilter/kis_pixelize_filter.h index 19b1dfb705..f1c73f6418 100644 --- a/plugins/filters/pixelizefilter/kis_pixelize_filter.h +++ b/plugins/filters/pixelizefilter/kis_pixelize_filter.h @@ -1,47 +1,47 @@ /* * This file is part of the KDE project * * Copyright (c) Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_PIXELIZE_FILTER_H_ #define _KIS_PIXELIZE_FILTER_H_ #include "filter/kis_filter.h" #include "kis_config_widget.h" class KisPixelizeFilter : public KisFilter { public: KisPixelizeFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const; static inline KoID id() { return KoID("pixelize", i18n("Pixelize")); } public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; #endif diff --git a/plugins/filters/posterize/posterize.cpp b/plugins/filters/posterize/posterize.cpp index b9e82783bf..4b7628b849 100644 --- a/plugins/filters/posterize/posterize.cpp +++ b/plugins/filters/posterize/posterize.cpp @@ -1,110 +1,110 @@ /* * Copyright (c) 2014 Manuel Riecke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "posterize.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(PosterizeFactory, "kritaposterize.json", registerPlugin();) Posterize::Posterize(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterPosterize())); } Posterize::~Posterize() { } KisFilterPosterize::KisFilterPosterize() : KisColorTransformationFilter(id(), categoryArtistic(), i18n("&Posterize...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); setShowConfigurationWidget(true); } KoColorTransformation* KisFilterPosterize::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { return new KisPosterizeColorTransformation(config->getInt("steps", 16), cs); } KisPosterizeColorTransformation::KisPosterizeColorTransformation(int steps, const KoColorSpace* cs) : m_colorSpace(cs), m_psize(cs->pixelSize()) { m_step = KoColorSpaceMathsTraits::max / steps; m_halfStep = m_step / 2; } KisConfigWidget* KisFilterPosterize::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 128, 16, i18n("Steps"), "steps")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } -KisFilterConfigurationSP KisFilterPosterize::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterPosterize::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); config->setProperty("steps", 16); return config; } void KisPosterizeColorTransformation::transform(const quint8* src, quint8* dst, qint32 nPixels) const { quint16 m_rgba[4]; quint16 m_mod[4]; while (nPixels--) { m_colorSpace->toRgbA16(src, reinterpret_cast(m_rgba), 1); m_mod[0] = m_rgba[0] % m_step; m_mod[1] = m_rgba[1] % m_step; m_mod[2] = m_rgba[2] % m_step; m_mod[3] = m_rgba[3] % m_step; m_rgba[0] = m_rgba[0] + (m_mod[0] > m_halfStep ? m_step - m_mod[0] : -m_mod[0]); m_rgba[1] = m_rgba[1] + (m_mod[1] > m_halfStep ? m_step - m_mod[1] : -m_mod[1]); m_rgba[2] = m_rgba[2] + (m_mod[2] > m_halfStep ? m_step - m_mod[2] : -m_mod[2]); m_rgba[3] = m_rgba[3] + (m_mod[3] > m_halfStep ? m_step - m_mod[3] : -m_mod[3]); m_colorSpace->fromRgbA16(reinterpret_cast(m_rgba), dst, 1); src += m_psize; dst += m_psize; } } #include "posterize.moc" diff --git a/plugins/filters/posterize/posterize.h b/plugins/filters/posterize/posterize.h index e66016bb05..d306424c77 100644 --- a/plugins/filters/posterize/posterize.h +++ b/plugins/filters/posterize/posterize.h @@ -1,61 +1,61 @@ /* * Copyright (c) 2014 Manuel Riecke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef POSTERIZE_H #define POSTERIZE_H #include #include #include "filter/kis_color_transformation_filter.h" #include "kis_config_widget.h" class Posterize : public QObject { Q_OBJECT public: Posterize(QObject *parent, const QVariantList &); virtual ~Posterize(); }; class KisFilterPosterize : public KisColorTransformationFilter { public: KisFilterPosterize(); public: virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const; virtual KisConfigWidget* createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; static inline KoID id() { return KoID("posterize", i18n("Posterize")); } protected: - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; }; class KisPosterizeColorTransformation : public KoColorTransformation { public: KisPosterizeColorTransformation(int steps, const KoColorSpace* cs); virtual void transform(const quint8* src, quint8* dst, qint32 nPixels) const; private: const KoColorSpace* m_colorSpace; quint32 m_psize; quint16 m_step; quint16 m_halfStep; }; #endif diff --git a/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp b/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp index 1c061b2d3f..9fcb7109ab 100644 --- a/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp +++ b/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp @@ -1,402 +1,402 @@ /* * This file is part of the KDE project * * Copyright (c) 2004 Michael Thaler * * ported from digikam, copyrighted 2004 by Gilles Caulier, * Original RainDrops algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_raindrops_filter.h" #include #include #include #include #include #include #include #include #include #include "KoIntegerMaths.h" #include #include #include #include #include #include #include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" KisRainDropsFilter::KisRainDropsFilter() : KisFilter(id(), KisFilter::categoryArtistic(), i18n("&Raindrops...")) { setSupportsPainting(false); setSupportsThreading(false); setSupportsAdjustmentLayers(true); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the RainDrops effect (inspired from Jason Waltman code) * * data => The image data in RGBA mode. * Width => Width of image. * Height => Height of image. * DropSize => Raindrop size * number => Maximum number of raindrops * fishEyes => FishEye coefficient * * Theory => This functions does several math's functions and the engine * is simple to undestand, but a little hard to implement. A * control will indicate if there is or not a raindrop in that * area, if not, a fisheye effect with a random size (max=DropSize) * will be applied, after this, a shadow will be applied too. * and after this, a blur function will finish the effect. */ void KisRainDropsFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); //read the filter configuration values from the KisFilterConfiguration object quint32 DropSize = config->getInt("dropSize", 80); quint32 number = config->getInt("number", 80); quint32 fishEyes = config->getInt("fishEyes", 30); qsrand(config->getInt("seed")); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; if (fishEyes <= 0) fishEyes = 1; if (fishEyes > 100) fishEyes = 100; int Width = applyRect.width(); int Height = applyRect.height(); bool** BoolMatrix = CreateBoolArray(Width, Height); int i, j, k, l, m, n; // loop variables int Bright; // Bright value for shadows and highlights int x, y; // center coordinates int Counter = 0; // Counter (duh !) int NewSize; // Size of current raindrop int halfSize; // Half of the current raindrop int Radius; // Maximum radius for raindrop int BlurRadius; // Blur Radius int BlurPixels; double r, a; // polar coordinates double OldRadius; // Radius before processing double NewfishEyes = (double)fishEyes * 0.01; // FishEye fishEyesicients double s; double R, G, B; bool FindAnother = false; // To search for good coordinates const KoColorSpace * cs = device->colorSpace(); // Init booleen Matrix. for (i = 0 ; (i < Width) && !(progressUpdater && progressUpdater->interrupted()) ; ++i) { for (j = 0 ; (j < Height) && !(progressUpdater && progressUpdater->interrupted()); ++j) { BoolMatrix[i][j] = false; } } KisRandomAccessorSP dstAccessor = device->createRandomAccessorNG(srcTopLeft.x(), srcTopLeft.y()); for (uint NumBlurs = 0; (NumBlurs <= number) && !(progressUpdater && progressUpdater->interrupted()); ++NumBlurs) { NewSize = (int)(qrand() * ((double)(DropSize - 5) / RAND_MAX) + 5); halfSize = NewSize / 2; Radius = halfSize; s = Radius / log(NewfishEyes * Radius + 1); Counter = 0; do { FindAnother = false; y = (int)(qrand() * ((double)(Width - 1) / RAND_MAX)); x = (int)(qrand() * ((double)(Height - 1) / RAND_MAX)); if (BoolMatrix[y][x]) FindAnother = true; else for (i = x - halfSize ; (i <= x + halfSize) && !(progressUpdater && progressUpdater->interrupted()); i++) for (j = y - halfSize ; (j <= y + halfSize) && !(progressUpdater && progressUpdater->interrupted()); j++) if ((i >= 0) && (i < Height) && (j >= 0) && (j < Width)) if (BoolMatrix[j][i]) FindAnother = true; Counter++; } while ((FindAnother && (Counter < 10000) && !(progressUpdater && progressUpdater->interrupted()))); if (Counter >= 10000) { NumBlurs = number; break; } for (i = -1 * halfSize ; (i < NewSize - halfSize) && !(progressUpdater && progressUpdater->interrupted()); i++) { for (j = -1 * halfSize ; (j < NewSize - halfSize) && !(progressUpdater && progressUpdater->interrupted()); j++) { r = sqrt((double)i * i + j * j); a = atan2(static_cast(i), static_cast(j)); if (r <= Radius) { OldRadius = r; r = (exp(r / s) - 1) / NewfishEyes; k = x + (int)(r * sin(a)); l = y + (int)(r * cos(a)); m = x + i; n = y + j; if ((k >= 0) && (k < Height) && (l >= 0) && (l < Width)) { if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { Bright = 0; if (OldRadius >= 0.9 * Radius) { if ((a <= 0) && (a > -2.25)) Bright = -80; else if ((a <= -2.25) && (a > -2.5)) Bright = -40; else if ((a <= 0.25) && (a > 0)) Bright = -40; } else if (OldRadius >= 0.8 * Radius) { if ((a <= -0.75) && (a > -1.50)) Bright = -40; else if ((a <= 0.10) && (a > -0.75)) Bright = -30; else if ((a <= -1.50) && (a > -2.35)) Bright = -30; } else if (OldRadius >= 0.7 * Radius) { if ((a <= -0.10) && (a > -2.0)) Bright = -20; else if ((a <= 2.50) && (a > 1.90)) Bright = 60; } else if (OldRadius >= 0.6 * Radius) { if ((a <= -0.50) && (a > -1.75)) Bright = -20; else if ((a <= 0) && (a > -0.25)) Bright = 20; else if ((a <= -2.0) && (a > -2.25)) Bright = 20; } else if (OldRadius >= 0.5 * Radius) { if ((a <= -0.25) && (a > -0.50)) Bright = 30; else if ((a <= -1.75) && (a > -2.0)) Bright = 30; } else if (OldRadius >= 0.4 * Radius) { if ((a <= -0.5) && (a > -1.75)) Bright = 40; } else if (OldRadius >= 0.3 * Radius) { if ((a <= 0) && (a > -2.25)) Bright = 30; } else if (OldRadius >= 0.2 * Radius) { if ((a <= -0.5) && (a > -1.75)) Bright = 20; } BoolMatrix[n][m] = true; QColor originalColor; dstAccessor->moveTo(srcTopLeft.x() + l, srcTopLeft.y() + k); cs->toQColor(dstAccessor->oldRawData(), &originalColor); int newRed = CLAMP(originalColor.red() + Bright, 0, quint8_MAX); int newGreen = CLAMP(originalColor.green() + Bright, 0, quint8_MAX); int newBlue = CLAMP(originalColor.blue() + Bright, 0, quint8_MAX); QColor newColor; newColor.setRgb(newRed, newGreen, newBlue); dstAccessor->moveTo(srcTopLeft.x() + n, srcTopLeft.y() + m); cs->fromQColor(newColor, dstAccessor->rawData()); } } } } } BlurRadius = NewSize / 25 + 1; for (i = -1 * halfSize - BlurRadius ; (i < NewSize - halfSize + BlurRadius) && !(progressUpdater && progressUpdater->interrupted()) ; i++) { for (j = -1 * halfSize - BlurRadius; ((j < NewSize - halfSize + BlurRadius) && !(progressUpdater && progressUpdater->interrupted())); ++j) { r = sqrt((double)i * i + j * j); if (r <= Radius * 1.1) { R = G = B = 0; BlurPixels = 0; for (k = -1 * BlurRadius; k < BlurRadius + 1; k++) for (l = -1 * BlurRadius; l < BlurRadius + 1; l++) { m = x + i + k; n = y + j + l; if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { QColor color; dstAccessor->moveTo(srcTopLeft.x() + n, srcTopLeft.y() + m); cs->toQColor(dstAccessor->rawData(), &color); R += color.red(); G += color.green(); B += color.blue(); BlurPixels++; } } m = x + i; n = y + j; if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { QColor color; color.setRgb((int)(R / BlurPixels), (int)(G / BlurPixels), (int)(B / BlurPixels)); dstAccessor->moveTo(srcTopLeft.x() + n, srcTopLeft.y() + m); cs->fromQColor(color, dstAccessor->rawData()); } } } } if (progressUpdater) progressUpdater->setValue(++count); } FreeBoolArray(BoolMatrix, Width); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to free a dinamic boolean array * * lpbArray => Dynamic boolean array * Columns => The array bidimension value * * Theory => An easy to undestand 'for' statement */ void KisRainDropsFilter::FreeBoolArray(bool** lpbArray, uint Columns) const { for (uint i = 0; i < Columns; ++i) free(lpbArray[i]); free(lpbArray); } /* Function to create a bidimentional dinamic boolean array * * Columns => Number of columns * Rows => Number of rows * * Theory => Using 'for' statement, we can alloc multiple dinamic arrays * To create more dimentions, just add some 'for's, ok? */ bool** KisRainDropsFilter::CreateBoolArray(uint Columns, uint Rows) const { bool** lpbArray = 0; lpbArray = (bool**) malloc(Columns * sizeof(bool*)); if (lpbArray == 0) return (0); for (uint i = 0; i < Columns; ++i) { lpbArray[i] = (bool*) malloc(Rows * sizeof(bool)); if (lpbArray[i] == 0) { FreeBoolArray(lpbArray, Columns); return (0); } } return (lpbArray); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* This function limits the RGB values * * ColorValue => Here, is an RGB value to be analized * * Theory => A color is represented in RGB value (e.g. 0xFFFFFF is * white color). But R, G and B values has 256 values to be used * so, this function analize the value and limits to this range */ uchar KisRainDropsFilter::LimitValues(int ColorValue) const { if (ColorValue > 255) // MAX = 255 ColorValue = 255; if (ColorValue < 0) // MIN = 0 ColorValue = 0; return ((uchar) ColorValue); } KisConfigWidget * KisRainDropsFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(1, 200, 80, i18n("Drop size"), "dropsize")); param.push_back(KisIntegerWidgetParam(1, 500, 80, i18n("Number"), "number")); param.push_back(KisIntegerWidgetParam(1, 100, 30, i18n("Fish eyes"), "fishEyes")); KisMultiIntegerFilterWidget * w = new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); - w->setConfiguration(factoryConfiguration(0)); + w->setConfiguration(factoryConfiguration()); return w; } -KisFilterConfigurationSP KisRainDropsFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisRainDropsFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("raindrops", 2); config->setProperty("dropsize", 80); config->setProperty("number", 80); config->setProperty("fishEyes", 30); config->setProperty("seed", QTime::currentTime().msec()); return config; } diff --git a/plugins/filters/raindropsfilter/kis_raindrops_filter.h b/plugins/filters/raindropsfilter/kis_raindrops_filter.h index 61712794b5..b542ac6276 100644 --- a/plugins/filters/raindropsfilter/kis_raindrops_filter.h +++ b/plugins/filters/raindropsfilter/kis_raindrops_filter.h @@ -1,51 +1,51 @@ /* * This file is part of Krita * * Copyright (c) Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_RAINDROPS_FILTER_H_ #define _KIS_RAINDROPS_FILTER_H_ #include "filter/kis_filter.h" #include "kis_config_widget.h" #include "kis_paint_device.h" class KisRainDropsFilter : public KisFilter { public: KisRainDropsFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const; static inline KoID id() { return KoID("raindrops", i18n("Raindrops")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; private: bool** CreateBoolArray(uint Columns, uint Rows) const; void FreeBoolArray(bool** lpbArray, uint Columns) const; uchar LimitValues(int ColorValue) const; }; #endif diff --git a/plugins/filters/randompickfilter/randompickfilter.cpp b/plugins/filters/randompickfilter/randompickfilter.cpp index f871e9ddb1..d88c3f7a9a 100644 --- a/plugins/filters/randompickfilter/randompickfilter.cpp +++ b/plugins/filters/randompickfilter/randompickfilter.cpp @@ -1,156 +1,156 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "randompickfilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_random_pick.h" #include "ui_wdgrandompickoptions.h" #include K_PLUGIN_FACTORY_WITH_JSON(KritaRandomPickFilterFactory, "kritarandompickfilter.json", registerPlugin();) KritaRandomPickFilter::KritaRandomPickFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterRandomPick()); } KritaRandomPickFilter::~KritaRandomPickFilter() { } KisFilterRandomPick::KisFilterRandomPick() : KisFilter(id(), categoryOther(), i18n("&Random Pick...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } void KisFilterRandomPick::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; double windowsize = (config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5; int seedThreshold = rand(); int seedH = rand(); int seedV = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedH = config->getInt("seedH", seedH); seedV = config->getInt("seedV", seedV); } KisRandomGenerator randT(seedThreshold); KisRandomGenerator randH(seedH); KisRandomGenerator randV(seedV); KisSequentialIterator dstIt(device, applyRect); KisRandomConstAccessorSP srcRA = device->createRandomConstAccessorNG(0, 0); double threshold = (100 - level) / 100.0; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; KoMixColorsOp * mixOp = cs->mixColorsOp(); do{ if (randT.doubleRandomAt(dstIt.x(), dstIt.y()) > threshold) { int x = static_cast(dstIt.x() + windowsize * (randH.doubleRandomAt(dstIt.x(), dstIt.y()) - 0.5)); int y = static_cast(dstIt.y() + windowsize * (randV.doubleRandomAt(dstIt.x(), dstIt.y()) -0.5)); srcRA->moveTo(x, y); pixels[0] = srcRA->oldRawData(); pixels[1] = dstIt.oldRawData(); mixOp->mixColors(pixels, weights, 2, dstIt.rawData()); } if (progressUpdater) progressUpdater->setValue(++count); } while(dstIt.nextPixel()); } KisConfigWidget * KisFilterRandomPick::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgRandomPick((KisFilter*)this, (QWidget*)parent); } -KisFilterConfigurationSP KisFilterRandomPick::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterRandomPick::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("randompick", 1); config->setProperty("level", 50); config->setProperty("windowsize", 2.5); config->setProperty("opacity", 100); config->setProperty("seedThreshold", rand()); config->setProperty("seedH", rand()); config->setProperty("seedV", rand()); return config; } QRect KisFilterRandomPick::neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod) const { Q_UNUSED(lod); QVariant value; int windowsize = ceil((config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5); return rect.adjusted(-windowsize, -windowsize, windowsize, windowsize); } #include "randompickfilter.moc" diff --git a/plugins/filters/randompickfilter/randompickfilter.h b/plugins/filters/randompickfilter/randompickfilter.h index 0937c67a0e..6056a9fb44 100644 --- a/plugins/filters/randompickfilter/randompickfilter.h +++ b/plugins/filters/randompickfilter/randompickfilter.h @@ -1,59 +1,59 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef RANDOMPICKFILTER_H #define RANDOMPICKFILTER_H #include #include #include "filter/kis_filter.h" class KisConfigWidget; class KritaRandomPickFilter : public QObject { Q_OBJECT public: KritaRandomPickFilter(QObject *parent, const QVariantList &); virtual ~KritaRandomPickFilter(); }; class KisFilterRandomPick : public KisFilter { public: KisFilterRandomPick(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("randompick", i18n("Random Pick")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; virtual QRect neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod = 0) const; }; #endif diff --git a/plugins/filters/roundcorners/kis_round_corners_filter.cpp b/plugins/filters/roundcorners/kis_round_corners_filter.cpp index 3f12d65cc4..5a244e524c 100644 --- a/plugins/filters/roundcorners/kis_round_corners_filter.cpp +++ b/plugins/filters/roundcorners/kis_round_corners_filter.cpp @@ -1,138 +1,138 @@ /* * This file is part of Krita * * Copyright (c) 2005 Michael Thaler * * ported from Gimp, Copyright (C) 1997 Eiichi Takamori * original pixelize.c for GIMP 0.54 by Tracy Scott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_round_corners_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KisRoundCornersFilter::KisRoundCornersFilter() : KisFilter(id(), KisFilter::categoryMap(), i18n("&Round Corners...")) { setSupportsPainting(false); } void KisRoundCornersFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); if (!device || !config) { warnKrita << "Invalid parameters for round corner filter"; dbgPlugins << device << " " << config; return; } //read the filter configuration values from the KisFilterConfiguration object qint32 radius = qMax(1, config->getInt("radius" , 30)); if (progressUpdater) { progressUpdater->setRange(0, applyRect.height()); } qint32 width = applyRect.width(); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(applyRect.x(), applyRect.y(), width); const KoColorSpace* cs = device->colorSpace(); QRect bounds = device->defaultBounds()->bounds(); for (qint32 y = applyRect.y(); y < applyRect.y() + applyRect.height(); y++) { qint32 x = applyRect.x(); do { if (x <= radius && y <= radius) { double dx = radius - x; double dy = radius - y; double dradius = static_cast(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } else if (x >= bounds.width() - radius && y <= radius) { double dx = x + radius - bounds.width(); double dy = radius - y; double dradius = static_cast(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } else if (x <= radius && y >= bounds.height() - radius) { double dx = radius - x; double dy = y + radius - bounds.height(); double dradius = static_cast(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } else if (x >= bounds.width() - radius && y >= bounds.height() - radius) { double dx = x + radius - bounds.width() ; double dy = y + radius - bounds.height(); double dradius = static_cast(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } ++x; } while(dstIt->nextPixel()); dstIt->nextRow(); if (progressUpdater) progressUpdater->setValue(y); } } KisConfigWidget * KisRoundCornersFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 100, 30, i18n("Radius"), "radius")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } -KisFilterConfigurationSP KisRoundCornersFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisRoundCornersFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("roundcorners", 1); config->setProperty("radius", 30); return config; } diff --git a/plugins/filters/roundcorners/kis_round_corners_filter.h b/plugins/filters/roundcorners/kis_round_corners_filter.h index 6afb1688de..2b9b25ea4f 100644 --- a/plugins/filters/roundcorners/kis_round_corners_filter.h +++ b/plugins/filters/roundcorners/kis_round_corners_filter.h @@ -1,47 +1,47 @@ /* * This file is part of the KDE project * * Copyright (c) Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_ROUND_CORNERS_FILTER_H_ #define _KIS_ROUND_CORNERS_FILTER_H_ #include "kis_paint_device.h" #include "filter/kis_filter.h" #include "kis_config_widget.h" class KisRoundCornersFilter : public KisFilter { public: KisRoundCornersFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("roundcorners", i18n("Round Corners")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; private: }; #endif diff --git a/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp b/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp index 5cd51d0df9..0d1c3dd3c1 100644 --- a/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp +++ b/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp @@ -1,112 +1,112 @@ /* * This file is part of Krita * * Copyright (c) 2005 Michael Thaler * * ported from Gimp, Copyright (C) 1997 Eiichi Takamori * original pixelize.c for GIMP 0.54 by Tracy Scott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_small_tiles_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" KisSmallTilesFilter::KisSmallTilesFilter() : KisFilter(id(), KisFilter::categoryMap(), i18n("&Small Tiles...")) { setSupportsPainting(true); setSupportsThreading(false); setSupportsAdjustmentLayers(false); } void KisSmallTilesFilter::processImpl(KisPaintDeviceSP device, const QRect& /*applyRect*/, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); //read the filter configuration values from the KisFilterConfiguration object quint32 numberOfTiles = config->getInt("numberOfTiles", 2); QRect srcRect = device->exactBounds(); int w = static_cast(srcRect.width() / numberOfTiles); int h = static_cast(srcRect.height() / numberOfTiles); KisPaintDeviceSP tile = device->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles); if (tile.isNull()) return; KisPainter gc(device); gc.setCompositeOp(COMPOSITE_COPY); if (progressUpdater) { progressUpdater->setRange(0, numberOfTiles); } for (uint y = 0; y < numberOfTiles; ++y) { for (uint x = 0; x < numberOfTiles; ++x) { gc.bitBlt(w * x, h * y, tile, 0, 0, w, h); } if (progressUpdater) progressUpdater->setValue(y); } gc.end(); } KisConfigWidget * KisSmallTilesFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 5, 1, i18n("Number of tiles"), "numberOfTiles")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } -KisFilterConfigurationSP KisSmallTilesFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisSmallTilesFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("smalltiles", 1); config->setProperty("numberOfTiles", 2); return config; } diff --git a/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h b/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h index c14495306e..72d045bf2a 100644 --- a/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h +++ b/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h @@ -1,51 +1,51 @@ /* * This file is part of the KDE project * * Copyright (c) Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_SMALL_TILES_FILTER_H_ #define _KIS_SMALL_TILES_FILTER_H_ #include "kis_paint_device.h" #include "filter/kis_filter.h" #include "kis_config_widget.h" class KisSmallTilesFilter : public KisFilter { public: KisSmallTilesFilter(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("smalltiles", i18n("Small Tiles")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; #endif diff --git a/plugins/filters/tests/kis_all_filter_test.cpp b/plugins/filters/tests/kis_all_filter_test.cpp index acb4a12262..8eed780ab0 100644 --- a/plugins/filters/tests/kis_all_filter_test.cpp +++ b/plugins/filters/tests/kis_all_filter_test.cpp @@ -1,316 +1,316 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_all_filter_test.h" #include #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_selection.h" #include "kis_processing_information.h" #include "filter/kis_filter.h" #include "kis_pixel_selection.h" #include "kis_transaction.h" #include bool compareQImages(QPoint & pt, const QImage & image1, const QImage & image2) { // QTime t; // t.start(); int w1 = image1.width(); int h1 = image1.height(); int w2 = image2.width(); int h2 = image2.height(); if (w1 != w2 || h1 != h2) { dbgKrita << w1 << " " << w2 << " " << h1 << " " << h2; pt.setX(-1); pt.setY(-1); return false; } for (int x = 0; x < w1; ++x) { for (int y = 0; y < h1; ++y) { if (image1.pixel(x, y) != image2.pixel(x, y)) { pt.setX(x); pt.setY(y); return false; } } } // dbgKrita << "compareQImages time elapsed:" << t.elapsed(); return true; } bool testFilterSrcNotIsDev(KisFilterSP f) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png"); QImage result(QString(FILES_DATA_DIR) + QDir::separator() + "carrot_" + f->id() + ".png"); KisPaintDeviceSP dev = new KisPaintDevice(cs); KisPaintDeviceSP dstdev = new KisPaintDevice(cs); dev->convertFromQImage(qimage, 0, 0, 0); // Get the predefined configuration from a file - KisFilterConfigurationSP kfc = f->defaultConfiguration(dev); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //dbgKrita << "creating new file for " << f->id(); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); //dbgKrita << "Read for " << f->id() << "\n" << s; kfc->fromXML(s); } dbgKrita << f->id();// << "\n" << kfc->toXML() << "\n"; f->process(dev, dstdev, 0, QRect(QPoint(0,0), qimage.size()), kfc); QPoint errpoint; if (!compareQImages(errpoint, result, dstdev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save(QString("src_not_is_dst_carrot_%1.png").arg(f->id())); return false; } return true; } bool testFilterNoTransaction(KisFilterSP f) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png"); QImage result(QString(FILES_DATA_DIR) + QDir::separator() + "carrot_" + f->id() + ".png"); KisPaintDeviceSP dev = new KisPaintDevice(cs); dev->convertFromQImage(qimage, 0, 0, 0); // Get the predefined configuration from a file - KisFilterConfigurationSP kfc = f->defaultConfiguration(dev); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //dbgKrita << "creating new file for " << f->id(); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); //dbgKrita << "Read for " << f->id() << "\n" << s; kfc->fromXML(s); } dbgKrita << f->id();// << "\n" << kfc->toXML() << "\n"; f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc); QPoint errpoint; if (!compareQImages(errpoint, result, dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save(QString("no_transactio_carrot_%1.png").arg(f->id())); return false; } return true; } bool testFilter(KisFilterSP f) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png"); QString resultFileName = QString(FILES_DATA_DIR) + QDir::separator() + "carrot_" + f->id() + ".png"; QImage result(resultFileName); if (!QFileInfo(resultFileName).exists()) { dbgKrita << resultFileName << " not found"; return false; } KisPaintDeviceSP dev = new KisPaintDevice(cs); dev->convertFromQImage(qimage, 0, 0, 0); KisTransaction * cmd = new KisTransaction(kundo2_noi18n(f->name()), dev); // Get the predefined configuration from a file - KisFilterConfigurationSP kfc = f->defaultConfiguration(dev); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //dbgKrita << "creating new file for " << f->id(); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); //dbgKrita << "Read for " << f->id() << "\n" << s; kfc->fromXML(s); } dbgKrita << f->id();// << "\n" << kfc->toXML() << "\n"; f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc); QPoint errpoint; delete cmd; if (!compareQImages(errpoint, result, dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dbgKrita << errpoint; dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save(QString("carrot_%1.png").arg(f->id())); return false; } return true; } bool testFilterWithSelections(KisFilterSP f) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png"); QImage result(QString(FILES_DATA_DIR) + QDir::separator() + "carrot_" + f->id() + ".png"); KisPaintDeviceSP dev = new KisPaintDevice(cs); dev->convertFromQImage(qimage, 0, 0, 0); // Get the predefined configuration from a file - KisFilterConfigurationSP kfc = f->defaultConfiguration(dev); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //dbgKrita << "creating new file for " << f->id(); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); //dbgKrita << "Read for " << f->id() << "\n" << s; kfc->fromXML(s); } dbgKrita << f->id();// << "\n"; << kfc->toXML() << "\n"; KisSelectionSP sel1 = new KisSelection(new KisSelectionDefaultBounds(dev)); sel1->pixelSelection()->select(qimage.rect()); f->process(dev, dev, sel1, QRect(QPoint(0,0), qimage.size()), kfc); QPoint errpoint; if (!compareQImages(errpoint, result, dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) { dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save(QString("sel_carrot_%1.png").arg(f->id())); return false; } return true; } void KisAllFilterTest::testAllFilters() { QStringList failures; QStringList successes; QList filterList = KisFilterRegistry::instance()->keys(); qSort(filterList); for (QList::Iterator it = filterList.begin(); it != filterList.end(); ++it) { if (testFilter(KisFilterRegistry::instance()->value(*it))) successes << *it; else failures << *it; } dbgKrita << "Success: " << successes; if (failures.size() > 0) { QFAIL(QString("Failed filters:\n\t %1").arg(failures.join("\n\t")).toLatin1()); } } void KisAllFilterTest::testAllFiltersNoTransaction() { QStringList failures; QStringList successes; QList filterList = KisFilterRegistry::instance()->keys(); qSort(filterList); for (QList::Iterator it = filterList.begin(); it != filterList.end(); ++it) { if (testFilterNoTransaction(KisFilterRegistry::instance()->value(*it))) successes << *it; else failures << *it; } dbgKrita << "Success (no transaction): " << successes; if (failures.size() > 0) { QFAIL(QString("Failed filters (no transaction):\n\t %1").arg(failures.join("\n\t")).toLatin1()); } } void KisAllFilterTest::testAllFiltersSrcNotIsDev() { QStringList failures; QStringList successes; QList filterList = KisFilterRegistry::instance()->keys(); qSort(filterList); for (QList::Iterator it = filterList.begin(); it != filterList.end(); ++it) { if (testFilterSrcNotIsDev(KisFilterRegistry::instance()->value(*it))) successes << *it; else failures << *it; } dbgKrita << "Src!=Dev Success: " << successes; if (failures.size() > 0) { QFAIL(QString("Src!=Dev Failed filters:\n\t %1").arg(failures.join("\n\t")).toLatin1()); } } void KisAllFilterTest::testAllFiltersWithSelections() { QStringList failures; QStringList successes; QList filterList = KisFilterRegistry::instance()->keys(); qSort(filterList); for (QList::Iterator it = filterList.begin(); it != filterList.end(); ++it) { if (testFilterWithSelections(KisFilterRegistry::instance()->value(*it))) successes << *it; else failures << *it; } dbgKrita << "Success: " << successes; if (failures.size() > 0) { QFAIL(QString("Failed filters with selections:\n\t %1").arg(failures.join("\n\t")).toLatin1()); } } QTEST_MAIN(KisAllFilterTest) diff --git a/plugins/filters/tests/kis_crash_filter_test.cpp b/plugins/filters/tests/kis_crash_filter_test.cpp index dd770f2106..565216b766 100644 --- a/plugins/filters/tests/kis_crash_filter_test.cpp +++ b/plugins/filters/tests/kis_crash_filter_test.cpp @@ -1,99 +1,99 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_crash_filter_test.h" #include #include #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_selection.h" #include "kis_processing_information.h" #include "filter/kis_filter.h" #include "kis_pixel_selection.h" #include bool KisCrashFilterTest::applyFilter(const KoColorSpace * cs, KisFilterSP f) { QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png"); KisPaintDeviceSP dev = new KisPaintDevice(cs); // dev->fill(0, 0, 100, 100, dev->defaultPixel()); dev->convertFromQImage(qimage, 0, 0, 0); // Get the predefined configuration from a file - KisFilterConfigurationSP kfc = f->defaultConfiguration(dev); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { dbgKrita << "creating new file for " << f->id(); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out.setCodec("UTF-8"); out << kfc->toXML(); } else { QString s; QTextStream in(&file); in.setCodec("UTF-8"); s = in.readAll(); kfc->fromXML(s); } dbgKrita << f->id() << ", " << cs->id() << ", " << cs->profile()->name();// << kfc->toXML() << "\n"; f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc); return true; } bool KisCrashFilterTest::testFilter(KisFilterSP f) { QList colorSpaces = KoColorSpaceRegistry::instance()->allColorSpaces(KoColorSpaceRegistry::AllColorSpaces, KoColorSpaceRegistry::AllProfiles); bool ok = false; Q_FOREACH (const KoColorSpace* colorSpace, colorSpaces) { // XXX: Let's not check the painterly colorspaces right now if (colorSpace->id().startsWith("KS", Qt::CaseInsensitive)) { continue; } ok = applyFilter(colorSpace, f); } return ok; } void KisCrashFilterTest::testCrashFilters() { QStringList failures; QStringList successes; QList filterList = KisFilterRegistry::instance()->keys(); qSort(filterList); for (QList::Iterator it = filterList.begin(); it != filterList.end(); ++it) { if (testFilter(KisFilterRegistry::instance()->value(*it))) successes << *it; else failures << *it; } dbgKrita << "Success: " << successes; if (failures.size() > 0) { QFAIL(QString("Failed filters:\n\t %1").arg(failures.join("\n\t")).toLatin1()); } } QTEST_MAIN(KisCrashFilterTest) diff --git a/plugins/filters/threshold/threshold.cpp b/plugins/filters/threshold/threshold.cpp index fbd51dd2d0..7d23faea0b 100644 --- a/plugins/filters/threshold/threshold.cpp +++ b/plugins/filters/threshold/threshold.cpp @@ -1,220 +1,220 @@ /* * This file is part of the KDE project * * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "threshold.h" #include #include #include #include #include #include #include #include #include #include "kis_gradient_slider.h" #include "kis_histogram.h" #include #include "kis_paint_device.h" #include "kis_painter.h" #include #include #include #include #include #include "KoColorModelStandardIds.h" #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaThresholdFactory, "kritathreshold.json", registerPlugin();) KritaThreshold::KritaThreshold(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterThreshold()); } KritaThreshold::~KritaThreshold() { } KisFilterThreshold::KisFilterThreshold() : KisFilter(id(), categoryAdjust(), i18n("&Threshold...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(false); setShowConfigurationWidget(true); setSupportsLevelOfDetail(true); setSupportsAdjustmentLayers(true); setSupportsThreading(true); } void KisFilterThreshold::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.height() * applyRect.width()); } int threshold = config->getInt("threshold"); KoColor white(Qt::white, device->colorSpace()); KoColor black(Qt::black, device->colorSpace()); KisSequentialIterator it(device, applyRect); int p = 0; const int pixelSize = device->colorSpace()->pixelSize(); do { if (device->colorSpace()->intensity8(it.oldRawData()) > threshold) { memcpy(it.rawData(), white.data(), pixelSize); } else { memcpy(it.rawData(), black.data(), pixelSize); } if (progressUpdater) progressUpdater->setValue(p++); } while (it.nextPixel()); } -KisFilterConfigurationSP KisFilterThreshold::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterThreshold::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("threshold", 1); config->setProperty("threshold", 128); return config; } KisConfigWidget *KisFilterThreshold::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisThresholdConfigWidget(parent, dev); } KisThresholdConfigWidget::KisThresholdConfigWidget(QWidget * parent, KisPaintDeviceSP dev) : KisConfigWidget(parent) { Q_ASSERT(dev); m_page.setupUi(this); m_page.thresholdGradient->enableGamma(false); m_page.thresholdGradient->enableWhite(false); m_page.intThreshold->setValue(128); connect(m_page.intThreshold, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.thresholdGradient, SIGNAL(sigModifiedGamma(double)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.intThreshold, SIGNAL(valueChanged(int)), m_page.thresholdGradient, SLOT(slotModifyBlack(int))); connect(m_page.thresholdGradient, SIGNAL(sigModifiedBlack(int)), m_page.intThreshold, SLOT(setValue(int))); connect((QObject*)(m_page.chkLogarithmic), SIGNAL(toggled(bool)), this, SLOT(slotDrawHistogram(bool))); KoHistogramProducer *producer = new KoGenericLabHistogramProducer(); m_histogram.reset( new KisHistogram(dev, dev->exactBounds(), producer, LINEAR) ); m_histlog = false; m_page.histview->resize(288,100); slotDrawHistogram(); } KisThresholdConfigWidget::~KisThresholdConfigWidget() { } void KisThresholdConfigWidget::slotDrawHistogram(bool logarithmic) { int wHeight = m_page.histview->height(); int wHeightMinusOne = wHeight - 1; int wWidth = m_page.histview->width(); if (m_histlog != logarithmic) { // Update the m_histogram if (logarithmic) m_histogram->setHistogramType(LOGARITHMIC); else m_histogram->setHistogramType(LINEAR); m_histlog = logarithmic; } QPalette appPalette = QApplication::palette(); QPixmap pix(wWidth-100, wHeight); pix.fill(QColor(appPalette.color(QPalette::Base))); QPainter p(&pix); p.setPen(QPen(Qt::gray, 1, Qt::SolidLine)); double highest = (double)m_histogram->calculations().getHighest(); qint32 bins = m_histogram->producer()->numberOfBins(); // use nearest neighbour interpolation if (m_histogram->getHistogramType() == LINEAR) { double factor = (double)(wHeight - wHeight / 5.0) / highest; for (int i = 0; i < wWidth; i++) { int binNo = qRound((double)i / wWidth * (bins - 1)); if ((int)m_histogram->getValue(binNo) != 0) p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - (int)m_histogram->getValue(binNo) * factor); } } else { double factor = (double)(wHeight - wHeight / 5.0) / (double)log(highest); for (int i = 0; i < wWidth; i++) { int binNo = qRound((double)i / wWidth * (bins - 1)) ; if ((int)m_histogram->getValue(binNo) != 0) p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - log((double)m_histogram->getValue(binNo)) * factor); } } m_page.histview->setPixmap(pix); } void KisThresholdConfigWidget::slotSetThreshold(int limit) { m_page.intThreshold->setMaximum(limit - 1); } KisPropertiesConfigurationSP KisThresholdConfigWidget::configuration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("threshold", 1); config->setProperty("threshold", m_page.intThreshold->value()); return config; } void KisThresholdConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { QVariant value; if (config->getProperty("threshold", value)) { m_page.intThreshold->setValue(value.toUInt()); m_page.thresholdGradient->slotModifyBlack(value.toUInt()); } } #include "threshold.moc" diff --git a/plugins/filters/threshold/threshold.h b/plugins/filters/threshold/threshold.h index 29b04d1381..ff84d21af0 100644 --- a/plugins/filters/threshold/threshold.h +++ b/plugins/filters/threshold/threshold.h @@ -1,91 +1,91 @@ /* * This file is part of Krita * * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef THRESHOLD_H #define THRESHOLD_H #include #include #include #include #include #include "ui_wdg_threshold.h" class WdgThreshold; class QWidget; class KisHistogram; class KritaThreshold : public QObject { Q_OBJECT public: KritaThreshold(QObject *parent, const QVariantList &); virtual ~KritaThreshold(); }; class KisFilterThreshold : public KisFilter { public: KisFilterThreshold(); public: static inline KoID id() { return KoID("threshold", i18n("Threshold")); } virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget *createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const; }; class KisThresholdConfigWidget : public KisConfigWidget { Q_OBJECT public: KisThresholdConfigWidget(QWidget *parent, KisPaintDeviceSP dev); virtual ~KisThresholdConfigWidget(); virtual KisPropertiesConfigurationSP configuration() const; void setConfiguration(const KisPropertiesConfigurationSP config); Ui::WdgThreshold m_page; private Q_SLOTS: void slotDrawHistogram(bool logarithmic = false); void slotSetThreshold(int); protected: QScopedPointer m_histogram; bool m_histlog; }; #endif diff --git a/plugins/filters/unsharp/kis_unsharp_filter.cpp b/plugins/filters/unsharp/kis_unsharp_filter.cpp index 9674691489..db212bce42 100644 --- a/plugins/filters/unsharp/kis_unsharp_filter.cpp +++ b/plugins/filters/unsharp/kis_unsharp_filter.cpp @@ -1,229 +1,229 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "kis_unsharp_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_lod_transform.h" #include "kis_wdg_unsharp.h" #include "ui_wdgunsharp.h" #include #include "KoColorSpaceTraits.h" KisUnsharpFilter::KisUnsharpFilter() : KisFilter(id(), categoryEnhance(), i18n("&Unsharp Mask...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsThreading(true); /** * Officially Unsharp Mask doesn't support LoD, because it * generates subtle artifacts when the unsharp radius is smaller * than current zoom level. But LoD devices can still appear when * the filter is used in Adjustment Layer. So the actual LoD is * still counted on. */ setSupportsLevelOfDetail(false); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisUnsharpFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgUnsharp(parent); } -KisFilterConfigurationSP KisUnsharpFilter::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisUnsharpFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("halfSize", 1); config->setProperty("amount", 50); config->setProperty("threshold", 0); config->setProperty("lightnessOnly", true); return config; } void KisUnsharpFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPointer filterUpdater = 0; QPointer convolutionUpdater = 0; KoProgressUpdater* updater = 0; if (progressUpdater) { updater = new KoProgressUpdater(progressUpdater); updater->start(100, i18n("Unsharp Mask")); // Two sub-sub tasks that each go from 0 to 100. convolutionUpdater = updater->startSubtask(); filterUpdater = updater->startSubtask(); } KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); QVariant value; KisLodTransformScalar t(device); const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0); const qreal amount = (config->getProperty("amount", value)) ? value.toDouble() : 25; const uint threshold = (config->getProperty("threshold", value)) ? value.toUInt() : 0; const uint lightnessOnly = (config->getProperty("lightnessOnly", value)) ? value.toBool() : true; QBitArray channelFlags = config->channelFlags(); KisGaussianKernel::applyGaussian(device, applyRect, halfSize, halfSize, channelFlags, progressUpdater); if (progressUpdater && progressUpdater->interrupted()) { return; } qreal weights[2]; qreal factor = 128; weights[0] = factor * (1. + amount); weights[1] = -factor * amount; if (lightnessOnly) { processLightnessOnly(device, applyRect, threshold, weights, factor, channelFlags); } else { processRaw(device, applyRect, threshold, weights, factor, channelFlags); } delete updater; if (progressUpdater) progressUpdater->setProgress(100); } void KisUnsharpFilter::processRaw(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray &channelFlags) const { const KoColorSpace *cs = device->colorSpace(); const int pixelSize = cs->pixelSize(); KoConvolutionOp * convolutionOp = cs->convolutionOp(); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(rect.x(), rect.y(), rect.width()); quint8 *colors[2]; colors[0] = new quint8[pixelSize]; colors[1] = new quint8[pixelSize]; for (int j = 0; j < rect.height(); j++) { do { quint8 diff = cs->difference(dstIt->oldRawData(), dstIt->rawDataConst()); if (diff > threshold) { memcpy(colors[0], dstIt->oldRawData(), pixelSize); memcpy(colors[1], dstIt->rawDataConst(), pixelSize); convolutionOp->convolveColors(colors, weights, dstIt->rawData(), factor, 0, 2, channelFlags); } else { memcpy(dstIt->rawData(), dstIt->oldRawData(), pixelSize); } } while (dstIt->nextPixel()); dstIt->nextRow(); } delete[] colors[0]; delete[] colors[1]; } void KisUnsharpFilter::processLightnessOnly(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray & /*channelFlags*/) const { const KoColorSpace *cs = device->colorSpace(); const int pixelSize = cs->pixelSize(); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(rect.x(), rect.y(), rect.width()); quint16 labColorSrc[4]; quint16 labColorDst[4]; const int posL = 0; const int posAplha = 3; const qreal factorInv = 1.0 / factor; for (int j = 0; j < rect.height(); j++) { do { quint8 diff = cs->differenceA(dstIt->oldRawData(), dstIt->rawDataConst()); if (diff > threshold) { cs->toLabA16(dstIt->oldRawData(), (quint8*)labColorSrc, 1); cs->toLabA16(dstIt->rawDataConst(), (quint8*)labColorDst, 1); qint32 valueL = (labColorSrc[posL] * weights[0] + labColorDst[posL] * weights[1]) * factorInv; labColorSrc[posL] = CLAMP(valueL, KoColorSpaceMathsTraits::min, KoColorSpaceMathsTraits::max); qint32 valueAlpha = (labColorSrc[posAplha] * weights[0] + labColorDst[posAplha] * weights[1]) * factorInv; labColorSrc[posAplha] = CLAMP(valueAlpha, KoColorSpaceMathsTraits::min, KoColorSpaceMathsTraits::max); cs->fromLabA16((quint8*)labColorSrc, dstIt->rawData(), 1); } else { memcpy(dstIt->rawData(), dstIt->oldRawData(), pixelSize); } } while (dstIt->nextPixel()); dstIt->nextRow(); } } QRect KisUnsharpFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0); return rect.adjusted(-halfSize * 2, -halfSize * 2, halfSize * 2, halfSize * 2); } QRect KisUnsharpFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0); return rect.adjusted( -halfSize, -halfSize, halfSize, halfSize); } diff --git a/plugins/filters/unsharp/kis_unsharp_filter.h b/plugins/filters/unsharp/kis_unsharp_filter.h index 34bfb5d6d5..5a59acedb5 100644 --- a/plugins/filters/unsharp/kis_unsharp_filter.h +++ b/plugins/filters/unsharp/kis_unsharp_filter.h @@ -1,64 +1,64 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_UNSHARP_FILTER_H #define KIS_UNSHARP_FILTER_H #include "filter/kis_filter.h" class KisUnsharpFilter : public KisFilter { public: KisUnsharpFilter(); void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("unsharp", i18n("Unsharp Mask")); } virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; QRect changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; QRect neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const; private: void processLightnessOnly(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray &channelFlags) const; void processRaw(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray &channelFlags) const; }; #endif diff --git a/plugins/filters/unsharp/tests/kis_unsharp_mask_test.cpp b/plugins/filters/unsharp/tests/kis_unsharp_mask_test.cpp index 4ad7a55101..826da4297f 100644 --- a/plugins/filters/unsharp/tests/kis_unsharp_mask_test.cpp +++ b/plugins/filters/unsharp/tests/kis_unsharp_mask_test.cpp @@ -1,67 +1,67 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_unsharp_mask_test.h" #include #include "kis_transaction.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "testutil.h" void KisUnsharpMaskTest::testUnsharpWithTransparency() { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QImage srcImage(TestUtil::fetchDataFileLazy("source_with_transparency.png")); QVERIFY(!srcImage.isNull()); QRect imageRect = srcImage.rect(); KisPaintDeviceSP dev = new KisPaintDevice(cs); dev->convertFromQImage(srcImage, 0, 0, 0); KisFilterSP f = KisFilterRegistry::instance()->value("unsharp"); Q_ASSERT(f); - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); Q_ASSERT(kfc); kfc->setProperty("halfSize", 3); kfc->setProperty("amount", 2.5); kfc->setProperty("threshold", 0); KisTransaction t(dev); f->process(dev, QRect(imageRect.topLeft(), imageRect.size()), kfc); t.end(); QImage resultImage = dev->convertToQImage(0, imageRect.x(), imageRect.y(), imageRect.width(), imageRect.height()); TestUtil::checkQImage(resultImage, "unsharp_mask_test", "with_transparency", "unsharp_with_transparency"); } QTEST_MAIN(KisUnsharpMaskTest) diff --git a/plugins/filters/wavefilter/wavefilter.cpp b/plugins/filters/wavefilter/wavefilter.cpp index d468c6165b..a711983e5c 100644 --- a/plugins/filters/wavefilter/wavefilter.cpp +++ b/plugins/filters/wavefilter/wavefilter.cpp @@ -1,179 +1,179 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "wavefilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_wave.h" #include "ui_wdgwaveoptions.h" #include K_PLUGIN_FACTORY_WITH_JSON(KritaWaveFilterFactory, "kritawavefilter.json", registerPlugin();) class KisWaveCurve { public: virtual ~KisWaveCurve() {} virtual double valueAt(int x, int y) = 0; }; class KisSinusoidalWaveCurve : public KisWaveCurve { public: KisSinusoidalWaveCurve(int amplitude, int wavelength, int shift) : m_amplitude(amplitude), m_wavelength(wavelength), m_shift(shift) { } ~KisSinusoidalWaveCurve() override {} double valueAt(int x, int y) override { return y + m_amplitude * cos((double)(m_shift + x) / m_wavelength); } private: int m_amplitude, m_wavelength, m_shift; }; class KisTriangleWaveCurve : public KisWaveCurve { public: KisTriangleWaveCurve(int amplitude, int wavelength, int shift) : m_amplitude(amplitude), m_wavelength(wavelength), m_shift(shift) { } ~KisTriangleWaveCurve() override {} double valueAt(int x, int y) override { return y + m_amplitude * pow(-1.0, (m_shift + x) / m_wavelength) *(0.5 - (double)((m_shift + x) % m_wavelength) / m_wavelength); } private: int m_amplitude, m_wavelength, m_shift; }; KritaWaveFilter::KritaWaveFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterWave()); } KritaWaveFilter::~KritaWaveFilter() { } KisFilterWave::KisFilterWave() : KisFilter(id(), categoryOther(), i18n("&Wave...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(false); setSupportsAdjustmentLayers(false); } -KisFilterConfigurationSP KisFilterWave::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisFilterWave::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("wave", 1); config->setProperty("horizontalwavelength", 50); config->setProperty("horizontalshift", 50); config->setProperty("horizontalamplitude", 4); config->setProperty("horizontalshape", 0); config->setProperty("verticalwavelength", 50); config->setProperty("verticalshift", 50); config->setProperty("verticalamplitude", 4); config->setProperty("verticalshape", 0); return config; } KisConfigWidget * KisFilterWave::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgWave((KisFilter*)this, (QWidget*)parent); } void KisFilterWave::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(device.data() != 0); int cost = (applyRect.width() * applyRect.height()) / 100; if (cost == 0) cost = 1; int count = 0; QVariant value; int horizontalwavelength = (config && config->getProperty("horizontalwavelength", value)) ? value.toInt() : 50; int horizontalshift = (config && config->getProperty("horizontalshift", value)) ? value.toInt() : 50; int horizontalamplitude = (config && config->getProperty("horizontalamplitude", value)) ? value.toInt() : 4; int horizontalshape = (config && config->getProperty("horizontalshape", value)) ? value.toInt() : 0; int verticalwavelength = (config && config->getProperty("verticalwavelength", value)) ? value.toInt() : 50; int verticalshift = (config && config->getProperty("verticalshift", value)) ? value.toInt() : 50; int verticalamplitude = (config && config->getProperty("verticalamplitude", value)) ? value.toInt() : 4; int verticalshape = (config && config->getProperty("verticalshape", value)) ? value.toInt() : 0; KisSequentialIterator dstIt(device, applyRect); KisWaveCurve* verticalcurve; if (verticalshape == 1) verticalcurve = new KisTriangleWaveCurve(verticalamplitude, verticalwavelength, verticalshift); else verticalcurve = new KisSinusoidalWaveCurve(verticalamplitude, verticalwavelength, verticalshift); KisWaveCurve* horizontalcurve; if (horizontalshape == 1) horizontalcurve = new KisTriangleWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift); else horizontalcurve = new KisSinusoidalWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift); KisRandomSubAccessorSP srcRSA = device->createRandomSubAccessor(); do { double xv = horizontalcurve->valueAt(dstIt.y(), dstIt.x()); double yv = verticalcurve->valueAt(dstIt.x(), dstIt.y()); srcRSA->moveTo(QPointF(xv, yv)); srcRSA->sampledOldRawData(dstIt.rawData()); if (progressUpdater) progressUpdater->setProgress((++count) / cost); } while (dstIt.nextPixel()); delete horizontalcurve; delete verticalcurve; } QRect KisFilterWave::neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod) const { Q_UNUSED(lod); QVariant value; int horizontalamplitude = (config && config->getProperty("horizontalamplitude", value)) ? value.toInt() : 4; int verticalamplitude = (config && config->getProperty("verticalamplitude", value)) ? value.toInt() : 4; return rect.adjusted(-horizontalamplitude, -verticalamplitude, horizontalamplitude, verticalamplitude); } #include "wavefilter.moc" diff --git a/plugins/filters/wavefilter/wavefilter.h b/plugins/filters/wavefilter/wavefilter.h index 16f435ef97..cd197a5cfe 100644 --- a/plugins/filters/wavefilter/wavefilter.h +++ b/plugins/filters/wavefilter/wavefilter.h @@ -1,61 +1,61 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef WAVEFILTER_H #define WAVEFILTER_H #include #include #include "filter/kis_filter.h" class KisConfigWidget; class KritaWaveFilter : public QObject { Q_OBJECT public: KritaWaveFilter(QObject *parent, const QVariantList &); virtual ~KritaWaveFilter(); }; class KisFilterWave : public KisFilter { public: KisFilterWave(); public: void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const; static inline KoID id() { return KoID("wave", i18n("Wave")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; public: virtual QRect neededRect(const QRect& rect, const KisFilterConfigurationSP config = 0, int lod = 0) const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; #endif diff --git a/plugins/generators/pattern/patterngenerator.cpp b/plugins/generators/pattern/patterngenerator.cpp index 1cb8889a88..09dffd5cec 100644 --- a/plugins/generators/pattern/patterngenerator.cpp +++ b/plugins/generators/pattern/patterngenerator.cpp @@ -1,121 +1,121 @@ /* * This file is part of the KDE project * * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "patterngenerator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_pattern.h" #include "ui_wdgpatternoptions.h" K_PLUGIN_FACTORY_WITH_JSON(KritaPatternGeneratorFactory, "kritapatterngenerator.json", registerPlugin();) KritaPatternGenerator::KritaPatternGenerator(QObject *parent, const QVariantList &) : QObject(parent) { KisGeneratorRegistry::instance()->add(new KoPatternGenerator()); } KritaPatternGenerator::~KritaPatternGenerator() { } KoPatternGenerator::KoPatternGenerator() : KisGenerator(id(), KoID("basic"), i18n("&Pattern...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } -KisFilterConfigurationSP KoPatternGenerator::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KoPatternGenerator::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("pattern", 1); QVariant v; v.setValue(QString("Grid01.pat")); config->setProperty("pattern", v); // v.setValue(KoColor()); // config->setProperty("color", v); return config; } KisConfigWidget * KoPatternGenerator::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgPattern(parent); } void KoPatternGenerator::generate(KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const { KisPaintDeviceSP dst = dstInfo.paintDevice(); Q_ASSERT(!dst.isNull()); Q_ASSERT(config); if (!config) return; QString patternName = config->getString("pattern", "Grid01.pat"); KoResourceServer *rserver = KoResourceServerProvider::instance()->patternServer(); KoPattern *pattern = rserver->resourceByName(patternName); // KoColor c = config->getColor("color"); KisFillPainter gc(dst); gc.setPattern(pattern); // gc.setPaintColor(c); gc.setProgress(progressUpdater); gc.setChannelFlags(config->channelFlags()); gc.setOpacity(OPACITY_OPAQUE_U8); gc.setSelection(dstInfo.selection()); gc.setWidth(size.width()); gc.setHeight(size.height()); gc.setFillStyle(KisFillPainter::FillStylePattern); gc.fillRect(QRect(dstInfo.topLeft(), size), pattern); gc.end(); } -#include "patterngenerator.moc" \ No newline at end of file +#include "patterngenerator.moc" diff --git a/plugins/generators/pattern/patterngenerator.h b/plugins/generators/pattern/patterngenerator.h index 36b7af3acb..3dbe8dddb4 100644 --- a/plugins/generators/pattern/patterngenerator.h +++ b/plugins/generators/pattern/patterngenerator.h @@ -1,59 +1,59 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PATTERN_GENERATOR_H #define PATTERN_GENERATOR_H #include #include #include "generator/kis_generator.h" class KisConfigWidget; class KritaPatternGenerator : public QObject { Q_OBJECT public: KritaPatternGenerator(QObject *parent, const QVariantList &); virtual ~KritaPatternGenerator(); }; class KoPatternGenerator : public KisGenerator { public: KoPatternGenerator(); using KisGenerator::generate; void generate(KisProcessingInformation dst, const QSize& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("pattern", i18n("Pattern")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; #endif diff --git a/plugins/generators/solid/colorgenerator.cpp b/plugins/generators/solid/colorgenerator.cpp index dd74c90121..b0631e0bb3 100644 --- a/plugins/generators/solid/colorgenerator.cpp +++ b/plugins/generators/solid/colorgenerator.cpp @@ -1,103 +1,103 @@ /* * This file is part of the KDE project * * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "colorgenerator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_color.h" #include "ui_wdgcoloroptions.h" K_PLUGIN_FACTORY_WITH_JSON(KritaColorGeneratorFactory, "kritacolorgenerator.json", registerPlugin();) KritaColorGenerator::KritaColorGenerator(QObject *parent, const QVariantList &) : QObject(parent) { KisGeneratorRegistry::instance()->add(new KisColorGenerator()); } KritaColorGenerator::~KritaColorGenerator() { } KisColorGenerator::KisColorGenerator() : KisGenerator(id(), KoID("basic"), i18n("&Solid Color...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } -KisFilterConfigurationSP KisColorGenerator::factoryConfiguration(const KisPaintDeviceSP) const +KisFilterConfigurationSP KisColorGenerator::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("color", 1); QVariant v; v.setValue(KoColor()); config->setProperty("color", v); return config; } KisConfigWidget * KisColorGenerator::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgColor(parent); } void KisColorGenerator::generate(KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const { KisPaintDeviceSP dst = dstInfo.paintDevice(); Q_ASSERT(!dst.isNull()); Q_ASSERT(config); KoColor c; if (config) { c = config->getColor("color"); KisFillPainter gc(dst); gc.setProgress(progressUpdater); gc.setChannelFlags(config->channelFlags()); gc.setOpacity(100); gc.setSelection(dstInfo.selection()); gc.fillRect(QRect(dstInfo.topLeft(), size), c); gc.end(); } } #include "colorgenerator.moc" diff --git a/plugins/generators/solid/colorgenerator.h b/plugins/generators/solid/colorgenerator.h index a141e7b1e4..abd8ef1f3a 100644 --- a/plugins/generators/solid/colorgenerator.h +++ b/plugins/generators/solid/colorgenerator.h @@ -1,59 +1,59 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef COLOR_GENERATOR_H #define COLOR_GENERATOR_H #include #include #include "generator/kis_generator.h" class KisConfigWidget; class KritaColorGenerator : public QObject { Q_OBJECT public: KritaColorGenerator(QObject *parent, const QVariantList &); virtual ~KritaColorGenerator(); }; class KisColorGenerator : public KisGenerator { public: KisColorGenerator(); using KisGenerator::generate; void generate(KisProcessingInformation dst, const QSize& size, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const; static inline KoID id() { return KoID("color", i18n("Color")); } - virtual KisFilterConfigurationSP factoryConfiguration(const KisPaintDeviceSP) const; + virtual KisFilterConfigurationSP factoryConfiguration() const; virtual KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const; }; #endif diff --git a/plugins/impex/libkra/kis_kra_loader.cpp b/plugins/impex/libkra/kis_kra_loader.cpp index 3c5e89a147..fd5e6ce844 100644 --- a/plugins/impex/libkra/kis_kra_loader.cpp +++ b/plugins/impex/libkra/kis_kra_loader.cpp @@ -1,1156 +1,1156 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2007 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_kra_loader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lazybrush/kis_colorize_mask.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_resource_server_provider.h" #include "kis_keyframe_channel.h" #include #include "KisDocument.h" #include "kis_config.h" #include "kis_kra_tags.h" #include "kis_kra_utils.h" #include "kis_kra_load_visitor.h" #include "kis_dom_utils.h" #include "kis_image_animation_interface.h" #include "kis_time_range.h" #include "kis_grid_config.h" #include "kis_guides_config.h" #include "kis_image_config.h" #include "KisProofingConfiguration.h" #include "kis_layer_properties_icons.h" #include "kis_node_view_color_scheme.h" /* Color model id comparison through the ages: 2.4 2.5 2.6 ideal ALPHA ALPHA ALPHA ALPHAU8 CMYK CMYK CMYK CMYKAU8 CMYKAF32 CMYKAF32 CMYKA16 CMYKAU16 CMYKAU16 GRAYA GRAYA GRAYA GRAYAU8 GrayF32 GRAYAF32 GRAYAF32 GRAYA16 GRAYAU16 GRAYAU16 LABA LABA LABA LABAU16 LABAF32 LABAF32 LABAU8 LABAU8 RGBA RGBA RGBA RGBAU8 RGBA16 RGBA16 RGBA16 RGBAU16 RgbAF32 RGBAF32 RGBAF32 RgbAF16 RgbAF16 RGBAF16 XYZA16 XYZA16 XYZA16 XYZAU16 XYZA8 XYZA8 XYZAU8 XyzAF16 XyzAF16 XYZAF16 XyzAF32 XYZAF32 XYZAF32 YCbCrA YCBCRA8 YCBCRA8 YCBCRAU8 YCbCrAU16 YCBCRAU16 YCBCRAU16 YCBCRF32 YCBCRF32 */ using namespace KRA; struct KisKraLoader::Private { public: KisDocument* document; QString imageName; // used to be stored in the image, is now in the documentInfo block QString imageComment; // used to be stored in the image, is now in the documentInfo block QMap layerFilenames; // temp storage during loading int syntaxVersion; // version of the fileformat we are loading vKisNodeSP selectedNodes; // the nodes that were active when saving the document. QMap assistantsFilenames; QList assistants; QMap keyframeFilenames; QStringList errorMessages; }; void convertColorSpaceNames(QString &colorspacename, QString &profileProductName) { if (colorspacename == "Grayscale + Alpha") { colorspacename = "GRAYA"; profileProductName.clear(); } else if (colorspacename == "RgbAF32") { colorspacename = "RGBAF32"; profileProductName.clear(); } else if (colorspacename == "RgbAF16") { colorspacename = "RGBAF16"; profileProductName.clear(); } else if (colorspacename == "CMYKA16") { colorspacename = "CMYKAU16"; } else if (colorspacename == "GrayF32") { colorspacename = "GRAYAF32"; profileProductName.clear(); } else if (colorspacename == "GRAYA16") { colorspacename = "GRAYAU16"; } else if (colorspacename == "XyzAF16") { colorspacename = "XYZAF16"; profileProductName.clear(); } else if (colorspacename == "XyzAF32") { colorspacename = "XYZAF32"; profileProductName.clear(); } else if (colorspacename == "YCbCrA") { colorspacename = "YCBCRA8"; } else if (colorspacename == "YCbCrAU16") { colorspacename = "YCBCRAU16"; } } KisKraLoader::KisKraLoader(KisDocument * document, int syntaxVersion) : m_d(new Private()) { m_d->document = document; m_d->syntaxVersion = syntaxVersion; } KisKraLoader::~KisKraLoader() { delete m_d; } KisImageSP KisKraLoader::loadXML(const KoXmlElement& element) { QString attr; KisImageSP image = 0; QString name; qint32 width; qint32 height; QString profileProductName; double xres; double yres; QString colorspacename; const KoColorSpace * cs; if ((attr = element.attribute(MIME)) == NATIVE_MIMETYPE) { if ((m_d->imageName = element.attribute(NAME)).isNull()) { m_d->errorMessages << i18n("Image does not have a name."); return KisImageSP(0); } if ((attr = element.attribute(WIDTH)).isNull()) { m_d->errorMessages << i18n("Image does not specify a width."); return KisImageSP(0); } width = KisDomUtils::toInt(attr); if ((attr = element.attribute(HEIGHT)).isNull()) { m_d->errorMessages << i18n("Image does not specify a height."); return KisImageSP(0); } height = KisDomUtils::toInt(attr); m_d->imageComment = element.attribute(DESCRIPTION); xres = 100.0 / 72.0; if (!(attr = element.attribute(X_RESOLUTION)).isNull()) { qreal value = KisDomUtils::toDouble(attr); if (value > 1.0) { xres = value / 72.0; } } yres = 100.0 / 72.0; if (!(attr = element.attribute(Y_RESOLUTION)).isNull()) { qreal value = KisDomUtils::toDouble(attr); if (value > 1.0) { yres = value / 72.0; } } if ((colorspacename = element.attribute(COLORSPACE_NAME)).isNull()) { // An old file: take a reasonable default. // Krita didn't support anything else in those // days anyway. colorspacename = "RGBA"; } profileProductName = element.attribute(PROFILE); // A hack for an old colorspacename convertColorSpaceNames(colorspacename, profileProductName); QString colorspaceModel = KoColorSpaceRegistry::instance()->colorSpaceColorModelId(colorspacename).id(); QString colorspaceDepth = KoColorSpaceRegistry::instance()->colorSpaceColorDepthId(colorspacename).id(); if (profileProductName.isNull()) { // no mention of profile so get default profile"; cs = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, ""); } else { cs = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, profileProductName); } if (cs == 0) { // try once more without the profile cs = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, ""); if (cs == 0) { m_d->errorMessages << i18n("Image specifies an unsupported color model: %1.", colorspacename); return KisImageSP(0); } } KisImageConfig cfgImage; KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); if (!(attr = element.attribute(PROOFINGPROFILENAME)).isNull()) { proofingConfig->proofingProfile = attr; } if (!(attr = element.attribute(PROOFINGMODEL)).isNull()) { proofingConfig->proofingModel = attr; } if (!(attr = element.attribute(PROOFINGDEPTH)).isNull()) { proofingConfig->proofingDepth = attr; } if (!(attr = element.attribute(PROOFINGINTENT)).isNull()) { proofingConfig->intent = (KoColorConversionTransformation::Intent) KisDomUtils::toInt(attr); } if (!(attr = element.attribute(PROOFINGADAPTATIONSTATE)).isNull()) { proofingConfig->adaptationState = KisDomUtils::toDouble(attr); } if (m_d->document) { image = new KisImage(m_d->document->createUndoStore(), width, height, cs, name); } else { image = new KisImage(0, width, height, cs, name); } image->setResolution(xres, yres); loadNodes(element, image, const_cast(image->rootLayer().data())); KoXmlNode child; for (child = element.lastChild(); !child.isNull(); child = child.previousSibling()) { KoXmlElement e = child.toElement(); if(e.tagName() == CANVASPROJECTIONCOLOR) { if (e.hasAttribute(COLORBYTEDATA)) { QByteArray colorData = QByteArray::fromBase64(e.attribute(COLORBYTEDATA).toLatin1()); KoColor color((const quint8*)colorData.data(), image->colorSpace()); image->setDefaultProjectionColor(color); } } if(e.tagName()== PROOFINGWARNINGCOLOR) { QDomDocument dom; KoXml::asQDomElement(dom, e); QDomElement eq = dom.firstChildElement(); proofingConfig->warningColor = KoColor::fromXML(eq.firstChildElement(), Integer8BitsColorDepthID.id(), QHash()); } if (e.tagName().toLower() == "animation") { loadAnimationMetadata(e, image); } } image->setProofingConfiguration(proofingConfig); for (child = element.lastChild(); !child.isNull(); child = child.previousSibling()) { KoXmlElement e = child.toElement(); if(e.tagName() == "compositions") { loadCompositions(e, image); } } } KoXmlNode child; for (child = element.lastChild(); !child.isNull(); child = child.previousSibling()) { KoXmlElement e = child.toElement(); if (e.tagName() == "grid") { loadGrid(e); } else if (e.tagName() == "guides") { loadGuides(e); } else if (e.tagName() == "assistants") { loadAssistantsList(e); } else if (e.tagName() == "audio") { loadAudio(e, image); } } return image; } void KisKraLoader::loadBinaryData(KoStore * store, KisImageSP image, const QString & uri, bool external) { // icc profile: if present, this overrides the profile product name loaded in loadXML. QString location = external ? QString() : uri; location += m_d->imageName + ICC_PATH; if (store->hasFile(location)) { if (store->open(location)) { QByteArray data; data.resize(store->size()); bool res = (store->read(data.data(), store->size()) > -1); store->close(); if (res) { const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(image->colorSpace()->colorModelId().id(), image->colorSpace()->colorDepthId().id(), data); if (profile && profile->valid()) { res = image->assignImageProfile(profile); } if (!res) { profile = KoColorSpaceRegistry::instance()->profileByName(KoColorSpaceRegistry::instance()->colorSpaceFactory(image->colorSpace()->id())->defaultProfile()); Q_ASSERT(profile && profile->valid()); image->assignImageProfile(profile); } } } } //load the embed proofing profile, it only needs to be loaded into Krita, not assigned. location = external ? QString() : uri; location += m_d->imageName + ICC_PROOFING_PATH; if (store->hasFile(location)) { if (store->open(location)) { QByteArray proofingData; proofingData.resize(store->size()); bool proofingProfileRes = (store->read(proofingData.data(), store->size())>-1); store->close(); if (proofingProfileRes) { const KoColorProfile *proofingProfile = KoColorSpaceRegistry::instance()->createColorProfile(image->proofingConfiguration()->proofingModel, image->proofingConfiguration()->proofingDepth, proofingData); if (proofingProfile->valid()){ //if (KoColorSpaceEngineRegistry::instance()->get("icc")) { // KoColorSpaceEngineRegistry::instance()->get("icc")->addProfile(proofingProfile->fileName()); //} KoColorSpaceRegistry::instance()->addProfile(proofingProfile); } } } } // Load the layers data: if there is a profile associated with a layer it will be set now. KisKraLoadVisitor visitor(image, store, m_d->layerFilenames, m_d->keyframeFilenames, m_d->imageName, m_d->syntaxVersion); if (external) { visitor.setExternalUri(uri); } image->rootLayer()->accept(visitor); if (!visitor.errorMessages().isEmpty()) { m_d->errorMessages.append(visitor.errorMessages()); } // annotations // exif location = external ? QString() : uri; location += m_d->imageName + EXIF_PATH; if (store->hasFile(location)) { QByteArray data; store->open(location); data = store->read(store->size()); store->close(); image->addAnnotation(KisAnnotationSP(new KisAnnotation("exif", "", data))); } // layer styles location = external ? QString() : uri; location += m_d->imageName + LAYER_STYLES_PATH; if (store->hasFile(location)) { KisPSDLayerStyleCollectionResource *collection = new KisPSDLayerStyleCollectionResource("Embedded Styles.asl"); collection->setName(i18nc("Auto-generated layer style collection name for embedded styles (collection)", "<%1> (embedded)", m_d->imageName)); KIS_ASSERT_RECOVER_NOOP(!collection->valid()); store->open(location); { KoStoreDevice device(store); device.open(QIODevice::ReadOnly); /** * ASL loading code cannot work with non-sequential IO devices, * so convert the device beforehand! */ QByteArray buf = device.readAll(); QBuffer raDevice(&buf); raDevice.open(QIODevice::ReadOnly); collection->loadFromDevice(&raDevice); } store->close(); if (collection->valid()) { KoResourceServer *server = KisResourceServerProvider::instance()->layerStyleCollectionServer(); server->addResource(collection, false); collection->assignAllLayerStyles(image->root()); } else { warnKrita << "WARNING: Couldn't load layer styles library from .kra!"; delete collection; } } if (m_d->document && m_d->document->documentInfo()->aboutInfo("title").isNull()) m_d->document->documentInfo()->setAboutInfo("title", m_d->imageName); if (m_d->document && m_d->document->documentInfo()->aboutInfo("comment").isNull()) m_d->document->documentInfo()->setAboutInfo("comment", m_d->imageComment); loadAssistants(store, uri, external); } vKisNodeSP KisKraLoader::selectedNodes() const { return m_d->selectedNodes; } QList KisKraLoader::assistants() const { return m_d->assistants; } QStringList KisKraLoader::errorMessages() const { return m_d->errorMessages; } void KisKraLoader::loadAssistants(KoStore *store, const QString &uri, bool external) { QString file_path; QString location; QMap handleMap; KisPaintingAssistant* assistant = 0; QMap::const_iterator loadedAssistant = m_d->assistantsFilenames.constBegin(); while (loadedAssistant != m_d->assistantsFilenames.constEnd()){ const KisPaintingAssistantFactory* factory = KisPaintingAssistantFactoryRegistry::instance()->get(loadedAssistant.value()); if (factory) { assistant = factory->createPaintingAssistant(); location = external ? QString() : uri; location += m_d->imageName + ASSISTANTS_PATH; file_path = location + loadedAssistant.key(); assistant->loadXml(store, handleMap, file_path); //If an assistant has too few handles than it should according to it's own setup, just don't load it// if (assistant->handles().size()==assistant->numHandles()){ m_d->assistants.append(toQShared(assistant)); } } loadedAssistant++; } } void KisKraLoader::loadAnimationMetadata(const KoXmlElement &element, KisImageSP image) { QDomDocument qDom; KoXml::asQDomElement(qDom, element); QDomElement qElement = qDom.firstChildElement(); float framerate; KisTimeRange range; int currentTime; KisImageAnimationInterface *animation = image->animationInterface(); if (KisDomUtils::loadValue(qElement, "framerate", &framerate)) { animation->setFramerate(framerate); } if (KisDomUtils::loadValue(qElement, "range", &range)) { animation->setFullClipRange(range); } if (KisDomUtils::loadValue(qElement, "currentTime", ¤tTime)) { animation->switchCurrentTimeAsync(currentTime); } } KisNodeSP KisKraLoader::loadNodes(const KoXmlElement& element, KisImageSP image, KisNodeSP parent) { KoXmlNode node = element.firstChild(); KoXmlNode child; if (!node.isNull()) { if (node.isElement()) { if (node.nodeName().toUpper() == LAYERS.toUpper() || node.nodeName().toUpper() == MASKS.toUpper()) { for (child = node.lastChild(); !child.isNull(); child = child.previousSibling()) { KisNodeSP node = loadNode(child.toElement(), image, parent); if (node) { image->nextLayerName(); // Make sure the nameserver is current with the number of nodes. image->addNode(node, parent); if (node->inherits("KisLayer") && child.childNodesCount() > 0) { loadNodes(child.toElement(), image, node); } } } } } } return parent; } KisNodeSP KisKraLoader::loadNode(const KoXmlElement& element, KisImageSP image, KisNodeSP parent) { // Nota bene: If you add new properties to layers, you should // ALWAYS define a default value in case the property is not // present in the layer definition: this helps a LOT with backward // compatibility. QString name = element.attribute(NAME, "No Name"); QUuid id = QUuid(element.attribute(UUID, QUuid().toString())); qint32 x = element.attribute(X, "0").toInt(); qint32 y = element.attribute(Y, "0").toInt(); qint32 opacity = element.attribute(OPACITY, QString::number(OPACITY_OPAQUE_U8)).toInt(); if (opacity < OPACITY_TRANSPARENT_U8) opacity = OPACITY_TRANSPARENT_U8; if (opacity > OPACITY_OPAQUE_U8) opacity = OPACITY_OPAQUE_U8; const KoColorSpace* colorSpace = 0; if ((element.attribute(COLORSPACE_NAME)).isNull()) { dbgFile << "No attribute color space for layer: " << name; colorSpace = image->colorSpace(); } else { QString colorspacename = element.attribute(COLORSPACE_NAME); QString profileProductName; convertColorSpaceNames(colorspacename, profileProductName); QString colorspaceModel = KoColorSpaceRegistry::instance()->colorSpaceColorModelId(colorspacename).id(); QString colorspaceDepth = KoColorSpaceRegistry::instance()->colorSpaceColorDepthId(colorspacename).id(); dbgFile << "Searching color space: " << colorspacename << colorspaceModel << colorspaceDepth << " for layer: " << name; // use default profile - it will be replaced later in completeLoading colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, ""); dbgFile << "found colorspace" << colorSpace; if (!colorSpace) { m_d->errorMessages << i18n("Layer %1 specifies an unsupported color model: %2.", name, colorspacename); return 0; } } const bool visible = element.attribute(VISIBLE, "1") == "0" ? false : true; const bool locked = element.attribute(LOCKED, "0") == "0" ? false : true; const bool collapsed = element.attribute(COLLAPSED, "0") == "0" ? false : true; int colorLabelIndex = element.attribute(COLOR_LABEL, "0").toInt(); QVector labels = KisNodeViewColorScheme::instance()->allColorLabels(); if (colorLabelIndex >= labels.size()) { colorLabelIndex = labels.size() - 1; } // Now find out the layer type and do specific handling QString nodeType; if (m_d->syntaxVersion == 1) { nodeType = element.attribute("layertype"); if (nodeType.isEmpty()) { nodeType = PAINT_LAYER; } } else { nodeType = element.attribute(NODE_TYPE); } if (nodeType.isEmpty()) { m_d->errorMessages << i18n("Layer %1 has an unsupported type.", name); return 0; } KisNodeSP node = 0; if (nodeType == PAINT_LAYER) node = loadPaintLayer(element, image, name, colorSpace, opacity); else if (nodeType == GROUP_LAYER) node = loadGroupLayer(element, image, name, colorSpace, opacity); else if (nodeType == ADJUSTMENT_LAYER) node = loadAdjustmentLayer(element, image, name, colorSpace, opacity); else if (nodeType == SHAPE_LAYER) node = loadShapeLayer(element, image, name, colorSpace, opacity); else if (nodeType == GENERATOR_LAYER) node = loadGeneratorLayer(element, image, name, colorSpace, opacity); else if (nodeType == CLONE_LAYER) node = loadCloneLayer(element, image, name, colorSpace, opacity); else if (nodeType == FILTER_MASK) node = loadFilterMask(element, parent); else if (nodeType == TRANSFORM_MASK) node = loadTransformMask(element, parent); else if (nodeType == TRANSPARENCY_MASK) node = loadTransparencyMask(element, parent); else if (nodeType == SELECTION_MASK) node = loadSelectionMask(image, element, parent); else if (nodeType == COLORIZE_MASK) node = loadColorizeMask(image, element, parent, colorSpace); else if (nodeType == FILE_LAYER) { node = loadFileLayer(element, image, name, opacity); } else { m_d->errorMessages << i18n("Layer %1 has an unsupported type: %2.", name, nodeType); return 0; } // Loading the node went wrong. Return empty node and leave to // upstream to complain to the user if (!node) { m_d->errorMessages << i18n("Failure loading layer %1 of type: %2.", name, nodeType); return 0; } node->setVisible(visible, true); node->setUserLocked(locked); node->setCollapsed(collapsed); node->setColorLabelIndex(colorLabelIndex); node->setX(x); node->setY(y); node->setName(name); if (! id.isNull()) // if no uuid in file, new one has been generated already node->setUuid(id); if (node->inherits("KisLayer") || node->inherits("KisColorizeMask")) { QString compositeOpName = element.attribute(COMPOSITE_OP, "normal"); node->setCompositeOpId(compositeOpName); } if (node->inherits("KisLayer")) { KisLayer* layer = qobject_cast(node.data()); QBitArray channelFlags = stringToFlags(element.attribute(CHANNEL_FLAGS, ""), colorSpace->channelCount()); layer->setChannelFlags(channelFlags); if (element.hasAttribute(LAYER_STYLE_UUID)) { QString uuidString = element.attribute(LAYER_STYLE_UUID); QUuid uuid(uuidString); if (!uuid.isNull()) { KisPSDLayerStyleSP dumbLayerStyle(new KisPSDLayerStyle()); dumbLayerStyle->setUuid(uuid); layer->setLayerStyle(dumbLayerStyle); } else { warnKrita << "WARNING: Layer style for layer" << layer->name() << "contains invalid UUID" << uuidString; } } } if (node->inherits("KisGroupLayer")) { if (element.hasAttribute(PASS_THROUGH_MODE)) { bool value = element.attribute(PASS_THROUGH_MODE, "0") != "0"; KisGroupLayer *group = qobject_cast(node.data()); group->setPassThroughMode(value); } } if (node->inherits("KisPaintLayer")) { KisPaintLayer* layer = qobject_cast(node.data()); QBitArray channelLockFlags = stringToFlags(element.attribute(CHANNEL_LOCK_FLAGS, ""), colorSpace->channelCount()); layer->setChannelLockFlags(channelLockFlags); bool onionEnabled = element.attribute(ONION_SKIN_ENABLED, "0") == "0" ? false : true; layer->setOnionSkinEnabled(onionEnabled); bool timelineEnabled = element.attribute(VISIBLE_IN_TIMELINE, "0") == "0" ? false : true; layer->setUseInTimeline(timelineEnabled); } if (element.attribute(FILE_NAME).isNull()) { m_d->layerFilenames[node.data()] = name; } else { m_d->layerFilenames[node.data()] = element.attribute(FILE_NAME); } if (element.hasAttribute("selected") && element.attribute("selected") == "true") { m_d->selectedNodes.append(node); } if (element.hasAttribute(KEYFRAME_FILE)) { m_d->keyframeFilenames.insert(node.data(), element.attribute(KEYFRAME_FILE)); } return node; } KisNodeSP KisKraLoader::loadPaintLayer(const KoXmlElement& element, KisImageSP image, const QString& name, const KoColorSpace* cs, quint32 opacity) { Q_UNUSED(element); KisPaintLayer* layer; layer = new KisPaintLayer(image, name, opacity, cs); Q_CHECK_PTR(layer); // Load exif info /*TODO: write and use the legacy stuff to load that exif tag for( KoXmlNode node = element.firstChild(); !node.isNull(); node = node.nextSibling() ) { KoXmlElement e = node.toElement(); if ( !e.isNull() && e.tagName() == "ExifInfo" ) { layer->paintDevice()->exifInfo()->load(e); } }*/ // TODO load metadata return layer; } KisNodeSP KisKraLoader::loadFileLayer(const KoXmlElement& element, KisImageSP image, const QString& name, quint32 opacity) { QString filename = element.attribute("source", QString()); if (filename.isNull()) return 0; bool scale = (element.attribute("scale", "true") == "true"); int scalingMethod = element.attribute("scalingmethod", "-1").toInt(); if (scalingMethod < 0) { if (scale) { scalingMethod = KisFileLayer::ToImagePPI; } else { scalingMethod = KisFileLayer::None; } } QString documentPath; if (m_d->document) { documentPath = m_d->document->url().toLocalFile(); } QFileInfo info(documentPath); QString basePath = info.absolutePath(); QString fullPath = basePath + QDir::separator() + filename; // Entering the event loop to show the messagebox will delete the image, so up the ref by one image->ref(); if (!QFileInfo(fullPath).exists()) { qApp->setOverrideCursor(Qt::ArrowCursor); QString msg = i18nc( "@info", "The file associated to a file layer with the name \"%1\" is not found.\n\n" "Expected path:\n" "%2\n\n" "Do you want to locate it manually?", name, fullPath); int result = QMessageBox::warning(0, i18nc("@title:window", "File not found"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if (result == QMessageBox::Yes) { KoFileDialog dialog(0, KoFileDialog::OpenFile, "OpenDocument"); dialog.setMimeTypeFilters(KisImportExportManager::mimeFilter(KisImportExportManager::Import)); dialog.setDefaultDir(basePath); QString url = dialog.filename(); if (!QFileInfo(basePath).exists()) { filename = url; } else { QDir d(basePath); filename = d.relativeFilePath(url); } } qApp->restoreOverrideCursor(); } KisLayer *layer = new KisFileLayer(image, basePath, filename, (KisFileLayer::ScalingMethod)scalingMethod, name, opacity); Q_CHECK_PTR(layer); return layer; } KisNodeSP KisKraLoader::loadGroupLayer(const KoXmlElement& element, KisImageSP image, const QString& name, const KoColorSpace* cs, quint32 opacity) { Q_UNUSED(element); Q_UNUSED(cs); QString attr; KisGroupLayer* layer; layer = new KisGroupLayer(image, name, opacity); Q_CHECK_PTR(layer); return layer; } KisNodeSP KisKraLoader::loadAdjustmentLayer(const KoXmlElement& element, KisImageSP image, const QString& name, const KoColorSpace* cs, quint32 opacity) { // XXX: do something with filterversion? Q_UNUSED(cs); QString attr; KisAdjustmentLayer* layer; QString filtername; if ((filtername = element.attribute(FILTER_NAME)).isNull()) { // XXX: Invalid adjustmentlayer! We should warn about it! warnFile << "No filter in adjustment layer"; return 0; } KisFilterSP f = KisFilterRegistry::instance()->value(filtername); if (!f) { warnFile << "No filter for filtername" << filtername << ""; return 0; // XXX: We don't have this filter. We should warn about it! } - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); // We'll load the configuration and the selection later. layer = new KisAdjustmentLayer(image, name, kfc, 0); Q_CHECK_PTR(layer); layer->setOpacity(opacity); return layer; } KisNodeSP KisKraLoader::loadShapeLayer(const KoXmlElement& element, KisImageSP image, const QString& name, const KoColorSpace* cs, quint32 opacity) { Q_UNUSED(element); Q_UNUSED(cs); QString attr; KoShapeBasedDocumentBase * shapeController = 0; if (m_d->document) { shapeController = m_d->document->shapeController(); } KisShapeLayer* layer = new KisShapeLayer(shapeController, image, name, opacity); Q_CHECK_PTR(layer); return layer; } KisNodeSP KisKraLoader::loadGeneratorLayer(const KoXmlElement& element, KisImageSP image, const QString& name, const KoColorSpace* cs, quint32 opacity) { Q_UNUSED(cs); // XXX: do something with generator version? KisGeneratorLayer* layer; QString generatorname = element.attribute(GENERATOR_NAME); if (generatorname.isNull()) { // XXX: Invalid generator layer! We should warn about it! warnFile << "No generator in generator layer"; return 0; } KisGeneratorSP generator = KisGeneratorRegistry::instance()->value(generatorname); if (!generator) { warnFile << "No generator for generatorname" << generatorname << ""; return 0; // XXX: We don't have this generator. We should warn about it! } - KisFilterConfigurationSP kgc = generator->defaultConfiguration(0); + KisFilterConfigurationSP kgc = generator->defaultConfiguration(); // We'll load the configuration and the selection later. layer = new KisGeneratorLayer(image, name, kgc, 0); Q_CHECK_PTR(layer); layer->setOpacity(opacity); return layer; } KisNodeSP KisKraLoader::loadCloneLayer(const KoXmlElement& element, KisImageSP image, const QString& name, const KoColorSpace* cs, quint32 opacity) { Q_UNUSED(cs); KisCloneLayerSP layer = new KisCloneLayer(0, image, name, opacity); KisCloneInfo info; if (! (element.attribute(CLONE_FROM_UUID)).isNull()) { info = KisCloneInfo(QUuid(element.attribute(CLONE_FROM_UUID))); } else { if ((element.attribute(CLONE_FROM)).isNull()) { return 0; } else { info = KisCloneInfo(element.attribute(CLONE_FROM)); } } layer->setCopyFromInfo(info); if ((element.attribute(CLONE_TYPE)).isNull()) { return 0; } else { layer->setCopyType((CopyLayerType) element.attribute(CLONE_TYPE).toInt()); } return layer; } KisNodeSP KisKraLoader::loadFilterMask(const KoXmlElement& element, KisNodeSP parent) { Q_UNUSED(parent); QString attr; KisFilterMask* mask; QString filtername; // XXX: should we check the version? if ((filtername = element.attribute(FILTER_NAME)).isNull()) { // XXX: Invalid filter layer! We should warn about it! warnFile << "No filter in filter layer"; return 0; } KisFilterSP f = KisFilterRegistry::instance()->value(filtername); if (!f) { warnFile << "No filter for filtername" << filtername << ""; return 0; // XXX: We don't have this filter. We should warn about it! } - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); // We'll load the configuration and the selection later. mask = new KisFilterMask(); mask->setFilter(kfc); Q_CHECK_PTR(mask); return mask; } KisNodeSP KisKraLoader::loadTransformMask(const KoXmlElement& element, KisNodeSP parent) { Q_UNUSED(element); Q_UNUSED(parent); KisTransformMask* mask; /** * We'll load the transform configuration later on a stage * of binary data loading */ mask = new KisTransformMask(); Q_CHECK_PTR(mask); return mask; } KisNodeSP KisKraLoader::loadTransparencyMask(const KoXmlElement& element, KisNodeSP parent) { Q_UNUSED(element); Q_UNUSED(parent); KisTransparencyMask* mask = new KisTransparencyMask(); Q_CHECK_PTR(mask); return mask; } KisNodeSP KisKraLoader::loadSelectionMask(KisImageSP image, const KoXmlElement& element, KisNodeSP parent) { Q_UNUSED(parent); KisSelectionMaskSP mask = new KisSelectionMask(image); bool active = element.attribute(ACTIVE, "1") == "0" ? false : true; mask->setActive(active); Q_CHECK_PTR(mask); return mask; } KisNodeSP KisKraLoader::loadColorizeMask(KisImageSP image, const KoXmlElement& element, KisNodeSP parent, const KoColorSpace *colorSpace) { Q_UNUSED(parent); KisColorizeMaskSP mask = new KisColorizeMask(); bool editKeystrokes = element.attribute(COLORIZE_EDIT_KEYSTROKES, "1") == "0" ? false : true; bool showColoring = element.attribute(COLORIZE_SHOW_COLORING, "1") == "0" ? false : true; KisLayerPropertiesIcons::setNodeProperty(mask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, editKeystrokes, image); KisLayerPropertiesIcons::setNodeProperty(mask, KisLayerPropertiesIcons::colorizeShowColoring, showColoring, image); delete mask->setColorSpace(colorSpace); mask->setImage(image); return mask; } void KisKraLoader::loadCompositions(const KoXmlElement& elem, KisImageSP image) { KoXmlNode child; for (child = elem.firstChild(); !child.isNull(); child = child.nextSibling()) { KoXmlElement e = child.toElement(); QString name = e.attribute("name"); bool exportEnabled = e.attribute("exportEnabled", "1") == "0" ? false : true; KisLayerCompositionSP composition(new KisLayerComposition(image, name)); composition->setExportEnabled(exportEnabled); KoXmlNode value; for (value = child.lastChild(); !value.isNull(); value = value.previousSibling()) { KoXmlElement e = value.toElement(); QUuid uuid(e.attribute("uuid")); bool visible = e.attribute("visible", "1") == "0" ? false : true; composition->setVisible(uuid, visible); bool collapsed = e.attribute("collapsed", "1") == "0" ? false : true; composition->setCollapsed(uuid, collapsed); } image->addComposition(composition); } } void KisKraLoader::loadAssistantsList(const KoXmlElement &elem) { KoXmlNode child; int count = 0; for (child = elem.firstChild(); !child.isNull(); child = child.nextSibling()) { KoXmlElement e = child.toElement(); QString type = e.attribute("type"); QString file_name = e.attribute("filename"); m_d->assistantsFilenames.insert(file_name,type); count++; } } void KisKraLoader::loadGrid(const KoXmlElement& elem) { QDomDocument dom; KoXml::asQDomElement(dom, elem); QDomElement domElement = dom.firstChildElement(); KisGridConfig config; config.loadDynamicDataFromXml(domElement); config.loadStaticData(); m_d->document->setGridConfig(config); } void KisKraLoader::loadGuides(const KoXmlElement& elem) { QDomDocument dom; KoXml::asQDomElement(dom, elem); QDomElement domElement = dom.firstChildElement(); KisGuidesConfig guides; guides.loadFromXml(domElement); m_d->document->setGuidesConfig(guides); } void KisKraLoader::loadAudio(const KoXmlElement& elem, KisImageSP image) { QDomDocument dom; KoXml::asQDomElement(dom, elem); QDomElement qElement = dom.firstChildElement(); QString fileName; if (KisDomUtils::loadValue(qElement, "masterChannelPath", &fileName)) { fileName = QDir::toNativeSeparators(fileName); QDir baseDirectory = QFileInfo(m_d->document->localFilePath()).absoluteDir(); fileName = baseDirectory.absoluteFilePath(fileName); QFileInfo info(fileName); if (!info.exists()) { qApp->setOverrideCursor(Qt::ArrowCursor); QString msg = i18nc( "@info", "Audio channel file \"%1\" doesn't exist!\n\n" "Expected path:\n" "%2\n\n" "Do you want to locate it manually?", info.fileName(), info.absoluteFilePath()); int result = QMessageBox::warning(0, i18nc("@title:window", "File not found"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if (result == QMessageBox::Yes) { info.setFile(KisImportExportManager::askForAudioFileName(info.absolutePath(), 0)); } qApp->restoreOverrideCursor(); } if (info.exists()) { image->animationInterface()->setAudioChannelFileName(info.absoluteFilePath()); } } bool audioMuted = false; if (KisDomUtils::loadValue(qElement, "audioMuted", &audioMuted)) { image->animationInterface()->setAudioMuted(audioMuted); } qreal audioVolume = 0.5; if (KisDomUtils::loadValue(qElement, "audioVolume", &audioVolume)) { image->animationInterface()->setAudioVolume(audioVolume); } } diff --git a/plugins/impex/libkra/tests/kis_kra_saver_test.cpp b/plugins/impex/libkra/tests/kis_kra_saver_test.cpp index 8161df5bd5..9b7d2162d6 100644 --- a/plugins/impex/libkra/tests/kis_kra_saver_test.cpp +++ b/plugins/impex/libkra/tests/kis_kra_saver_test.cpp @@ -1,429 +1,429 @@ /* * Copyright (c) 2007 Boudewijn Rempt boud@valdyas.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_kra_saver_test.h" #include #include #include #include #include #include #include "filter/kis_filter_registry.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter.h" #include "KisDocument.h" #include "kis_image.h" #include "kis_pixel_selection.h" #include "kis_group_layer.h" #include "kis_paint_layer.h" #include "kis_clone_layer.h" #include "kis_adjustment_layer.h" #include "kis_shape_layer.h" #include "kis_filter_mask.h" #include "kis_transparency_mask.h" #include "kis_selection_mask.h" #include "kis_selection.h" #include "kis_fill_painter.h" #include "kis_shape_selection.h" #include "util.h" #include "testutil.h" #include "kis_keyframe_channel.h" #include "kis_image_animation_interface.h" #include "kis_layer_properties_icons.h" #include "kis_transform_mask_params_interface.h" #include #include #include void KisKraSaverTest::initTestCase() { KoResourcePaths::addResourceDir("ko_patterns", QString(SYSTEM_RESOURCES_DATA_DIR) + "/patterns"); KisFilterRegistry::instance(); KisGeneratorRegistry::instance(); } void KisKraSaverTest::testCrashyShapeLayer() { /** * KisShapeLayer used to call setImage from its destructor and * therefore causing an infinite recursion (when at least one transparency * mask was preset. This testcase just checks that. */ QScopedPointer doc(createCompleteDocument(true)); Q_UNUSED(doc); } void KisKraSaverTest::testRoundTrip() { KisDocument* doc = createCompleteDocument(); KoColor bgColor(Qt::red, doc->image()->colorSpace()); doc->image()->setDefaultProjectionColor(bgColor); doc->exportDocument(QUrl::fromLocalFile("roundtriptest.kra")); QStringList list; KisCountVisitor cv1(list, KoProperties()); doc->image()->rootLayer()->accept(cv1); KisDocument *doc2 = KisPart::instance()->createDocument(); doc2->loadNativeFormat("roundtriptest.kra"); KisCountVisitor cv2(list, KoProperties()); doc2->image()->rootLayer()->accept(cv2); QCOMPARE(cv1.count(), cv2.count()); // check whether the BG color is saved correctly QCOMPARE(doc2->image()->defaultProjectionColor(), bgColor); // test round trip of a transform mask KisNode* tnode = TestUtil::findNode(doc2->image()->rootLayer(), "testTransformMask").data(); QVERIFY(tnode); KisTransformMask *tmask = dynamic_cast(tnode); QVERIFY(tmask); KisDumbTransformMaskParams *params = dynamic_cast(tmask->transformParams().data()); QVERIFY(params); QTransform t = params->testingGetTransform(); QCOMPARE(t, createTestingTransform()); delete doc2; delete doc; } void KisKraSaverTest::testSaveEmpty() { KisDocument* doc = createEmptyDocument(); doc->exportDocument(QUrl::fromLocalFile("emptytest.kra")); QStringList list; KisCountVisitor cv1(list, KoProperties()); doc->image()->rootLayer()->accept(cv1); KisDocument *doc2 = KisPart::instance()->createDocument(); doc2->loadNativeFormat("emptytest.kra"); KisCountVisitor cv2(list, KoProperties()); doc2->image()->rootLayer()->accept(cv2); QCOMPARE(cv1.count(), cv2.count()); delete doc2; delete doc; } #include #include "generator/kis_generator_registry.h" #include void testRoundTripFillLayerImpl(const QString &testName, KisFilterConfigurationSP config) { TestUtil::ExternalImageChecker chk(testName, "fill_layer"); chk.setFuzzy(2); QScopedPointer doc(KisPart::instance()->createDocument()); // mask parent should be destructed before the document! QRect refRect(0,0,512,512); TestUtil::MaskParent p(refRect); doc->setCurrentImage(p.image); doc->documentInfo()->setAboutInfo("title", p.image->objectName()); KisSelectionSP selection; KisGeneratorLayerSP glayer = new KisGeneratorLayer(p.image, "glayer", config, selection); p.image->addNode(glayer, p.image->root(), KisNodeSP()); glayer->setDirty(); p.image->waitForDone(); chk.checkImage(p.image, "00_initial_layer_update"); doc->exportDocument(QUrl::fromLocalFile("roundtrip_fill_layer_test.kra")); QScopedPointer doc2(KisPart::instance()->createDocument()); doc2->loadNativeFormat("roundtrip_fill_layer_test.kra"); doc2->image()->waitForDone(); chk.checkImage(doc2->image(), "01_fill_layer_round_trip"); QVERIFY(chk.testPassed()); } void KisKraSaverTest::testRoundTripFillLayerColor() { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisGeneratorSP generator = KisGeneratorRegistry::instance()->get("color"); Q_ASSERT(generator); // warning: we pass null paint device to the default constructed value - KisFilterConfigurationSP config = generator->factoryConfiguration(0); + KisFilterConfigurationSP config = generator->factoryConfiguration(); Q_ASSERT(config); QVariant v; v.setValue(KoColor(Qt::red, cs)); config->setProperty("color", v); testRoundTripFillLayerImpl("fill_layer_color", config); } void KisKraSaverTest::testRoundTripFillLayerPattern() { KisGeneratorSP generator = KisGeneratorRegistry::instance()->get("pattern"); QVERIFY(generator); // warning: we pass null paint device to the default constructed value - KisFilterConfigurationSP config = generator->factoryConfiguration(0); + KisFilterConfigurationSP config = generator->factoryConfiguration(); QVERIFY(config); QVariant v; v.setValue(QString("11_drawed_furry.png")); config->setProperty("pattern", v); testRoundTripFillLayerImpl("fill_layer_pattern", config); } #include "kis_psd_layer_style.h" void KisKraSaverTest::testRoundTripLayerStyles() { TestUtil::ExternalImageChecker chk("kra_saver_test", "layer_styles"); QRect imageRect(0,0,512,512); // the document should be created before the image! QScopedPointer doc(KisPart::instance()->createDocument()); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(new KisSurrogateUndoStore(), imageRect.width(), imageRect.height(), cs, "test image"); KisPaintLayerSP layer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisPaintLayerSP layer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisPaintLayerSP layer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); image->addNode(layer1); image->addNode(layer2); image->addNode(layer3); doc->setCurrentImage(image); doc->documentInfo()->setAboutInfo("title", image->objectName()); layer1->paintDevice()->fill(QRect(100, 100, 100, 100), KoColor(Qt::red, cs)); layer2->paintDevice()->fill(QRect(200, 200, 100, 100), KoColor(Qt::green, cs)); layer3->paintDevice()->fill(QRect(300, 300, 100, 100), KoColor(Qt::blue, cs)); KisPSDLayerStyleSP style(new KisPSDLayerStyle()); style->dropShadow()->setEffectEnabled(true); style->dropShadow()->setAngle(-90); style->dropShadow()->setUseGlobalLight(false); layer1->setLayerStyle(style->clone()); style->dropShadow()->setAngle(180); style->dropShadow()->setUseGlobalLight(true); layer2->setLayerStyle(style->clone()); style->dropShadow()->setAngle(90); style->dropShadow()->setUseGlobalLight(false); layer3->setLayerStyle(style->clone()); image->initialRefreshGraph(); chk.checkImage(image, "00_initial_layers"); doc->exportDocument(QUrl::fromLocalFile("roundtrip_layer_styles.kra")); QScopedPointer doc2(KisPart::instance()->createDocument()); doc2->loadNativeFormat("roundtrip_layer_styles.kra"); doc2->image()->waitForDone(); chk.checkImage(doc2->image(), "00_initial_layers"); QVERIFY(chk.testPassed()); } void KisKraSaverTest::testRoundTripAnimation() { QScopedPointer doc(KisPart::instance()->createDocument()); QRect imageRect(0,0,512,512); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(new KisSurrogateUndoStore(), imageRect.width(), imageRect.height(), cs, "test image"); KisPaintLayerSP layer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); image->addNode(layer1); layer1->paintDevice()->fill(QRect(100, 100, 50, 50), KoColor(Qt::black, cs)); layer1->paintDevice()->setDefaultPixel(KoColor(Qt::red, cs)); KUndo2Command parentCommand; layer1->enableAnimation(); KisKeyframeChannel *rasterChannel = layer1->getKeyframeChannel(KisKeyframeChannel::Content.id(), true); QVERIFY(rasterChannel); rasterChannel->addKeyframe(10, &parentCommand); image->animationInterface()->switchCurrentTimeAsync(10); image->waitForDone(); layer1->paintDevice()->fill(QRect(200, 50, 10, 10), KoColor(Qt::black, cs)); layer1->paintDevice()->moveTo(25, 15); layer1->paintDevice()->setDefaultPixel(KoColor(Qt::green, cs)); rasterChannel->addKeyframe(20, &parentCommand); image->animationInterface()->switchCurrentTimeAsync(20); image->waitForDone(); layer1->paintDevice()->fill(QRect(150, 200, 30, 30), KoColor(Qt::black, cs)); layer1->paintDevice()->moveTo(100, 50); layer1->paintDevice()->setDefaultPixel(KoColor(Qt::blue, cs)); QVERIFY(!layer1->useInTimeline()); layer1->setUseInTimeline(true); doc->setCurrentImage(image); doc->exportDocument(QUrl::fromLocalFile("roundtrip_animation.kra")); QScopedPointer doc2(KisPart::instance()->createDocument()); doc2->loadNativeFormat("roundtrip_animation.kra"); KisImageSP image2 = doc2->image(); KisNodeSP node = image2->root()->firstChild(); QVERIFY(node->inherits("KisPaintLayer")); KisPaintLayerSP layer2 = qobject_cast(node.data()); cs = layer2->paintDevice()->colorSpace(); QCOMPARE(image2->animationInterface()->currentTime(), 20); KisKeyframeChannel *channel = layer2->getKeyframeChannel(KisKeyframeChannel::Content.id()); QVERIFY(channel); QCOMPARE(channel->keyframeCount(), 3); image2->animationInterface()->switchCurrentTimeAsync(0); image2->waitForDone(); QCOMPARE(layer2->paintDevice()->nonDefaultPixelArea(), QRect(64, 64, 128, 128)); QCOMPARE(layer2->paintDevice()->x(), 0); QCOMPARE(layer2->paintDevice()->y(), 0); QCOMPARE(layer2->paintDevice()->defaultPixel(), KoColor(Qt::red, cs)); image2->animationInterface()->switchCurrentTimeAsync(10); image2->waitForDone(); QCOMPARE(layer2->paintDevice()->nonDefaultPixelArea(), QRect(217, 15, 64, 64)); QCOMPARE(layer2->paintDevice()->x(), 25); QCOMPARE(layer2->paintDevice()->y(), 15); QCOMPARE(layer2->paintDevice()->defaultPixel(), KoColor(Qt::green, cs)); image2->animationInterface()->switchCurrentTimeAsync(20); image2->waitForDone(); QCOMPARE(layer2->paintDevice()->nonDefaultPixelArea(), QRect(228, 242, 64, 64)); QCOMPARE(layer2->paintDevice()->x(), 100); QCOMPARE(layer2->paintDevice()->y(), 50); QCOMPARE(layer2->paintDevice()->defaultPixel(), KoColor(Qt::blue, cs)); QVERIFY(layer2->useInTimeline()); } #include "lazybrush/kis_lazy_fill_tools.h" void KisKraSaverTest::testRoundTripColorizeMask() { QRect imageRect(0,0,512,512); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); const KoColorSpace * weirdCS = KoColorSpaceRegistry::instance()->rgb16(); QScopedPointer doc(KisPart::instance()->createDocument()); KisImageSP image = new KisImage(new KisSurrogateUndoStore(), imageRect.width(), imageRect.height(), cs, "test image"); doc->setCurrentImage(image); KisPaintLayerSP layer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, weirdCS); image->addNode(layer1); KisColorizeMaskSP mask = new KisColorizeMask(); image->addNode(mask, layer1); mask->initializeCompositeOp(); delete mask->setColorSpace(layer1->colorSpace()); { KisPaintDeviceSP key1 = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8()); key1->fill(QRect(50,50,10,20), KoColor(Qt::black, key1->colorSpace())); mask->testingAddKeyStroke(key1, KoColor(Qt::green, layer1->colorSpace())); // KIS_DUMP_DEVICE_2(key1, refRect, "key1", "dd"); } { KisPaintDeviceSP key2 = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8()); key2->fill(QRect(150,50,10,20), KoColor(Qt::black, key2->colorSpace())); mask->testingAddKeyStroke(key2, KoColor(Qt::red, layer1->colorSpace())); // KIS_DUMP_DEVICE_2(key2, refRect, "key2", "dd"); } { KisPaintDeviceSP key3 = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8()); key3->fill(QRect(0,0,10,10), KoColor(Qt::black, key3->colorSpace())); mask->testingAddKeyStroke(key3, KoColor(Qt::blue, layer1->colorSpace()), true); // KIS_DUMP_DEVICE_2(key3, refRect, "key3", "dd"); } KisLayerPropertiesIcons::setNodeProperty(mask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, false, image); KisLayerPropertiesIcons::setNodeProperty(mask, KisLayerPropertiesIcons::colorizeShowColoring, false, image); doc->exportDocument(QUrl::fromLocalFile("roundtrip_colorize.kra")); QScopedPointer doc2(KisPart::instance()->createDocument()); doc2->loadNativeFormat("roundtrip_colorize.kra"); KisImageSP image2 = doc2->image(); KisNodeSP node = image2->root()->firstChild()->firstChild(); KisColorizeMaskSP mask2 = dynamic_cast(node.data()); QVERIFY(mask2); QCOMPARE(mask2->compositeOpId(), mask->compositeOpId()); QCOMPARE(mask2->colorSpace(), mask->colorSpace()); QCOMPARE(KisLayerPropertiesIcons::nodeProperty(mask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, true).toBool(), false); QCOMPARE(KisLayerPropertiesIcons::nodeProperty(mask, KisLayerPropertiesIcons::colorizeShowColoring, true).toBool(), false); QList strokes = mask->fetchKeyStrokesDirect(); qDebug() << ppVar(strokes.size()); QCOMPARE(strokes[0].dev->exactBounds(), QRect(50,50,10,20)); QCOMPARE(strokes[0].isTransparent, false); QCOMPARE(strokes[0].color.colorSpace(), weirdCS); QCOMPARE(strokes[1].dev->exactBounds(), QRect(150,50,10,20)); QCOMPARE(strokes[1].isTransparent, false); QCOMPARE(strokes[1].color.colorSpace(), weirdCS); QCOMPARE(strokes[2].dev->exactBounds(), QRect(0,0,10,10)); QCOMPARE(strokes[2].isTransparent, true); QCOMPARE(strokes[2].color.colorSpace(), weirdCS); } QTEST_MAIN(KisKraSaverTest) diff --git a/plugins/impex/ora/kis_open_raster_stack_load_visitor.cpp b/plugins/impex/ora/kis_open_raster_stack_load_visitor.cpp index 7e193fc645..f572197dba 100644 --- a/plugins/impex/ora/kis_open_raster_stack_load_visitor.cpp +++ b/plugins/impex/ora/kis_open_raster_stack_load_visitor.cpp @@ -1,254 +1,254 @@ /* * Copyright (c) 2006-2007,2009 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_open_raster_stack_load_visitor.h" #include #include #include // Includes from krita/image #include #include #include #include #include #include #include #include #include #include #include #include "KisDocument.h" #include "kis_open_raster_load_context.h" struct KisOpenRasterStackLoadVisitor::Private { KisImageSP image; vKisNodeSP activeNodes; KisUndoStore* undoStore; KisOpenRasterLoadContext* loadContext; double xRes; double yRes; }; KisOpenRasterStackLoadVisitor::KisOpenRasterStackLoadVisitor(KisUndoStore* undoStore, KisOpenRasterLoadContext* orlc) : d(new Private) { d->undoStore = undoStore; d->loadContext = orlc; } KisOpenRasterStackLoadVisitor::~KisOpenRasterStackLoadVisitor() { delete d; } KisImageSP KisOpenRasterStackLoadVisitor::image() { return d->image; } vKisNodeSP KisOpenRasterStackLoadVisitor::activeNodes() { return d->activeNodes; } void KisOpenRasterStackLoadVisitor::loadImage() { QDomDocument doc = d->loadContext->loadStack(); for (QDomNode node = doc.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isElement() && node.nodeName() == "image") { // it's the image root QDomElement subelem = node.toElement(); int width = 0; if (!subelem.attribute("w").isNull()) { width = subelem.attribute("w").toInt(); } int height = 0; if (!subelem.attribute("h").isNull()) { height = subelem.attribute("h").toInt(); } d->xRes = 75.0/72; // Setting the default value of the X Resolution = 75ppi if (!subelem.attribute("xres").isNull()){ d->xRes = (KisDomUtils::toDouble(subelem.attribute("xres")) / 72); } d->yRes = 75.0/72; if (!subelem.attribute("yres").isNull()){ d->yRes = (KisDomUtils::toDouble(subelem.attribute("yres")) / 72); } dbgFile << ppVar(width) << ppVar(height); d->image = new KisImage(d->undoStore, width, height, KoColorSpaceRegistry::instance()->rgb8(), "OpenRaster Image (name)"); for (QDomNode node2 = node.firstChild(); !node2.isNull(); node2 = node2.nextSibling()) { if (node2.isElement() && node2.nodeName() == "stack") { // it's the root layer ! QDomElement subelem2 = node2.toElement(); loadGroupLayer(subelem2, d->image->rootLayer()); break; } } } } } void KisOpenRasterStackLoadVisitor::loadLayerInfo(const QDomElement& elem, KisLayerSP layer) { layer->setName(elem.attribute("name")); layer->setX(elem.attribute("x").toInt()); layer->setY(elem.attribute("y").toInt()); if (elem.attribute("visibility") == "hidden") { layer->setVisible(false); } else { layer->setVisible(true); } if (elem.hasAttribute("edit-locked")) { layer->setUserLocked(elem.attribute("edit-locked") == "true"); } if (elem.hasAttribute("selected") && elem.attribute("selected") == "true") { d->activeNodes.append(layer); } QString compop = elem.attribute("composite-op"); if (compop.startsWith("svg:")) { //we don't have a 'composite op clear' despite the registery reserving a string for it, doesn't matter, ora doesn't use it. //if (compop == "svg:clear") layer->setCompositeOpId(COMPOSITE_CLEAR); if (compop == "svg:src-over") layer->setCompositeOpId(COMPOSITE_OVER); //not part of the spec. //if (compop == "svg:dst-over") layer->setCompositeOpId(COMPOSITE_BEHIND); //dst-in "The source that overlaps the destination, replaces the destination." if (compop == "svg:dst-in") layer->setCompositeOpId(COMPOSITE_DESTINATION_IN); //dst-out "dst is placed, where it falls outside of the source." if (compop == "svg:dst-out") layer->setCompositeOpId(COMPOSITE_ERASE); //src-atop "Destination which overlaps the source replaces the source. Source is placed elsewhere." //this is basically our alpha-inherit. if (compop == "svg:src-atop") layer->disableAlphaChannel(true); //dst-atop if (compop == "svg:dst-atop") layer->setCompositeOpId(COMPOSITE_DESTINATION_ATOP); //plus is svg standard's way of saying addtion... photoshop calls this linear dodge, btw, maybe make a similar alias? if (compop == "svg:plus") layer->setCompositeOpId(COMPOSITE_ADD); if (compop == "svg:multiply") layer->setCompositeOpId(COMPOSITE_MULT); if (compop == "svg:screen") layer->setCompositeOpId(COMPOSITE_SCREEN); if (compop == "svg:overlay") layer->setCompositeOpId(COMPOSITE_OVERLAY); if (compop == "svg:darken") layer->setCompositeOpId(COMPOSITE_DARKEN); if (compop == "svg:lighten") layer->setCompositeOpId(COMPOSITE_LIGHTEN); if (compop == "svg:color-dodge") layer->setCompositeOpId(COMPOSITE_DODGE); if (compop == "svg:color-burn") layer->setCompositeOpId(COMPOSITE_BURN); if (compop == "svg:hard-light") layer->setCompositeOpId(COMPOSITE_HARD_LIGHT); if (compop == "svg:soft-light") layer->setCompositeOpId(COMPOSITE_SOFT_LIGHT_SVG); if (compop == "svg:difference") layer->setCompositeOpId(COMPOSITE_DIFF); if (compop == "svg:color") layer->setCompositeOpId(COMPOSITE_COLOR); if (compop == "svg:luminosity") layer->setCompositeOpId(COMPOSITE_LUMINIZE); if (compop == "svg:hue") layer->setCompositeOpId(COMPOSITE_HUE); if (compop == "svg:saturation") layer->setCompositeOpId(COMPOSITE_SATURATION); //Exclusion isn't in the official list. //if (compop == "svg:exclusion") layer->setCompositeOpId(COMPOSITE_EXCLUSION); } else if (compop.startsWith("krita:")) { compop = compop.remove(0, 6); layer->setCompositeOpId(compop); } else { // to fix old bugs in krita's ora export if (compop == "color-dodge") layer->setCompositeOpId(COMPOSITE_DODGE); if (compop == "difference") layer->setCompositeOpId(COMPOSITE_DIFF); if (compop == "svg:add") layer->setCompositeOpId(COMPOSITE_ADD); } } void KisOpenRasterStackLoadVisitor::loadAdjustmentLayer(const QDomElement& elem, KisAdjustmentLayerSP aL) { loadLayerInfo(elem, aL); } void KisOpenRasterStackLoadVisitor::loadPaintLayer(const QDomElement& elem, KisPaintLayerSP pL) { loadLayerInfo(elem, pL); dbgFile << "Loading was unsuccessful"; } void KisOpenRasterStackLoadVisitor::loadGroupLayer(const QDomElement& elem, KisGroupLayerSP gL) { dbgFile << "Loading group layer"; loadLayerInfo(elem, gL); for (QDomNode node = elem.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isElement()) { QDomElement subelem = node.toElement(); if (node.nodeName() == "stack") { double opacity = 1.0; if (!subelem.attribute("opacity").isNull()) { opacity = KisDomUtils::toDouble(subelem.attribute("opacity", "1.0")); } KisGroupLayerSP layer = new KisGroupLayer(d->image, "", opacity * 255); bool passThrough = true; if (subelem.attribute("isolation")=="isolate") { passThrough = false; } layer->setPassThroughMode(passThrough); d->image->addNode(layer.data(), gL.data(), 0); loadGroupLayer(subelem, layer); } else if (node.nodeName() == "layer") { QString filename = subelem.attribute("src"); if (!filename.isNull()) { double opacity = 1.0; opacity = KisDomUtils::toDouble(subelem.attribute("opacity", "1.0")); KisImageSP pngImage = d->loadContext->loadDeviceData(filename); if (pngImage) { // If ORA doesn't have resolution info, load the default value(75 ppi) else fetch from stack.xml d->image->setResolution(d->xRes, d->yRes); // now get the device KisPaintDeviceSP device = pngImage->projection(); delete pngImage.data(); KisPaintLayerSP layer = new KisPaintLayer(gL->image() , "", opacity * 255, device); d->image->addNode(layer.data(), gL.data(), 0); loadPaintLayer(subelem, layer); dbgFile << "Loading was successful"; } } } else if (node.nodeName() == "filter") { QString filterType = subelem.attribute("type"); QStringList filterTypeSplit = filterType.split(':'); KisFilterSP f = 0; if (filterTypeSplit[0] == "applications" && filterTypeSplit[1] == "krita") { f = KisFilterRegistry::instance()->value(filterTypeSplit[2]); } - KisFilterConfigurationSP kfc = f->defaultConfiguration(0); + KisFilterConfigurationSP kfc = f->defaultConfiguration(); KisAdjustmentLayerSP layer = new KisAdjustmentLayer(gL->image() , "", kfc, KisSelectionSP(0)); d->image->addNode(layer.data(), gL.data(), 0); loadAdjustmentLayer(subelem, layer); } else { dbgFile << "Unknown element : " << node.nodeName(); } } } } diff --git a/plugins/impex/psd/psd_export.cc b/plugins/impex/psd/psd_export.cc index 62041cdab1..045b33c97d 100644 --- a/plugins/impex/psd/psd_export.cc +++ b/plugins/impex/psd/psd_export.cc @@ -1,97 +1,98 @@ /* * Copyright (c) 2009 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "psd_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "psd_saver.h" class KisExternalLayer; K_PLUGIN_FACTORY_WITH_JSON(ExportFactory, "krita_psd_export.json", registerPlugin();) psdExport::psdExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } psdExport::~psdExport() { } KisImportExportFilter::ConversionStatus psdExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) { PSDSaver psdSaver(document); KisImageBuilder_Result res; if ((res = psdSaver.buildFile(io)) == KisImageBuilder_RESULT_OK) { dbgFile <<"success !"; return KisImportExportFilter::OK; } dbgFile <<" Result =" << res; return KisImportExportFilter::InternalError; } void psdExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("PSDLayerStyleCheck")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("NodeTypeCheck/KisGroupLayer")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("MultiLayerCheck")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("sRGBProfileCheck")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("MultiLayerCheck")->create(KisExportCheckBase::SUPPORTED)); + addCapability(KisExportCheckRegistry::instance()->get("KisTransparencyMask")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("ColorModelHomogenousCheck")->create(KisExportCheckBase::UNSUPPORTED, i18nc("image conversion warning", "Your image contains one or more layers with a color model that is different from the image."))); ImageSizeCheckFactory *factory = dynamic_cast(KisExportCheckRegistry::instance()->get("ImageSizeCheck")); if (factory) { addCapability(factory->create(30000, 30000, KisExportCheckBase::SUPPORTED)); } QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID) << QPair(RGBAColorModelID, Integer16BitsColorDepthID) << QPair(RGBAColorModelID, Float16BitsColorDepthID) << QPair(RGBAColorModelID, Float32BitsColorDepthID) << QPair(GrayAColorModelID, Integer8BitsColorDepthID) << QPair(GrayAColorModelID, Integer16BitsColorDepthID) << QPair(CMYKAColorModelID, Integer8BitsColorDepthID) << QPair(CMYKAColorModelID, Integer16BitsColorDepthID) << QPair(LABAColorModelID, Integer8BitsColorDepthID) << QPair(LABAColorModelID, Integer16BitsColorDepthID); addSupportedColorModels(supportedColorModels, "PSD"); } #include diff --git a/plugins/paintops/filterop/kis_filterop_settings.cpp b/plugins/paintops/filterop/kis_filterop_settings.cpp index 876aa8b498..13aeef995e 100644 --- a/plugins/paintops/filterop/kis_filterop_settings.cpp +++ b/plugins/paintops/filterop/kis_filterop_settings.cpp @@ -1,88 +1,88 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004-2008 Boudewijn Rempt * Copyright (c) 2004 Clarence Dang * Copyright (c) 2004 Adrian Page * Copyright (c) 2004 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_filterop_settings.h" #include #include #include #include #include #include #include #include #include KisFilterOpSettings::KisFilterOpSettings() { setPropertyNotSaved(FILTER_CONFIGURATION); } KisFilterOpSettings::~KisFilterOpSettings() { } bool KisFilterOpSettings::paintIncremental() { return true; // We always paint on the existing data } KisFilterConfigurationSP KisFilterOpSettings::filterConfig() const { if (hasProperty(FILTER_ID)) { KisFilterSP filter = KisFilterRegistry::instance()->get(getString(FILTER_ID)); if (filter) { - KisFilterConfigurationSP configuration = filter->factoryConfiguration(0); + KisFilterConfigurationSP configuration = filter->factoryConfiguration(); configuration->fromXML(getString(FILTER_CONFIGURATION)); return configuration; } } return 0; } void KisFilterOpSettings::toXML(QDomDocument& doc, QDomElement& root) const { KisPaintOpSettings::toXML(doc, root); KisFilterConfigurationSP configuration = filterConfig(); if (configuration) { QDomElement e = doc.createElement("filterconfig"); configuration->toXML(doc, e); root.appendChild(e); } } void KisFilterOpSettings::fromXML(const QDomElement& e) { KisPaintOpSettings::fromXML(e); QDomElement element = e.firstChildElement("filterconfig"); if (hasProperty(FILTER_ID)) { KisFilterSP filter = KisFilterRegistry::instance()->get(getString(FILTER_ID)); if (filter) { - KisFilterConfigurationSP configuration = filter->factoryConfiguration(0); + KisFilterConfigurationSP configuration = filter->factoryConfiguration(); configuration->fromXML(element); setProperty(FILTER_CONFIGURATION, configuration->toXML()); } } } diff --git a/sdk/tests/qimage_based_test.h b/sdk/tests/qimage_based_test.h index 19d5b660b0..ad666d2175 100644 --- a/sdk/tests/qimage_based_test.h +++ b/sdk/tests/qimage_based_test.h @@ -1,316 +1,316 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __QIMAGE_BASED_TEST_H #define __QIMAGE_BASED_TEST_H #include "testutil.h" #include #include #include #include #include #include "KisDocument.h" #include "kis_shape_layer.h" #include "kis_undo_stores.h" #include "kis_image.h" #include "kis_selection.h" #include "kis_paint_layer.h" #include "kis_adjustment_layer.h" #include "kis_transparency_mask.h" #include "kis_clone_layer.h" #include "filter/kis_filter.h" #include "filter/kis_filter_registry.h" #include "commands/kis_selection_commands.h" namespace TestUtil { class QImageBasedTest { public: QImageBasedTest(const QString &directoryName) : m_directoryName(directoryName) { } // you need to declare your own test function // See KisProcessingTest for example protected: /** * Creates a complex image connected to a surrogate undo store */ KisImageSP createImage(KisSurrogateUndoStore *undoStore) { QImage sourceImage(fetchDataFileLazy("hakonepa.png")); QRect imageRect = QRect(QPoint(0,0), sourceImage.size()); QRect transpRect(50,50,300,300); QRect blurRect(66,66,300,300); QPoint blurShift(34,34); QPoint cloneShift(75,75); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(undoStore, imageRect.width(), imageRect.height(), cs, "merge test"); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); - KisFilterConfigurationSP configuration = filter->defaultConfiguration(0); + KisFilterConfigurationSP configuration = filter->defaultConfiguration(); Q_ASSERT(configuration); KisAdjustmentLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration, 0); blur1->internalSelection()->clear(); blur1->internalSelection()->pixelSelection()->select(blurRect); blur1->setX(blurShift.x()); blur1->setY(blurShift.y()); KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); paintLayer1->paintDevice()->convertFromQImage(sourceImage, 0, 0, 0); KisCloneLayerSP cloneLayer1 = new KisCloneLayer(paintLayer1, image, "clone1", OPACITY_OPAQUE_U8); cloneLayer1->setX(cloneShift.x()); cloneLayer1->setY(cloneShift.y()); image->addNode(cloneLayer1); image->addNode(blur1); image->addNode(paintLayer1); KisTransparencyMaskSP transparencyMask1 = new KisTransparencyMask(); transparencyMask1->setName("tmask1"); transparencyMask1->testingInitSelection(transpRect, paintLayer1); image->addNode(transparencyMask1, paintLayer1); return image; } /** * Creates a simple image with one empty layer and connects it to * a surrogate undo store */ KisImageSP createTrivialImage(KisSurrogateUndoStore *undoStore) { QRect imageRect = QRect(0, 0, 640, 441); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(undoStore, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); image->addNode(paintLayer1); return image; } void addGlobalSelection(KisImageSP image) { QRect selectionRect(40,40,300,300); KisSelectionSP selection = new KisSelection(new KisSelectionDefaultBounds(0, image)); KisPixelSelectionSP pixelSelection = selection->pixelSelection(); pixelSelection->select(selectionRect); KUndo2Command *cmd = new KisSetGlobalSelectionCommand(image, selection); image->undoAdapter()->addCommand(cmd); } void addShapeLayer(KisDocument *doc, KisImageSP image) { KisShapeLayerSP shapeLayer = new KisShapeLayer(doc->shapeController(), image.data(), "shape", OPACITY_OPAQUE_U8); image->addNode(shapeLayer); KoShapeFactoryBase *f1 = KoShapeRegistry::instance()->get("StarShape"); KoShapeFactoryBase *f2 = KoShapeRegistry::instance()->get("RectangleShape"); KoShape *shape1 = f1->createDefaultShape(); KoShape *shape2 = f2->createDefaultShape(); shape1->setPosition(QPointF(100,100)); shape2->setPosition(QPointF(200,200)); shapeLayer->addShape(shape1); shapeLayer->addShape(shape2); QApplication::processEvents(); } bool checkLayersInitial(KisImageWSP image, int baseFuzzyness = 0) { QString prefix = "initial_with_selection"; QString prefix2 = findNode(image->root(), "shape") ? "_with_shape" : ""; return checkLayers(image, prefix + prefix2, baseFuzzyness); } bool checkLayersInitialRootOnly(KisImageWSP image, int baseFuzzyness = 0) { QString prefix = "initial_with_selection"; QString prefix2 = findNode(image->root(), "shape") ? "_with_shape" : ""; return checkLayers(image, prefix + prefix2, baseFuzzyness, false); } /** * Checks the content of image's layers against the set of * QImages stored in @p prefix subfolder */ bool checkLayers(KisImageWSP image, const QString &prefix, int baseFuzzyness = 0, bool recursive = true) { QVector images; QVector names; fillNamesImages(image->root(), image->bounds(), images, names, recursive); bool valid = true; const int stackSize = images.size(); for(int i = 0; i < stackSize; i++) { if(!checkOneQImage(images[i], prefix, names[i], baseFuzzyness)) { valid = false; } } return valid; } /** * Checks the content of one image's layer against the QImage * stored in @p prefix subfolder */ bool checkOneLayer(KisImageWSP image, KisNodeSP node, const QString &prefix, int baseFuzzyness = 0) { QVector images; QVector names; fillNamesImages(node, image->bounds(), images, names); return checkOneQImage(images.first(), prefix, names.first(), baseFuzzyness); } // add default bounds param bool checkOneDevice(KisPaintDeviceSP device, const QString &prefix, const QString &name, int baseFuzzyness = 0) { QImage image = device->convertToQImage(0); return checkOneQImage(image, prefix, name, baseFuzzyness); } KisNodeSP findNode(KisNodeSP root, const QString &name) { return TestUtil::findNode(root, name); } private: bool checkOneQImage(const QImage &image, const QString &prefix, const QString &name, int baseFuzzyness) { QString realName = prefix + "_" + name + ".png"; QString expectedName = prefix + "_" + name + "_expected.png"; bool valid = true; QString fullPath = fetchDataFileLazy(m_directoryName + QDir::separator() + prefix + QDir::separator() + realName); if (fullPath.isEmpty()) { // Try without the testname subdirectory fullPath = fetchDataFileLazy(prefix + QDir::separator() + realName); } if (fullPath.isEmpty()) { // Try without the prefix subdirectory fullPath = fetchDataFileLazy(m_directoryName + QDir::separator() + realName); } QImage ref(fullPath); QPoint temp; int fuzzy = baseFuzzyness; { QStringList terms = name.split('_'); if(terms[0] == "root" || terms[0] == "blur1" || terms[0] == "shape") { fuzzy++; } } if(ref != image && !TestUtil::compareQImages(temp, ref, image, fuzzy)) { dbgKrita << "--- Wrong image:" << realName; valid = false; image.save(QString(FILES_OUTPUT_DIR) + QDir::separator() + realName); ref.save(QString(FILES_OUTPUT_DIR) + QDir::separator() + expectedName); } return valid; } void fillNamesImages(KisNodeSP node, const QRect &rc, QVector &images, QVector &names, bool recursive = true) { while (node) { if(node->paintDevice()) { names.append(node->name() + "_paintDevice"); images.append(node->paintDevice()-> convertToQImage(0, rc.x(), rc.y(), rc.width(), rc.height())); } if(node->original() && node->original() != node->paintDevice()) { names.append(node->name() + "_original"); images.append(node->original()-> convertToQImage(0, rc.x(), rc.y(), rc.width(), rc.height())); } if(node->projection() && node->projection() != node->paintDevice()) { names.append(node->name() + "_projection"); images.append(node->projection()-> convertToQImage(0, rc.x(), rc.y(), rc.width(), rc.height())); } if (recursive) { fillNamesImages(node->firstChild(), rc, images, names); } node = node->nextSibling(); } } private: QString m_directoryName; }; } #endif /* __QIMAGE_BASED_TEST_H */