From 7fd699955bd443f7e49e71add10f1f0858698588 Mon Sep 17 00:00:00 2001 From: Hombre Date: Mon, 23 Jan 2017 21:04:04 +0100 Subject: [PATCH 01/42] Syntax correction in French strings --- rtdata/languages/Francais | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index e45cee225..a777a07ad 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -36,7 +36,7 @@ CURVEEDITOR_TYPE;Type: DIRBROWSER_FOLDERS;Répertoires EDITWINDOW_TITLE;Édition d'image EDIT_OBJECT_TOOLTIP;Affiche des éléments dans la fenêtre de prévisualisation qui vous permettront d'ajuster cet outil. -EDIT_PIPETTE_TOOLTIP;Pour ajouter un point d'ajustement de la courbe, maintenez la touche Ctrl préssée et cliquez dans l'image avec le bouton gauche.\nPour ajuster le point, pressez la touche Ctrl lors du clic-gauche sur la zone correspondande dans l'apperçu, puis relachez Ctrl (sauf si vous désirez un control plus fin) et tout en gardant le bouton gauche appuyé, déplacez le curseur vers le haut ou le bas pour ajuster la position du point. +EDIT_PIPETTE_TOOLTIP;Pour ajouter un point d'ajustement de la courbe, maintenez la touche Ctrl pressée et cliquez dans l'image avec le bouton gauche.\nPour ajuster le point, pressez la touche Ctrl lors du clic-gauche sur la zone correspondante dans l'aperçu, puis relachez Ctrl (sauf si vous désirez un contrôle plus fin) et tout en gardant le bouton gauche appuyé, déplacez le curseur vers le haut ou le bas pour ajuster la position du point. EXIFFILTER_APERTURE;Ouverture EXIFFILTER_CAMERA;Appareil photo EXIFFILTER_EXPOSURECOMPENSATION;Compensation d'exposition (EV) @@ -79,7 +79,7 @@ EXPORT_BYPASS_SHARPENING;Ignorer la netteté EXPORT_BYPASS_SHARPENMICRO;Ignorer netteté des microcontrastes EXPORT_BYPASS_SH_HQ;Ignorer Ombres/Hautes lumières (HQ) EXPORT_FASTEXPORTOPTIONS;Options d'Export Rapide -EXPORT_INSTRUCTIONS;Les options d'Export Rapide permettent de forcer des paramètres afin d'éviter d'utiliser des outils très consommateur de temps et de ressources, et d'utiliser ces options dans la file de traitement. Cette méthode est recommandée pour la génération rapide d'images de basse résolution quand la vitesse est une priorité ou lorsqu'on désir une version redimensionnée d'une ou plusieurs images de sortie sans avoir à modifier leurs paramètres de développement. +EXPORT_INSTRUCTIONS;Les options d'Export Rapide permettent de forcer des paramètres afin d'éviter d'utiliser des outils très consommateurs de temps et de ressources, et d'utiliser ces options dans la file de traitement. Cette méthode est recommandée pour la génération rapide d'images de basse résolution quand la vitesse est une priorité ou lorsqu'on désire une version redimensionnée d'une ou plusieurs images de sortie sans avoir à modifier leurs paramètres de développement. EXPORT_MAXHEIGHT;Hauteur maximum: EXPORT_MAXWIDTH;Largeur maximum: EXPORT_PUTTOQUEUEFAST;Mettre dans la file de traitement\npour Export Rapide From e5c00f0a9d18ea9741f1ba4963178fc4adce9bc2 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 25 Jan 2017 00:18:52 +0100 Subject: [PATCH 02/42] Complete revision to how RawTherapee's version is handled in CMake and in other files, #3628 --- AboutThisBuild.cmake | 67 +++++++++++++---- AboutThisBuild.txt.in | 6 +- CMakeLists.txt | 1 - rtdata/CMakeLists.txt | 54 +++++--------- rtengine/imageio.cc | 2 +- rtengine/procparams.cc | 2 +- rtexif/rtexif.cc | 4 +- rtgui/cacheimagedata.cc | 2 +- rtgui/main.cc | 6 +- rtgui/options.cc | 5 +- rtgui/options.h | 1 - rtgui/rtwindow.cc | 66 +++-------------- rtgui/splash.cc | 5 -- rtgui/version.h.in | 4 +- tools/buildRT | 6 +- tools/compareRT | 4 +- tools/generateReleaseInfo | 82 ++++++++++++++++++--- tools/generateSourceTarball | 33 +++++---- tools/win/InnoSetup/WindowsInnoSetup.iss.in | 57 +++++++------- win.cmake | 3 - 20 files changed, 217 insertions(+), 193 deletions(-) diff --git a/AboutThisBuild.cmake b/AboutThisBuild.cmake index 2163ed0cb..bfb3d6eb5 100644 --- a/AboutThisBuild.cmake +++ b/AboutThisBuild.cmake @@ -22,31 +22,68 @@ if (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) message(STATUS "git command found: ${GIT_CMD}") endif () + # Get version description. + # Depending on whether you checked out a branch (dev) or a tag (release), + # "git describe" will return "5.0-gtk2-2-g12345678" or "5.0-gtk2", respectively. + execute_process(COMMAND ${GIT_CMD} describe --tags --always OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") + + # Get branch name. + # Will return empty if you checked out a commit or tag. Empty string handled later. execute_process(COMMAND ${GIT_CMD} symbolic-ref --short -q HEAD OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") - execute_process(COMMAND ${GIT_CMD} describe --tags --always OUTPUT_VARIABLE GIT_VERSION_WHOLE OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") - string(REGEX REPLACE "-g.*" "" GIT_VERSION ${GIT_VERSION_WHOLE}) - string(REPLACE "-" "." GIT_VERSION ${GIT_VERSION}) - execute_process(COMMAND ${GIT_CMD} rev-parse --verify HEAD OUTPUT_VARIABLE GIT_CHANGESET OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") - string(REGEX REPLACE ".*-(.*)-g.*" "\\1" GIT_TAGDISTANCE ${GIT_VERSION_WHOLE}) + + # Get commit hash. + execute_process(COMMAND ${GIT_CMD} rev-parse --short --verify HEAD OUTPUT_VARIABLE GIT_COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") + + # Get commit date, YYYY-MM-DD. + execute_process(COMMAND ${GIT_CMD} show -s --format=%cd --date=format:%Y-%m-%d OUTPUT_VARIABLE GIT_COMMIT_DATE OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") + + # Get number of commits since tagging. This is what "GIT_DESCRIBE" uses. + # Works when checking out branch, tag or commit. + # Get a list of all tags in repo: + execute_process(COMMAND ${GIT_CMD} tag --merged HEAD OUTPUT_VARIABLE GIT_TAG WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") + # Replace newlines with semicolons so that it can be split: + string(REPLACE "\n" ";" GIT_TAG_LIST "${GIT_TAG}") + execute_process(COMMAND ${GIT_CMD} rev-list --count HEAD --not ${GIT_TAG_LIST} OUTPUT_VARIABLE GIT_COMMITS_SINCE_TAG OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") + + # Get number of commits since branching. + # Works when checking out branch, tag or commit. + execute_process(COMMAND ${GIT_CMD} rev-list --count HEAD --not --tags OUTPUT_VARIABLE GIT_COMMITS_SINCE_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") + + # If user checked-out something which is not a branch, use the description as branch name. + if (GIT_BRANCH STREQUAL "") + set (GIT_BRANCH "${GIT_DESCRIBE}") + endif() + + # Create numeric version. + # This version is nonsense, either don't use it at all or use it only where you have no other choice, e.g. Inno Setup's VersionInfoVersion. + # Strip everything after hyphen, e.g. "5.0-gtk2" -> "5.0", "5.1-rc1" -> "5.1" (ergo BS). + if (GIT_COMMITS_SINCE_TAG STREQUAL "") + set (GIT_NUMERIC_VERSION_BS "0.0.0") + else () + string(REGEX REPLACE "-.*" "" GIT_NUMERIC_VERSION_BS ${GIT_DESCRIBE}) + set(GIT_NUMERIC_VERSION_BS "${GIT_NUMERIC_VERSION_BS}.${GIT_COMMITS_SINCE_TAG}") + endif () + + message(STATUS "Git checkout information:") + message(STATUS " Commit description: ${GIT_DESCRIBE}") + message(STATUS " Branch: ${GIT_BRANCH}") + message(STATUS " Commit: ${GIT_COMMIT}") + message(STATUS " Commit date: ${GIT_COMMIT_DATE}") + message(STATUS " Commits since tag: ${GIT_COMMITS_SINCE_TAG}") + message(STATUS " Commits since branch: ${GIT_COMMITS_SINCE_BRANCH}") + message(STATUS " Version (unreliable): ${GIT_NUMERIC_VERSION_BS}") + if (NOT DEFINED CACHE_NAME_SUFFIX) - string(REGEX REPLACE "-.*" "" CACHE_NAME_SUFFIX ${GIT_VERSION_WHOLE}) + set(CACHE_NAME_SUFFIX "${GIT_DESCRIBE}") message(STATUS "CACHE_NAME_SUFFIX was not defined, it is now \"${CACHE_NAME_SUFFIX}\"") - elseif (CACHE_NAME_SUFFIX STREQUAL "latesttag") - string(REGEX REPLACE "-.*" "" CACHE_NAME_SUFFIX ${GIT_VERSION_WHOLE}) - message(STATUS "CACHE_NAME_SUFFIX was \"latesttag\", it is now \"${CACHE_NAME_SUFFIX}\"") else () message(STATUS "CACHE_NAME_SUFFIX is \"${CACHE_NAME_SUFFIX}\"") endif () + else (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) include("${PROJECT_SOURCE_DIR}/ReleaseInfo.cmake") endif (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) -if (VERSION_SUFFIX STREQUAL "") - set (GIT_VERSION_SUFFIX "${GIT_VERSION}") -else () - set (GIT_VERSION_SUFFIX "${GIT_VERSION} ${VERSION_SUFFIX}") -endif () - # build version.h from template configure_file ("${PROJECT_SOURCE_DIR}/rtgui/version.h.in" "${CMAKE_BINARY_DIR}/rtgui/version.h") # build AboutThisBuild.txt from template diff --git a/AboutThisBuild.txt.in b/AboutThisBuild.txt.in index b8ae4be1a..ea3269c09 100644 --- a/AboutThisBuild.txt.in +++ b/AboutThisBuild.txt.in @@ -1,6 +1,7 @@ +Version: ${GIT_DESCRIBE} Branch: ${GIT_BRANCH} -Version: ${GIT_VERSION_SUFFIX} -Changeset: ${GIT_CHANGESET} +Commit: ${GIT_COMMIT} +Commit date: ${GIT_COMMIT_DATE} Compiler: ${COMPILER_INFO} Processor: ${PROC_LABEL} System: ${SYSTEM} @@ -11,4 +12,3 @@ Build flags: ${CXX_FLAGS} Link flags: ${LFLAGS} OpenMP support: ${OPTION_OMP} MMAP support: ${WITH_MYFILE_MMAP} - diff --git a/CMakeLists.txt b/CMakeLists.txt index 0173856b1..1ffce3a7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,7 +359,6 @@ set(ABOUT_COMMAND_WITH_ARGS ${CMAKE_COMMAND} -DPROC_LABEL:STRING="${PROC_LABEL}" -DPROC_BIT_DEPTH:STRING="${PROC_BIT_DEPTH}" -DBUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DVERSION_SUFFIX:STRING=${VERSION_SUFFIX} -DGTKMM_VERSION:STRING=${GTKMM_VERSION} -DOPTION_OMP:STRING=${OPTION_OMP} -DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP}) diff --git a/rtdata/CMakeLists.txt b/rtdata/CMakeLists.txt index ad8fe3421..939584061 100644 --- a/rtdata/CMakeLists.txt +++ b/rtdata/CMakeLists.txt @@ -19,43 +19,23 @@ else (WIN32) endif (WIN32) if (WIN32) - if (CMAKE_SIZEOF_VOID_P EQUAL 4) - set(BUILD_BIT_DEPTH 32) - # 32 bits builds has to be installable on 64 bits system, to support WinXP/64. - set(ARCHITECTURE_ALLOWED "x86 x64 ia64") - # installing in 32 bits mode even on 64 bits OS and architecture - set(INSTALL_MODE "") - # set part of the output archive name - set(SYSTEM_NAME "WinXP") - elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(BUILD_BIT_DEPTH 64) - # Restricting the 64 bits builds to 64 bits systems only - set(ARCHITECTURE_ALLOWED "x64 ia64") - # installing in 64 bits mode for all 64 bits processors, even for itanium architecture - set(INSTALL_MODE "x64 ia64") - # set part of the output archive name - set(SYSTEM_NAME "WinVista") - endif (CMAKE_SIZEOF_VOID_P EQUAL 4) - - # If we find ReleaseInfo.cmake we use the info from there and don't need Git to be installed - find_file(REL_INFO_FILE ReleaseInfo.cmake PATHS "${PROJECT_SOURCE_DIR}" NO_DEFAULT_PATH) - if (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) - # we look for the git command in this paths by order of preference - find_file(GIT_CMD git.exe HINTS ENV Path PATH_SUFFIXES ../) - - # Fail if Git is not installed - if (GIT_CMD STREQUAL GIT_CMD-NOTFOUND) - message(FATAL_ERROR "git command not found!") - else () - message(STATUS "git command found: ${GIT_CMD}") - endif () - - execute_process(COMMAND ${GIT_CMD} describe --tags --always OUTPUT_VARIABLE GIT_VERSION_WHOLE OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") - string(REGEX REPLACE "-.*" "" GIT_VERSION ${GIT_VERSION_WHOLE}) - string(REGEX REPLACE ".*-(.*)-g.*" "\\1" GIT_TAGDISTANCE ${GIT_VERSION_WHOLE}) - else (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) - include("${PROJECT_SOURCE_DIR}/ReleaseInfo.cmake") - endif (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + set(BUILD_BIT_DEPTH 32) + # 32 bits builds has to be installable on 64 bits system, to support WinXP/64. + set(ARCHITECTURE_ALLOWED "x86 x64 ia64") + # installing in 32 bits mode even on 64 bits OS and architecture + set(INSTALL_MODE "") + # set part of the output archive name + set(SYSTEM_NAME "WinXP") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BUILD_BIT_DEPTH 64) + # Restricting the 64 bits builds to 64 bits systems only + set(ARCHITECTURE_ALLOWED "x64 ia64") + # installing in 64 bits mode for all 64 bits processors, even for itanium architecture + set(INSTALL_MODE "x64 ia64") + # set part of the output archive name + set(SYSTEM_NAME "WinVista") + endif (CMAKE_SIZEOF_VOID_P EQUAL 4) configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/../tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss" DESTINATION ${BINDIR}) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index 1f170de9a..05684aaa7 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -1351,7 +1351,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) } - TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " VERSION); + TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION); TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width); TIFFSetField (out, TIFFTAG_IMAGELENGTH, height); TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e96d8ee2f..788c422d6 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -26,7 +26,7 @@ #include "../rtgui/paramsedited.h" #include "../rtgui/options.h" #include -#define APPVERSION VERSION +#define APPVERSION RTVERSION using namespace std; extern Options options; diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 64ddd0ee3..58b60ee3f 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -278,7 +278,7 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring try { kf->set_string ("RT General", "CachePath", options.cacheBaseDir); - kf->set_string ("RT General", "AppVersion", VERSION); + kf->set_string ("RT General", "AppVersion", RTVERSION); kf->set_integer("RT General", "ProcParamsVersion", PPVERSION); kf->set_string ("RT General", "ImageFileName", imageFName); kf->set_string ("RT General", "OutputProfileFileName", profileFName); @@ -2797,7 +2797,7 @@ std::vector ExifManager::getDefaultTIFFTags (TagDirectory* forthis) defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "XResolution"), 300, RATIONAL)); defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "YResolution"), 300, RATIONAL)); defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "ResolutionUnit"), 2, SHORT)); - defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "Software"), "RawTherapee " VERSION)); + defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "Software"), "RawTherapee " RTVERSION)); defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "Orientation"), 1, SHORT)); defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "SamplesPerPixel"), 3, SHORT)); defTags.push_back (new Tag (forthis, lookupAttrib(ifdAttribs, "BitsPerSample"), 8, SHORT)); diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 220dcb2e8..34983d46a 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -203,7 +203,7 @@ int CacheImageData::save (const Glib::ustring& fname) } catch (Glib::Error&) {} keyFile.set_string ("General", "MD5", md5); - keyFile.set_string ("General", "Version", VERSION); // Application's version + keyFile.set_string ("General", "Version", RTVERSION); keyFile.set_boolean ("General", "Supported", supported); keyFile.set_integer ("General", "Format", format); keyFile.set_boolean ("General", "RecentlySaved", recentlySaved); diff --git a/rtgui/main.cc b/rtgui/main.cc index a3b4a60f2..a8ded72e5 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -214,7 +214,7 @@ int main(int argc, char **argv) SetConsoleCtrlHandler( NULL, true ); // Set title of console char consoletitle[128]; - sprintf(consoletitle, "RawTherapee %s Console", VERSION); + sprintf(consoletitle, "RawTherapee %s Console", RTVERSION); SetConsoleTitle(consoletitle); // increase size of screen buffer COORD c; @@ -240,7 +240,7 @@ int main(int argc, char **argv) consoleOpened = true; // printing RT's version in every case, particularly useful for the 'verbose' mode, but also for the batch processing - std::cout << "RawTherapee, version " << VERSION << std::endl; + std::cout << "RawTherapee, version " << RTVERSION << std::endl; std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; } } @@ -263,7 +263,7 @@ int main(int argc, char **argv) if (argc > 1 || options.rtSettings.verbose) { // printing RT's version in all case, particularly useful for the 'verbose' mode, but also for the batch processing - std::cout << "RawTherapee, version " << VERSION << std::endl; + std::cout << "RawTherapee, version " << RTVERSION << std::endl; #ifdef WIN32 std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; #endif diff --git a/rtgui/options.cc b/rtgui/options.cc index 397b5996a..7d3475ef6 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -46,8 +46,7 @@ Glib::ustring Options::rtdir; Glib::ustring Options::cacheBaseDir; Options options; -Glib::ustring versionString = VERSION; -Glib::ustring versionSuffixString = VERSION_SUFFIX; +Glib::ustring versionString = RTVERSION; Glib::ustring paramFileExtension = ".pp3"; Options::Options () @@ -1864,7 +1863,7 @@ int Options::saveToFile (Glib::ustring fname) keyFile.set_string ("General", "Theme", theme); keyFile.set_boolean ("General", "SlimUI", slimUI); keyFile.set_boolean ("General", "UseSystemTheme", useSystemTheme); - keyFile.set_string ("General", "Version", VERSION); + keyFile.set_string ("General", "Version", RTVERSION); keyFile.set_string ("General", "DarkFramesPath", rtSettings.darkFramesPath); keyFile.set_string ("General", "FlatFieldsPath", rtSettings.flatFieldsPath); keyFile.set_boolean ("General", "Verbose", rtSettings.verbose); diff --git a/rtgui/options.h b/rtgui/options.h index ab0726798..4a556a65c 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -343,7 +343,6 @@ extern Glib::ustring argv0; extern Glib::ustring argv1; extern bool simpleEditor; extern Glib::ustring versionString; -extern Glib::ustring versionSuffixString; extern Glib::ustring paramFileExtension; #endif diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 21bfb0886..e76604baa 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -119,10 +119,6 @@ RTWindow::RTWindow () #endif versionStr = "RawTherapee " + versionString; - if (!versionSuffixString.empty()) { - versionStr += " " + versionSuffixString; - } - set_title_decorated(""); property_allow_shrink() = true; set_default_size(options.windowWidth, options.windowHeight); @@ -309,30 +305,6 @@ RTWindow::~RTWindow() } } -void RTWindow::findVerNumbers(int* numbers, Glib::ustring versionStr) -{ - numbers[0] = numbers[1] = numbers[2] = numbers[3] = 0; - int n = 0; - - for (unsigned int i = 0; i < versionStr.length(); i++) { - char chr = (char)versionStr.at(i); - - if (chr >= '0' && chr <= '9') { - numbers[n] *= 10; - numbers[n] += (int)(chr - '0'); - } else { - n++; - - if (n > 4) { - printf("Error: malformed version string; \"%s\" must follow this format: xx.xx.xx.xx. Admitting it's a developer version...\n", versionStr.c_str()); - // Reseting the already found numbers - numbers[0] = numbers[1] = numbers[2] = numbers[3] = 100; - return; - } - } - } -} - void RTWindow::on_realize () { Gtk::Window::on_realize (); @@ -349,38 +321,20 @@ void RTWindow::on_realize () // Check if first run of this version, then display the Release Notes text if (options.version != versionString) { - int prevVerNbr[4]; - int currVerNbr[4]; - findVerNumbers(prevVerNbr, options.version); - findVerNumbers(currVerNbr, versionString); - // Now we can update the version parameter with the right value + // Update the version parameter with the right value options.version = versionString; - bool showReleaseNotes = false; + splash = new Splash (*this); + splash->set_transient_for (*this); + splash->signal_delete_event().connect( sigc::mem_fun(*this, &RTWindow::splashClosed) ); - // Check if the current version is newer - if (currVerNbr[0] > prevVerNbr[0]) { - showReleaseNotes = true; - } else if (currVerNbr[1] > prevVerNbr[1]) { - showReleaseNotes = true; - } else if (currVerNbr[2] > prevVerNbr[2]) { - showReleaseNotes = true; - } - - if (showReleaseNotes) { - // this is a first run! - splash = new Splash (*this); - splash->set_transient_for (*this); - splash->signal_delete_event().connect( sigc::mem_fun(*this, &RTWindow::splashClosed) ); - - if (splash->hasReleaseNotes()) { - splash->showReleaseNotes(); - splash->show (); - } else { - delete splash; - splash = nullptr; - } + if (splash->hasReleaseNotes()) { + splash->showReleaseNotes(); + splash->show (); + } else { + delete splash; + splash = nullptr; } } } diff --git a/rtgui/splash.cc b/rtgui/splash.cc index 87408598e..0295a9c9f 100644 --- a/rtgui/splash.cc +++ b/rtgui/splash.cc @@ -27,7 +27,6 @@ extern Glib::ustring argv0; extern Glib::ustring creditsPath; extern Glib::ustring licensePath; extern Glib::ustring versionString; -extern Glib::ustring versionSuffixString; SplashImage::SplashImage () { @@ -70,10 +69,6 @@ bool SplashImage::on_expose_event (GdkEventExpose* event) int w, h; Glib::ustring versionStr(versionString); - if (!versionSuffixString.empty()) { - versionStr += " " + versionSuffixString; - } - version = create_pango_layout (versionStr); version->set_markup("" + versionStr + ""); version->get_pixel_size (w, h); diff --git a/rtgui/version.h.in b/rtgui/version.h.in index 03630075b..39ecd6426 100644 --- a/rtgui/version.h.in +++ b/rtgui/version.h.in @@ -4,9 +4,7 @@ #ifndef _VERSION_ #define _VERSION_ -#define VERSION "${GIT_VERSION}" -#define VERSION_SUFFIX "${VERSION_SUFFIX}" -#define TAGDISTANCE ${GIT_TAGDISTANCE} +#define RTVERSION "${GIT_DESCRIBE}" #define CACHEFOLDERNAME "RawTherapee${CACHE_NAME_SUFFIX}" #endif diff --git a/tools/buildRT b/tools/buildRT index 66ed43894..71370e8df 100755 --- a/tools/buildRT +++ b/tools/buildRT @@ -83,7 +83,7 @@ while getopts "bc:fnp:s:t:uvh?-" opt; do " -s " \ "Suffix of destination build directory, so that if you have applied a patch, say \"dustremoval-1.patch\", and want to have RawTherapee compiled to a folder whose name ends with \"_dustremoval1\", you would set \"-s dustremoval1\" (the underscore is automated)." "" \ " -t \"\"" \ - "Suffix displayed next to the RawTherapee version in the window titlebar. It is recommended that you include the changeset of the newest public commit (the one you would see if you cloned the repository anew) so it is clear which commit you applied the patches to. E.g.:" "-t \": ee72ddbcfd4e + dustremoval-1.patch + mustafa ibrahim\"" "" \ + "Suffix displayed next to the RawTherapee version in the window titlebar. It is recommended that you include the commit of the newest public commit (the one you would see if you cloned the repository anew) so it is clear which commit you applied the patches to. E.g.:" "-t \": ee72ddbcfd4e + dustremoval-1.patch + mustafa ibrahim\"" "" \ " -u" \ "Check for an update of buildRT on GitHub." "" \ " -v" \ @@ -193,7 +193,7 @@ if [[ ! -d "${repo}" ]]; then currentBranch="$(git branch | grep "*" | sed -e 's/.* \+//')" rev="$(git rev-list --all --count)" node="$(git rev-parse --short HEAD)" - printf "\nRepository state:\n Branch: ${currentBranch}\n RawTherapee-${verLatesttag}.${verLatesttagdistance}\n Changeset: ${rev}:${node}\n Latest tag: ${verLatesttag}\n\n" + printf "\nRepository state:\n Branch: ${currentBranch}\n RawTherapee-${verLatesttag}.${verLatesttagdistance}\n Commit: ${rev}:${node}\n Latest tag: ${verLatesttag}\n\n" alert "Repository cloned succesfully. What would you like to do next?" printf "%b" "Repository cloned succesfully.\n" "Press 'q' to quit or any other key to continue... " read -r -n 1 @@ -239,7 +239,7 @@ verLatesttagdistance="$(git describe --tags | sed -e 's/.*-\([0-9]\+\)-.*/\1/')" currentBranch="$(git branch | grep "*" | sed -e 's/.* \+//')" rev="$(git rev-list --all --count)" node="$(git rev-parse --short HEAD)" -printf "\nRepository state:\n Branch: ${currentBranch}\n RawTherapee-${verLatesttag}.${verLatesttagdistance}\n Changeset: ${rev}:${node}\n Latest tag: ${verLatesttag}\n\n" +printf "\nRepository state:\n Branch: ${currentBranch}\n RawTherapee-${verLatesttag}.${verLatesttagdistance}\n Commit: ${rev}:${node}\n Latest tag: ${verLatesttag}\n\n" #--- Print the menu branches=() diff --git a/tools/compareRT b/tools/compareRT index cca18bee6..d701508f7 100755 --- a/tools/compareRT +++ b/tools/compareRT @@ -37,8 +37,8 @@ for rtDir in "${rtDirs[@]}"; do c=1 pp3name=${pp3%.*} pp3name=${pp3name#*/} - v+=("$(grep "Changeset:.*" "${rtDir}/AboutThisBuild.txt" | sed "s/Changeset: //")") - printf "%s\n" "Developing images using RawTherapee changeset ${v[$i]} - ${rtDir}" + v+=("$(grep "Commit:.*" "${rtDir}/AboutThisBuild.txt" | sed "s/Commit: //")") + printf "%s\n" "Developing images using RawTherapee commit ${v[$i]} - ${rtDir}" for img in "${imgs[@]}"; do printf "%s" "${c}/${#imgs[@]} - " "${rtDir}rawtherapee" -o "${outDir}${img%.*}_${v[i]}_${pp3%.*}.tif" -p "${pp3}" -t -Y -c "$img" | grep Processing diff --git a/tools/generateReleaseInfo b/tools/generateReleaseInfo index 79189ad44..b7480e875 100755 --- a/tools/generateReleaseInfo +++ b/tools/generateReleaseInfo @@ -1,12 +1,76 @@ #!/usr/bin/env bash -gitBranch="`git symbolic-ref --short -q HEAD`" -gitVersion="`git describe --tags --always`" -gitLatesttag="`echo $gitVersion | sed 's/-.*//'`" -gitLatesttagdistance="`echo $gitVersion | sed 's/.*-\(.*\)-g.*/\1/'`" -gitChangeset="`git rev-parse --verify HEAD`" +# This script is called from tools/generateSourceTarball +# It is used to generate a ReleaseInfo.cmake file with commit information which +# enables compilation without needing to have git installed. -echo "set(GIT_BRANCH $gitBranch) -set(GIT_VERSION $gitLatesttag.$gitLatesttagdistance) -set(GIT_CHANGESET $gitChangeset) -set(GIT_TAGDISTANCE $gitLatesttagdistance)" > ReleaseInfo.cmake +rm -f ReleaseInfo.cmake +# Get version description. +# Depending on whether you checked out a branch (dev) or a tag (release), +# "git describe" will return "5.0-gtk2-2-g12345678" or "5.0-gtk2", respectively. +gitDescribe="$(git describe --tags --always)" + +# Get branch name. +# Will return empty if you checked out a commit or tag. Empty string handled later. +gitBranch="$(git symbolic-ref --short -q HEAD)" + +# Get commit hash. +gitCommit="$(git rev-parse --short --verify HEAD)" + +# Get commit date, YYYY-MM-DD. +gitCommitDate="$(git show -s --format=%cd --date=format:%Y-%m-%d)" + +# Get number of commits since tagging. This is what gitDescribe uses. +# Works when checking out branch, tag or commit. +gitCommitsSinceTag="$(git rev-list --count HEAD --not $(git tag --merged HEAD))" + +# Get number of commits since branching. +# Works when checking out branch, tag or commit. +gitCommitsSinceBranch="$(git rev-list --count HEAD --not --tags)" + +if [[ -z $gitDescribe ]]; then + printf '%s\n' "Failed finding commit description, aborting." + exit 1 +fi +if [[ -z $gitBranch ]]; then + printf '%s\n' "No branch found. Using commit description as branch name." + gitBranch="$gitDescribe" +fi +if [[ -z $gitCommit ]]; then + printf '%s\n' "Failed finding commit hash, aborting." + exit 1 +fi +if [[ -z $gitCommitDate ]]; then + printf '%s\n' "Failed finding commit date, aborting." + exit 1 +fi + +# Create numeric version. +# This version is nonsense, either don't use it at all or use it only where you have no other choice, e.g. Inno Setup's VersionInfoVersion. +# Strip everything after hyphen, e.g. "5.0-gtk2" -> "5.0", "5.1-rc1" -> "5.1" (ergo BS). +if [[ -z $gitCommitsSinceTag ]]; then + gitVersionNumericBS="0.0.0" +else + gitVersionNumericBS="${gitDescribe%%-*}" # Remove everything after first hyphen. + gitVersionNumericBS="${gitVersionNumericBS}.${gitCommitsSinceTag}" # Remove everything until after first hyphen: 5.0 +fi + +cat < ReleaseInfo.cmake +set(GIT_DESCRIBE $gitDescribe) +set(GIT_BRANCH $gitBranch) +set(GIT_COMMIT $gitCommit) +set(GIT_COMMIT_DATE $gitCommitDate) +set(GIT_COMMITS_SINCE_TAG $gitCommitsSinceTag) +set(GIT_COMMITS_SINCE_BRANCH $gitCommitsSinceBranch) +set(GIT_VERSION_NUMERIC_BS $gitVersionNumericBS) +EOF + +printf '%s\n' "Git information extracted:" \ + " Description: ${gitDescribe}" \ + " Branch: ${gitBranch}" \ + " Commit: ${gitCommit}" \ + " Commit date: ${gitCommitDate}" \ + " Commits since tag: ${gitCommitsSinceTag}" \ + " Commits since branch: ${gitCommitsSinceBranch}" \ + " Unreliable verison: ${gitVersionNumericBS}" \ + "" diff --git a/tools/generateSourceTarball b/tools/generateSourceTarball index 98173c00f..022e5646d 100755 --- a/tools/generateSourceTarball +++ b/tools/generateSourceTarball @@ -1,17 +1,24 @@ #!/usr/bin/env bash +# Run from the root of the cloned repository. +# This script is used to generate a source code tarball which includes commit +# metadata so that RawTherapee can be compiled without needing to install git. +# It is meant to be used every time a release is made after creating an +# annotated tag in git. +# It is your job to checkout the tag before running this script. -if [[ ! "$1" ]]; then - printf "%s\n" "Usage: $0 " "Example: $0 4.2" - exit +./tools/generateReleaseInfo +ret=$? +if [[ $ret -ne 0 ]]; then + printf '%s\n' "Something went wrong while running tools/generateReleaseInfo" "Aborting." + exit 1 fi +desc="$(grep GIT_DESCRIBE ReleaseInfo.cmake)" # Gets whole string: set(GIT_DESCRIBE 5.0-gtk2-1-g96bf9129) +desc="${desc#*GIT_DESCRIBE }" # Removes front: 5.0-gtk2-1-g96bf9129) +desc="${desc%)}" # Removes back: 5.0-gtk2-1-g96bf9129 -git checkout "$1" || exit 0 -tools/generateReleaseInfo -mkdir rawtherapee-"$1" -mv ReleaseInfo.cmake rawtherapee-"$1" -#hg archive -X ".hg*" -X "rtgui/config.h" -X "rtgui/version.h" -X "rtdata/rawtherapee.desktop" rawtherapee-"$1".tar -git archive --format=tar "$1" > rawtherapee-"$1".tar -tar --append --file=rawtherapee-"$1".tar rawtherapee-"$1"/ReleaseInfo.cmake -xz -z -9e rawtherapee-"$1".tar -rm -r rawtherapee-"$1" -git checkout +mkdir "rawtherapee-${desc}" || exit 1 +mv ReleaseInfo.cmake "rawtherapee-${desc}" || exit 1 +git archive --format=tar --prefix="rawtherapee-${desc}/" -o "rawtherapee-${desc}.tar" HEAD || exit 1 +tar --append --file="rawtherapee-${desc}.tar" "rawtherapee-${desc}/ReleaseInfo.cmake" || exit 1 +xz -z -9e "rawtherapee-${desc}.tar" || exit 1 +rm -r "rawtherapee-${desc}" diff --git a/tools/win/InnoSetup/WindowsInnoSetup.iss.in b/tools/win/InnoSetup/WindowsInnoSetup.iss.in index 1ba02590d..05fdffefe 100644 --- a/tools/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/tools/win/InnoSetup/WindowsInnoSetup.iss.in @@ -1,30 +1,26 @@ -; Script initially generated by the Inno Setup Script Wizard -; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! - - - -; This script has to be used by "INNO Setup" (http://www.jrsoftware.org/) to create a setup executable. -; When the "make install" process ends, you can double click on this file to load it into -; INNO Setup, then execute it to create the archive. It expect to find all the dependency libs -; in the root destination folder (the one of the 'make install' process), and the usual 'lib' directory. -; Please note that all *.dll files will be added, so be carefull on which dll are present in the directory -; before compiling the INNO Setup script. +; Script initially generated by the Inno Setup Script Wizard. +; Documentation: http://www.jrsoftware.org/ishelp/ ; -; It also search for and bundles all "rawtherapee*.exe" files, which mean that you can bundle a Release and -; a Debug build at the same time (for conveniency), but official downloads must only contain the Release -; version. +; This script is used by "Inno Setup" (http://www.jrsoftware.org/) to create a +; setup executable. When the "make install" process ends, double-click on this +; file to load it into Inno Setup, then execute it to create the installer. It +; expects to find all the dependency libs in the root destination folder (the +; one from the 'make install' process), and the usual 'lib' directory. +; Note that all *.dll files will be added, so be careful which DLLs are present +; in the folder before running this script. ; -; In all cases, you have to bundle at least one file named "rawtherapee.exe", which INNO Setup will require -; as a default executable to run. +; This script searches for and bundles all "rawtherapee*.exe" files, allowing +; you to bundle a "release" as well as a "debug" version at the same time. +; At least one "rawtherapee.exe" file is required. ; -; This script is configured to check that the operating system's bit depth is the same than the executable file. -; Please note that the ia64 architecture is not supported (is it really necessary?) - - +; This script is configured to check that the operating system's bit depth is +; the same as that of the executable file. +; +; The IA-64 architecture is not supported. #define MyAppName "RawTherapee" -#define MyAppVersion "${GIT_VERSION}" -#define MyAppFullVersion "${GIT_VERSION}.${GIT_TAGDISTANCE}" +#define MyAppVersion "${GIT_DESCRIBE}" +#define MyAppVersionNumeric "${GIT_NUMERIC_VERSION_BS}" #define MyAppPublisher "rawtherapee.com" #define MyAppURL "http://www.rawtherapee.com/" #define MyAppExeName "rawtherapee.exe" @@ -42,18 +38,17 @@ AppId={{128459AB-59A7-430A-8BD0-3D8803D50400} AppName={#MyAppName} AppVersion={#MyAppVersion} -VersionInfoVersion={#MyAppFullVersion} -;AppVerName={#MyAppName} {#MyAppVersion} +VersionInfoVersion={#MyAppVersionNumeric} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} -DefaultDirName={pf}\{#MyAppName}-{#MyAppFullVersion} -DefaultGroupName={#MyAppName} {#MyAppFullVersion} +DefaultDirName={pf}\{#MyAppName}\{#MyAppVersion} +DefaultGroupName={#MyAppName} AllowNoIcons=yes LicenseFile={#MyBuildBasePath}\LICENSE.txt OutputDir={#MyBuildBasePath}\..\ -OutputBaseFilename={#MyAppName}_{#MySystemName}_{#MyBitDepth}_{#MyAppFullVersion} +OutputBaseFilename={#MyAppName}_{#MyAppVersion}_{#MySystemName}_{#MyBitDepth} SetupIconFile={#MySourceBasePath}\rtdata\icons\RT.ico WizardImageFile={#MySourceBasePath}\tools\win\InnoSetup\installerStrip.bmp WizardImageBackColor=$2A2A2A @@ -97,7 +92,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 [Files] -Source: "{#MyBuildBasePath}\rawtherapee.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#MyBuildBasePath}\rawtherapee*.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\camconst.json"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\dcpprofiles\*"; DestDir: "{app}\dcpprofiles\"; Flags: ignoreversion recursesubdirs createallsubdirs ;Source: "{#MyBuildBasePath}\etc\*"; DestDir: "{app}\etc\"; Flags: ignoreversion recursesubdirs createallsubdirs @@ -122,11 +117,11 @@ Source: "{#MyBuildBasePath}\fonts\DroidSansMonoSlashed.ttf"; DestDir: "{fonts}"; ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] -Name: "{group}\{#MyAppName} {#MyAppFullVersion}"; Filename: "{app}\{#MyAppExeName}" +Name: "{group}\{#MyAppName} {#MyAppVersion}"; Filename: "{app}\{#MyAppExeName}" Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" -Name: "{commondesktop}\{#MyAppName}{#MyAppFullVersion}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon -Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName} {#MyAppFullVersion}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon +Name: "{commondesktop}\{#MyAppName} {#MyAppVersion}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName} {#MyAppVersion}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon [Run] Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent diff --git a/win.cmake b/win.cmake index b4bbc66a2..2259c144f 100644 --- a/win.cmake +++ b/win.cmake @@ -22,9 +22,6 @@ set(CACHE_NAME_SUFFIX "" CACHE STRING "RawTherapee's cache folder suffix (leave # This line will let you chose the target number, and the associated processor set(PROC_TARGET_NUMBER 0 CACHE STRING "Target Processor") -# To add a version suffix (text) after the standard version number, e.g. for patched builds -set(VERSION_SUFFIX "" CACHE STRING "For patched builds, use this string to add a version suffix (text); KEEP EMPTY FOR RELEASE BULDS") - # If you want to force the target processor name when PROC_TARGET_NUMBER = 0 or 2, # uncomment the next line and replace labelWithoutQuotes by its value #set (PROC_LABEL labelWithoutQuotes CACHE STRING "Target Processor label") From 77d5f8779bf183080a837a709ad6d9c2b1e34569 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Sat, 28 Jan 2017 02:29:22 +0100 Subject: [PATCH 03/42] Cleaned up CMake logic thanks to Hombre, #3628 --- CMakeLists.txt | 6 +++--- AboutThisBuild.cmake => UpdateInfo.cmake | 22 ++++++++++++++++++++++ rtdata/CMakeLists.txt | 19 ------------------- rtengine/CMakeLists.txt | 2 +- rtexif/CMakeLists.txt | 2 +- rtgui/CMakeLists.txt | 2 +- 6 files changed, 28 insertions(+), 25 deletions(-) rename AboutThisBuild.cmake => UpdateInfo.cmake (82%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ffce3a7e..9c4e74def 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,7 +331,7 @@ if (OUT_OF_SOURCE_BUILD) endforeach(f) endif () -## BEGIN: Generating AboutThisBuild.txt +## BEGIN: Create AboutThisBuild.txt and other version-dependent files. # set the bit number information of the platform if (CMAKE_SIZEOF_VOID_P EQUAL 4) set(PROC_BIT_DEPTH 32 bits) @@ -382,9 +382,9 @@ endif (WIN32) list(APPEND ABOUT_COMMAND_WITH_ARGS -P "${PROJECT_SOURCE_DIR}/AboutThisBuild.cmake") -add_custom_target(AboutFile ALL +add_custom_target(UpdateInfo ALL COMMAND ${ABOUT_COMMAND_WITH_ARGS} - COMMENT "Creating the about file") + COMMENT "Creating AboutThisBuild.txt and other version-dependent files") ## END: Generating AboutThisBuild.txt diff --git a/AboutThisBuild.cmake b/UpdateInfo.cmake similarity index 82% rename from AboutThisBuild.cmake rename to UpdateInfo.cmake index bfb3d6eb5..40cdab6d6 100644 --- a/AboutThisBuild.cmake +++ b/UpdateInfo.cmake @@ -84,6 +84,28 @@ else (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) include("${PROJECT_SOURCE_DIR}/ReleaseInfo.cmake") endif (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) +if (WIN32) + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + set(BUILD_BIT_DEPTH 32) + # 32 bits builds has to be installable on 64 bits system, to support WinXP/64. + set(ARCHITECTURE_ALLOWED "x86 x64 ia64") + # installing in 32 bits mode even on 64 bits OS and architecture + set(INSTALL_MODE "") + # set part of the output archive name + set(SYSTEM_NAME "WinXP") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BUILD_BIT_DEPTH 64) + # Restricting the 64 bits builds to 64 bits systems only + set(ARCHITECTURE_ALLOWED "x64 ia64") + # installing in 64 bits mode for all 64 bits processors, even for itanium architecture + set(INSTALL_MODE "x64 ia64") + # set part of the output archive name + set(SYSTEM_NAME "WinVista") + endif (CMAKE_SIZEOF_VOID_P EQUAL 4) + + configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/../tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss") +endif (WIN32) + # build version.h from template configure_file ("${PROJECT_SOURCE_DIR}/rtgui/version.h.in" "${CMAKE_BINARY_DIR}/rtgui/version.h") # build AboutThisBuild.txt from template diff --git a/rtdata/CMakeLists.txt b/rtdata/CMakeLists.txt index 939584061..b3f44a68c 100644 --- a/rtdata/CMakeLists.txt +++ b/rtdata/CMakeLists.txt @@ -19,25 +19,6 @@ else (WIN32) endif (WIN32) if (WIN32) - if (CMAKE_SIZEOF_VOID_P EQUAL 4) - set(BUILD_BIT_DEPTH 32) - # 32 bits builds has to be installable on 64 bits system, to support WinXP/64. - set(ARCHITECTURE_ALLOWED "x86 x64 ia64") - # installing in 32 bits mode even on 64 bits OS and architecture - set(INSTALL_MODE "") - # set part of the output archive name - set(SYSTEM_NAME "WinXP") - elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(BUILD_BIT_DEPTH 64) - # Restricting the 64 bits builds to 64 bits systems only - set(ARCHITECTURE_ALLOWED "x64 ia64") - # installing in 64 bits mode for all 64 bits processors, even for itanium architecture - set(INSTALL_MODE "x64 ia64") - # set part of the output archive name - set(SYSTEM_NAME "WinVista") - endif (CMAKE_SIZEOF_VOID_P EQUAL 4) - - configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/../tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss" DESTINATION ${BINDIR}) endif (WIN32) diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 477ccecae..dbab1dc2d 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -29,7 +29,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}") add_library (rtengine ${RTENGINESOURCEFILES}) -add_dependencies (rtengine AboutFile) +add_dependencies (rtengine UpdateInfo) #It may be nice to store library version too IF (BUILD_SHARED_LIBS) diff --git a/rtexif/CMakeLists.txt b/rtexif/CMakeLists.txt index a2e713ed7..7dad67006 100644 --- a/rtexif/CMakeLists.txt +++ b/rtexif/CMakeLists.txt @@ -1,5 +1,5 @@ add_library (rtexif rtexif.cc stdattribs.cc nikonattribs.cc canonattribs.cc pentaxattribs.cc fujiattribs.cc sonyminoltaattribs.cc olympusattribs.cc kodakattribs.cc) -add_dependencies (rtexif AboutFile) +add_dependencies (rtexif UpdateInfo) IF (WIN32) set_target_properties (rtexif PROPERTIES COMPILE_FLAGS " -ffast-math -fexpensive-optimizations") diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index ad896041f..be2186e63 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -62,7 +62,7 @@ endif (WIN32) configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h") add_executable (rth ${EXTRA_SRC} ${BASESOURCEFILES}) -add_dependencies (rth AboutFile) +add_dependencies (rth UpdateInfo) set_target_properties (rth PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rawtherapee) #target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} From cded30dcbbdad0b7976b78a323395cabf3d28b5e Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Sat, 28 Jan 2017 02:32:31 +0100 Subject: [PATCH 04/42] Fix previous commit: Update old name. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c4e74def..71c628635 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,7 +380,7 @@ else (WIN32) -DCOMPILER_INFO:STRING=${COMPILER_INFO}) endif (WIN32) -list(APPEND ABOUT_COMMAND_WITH_ARGS -P "${PROJECT_SOURCE_DIR}/AboutThisBuild.cmake") +list(APPEND ABOUT_COMMAND_WITH_ARGS -P "${PROJECT_SOURCE_DIR}/UpdateInfo.cmake") add_custom_target(UpdateInfo ALL COMMAND ${ABOUT_COMMAND_WITH_ARGS} From 2356af62465b3b9fe99bd5a89b91e9fbb8c89a83 Mon Sep 17 00:00:00 2001 From: Hombre Date: Sat, 28 Jan 2017 03:03:15 +0100 Subject: [PATCH 05/42] Bugfix of paths in UpdateInfo.cmake --- UpdateInfo.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UpdateInfo.cmake b/UpdateInfo.cmake index 40cdab6d6..1192294d1 100644 --- a/UpdateInfo.cmake +++ b/UpdateInfo.cmake @@ -103,7 +103,7 @@ if (WIN32) set(SYSTEM_NAME "WinVista") endif (CMAKE_SIZEOF_VOID_P EQUAL 4) - configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/../tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsInnoSetup.iss") + configure_file ("${PROJECT_SOURCE_DIR}/tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_BINARY_DIR}/rtdata/WindowsInnoSetup.iss") endif (WIN32) # build version.h from template From 52dca96723965e6a8f954c29ef156a6cf5da23b1 Mon Sep 17 00:00:00 2001 From: Hombre Date: Sat, 28 Jan 2017 22:39:50 +0100 Subject: [PATCH 06/42] Bigfix of InnoSetup parameters (#3628) --- CMakeLists.txt | 4 +++- UpdateInfo.cmake | 6 +++--- tools/win/InnoSetup/WindowsInnoSetup.iss.in | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71c628635..c412f591f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -367,7 +367,9 @@ if (WIN32) list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Windows -DCXX_FLAGS:STRING="${CXX_FLAGS}" -DLFLAGS:STRING="${LFLAGS}" - -DCOMPILER_INFO:STRING="${COMPILER_INFO}") + -DCOMPILER_INFO:STRING="${COMPILER_INFO}" + -DCMAKE_INSTALL_PREFIX:STRING="${CMAKE_INSTALL_PREFIX}" + -DBIT_DEPTH:STRING="${CMAKE_SIZEOF_VOID_P}") elseif (APPLE) list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Apple -DCXX_FLAGS:STRING=${CXX_FLAGS} diff --git a/UpdateInfo.cmake b/UpdateInfo.cmake index 1192294d1..ff0f12482 100644 --- a/UpdateInfo.cmake +++ b/UpdateInfo.cmake @@ -85,7 +85,7 @@ else (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) endif (REL_INFO_FILE STREQUAL REL_INFO_FILE-NOTFOUND) if (WIN32) - if (CMAKE_SIZEOF_VOID_P EQUAL 4) + if (BIT_DEPTH EQUAL 4) set(BUILD_BIT_DEPTH 32) # 32 bits builds has to be installable on 64 bits system, to support WinXP/64. set(ARCHITECTURE_ALLOWED "x86 x64 ia64") @@ -93,7 +93,7 @@ if (WIN32) set(INSTALL_MODE "") # set part of the output archive name set(SYSTEM_NAME "WinXP") - elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + elseif (BIT_DEPTH EQUAL 8) set(BUILD_BIT_DEPTH 64) # Restricting the 64 bits builds to 64 bits systems only set(ARCHITECTURE_ALLOWED "x64 ia64") @@ -101,7 +101,7 @@ if (WIN32) set(INSTALL_MODE "x64 ia64") # set part of the output archive name set(SYSTEM_NAME "WinVista") - endif (CMAKE_SIZEOF_VOID_P EQUAL 4) + endif (BIT_DEPTH EQUAL 4) configure_file ("${PROJECT_SOURCE_DIR}/tools/win/InnoSetup/WindowsInnoSetup.iss.in" "${CMAKE_BINARY_DIR}/rtdata/WindowsInnoSetup.iss") endif (WIN32) diff --git a/tools/win/InnoSetup/WindowsInnoSetup.iss.in b/tools/win/InnoSetup/WindowsInnoSetup.iss.in index 05fdffefe..82aa7a60d 100644 --- a/tools/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/tools/win/InnoSetup/WindowsInnoSetup.iss.in @@ -74,7 +74,6 @@ Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl" Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl" Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl" -Name: "nepali"; MessagesFile: "compiler:Languages\Nepali.islu" Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl" Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl" Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl" From 3809a15d98836c91db66135562ffccf00ab26a7f Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Sat, 28 Jan 2017 22:52:56 +0100 Subject: [PATCH 07/42] Updated splash screen SVG + PNG. --- rtdata/images/rt_splash_5.svg | 204 +++++++++++++++++++++------------- rtdata/images/splash.png | Bin 78654 -> 75666 bytes 2 files changed, 129 insertions(+), 75 deletions(-) diff --git a/rtdata/images/rt_splash_5.svg b/rtdata/images/rt_splash_5.svg index 78620dd68..8f556f37e 100644 --- a/rtdata/images/rt_splash_5.svg +++ b/rtdata/images/rt_splash_5.svg @@ -21,7 +21,7 @@ inkscape:export-xdpi="90" inkscape:export-ydpi="90"> RawTherapee logo white font white glow + id="title5575">RawTherapee Splash Screen + inkscape:snap-global="true" + showguides="true" + inkscape:guide-bbox="true"> + + + + + + + + + + + @@ -1417,17 +1468,17 @@ image/svg+xml - RawTherapee logo white font white glow + RawTherapee Splash Screen - RawTherapee + Morgan Hardwood rawtherapee logo - white + splash www.rawtherapee.com @@ -1647,40 +1698,11 @@ y="152.4408" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;font-family:OxygenSans;-inkscape-font-specification:OxygenSans;text-align:justify;text-anchor:start;fill:#ffffff;fill-opacity:1" />Select the desired element and apply one of the effects in the Filter Editor. You might need to ungroup the element before applying. For example to set the RT ring to have a colorful glow, select it and enable the "ring glow". You can change the flood color of the "ring shadow" effect to make it white if you want to make the logo usable on a dark background.Apply glow effects using filters. You might need to ungroup the circle elements before applying. You can change the flood color of the "ring shadow" effect to make it white if you want to make the logo usable on a dark background.For logo specifics, refer to rt_logo.svg Raw - Therapee - For logo specifics, refer to rt_logo.svg "Raw" font Eras-UltraBlk, 69px, -3px spacing between characters, skewed 2° to the right."Raw": font ITC Eras Std Ultra, appears in Inkscape as"Therapee" font Eras-Medium, 68px, 4px spacing between characters, skewed 2° to the right. ITC Eras Standard - Ultra-Bold,Both have a dropshadow with an opacity of 0.40 and Gaussian blur standard deviation of 3.5. 60pt, -3px spacing between characters.Version number Eras bold 64 or less."Therapee": font ITC Eras Std Medium, appears in Inkscape asEras font from "freefonts-0.10": ITC Eras Standard - Medium,ftp://ftp.gimp.org/pub/gimp/fonts/ 60pt, +1px spacing between characters.Version: font ITC Eras Std Bold, appears in Inkscape as ITC Eras Standard - Bold, 64pt, skewed -3°. RawTherapee splash screen design version 1.0 from 2014-05-03 | www.rawtherapee.com - GNU GPLv3 + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6px;font-family:OxygenSans;-inkscape-font-specification:OxygenSans;letter-spacing:1px;fill:#ffcc00;fill-opacity:1">RawTherapee splash screen design version 1.1 from 2017-01-28 | www.rawtherapee.com 5 + Raw + Therapee + GNU GPLv3 + 5 ;S%ROr&gQrSE7)q-^M5Y;3b_Y1|ElVnT)rIy;%! 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

= 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 Ma214dJ=7xXe^=8f%m4rY literal 78654 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 Md38v=tY!HB0BMX^EC2ui From f1e253b176139ed83db4348a018e665adb1206b5 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Sun, 29 Jan 2017 20:53:03 +0100 Subject: [PATCH 08/42] Git version fix for macOS files. --- tools/osx/Info.plist.in | 6 +++--- tools/osx/macosx_bundle.sh | 37 +++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/tools/osx/Info.plist.in b/tools/osx/Info.plist.in index 5b08d63a1..e78db0cc4 100644 --- a/tools/osx/Info.plist.in +++ b/tools/osx/Info.plist.in @@ -111,7 +111,7 @@ CFBundleExecutable rawtherapee CFBundleGetInfoString - @version@, Copyright © 2004-2010 Gábor Horváth, 2010-2016 RT dev team + @version@, Copyright © 2004-2010 Gábor Horváth, 2010-2017 RawTherapee Development Team CFBundleIconFile rawtherapee.icns CFBundleIdentifier @@ -127,7 +127,7 @@ CFBundleSignature ???? CFBundleVersion - @version@ + @shortVersion@ LSExecutableArchitectures @arch@ @@ -135,7 +135,7 @@ NSHighResolutionCapable NSHumanReadableCopyright - Copyright © 2004-2013 Gábor Horváth + Copyright © 2004-2010 Gábor Horváth, 2010-2017 RawTherapee Development Team UTExportedTypeDeclarations diff --git a/tools/osx/macosx_bundle.sh b/tools/osx/macosx_bundle.sh index 2803396ba..89e0c23b0 100644 --- a/tools/osx/macosx_bundle.sh +++ b/tools/osx/macosx_bundle.sh @@ -33,12 +33,33 @@ fi # update project version if test -x "$(which git)" -a -d "${PROJECT_SOURCE_DIR}/.git"; then - # This is what the version ought to look like to be accurate in the git universe: - PROJECT_FULL_VERSION="$(git describe --tags --always | sed 's/-g.*//')_$(git symbolic-ref --short -q HEAD)" - # outputs: 4.2-677-g904467b_master - # but Apple requirements https://goo.gl/eWDQv6 state we should use this: - PROJECT_VERSION="$(git describe --tags --always | sed -e 's/-g.*//' -e 's/-/./')" - # outputs: 4.2.677 + ### This section is copied from tools/generateReleaseInfo + # Get version description. + # Depending on whether you checked out a branch (dev) or a tag (release), + # "git describe" will return "5.0-gtk2-2-g12345678" or "5.0-gtk2", respectively. + gitDescribe="$(git describe --tags --always)" + + # Apple requires a numeric version of the form n.n.n + # https://goo.gl/eWDQv6 + + # Get number of commits since tagging. This is what gitDescribe uses. + # Works when checking out branch, tag or commit. + gitCommitsSinceTag="$(git rev-list --count HEAD --not $(git tag --merged HEAD))" + + # Create numeric version. + # This version is nonsense, either don't use it at all or use it only where you have no other choice, e.g. Inno Setup's VersionInfoVersion. + # Strip everything after hyphen, e.g. "5.0-gtk2" -> "5.0", "5.1-rc1" -> "5.1" (ergo BS). + if [[ -z $gitCommitsSinceTag ]]; then + gitVersionNumericBS="0.0.0" + else + gitVersionNumericBS="${gitDescribe%%-*}" # Remove everything after first hyphen. + gitVersionNumericBS="${gitVersionNumericBS}.${gitCommitsSinceTag}" # Remove everything until after first hyphen: 5.0 + fi + ### Copy end. + + PROJECT_FULL_VERSION="$gitDescribe" + PROJECT_VERSION="$gitVersionNumericBS" + fi # if not specify CMAKE_OSX_DEPLOYMENT_TARGET when compiling, @@ -85,7 +106,7 @@ ETC="${MACOS}"/etc EXECUTABLE="${MACOS}"/rawtherapee message "Removing old files" -rm -rf "${APP}" ${PROJECT_NAME}_*.dmg +rm -rf "${APP}" "${PROJECT_NAME}_*.dmg" message "Creating bundle container" install -d "${RESOURCES}" \ @@ -163,7 +184,7 @@ install -m 0755 "${PROJECT_SOURCE_DATA_DIR}"/executable_loader.in "${MACOS}"/raw cp "${PROJECT_SOURCE_DATA_DIR}"/{rawtherapee,profile}.icns "${RESOURCES}" cp "${PROJECT_SOURCE_DATA_DIR}"/PkgInfo "${CONTENTS}" install -m 0644 "${PROJECT_SOURCE_DATA_DIR}"/Info.plist.in "${CONTENTS}"/Info.plist -sed -i "" -e "s|@version@|${PROJECT_VERSION}| +sed -i "" -e "s|@version@|${PROJECT_FULL_VERSION}| s|@shortVersion@|${PROJECT_VERSION}| s|@arch@|${arch}|" \ "${CONTENTS}"/Info.plist From bc19897bc782cbee7994a1eaa3769de834a8f1e1 Mon Sep 17 00:00:00 2001 From: Hombre Date: Mon, 30 Jan 2017 01:32:36 +0100 Subject: [PATCH 09/42] Changed AppId value for InnoSetup installer (#3628) --- tools/win/InnoSetup/WindowsInnoSetup.iss.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/win/InnoSetup/WindowsInnoSetup.iss.in b/tools/win/InnoSetup/WindowsInnoSetup.iss.in index 82aa7a60d..55305d5f0 100644 --- a/tools/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/tools/win/InnoSetup/WindowsInnoSetup.iss.in @@ -35,7 +35,7 @@ ; NOTE: The value of AppId uniquely identifies this application. ; Do not use the same AppId value in installers for other applications. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) -AppId={{128459AB-59A7-430A-8BD0-3D8803D50400} +AppId={#MyAppName}{#MyAppVersion} AppName={#MyAppName} AppVersion={#MyAppVersion} VersionInfoVersion={#MyAppVersionNumeric} From 139df58adeb46792500dc2f283731d334177a919 Mon Sep 17 00:00:00 2001 From: Beep6581 Date: Mon, 30 Jan 2017 22:47:27 +0100 Subject: [PATCH 10/42] Unimportant typo fixed --- tools/generateReleaseInfo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/generateReleaseInfo b/tools/generateReleaseInfo index b7480e875..fa71638bd 100755 --- a/tools/generateReleaseInfo +++ b/tools/generateReleaseInfo @@ -72,5 +72,5 @@ printf '%s\n' "Git information extracted:" \ " Commit date: ${gitCommitDate}" \ " Commits since tag: ${gitCommitsSinceTag}" \ " Commits since branch: ${gitCommitsSinceBranch}" \ - " Unreliable verison: ${gitVersionNumericBS}" \ + " Unreliable version: ${gitVersionNumericBS}" \ "" From 03919242b1407dbc36ba5587b85f90b5c2300734 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 30 Jan 2017 22:50:21 +0100 Subject: [PATCH 11/42] Consistency between generateReleaseInfo and UpdateInfo.cmake --- tools/generateReleaseInfo | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/generateReleaseInfo b/tools/generateReleaseInfo index fa71638bd..ee3493e70 100755 --- a/tools/generateReleaseInfo +++ b/tools/generateReleaseInfo @@ -65,12 +65,12 @@ set(GIT_COMMITS_SINCE_BRANCH $gitCommitsSinceBranch) set(GIT_VERSION_NUMERIC_BS $gitVersionNumericBS) EOF -printf '%s\n' "Git information extracted:" \ - " Description: ${gitDescribe}" \ +printf '%s\n' "Git checkout information:" \ + " Commit description: ${gitDescribe}" \ " Branch: ${gitBranch}" \ " Commit: ${gitCommit}" \ " Commit date: ${gitCommitDate}" \ " Commits since tag: ${gitCommitsSinceTag}" \ " Commits since branch: ${gitCommitsSinceBranch}" \ - " Unreliable version: ${gitVersionNumericBS}" \ + " Version (unreliable): ${gitVersionNumericBS}" \ "" From 06c820ea8ab15a8d7e2254c6eaa5895d029fd0b2 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 30 Jan 2017 23:11:14 +0100 Subject: [PATCH 12/42] Release notes Package Maintainers section updated. --- RELEASE_NOTES.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index bfb32545d..38f8f82bc 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -37,9 +37,10 @@ New Features: News Relevant to Package Maintainers ------------------------------------ -- Branch "master" uses GTK2, branch "gtk3" requires GTK+ >=3.16. -- There are known bugs using GTK+ versions 3.20-3.22 where scrollbars may appear stuck (issue #3545) and where the Retinex tool's "Gain and Offset" panel may appear under the "Transmission" panel (issue #3525) until the user hovers the mouse cursor over a curve button. For this reason we recommend using GTK+ 3.16-3.18 if possible. +- Branch "master" uses GTK2, branch "gtk3" requires GTK+ >=3.16. There are known bugs using GTK+ versions 3.20-3.22 where scrollbars may appear stuck (issue #3545) and where the Retinex tool's "Gain and Offset" panel may appear under the "Transmission" panel (issue #3525) until the user hovers the mouse cursor over a curve button. For this reason we recommend using GTK+ 3.16-3.18 if possible. - RawTherapee 5 requires GCC-4.9 or higher, or Clang. +- Do not use -ffast-math +- Use -o3 - Use -DCMAKE_CXX_FLAGS="-std=c++11" - For stable builds (RT5) use -DCACHE_NAME_SUFFIX="" - For development builds use -DCACHE_NAME_SUFFIX="5-dev" From 9117f5f4386a12742eb6e7d0bdc68e6ce8dad7bb Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 30 Jan 2017 23:44:40 +0100 Subject: [PATCH 13/42] astyle'd rtgui/options.cc to help merge --- rtgui/options.cc | 62 ++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/rtgui/options.cc b/rtgui/options.cc index 7d3475ef6..215719363 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -2098,41 +2098,41 @@ int Options::saveToFile (Glib::ustring fname) keyFile.set_double ("Sounds", "LngEditProcDoneSecs", sndLngEditProcDoneSecs); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpening" , fastexport_bypass_sharpening ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenEdge" , fastexport_bypass_sharpenEdge ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenMicro" , fastexport_bypass_sharpenMicro ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpening", fastexport_bypass_sharpening ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenEdge", fastexport_bypass_sharpenEdge ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenMicro", fastexport_bypass_sharpenMicro ); //keyFile.set_boolean ("Fast Export", "fastexport_bypass_lumaDenoise" , fastexport_bypass_lumaDenoise ); //keyFile.set_boolean ("Fast Export", "fastexport_bypass_colorDenoise" , fastexport_bypass_colorDenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_defringe" , fastexport_bypass_defringe ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise" , fastexport_bypass_dirpyrDenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sh_hq" , fastexport_bypass_sh_hq ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer" , fastexport_bypass_dirpyrequalizer ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_wavelet" , fastexport_bypass_wavelet ); - keyFile.set_string ("Fast Export", "fastexport_raw_bayer_method" , fastexport_raw_bayer_method ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_defringe", fastexport_bypass_defringe ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise", fastexport_bypass_dirpyrDenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sh_hq", fastexport_bypass_sh_hq ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer", fastexport_bypass_dirpyrequalizer ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_wavelet", fastexport_bypass_wavelet ); + keyFile.set_string ("Fast Export", "fastexport_raw_bayer_method", fastexport_raw_bayer_method ); //keyFile.set_boolean ("Fast Export", "fastexport_bypass_bayer_raw_all_enhance" , fastexport_bypass_raw_bayer_all_enhance ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" , fastexport_bypass_raw_bayer_dcb_iterations ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" , fastexport_bypass_raw_bayer_dcb_enhance ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations", fastexport_bypass_raw_bayer_dcb_iterations ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance", fastexport_bypass_raw_bayer_dcb_enhance ); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations", fastexport_bypass_raw_bayer_lmmse_iterations); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" , fastexport_bypass_raw_bayer_linenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" , fastexport_bypass_raw_bayer_greenthresh ); - keyFile.set_string ("Fast Export", "fastexport_raw_xtrans_method" , fastexport_raw_xtrans_method ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" , fastexport_bypass_raw_ccSteps ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca" , fastexport_bypass_raw_ca ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df" , fastexport_bypass_raw_df ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ff" , fastexport_bypass_raw_ff ); - keyFile.set_string ("Fast Export", "fastexport_icm_input" , fastexport_icm_input ); - keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working ); - keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output ); - keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent ); - keyFile.set_boolean ("Fast Export", "fastexport_icm_output_bpc" , fastexport_icm_outputBPC ); - keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma ); - keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled ); - keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale ); - keyFile.set_string ("Fast Export", "fastexport_resize_appliesTo" , fastexport_resize_appliesTo ); - keyFile.set_string ("Fast Export", "fastexport_resize_method" , fastexport_resize_method ); - keyFile.set_integer ("Fast Export", "fastexport_resize_dataspec" , fastexport_resize_dataspec ); - keyFile.set_integer ("Fast Export", "fastexport_resize_width" , fastexport_resize_width ); - keyFile.set_integer ("Fast Export", "fastexport_resize_height" , fastexport_resize_height ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise", fastexport_bypass_raw_bayer_linenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh", fastexport_bypass_raw_bayer_greenthresh ); + keyFile.set_string ("Fast Export", "fastexport_raw_xtrans_method", fastexport_raw_xtrans_method ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps", fastexport_bypass_raw_ccSteps ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca", fastexport_bypass_raw_ca ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df", fastexport_bypass_raw_df ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ff", fastexport_bypass_raw_ff ); + keyFile.set_string ("Fast Export", "fastexport_icm_input", fastexport_icm_input ); + keyFile.set_string ("Fast Export", "fastexport_icm_working", fastexport_icm_working ); + keyFile.set_string ("Fast Export", "fastexport_icm_output", fastexport_icm_output ); + keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent", fastexport_icm_outputIntent ); + keyFile.set_boolean ("Fast Export", "fastexport_icm_output_bpc", fastexport_icm_outputBPC ); + keyFile.set_string ("Fast Export", "fastexport_icm_gamma", fastexport_icm_gamma ); + keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled", fastexport_resize_enabled ); + keyFile.set_double ("Fast Export", "fastexport_resize_scale", fastexport_resize_scale ); + keyFile.set_string ("Fast Export", "fastexport_resize_appliesTo", fastexport_resize_appliesTo ); + keyFile.set_string ("Fast Export", "fastexport_resize_method", fastexport_resize_method ); + keyFile.set_integer ("Fast Export", "fastexport_resize_dataspec", fastexport_resize_dataspec ); + keyFile.set_integer ("Fast Export", "fastexport_resize_width", fastexport_resize_width ); + keyFile.set_integer ("Fast Export", "fastexport_resize_height", fastexport_resize_height ); keyFile.set_string ("Dialogs", "LastIccDir", lastIccDir); keyFile.set_string ("Dialogs", "LastDarkframeDir", lastDarkframeDir); From eb14b15ea5e126d1676b6191ee099a519ba2859b Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 30 Jan 2017 23:45:03 +0100 Subject: [PATCH 14/42] astyle'd rtgui/options.cc to help merge --- rtgui/options.cc | 70 ++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/rtgui/options.cc b/rtgui/options.cc index 2b8203728..431ac40d5 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -1454,11 +1454,11 @@ int Options::readFromFile (Glib::ustring fname) } if (keyFile.has_key ("Color Management", "PrinterIntent")) { - rtSettings.printerIntent = static_cast(keyFile.get_integer("Color Management", "PrinterIntent")); + rtSettings.printerIntent = static_cast (keyFile.get_integer ("Color Management", "PrinterIntent")); } if (keyFile.has_key ("Color Management", "PrinterBPC")) { - rtSettings.printerBPC = keyFile.get_boolean("Color Management", "PrinterBPC"); + rtSettings.printerBPC = keyFile.get_boolean ("Color Management", "PrinterBPC"); } if (keyFile.has_key ("Color Management", "PrinterProfile")) { @@ -1486,7 +1486,7 @@ int Options::readFromFile (Glib::ustring fname) } if (keyFile.has_key ("Color Management", "MonitorBPC")) { - rtSettings.monitorBPC = keyFile.get_boolean("Color Management", "MonitorBPC"); + rtSettings.monitorBPC = keyFile.get_boolean ("Color Management", "MonitorBPC"); } if (keyFile.has_key ("Color Management", "CRI")) { @@ -1825,7 +1825,7 @@ bool Options::safeDirGet (const Glib::KeyFile& keyFile, const Glib::ustring& sec const Glib::ustring& entryName, Glib::ustring& destination) { try { - + if (keyFile.has_key (section, entryName) && !keyFile.get_string (section, entryName).empty ()) { destination = keyFile.get_string (section, entryName); return true; @@ -2103,41 +2103,41 @@ int Options::saveToFile (Glib::ustring fname) keyFile.set_double ("Sounds", "LngEditProcDoneSecs", sndLngEditProcDoneSecs); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpening" , fastexport_bypass_sharpening ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenEdge" , fastexport_bypass_sharpenEdge ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenMicro" , fastexport_bypass_sharpenMicro ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpening", fastexport_bypass_sharpening ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenEdge", fastexport_bypass_sharpenEdge ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sharpenMicro", fastexport_bypass_sharpenMicro ); //keyFile.set_boolean ("Fast Export", "fastexport_bypass_lumaDenoise" , fastexport_bypass_lumaDenoise ); //keyFile.set_boolean ("Fast Export", "fastexport_bypass_colorDenoise" , fastexport_bypass_colorDenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_defringe" , fastexport_bypass_defringe ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise" , fastexport_bypass_dirpyrDenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_sh_hq" , fastexport_bypass_sh_hq ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer" , fastexport_bypass_dirpyrequalizer ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_wavelet" , fastexport_bypass_wavelet ); - keyFile.set_string ("Fast Export", "fastexport_raw_bayer_method" , fastexport_raw_bayer_method ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_defringe", fastexport_bypass_defringe ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise", fastexport_bypass_dirpyrDenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_sh_hq", fastexport_bypass_sh_hq ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer", fastexport_bypass_dirpyrequalizer ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_wavelet", fastexport_bypass_wavelet ); + keyFile.set_string ("Fast Export", "fastexport_raw_bayer_method", fastexport_raw_bayer_method ); //keyFile.set_boolean ("Fast Export", "fastexport_bypass_bayer_raw_all_enhance" , fastexport_bypass_raw_bayer_all_enhance ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" , fastexport_bypass_raw_bayer_dcb_iterations ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" , fastexport_bypass_raw_bayer_dcb_enhance ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations", fastexport_bypass_raw_bayer_dcb_iterations ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance", fastexport_bypass_raw_bayer_dcb_enhance ); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations", fastexport_bypass_raw_bayer_lmmse_iterations); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" , fastexport_bypass_raw_bayer_linenoise ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" , fastexport_bypass_raw_bayer_greenthresh ); - keyFile.set_string ("Fast Export", "fastexport_raw_xtrans_method" , fastexport_raw_xtrans_method ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" , fastexport_bypass_raw_ccSteps ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca" , fastexport_bypass_raw_ca ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df" , fastexport_bypass_raw_df ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ff" , fastexport_bypass_raw_ff ); - keyFile.set_string ("Fast Export", "fastexport_icm_input" , fastexport_icm_input ); - keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working ); - keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output ); - keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent ); - keyFile.set_boolean ("Fast Export", "fastexport_icm_output_bpc" , fastexport_icm_outputBPC ); - keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma ); - keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled ); - keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale ); - keyFile.set_string ("Fast Export", "fastexport_resize_appliesTo" , fastexport_resize_appliesTo ); - keyFile.set_string ("Fast Export", "fastexport_resize_method" , fastexport_resize_method ); - keyFile.set_integer ("Fast Export", "fastexport_resize_dataspec" , fastexport_resize_dataspec ); - keyFile.set_integer ("Fast Export", "fastexport_resize_width" , fastexport_resize_width ); - keyFile.set_integer ("Fast Export", "fastexport_resize_height" , fastexport_resize_height ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise", fastexport_bypass_raw_bayer_linenoise ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh", fastexport_bypass_raw_bayer_greenthresh ); + keyFile.set_string ("Fast Export", "fastexport_raw_xtrans_method", fastexport_raw_xtrans_method ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps", fastexport_bypass_raw_ccSteps ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca", fastexport_bypass_raw_ca ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df", fastexport_bypass_raw_df ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ff", fastexport_bypass_raw_ff ); + keyFile.set_string ("Fast Export", "fastexport_icm_input", fastexport_icm_input ); + keyFile.set_string ("Fast Export", "fastexport_icm_working", fastexport_icm_working ); + keyFile.set_string ("Fast Export", "fastexport_icm_output", fastexport_icm_output ); + keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent", fastexport_icm_outputIntent ); + keyFile.set_boolean ("Fast Export", "fastexport_icm_output_bpc", fastexport_icm_outputBPC ); + keyFile.set_string ("Fast Export", "fastexport_icm_gamma", fastexport_icm_gamma ); + keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled", fastexport_resize_enabled ); + keyFile.set_double ("Fast Export", "fastexport_resize_scale", fastexport_resize_scale ); + keyFile.set_string ("Fast Export", "fastexport_resize_appliesTo", fastexport_resize_appliesTo ); + keyFile.set_string ("Fast Export", "fastexport_resize_method", fastexport_resize_method ); + keyFile.set_integer ("Fast Export", "fastexport_resize_dataspec", fastexport_resize_dataspec ); + keyFile.set_integer ("Fast Export", "fastexport_resize_width", fastexport_resize_width ); + keyFile.set_integer ("Fast Export", "fastexport_resize_height", fastexport_resize_height ); keyFile.set_string ("Dialogs", "LastIccDir", lastIccDir); keyFile.set_string ("Dialogs", "LastDarkframeDir", lastDarkframeDir); From 9ce41d8e91958cc78fffdd81a095c4e1f4e65e68 Mon Sep 17 00:00:00 2001 From: Hombre Date: Tue, 31 Jan 2017 00:22:54 +0100 Subject: [PATCH 15/42] Fix deprecated Glib::RecMutex on Windows + remove useless GThreadEnter (no issue) --- rtgui/filebrowser.cc | 1 - rtgui/main.cc | 4 ---- 2 files changed, 5 deletions(-) diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index b11361db2..841c2082a 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -601,7 +601,6 @@ void FileBrowser::addEntry (FileBrowserEntry* entry) void FileBrowser::addEntry_ (FileBrowserEntry* entry) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected entry->selected = false; entry->drawable = false; entry->framed = editedFiles.find (entry->filename) != editedFiles.end(); diff --git a/rtgui/main.cc b/rtgui/main.cc index a8ded72e5..d21904f23 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -89,11 +89,7 @@ Glib::ustring fname_to_utf8 (const char* fname) } // This recursive mutex will be used by gdk_threads_enter/leave instead of a simple mutex -#ifdef WIN32 -static Glib::RecMutex myGdkRecMutex; -#else static Glib::Threads::RecMutex myGdkRecMutex; -#endif static void myGdkLockEnter() { From 601a05a402e0a1d48d4ed514edb320d631437e48 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Tue, 31 Jan 2017 10:28:44 +0100 Subject: [PATCH 16/42] Removed "std=c++11" from release notes. --- RELEASE_NOTES.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 38f8f82bc..725844203 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -41,7 +41,6 @@ News Relevant to Package Maintainers - RawTherapee 5 requires GCC-4.9 or higher, or Clang. - Do not use -ffast-math - Use -o3 -- Use -DCMAKE_CXX_FLAGS="-std=c++11" - For stable builds (RT5) use -DCACHE_NAME_SUFFIX="" - For development builds use -DCACHE_NAME_SUFFIX="5-dev" - Windows builders should compile on a drive letter which users are most unlikely to have, such as Y:, due to the "There is no disk in the drive" error (issue #3544). From 968d991d97fc2c7d57712d7cd860c077be712ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Tue, 31 Jan 2017 20:47:18 +0100 Subject: [PATCH 17/42] Fix call to `abs()` with `unsigned int` (fixes #3339, #3652) --- rtengine/dcraw.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 4a5e7f1c8..a3bd3e523 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -2011,7 +2011,7 @@ void CLASS hasselblad_correct() {bhu-1,0},{bhu-1,bwu/2},{bhu-1,bwu-1}}; for (col = 0; col < bw; col++) { for (i = 0; i < 9; i++) { - ushort dist = (ushort)sqrt(abs(corners[i][0] - row) * abs(corners[i][0] - row) + abs(corners[i][1] - col) * abs(corners[i][1] - col)); + ushort dist = (ushort)sqrt(abs((int)(corners[i][0] - row)) * abs((int)(corners[i][0] - row)) + abs((int)(corners[i][1] - col)) * abs((int)(corners[i][1] - col))); ushort weight = dist > maxdist ? 0 : maxdist - dist; corners_weight[9*(row*bw+col)+i] = weight; } From 6c2cd39f30c467c9fb31667d12ee683045c3098e Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Tue, 31 Jan 2017 21:37:09 +0100 Subject: [PATCH 18/42] Added back the TooWaBlue theme + images for GTK+ 3.16-3.18. https://discuss.pixls.us/t/rawtherapee-5-released-congrats-to-the-team/3133/47 Revert "TooWaBlue updated to 2.31, theme images removed, #3604" This reverts commit 9f811772a96b905541b0f051cd15e8564e7285fc. --- rtdata/themes/TooWaBlue-GTK3-_19.css | 881 ++++++++++++++++++ .../svg/twb/checkbox-checked-disabled.svg | 124 +++ .../images/svg/twb/checkbox-checked.svg | 124 +++ .../twb/checkbox-inconsistent-disabled.svg | 124 +++ .../images/svg/twb/checkbox-inconsistent.svg | 124 +++ .../svg/twb/checkbox-unchecked-disabled.svg | 118 +++ .../images/svg/twb/checkbox-unchecked.svg | 118 +++ .../images/svg/twb/radio-checked-disabled.svg | 122 +++ .../themes/images/svg/twb/radio-checked.svg | 122 +++ .../svg/twb/radio-inconsistent-disabled.svg | 122 +++ .../images/svg/twb/radio-inconsistent.svg | 122 +++ .../svg/twb/radio-unchecked-disabled.svg | 116 +++ .../themes/images/svg/twb/radio-unchecked.svg | 116 +++ .../images/twb/checkbox-checked-disabled.png | Bin 0 -> 378 bytes rtdata/themes/images/twb/checkbox-checked.png | Bin 0 -> 428 bytes .../twb/checkbox-inconsistent-disabled.png | Bin 0 -> 265 bytes .../images/twb/checkbox-inconsistent.png | Bin 0 -> 295 bytes .../twb/checkbox-unchecked-disabled.png | Bin 0 -> 247 bytes .../themes/images/twb/checkbox-unchecked.png | Bin 0 -> 272 bytes .../images/twb/radio-checked-disabled.png | Bin 0 -> 524 bytes rtdata/themes/images/twb/radio-checked.png | Bin 0 -> 593 bytes .../twb/radio-inconsistent-disabled.png | Bin 0 -> 556 bytes .../themes/images/twb/radio-inconsistent.png | Bin 0 -> 631 bytes .../images/twb/radio-unchecked-disabled.png | Bin 0 -> 438 bytes rtdata/themes/images/twb/radio-unchecked.png | Bin 0 -> 503 bytes 25 files changed, 2333 insertions(+) create mode 100644 rtdata/themes/TooWaBlue-GTK3-_19.css create mode 100644 rtdata/themes/images/svg/twb/checkbox-checked-disabled.svg create mode 100644 rtdata/themes/images/svg/twb/checkbox-checked.svg create mode 100644 rtdata/themes/images/svg/twb/checkbox-inconsistent-disabled.svg create mode 100644 rtdata/themes/images/svg/twb/checkbox-inconsistent.svg create mode 100644 rtdata/themes/images/svg/twb/checkbox-unchecked-disabled.svg create mode 100644 rtdata/themes/images/svg/twb/checkbox-unchecked.svg create mode 100644 rtdata/themes/images/svg/twb/radio-checked-disabled.svg create mode 100644 rtdata/themes/images/svg/twb/radio-checked.svg create mode 100644 rtdata/themes/images/svg/twb/radio-inconsistent-disabled.svg create mode 100644 rtdata/themes/images/svg/twb/radio-inconsistent.svg create mode 100644 rtdata/themes/images/svg/twb/radio-unchecked-disabled.svg create mode 100644 rtdata/themes/images/svg/twb/radio-unchecked.svg create mode 100644 rtdata/themes/images/twb/checkbox-checked-disabled.png create mode 100644 rtdata/themes/images/twb/checkbox-checked.png create mode 100644 rtdata/themes/images/twb/checkbox-inconsistent-disabled.png create mode 100644 rtdata/themes/images/twb/checkbox-inconsistent.png create mode 100644 rtdata/themes/images/twb/checkbox-unchecked-disabled.png create mode 100644 rtdata/themes/images/twb/checkbox-unchecked.png create mode 100644 rtdata/themes/images/twb/radio-checked-disabled.png create mode 100644 rtdata/themes/images/twb/radio-checked.png create mode 100644 rtdata/themes/images/twb/radio-inconsistent-disabled.png create mode 100644 rtdata/themes/images/twb/radio-inconsistent.png create mode 100644 rtdata/themes/images/twb/radio-unchecked-disabled.png create mode 100644 rtdata/themes/images/twb/radio-unchecked.png diff --git a/rtdata/themes/TooWaBlue-GTK3-_19.css b/rtdata/themes/TooWaBlue-GTK3-_19.css new file mode 100644 index 000000000..24442aae3 --- /dev/null +++ b/rtdata/themes/TooWaBlue-GTK3-_19.css @@ -0,0 +1,881 @@ +/* + This file is part of RawTherapee. + + Copyright (c) 2016 TooWaBoo (v1.19.4) + Many thanks to the RawTherapee Developer Team for this great piece of software + + RawTherapee 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 3 of the License, or + (at your option) any later version. + + RawTherapee 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 RawTherapee. If not, see . +*/ + +/*** Change me *** rgb(red,green,blue) *** allowed values from 0 to 255 for each color ***/ + +@define-color accent-color rgb(35,99,166); /*** Highlight/selected color for Tab indicator, List, Dropdown menu, Borders ... ***/ +@define-color text-hl-color rgb(210,210,210); /*** Highlight/selected text color ***/ + +@define-color accent-color2 rgb(35,99,166); /*** Slider, Progressbar, Scrollbar ***/ +@define-color accent-color4 rgb(35,99,166); /*** Slider knob ***/ + +@define-color accent-color3 rgb(35,99,166); /*** Selected thumbnail background color ***/ +@define-color text-hl-color3 rgb(210,210,210); /*** Selected thumbnail text color ***/ + +/*** Change me end ************************************************************************/ + +@define-color text-color rgb(180,180,180); +@define-color text-hl-color2 rgb(192,192,192); +@define-color text-tbEntry rgb(192,192,192); +@define-color bg-dark-grey rgb(36,36,36); +@define-color bg-grey rgb(70,70,70); +@define-color bg-light-grey rgb(88,88,88); +@define-color border-color rgba(255,255,255,.25); +@define-color bg-list-hover rgba(255,255,255,.065); +@define-color bg-scale-entry rgba(0,0,0,.14); +@define-color bg-button-border rgba(0,0,0,.48); +@define-color bg-button-border-hover rgba(0,0,0,.58); +@define-color bg-entry-border rgba(0,0,0,.40); +@define-color bg-button-hover rgba(0,0,0,.22); +@define-color bg-spin-button-hover rgba(0,0,0,.25); +@define-color bg-entry-IPTC @bg-dark-grey; +@define-color view-grid-border rgb(64,64,64); + +* { + color: @text-color; + transition: none; + text-shadow: none; + icon-shadow: none; + box-shadow: none; + outline-style: none; /* removes the ugly dotted focus line */ + border-image: none; + -GtkCheckButton-indicator-size: 16; + -GtkCheckMenuItem-indicator-size: 16; + -GtkCheckButton-indicator-spacing: 2; +} + +.undershoot { + background-image: none; /* removes the dotted scrollbar line */ +} +GtkWindow { + background-color: @bg-light-grey; +} +GtkDialog { + background-color: @bg-grey; + -GtkDialog-content-area-spacing: 7; + -GtkDialog-action-area-border: 0; + -GtkDialog-content-area-border: 8; +} + +GtkFontChooser, +GtkColorChooser { + -GtkDialog-action-area-border: 4; + -GtkDialog-content-area-border: 0; +} + +.frame { + border: none; +} +#PrefNotebook > .frame { + border: 1px solid rgba(0,0,0,.50); + border-top: none; +} +#BatchQueueButtonsMainContainer GtkFrame { + padding: 4px 4px 4px 10px; +} + +/*** Add space between buttons and image area***/ +#BeforeAfterContainer GtkFrame { + padding: 2px 0 4px; +} +/*** Add space between before/after image ***/ +#BeforeAfterContainer GtkContainer:nth-child(1) > GtkContainer:nth-child(2) GtkFrame { + padding-right: 14px; +} + +/*** Menu bubble box ***/ +GtkPopover { + background-color: @bg-grey; + border: 1px solid @accent-color; + border-radius: 0; +} + +.menu { + background-color: @bg-dark-grey; + border: 1px solid @accent-color; +} +.menu > .menuitem { + padding: 2px 4px; +} +.menu > .menuitem:hover { + background-color: @accent-color; +} +.menu > .menuitem:hover > * > *, +.menu > .menuitem:hover > * { + color: @text-hl-color; +} + +GtkNotebook { + padding: 4px; + background-color: @bg-light-grey; +} +GtkDialog GtkNotebook { + padding: 2px 0 0; +} +#PrefNotebook { + padding: 4px 8px; +} +#RightNotebook { + padding: 0 0 0 4px; +} + +GtkPaned { + -GtkPaned-handle-size: 4px; + background-color: transparent; +} +.pane-separator { + background-color: @bg-light-grey; +} +GtkDialog .pane-separator { + background-color: @bg-grey; +} + +/*** Separator ***/ +.separator { + color: @bg-light-grey; +} +GtkDialog .separator { + color: @border-color; +} +#RightNotebook .separator { + color: @bg-dark-grey; +} + /*** Navigator ***/ +#Navigator .separator { + color: @view-grid-border; +} +/*** end ***/ + +/*** Background color image area***/ +GtkDrawingArea { + background-color: @bg-grey; + border: 1px solid rgba(0,0,0,.32); +} +/*** Histogram ***/ +#HistogramPanel, +#HistogramArea { + background-color: @bg-dark-grey; + border: none; +} +/*** Histogram RGB-Bar***/ +#HistogramRGBArea { + background-color: rgb(128,128,128); + border: none; +} +/*** Navigator ***/ +#Navigator GtkDrawingArea { + background-color: @bg-dark-grey; + border: 1px solid @bg-dark-grey; +} +#Navigator { + background-color: @bg-dark-grey; + border-top: 156px solid @bg-light-grey; +} + +#RightNotebook GtkDrawingArea { + background-color: @bg-dark-grey; +} + +/*** Label ***/ + .label { + padding: 0 4px; +} + /*** Increase space between labels in navigater ***/ +#Navigator .label { + padding: 6px 0 3px; +} +#Navigator GtkTable .label { + padding: 0 0 4px; +} + /***/ +GtkDialog .label, +#ToolPanelNotebook .label, +.notebook tab .label { + padding: 0 1px; +} +.button .label { + padding: 0; +} + + /*** Add left and right space between frame and labels ***/ +.frame > .label, +#ToolPanelNotebook .frame > .label { + padding: 4px; +} +#BatchQueueButtonsMainContainer GtkFrame:nth-child(3) > .label{ + padding: 2px 0px 4px; +} + +#MyExpanderTitle .label { + padding: 2px 3px; +} +/*** end ***/ + +.tooltip { + border-radius: 0; + padding: 0; +} +.tooltip.background { + background-color: @bg-dark-grey; + border: 1px solid @accent-color; +} + +/*** PartialPaste ***/ +#PartialPaste:nth-child(2) { + background-color: @bg-light-grey; + border: 1px solid rgba(0,0,0,.50); +} +#PartialPaste > .frame { + padding: 8px 10px; +} +#PartialPasteHeaderSep { + color: rgb(192,192,192); +} +#PartialPasteHeader .label { + color: rgb(213,213,213); +} +/*** end ***/ + +/*** Scrollbar ***/ +.scrollbar.trough { + background-color: rgba(0,0,0,.38); + background-image: none; + border: none; +} +.scrollbar.slider:active { + background-color: shade(@accent-color2,1.12); +} + +/*** end ***/ + +/*** Scale & Progressbar ***/ +.scale { + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px rgba(242, 242, 242, 0.1); + -GtkRange-trough-border: 6; + -GtkScale-slider-length: 15; + -GtkRange-slider-width: 15; +} +.scale.trough, +#ToolPanelNotebook .scale.trough { + background-color: @bg-scale-entry; + border-color: @bg-dark-grey; + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px rgba(242, 242, 242, 0.1); +} +.scale.trough.highlight, +#ToolPanelNotebook .scale.trough.highlight { + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px rgba(242, 242, 242, 0.1); + background-image: none; + background-color: @accent-color2; + border: 1px solid @bg-dark-grey; + color: @text-hl-color2; +} +.scale.slider, +#ToolPanelNotebook .scale.slider { + background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); + border: 1px solid shade(@bg-dark-grey, 1.25); + box-shadow: none; +} +.scale.fine-tune { + -GtkRange-trough-border: 5; +} +.scale.scale-has-marks-below { + -GtkRange-trough-border: 6; + -GtkScale-slider-length: 6; + -GtkRange-slider-width: 19; +} +.scale.slider.scale-has-marks-below { + border-radius: 0 0 20px 20px; + border: 1px solid @bg-dark-grey; +} +.scale.fine-tune.scale-has-marks-below { + -GtkRange-trough-border: 5; +} +.scale.slider:hover, +#ToolPanelNotebook .scale.slider:hover { + background-image: linear-gradient(to bottom, shade (@accent-color4,1.25), shade (@accent-color4,.95)); +} + +.scale.slider:active, +#ToolPanelNotebook .scale.slider:active { + background-image: linear-gradient(to bottom, shade (@accent-color4,1.25), shade (@accent-color4,.95)); +} + +GtkProgressBar { + -GtkProgressBar-min-vertical-bar-width: 8; + -GtkProgressBar-min-horizontal-bar-height: 8; + -GtkProgressBar-yspacing: 4px; + border-radius: 10px; + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px rgba(242, 242, 242, 0.1); +} +.progressbar { + background-image: none; + background-color: @accent-color2; + border-color: @bg-dark-grey; +} +GtkProgressBar.trough { + background-image: none; + background-color: @bg-scale-entry; +} +#MainNotebook > GtkGrid GtkProgressBar { + box-shadow: none; +} +#MainNotebook > GtkGrid GtkProgressBar.trough { + background-image: none; + background-color: @bg-dark-grey; + border-color: @bg-dark-grey; +} +/*** end ***/ + +/*** Load/Save ***/ +GtkFileChooserWidget { + background-color: @bg-grey; +} +GtkFileChooserWidget > GtkBox { + border-bottom-color: @bg-dark-grey; +} +GtkFileChooserWidget GtkBox { + background-color: transparent; +} +GtkFileChooserWidget GtkListBox * { + padding-top: 1px; + padding-bottom: 1px; +} +GtkFileChooserWidget GtkListBox { + background-color: @bg-dark-grey; +} +GtkFileChooserWidget .list-row * { + padding: 1px 4px; +} +GtkFileChooserWidget .list-row:hover { + background-color: @bg-list-hover; +} +GtkFileChooserWidget .list-row:hover * { + color: @text-hl-color2; +} +GtkFileChooserWidget .list-row:selected { + background-color: @accent-color; +} +GtkFileChooserWidget .list-row:selected * { + color: @text-hl-color; +} +/*** end ***/ + +/*** Tab Bars ***/ +.notebook tab, .notebook.header { + background-color: @bg-dark-grey; + border-color: @bg-dark-grey; +} +#MainNotebook tab { + padding: 5px; +} +.notebook tab.top { + border-width: 0 0 5px 0; +} +.notebook tab.left { + border-width: 0 5px 0 0; +} +#RightNotebook tab.left, +#PrefNotebook tab, +GtkDialog tab { + padding: 9px; +} +#ToolPanelNotebook tab { + padding: 10px 4px 7px; +} +#MetaPanelNotebook tab { + padding: 8px 4px; +} + +.notebook tab:active { + border-color: @accent-color; +} + +/*** end ***/ + +/*** File Browser ***/ +#FileBrowser GtkDrawingArea { + background-color: @bg-grey; +} +#FileBrowser GtkDrawingArea:selected { + background-color: @accent-color3; + color: @text-hl-color3; +} +/*** end ***/ + +/*** Image ***/ +GtkImage { + padding: 0; +} +#MainNotebook > GtkGrid GtkImage { + padding: 1px; +} + +#ToolPanelNotebook GtkImage{ + padding: 0 4px; +} +#MyExpanderTitle GtkImage{ + padding: 0; +} + +#ToolPanelNotebook tab GtkImage, +#ToolPanelNotebook .button GtkImage { + padding: 1px 0; +} + +GtkDialog .button GtkImage{ + padding: 0; +} +GtkFileChooserWidget .button GtkImage{ + padding: 0 4px; +} +/*** end ***/ + +/*** Toolpanel ***/ +#ToolPanelNotebook { + background-color: @bg-dark-grey; + padding: 0; + border-top: 4px solid @bg-dark-grey; +} + +#ToolPanelNotebook GtkScrolledWindow GtkViewport.frame { + padding: 0 4px; +} +#ToolPanelNotebook .separator { + color: transparent; +} +#ToolPanelNotebook GtkFrame, +#PrefNotebook GtkFrame { + border: 1px solid @border-color; + border-radius: 0; + padding: 5px; +} + +#ToolPanelNotebook GtkDrawingArea { + background-color: @bg-dark-grey; + border-color: @bg-light-grey; + color: @text-color; +} +#ToolPanelNotebook GtkDrawingArea { + border-radius: 1px; /* BUG: if 0, scale mini sliders look funny */ +} + +#ExpanderBox #ExpanderBox, +#ExpanderBox2, +#ExpanderBox3 { + border: 1px solid @border-color; +} + +#ExpanderBox, +#ExpanderBox2, +#ExpanderBox3 { + background-color: @bg-grey; + border-radius: 0; +} + +#MyExpanderTitle .label { + color: @text-color; +} +#MyExpanderTitle:hover .label { + color: @text-hl-color2; +} +/*** end ***/ + +/*** View ***/ +.view { + background-color: @bg-dark-grey; + border-color: @view-grid-border; +} +#PrefNotebook .view { + background-color: @bg-grey; +} +#MainNotebook .view.cell:nth-child(2) { + padding: 1px 0px 1px 4px; +} +.view row:hover { + background-color: @bg-list-hover; + color: @text-hl-color2; +} +#PrefNotebook .view row:hover { + background-color: @bg-light-grey; + color: @text-hl-color2; +} +.view row:selected { + color: @text-hl-color; + background-color: @accent-color; +} +#PrefNotebook .view row:selected { + color: @text-hl-color; + background-color: @accent-color; +} +/*** end ***/ + +/*** Metadata ***/ +#MetaPanelNotebook { + padding: 8px 11px 0; +} +#MetaPanelNotebook GtkScrolledWindow GtkViewport.frame { + padding: 8px 10px; +} +#MetaPanelNotebook.frame { + background-color: @bg-grey; + border-bottom: none; + border-top: 4px solid @bg-dark-grey; + border-left: 9px solid @bg-dark-grey; + border-right: 9px solid @bg-dark-grey; +} +#MetaPanelNotebook .separator { + color: @border-color; +} +#MetaPanelNotebook.header { + background-color: @bg-dark-grey; + +} +#MetaPanelNotebook GtkTreeView { + padding: 1px; + background-color: @bg-grey; +} +#MetaPanelNotebook .frame GtkTreeView { + padding: 0px; + background-color: @bg-entry-IPTC; +} +#MetaPanelNotebook GtkTreeView:hover, +#MetaPanelNotebook .frame GtkTreeView:hover { + background-color: @bg-list-hover; + color: @text-hl-color; +} +#MetaPanelNotebook GtkTreeView:selected, +#MetaPanelNotebook .frame GtkTreeView:selected { + color: @text-hl-color; + background-color: @accent-color; +} +#MetaPanelNotebook GtkTextView { + color: @text-color; + background-color: @bg-entry-IPTC; + padding: 2px 4px; +} +/*** end ***/ + +/*** Entry ***/ +.entry { + background-image: none; + background-color: @bg-scale-entry; + border: 1px solid @bg-entry-border; + border-radius: 0; + padding: 2px 4px; + color: @text-color; + box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242 , 242, 242, 0.1); +} +#FileBrowser .entry { + padding: 3px 4px; +} +.entry:focused:selected { + color: @text-hl-color; + background-color: @accent-color; +} +.entry:not(:focused):not(:insensitive) {/*Workaround*/ + color: @text-color; + background-color: transparent; +} +.entry:not(:selected):not(:insensitive) { + color: @text-color; + background-color: @bg-scale-entry; +} +#ToolPanelNotebook .entry { + padding: 0 4px 0 8px; + border-radius: 20px 0 0 20px; + background-color: rgba(255,255,255,.12); + border: 1px solid rgba(0,0,0,.46); + color: @text-tbEntry; + box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255 , 255, 255, 0.12); +} +#ToolPanelNotebook .entry:focused:selected { + color: @text-hl-color; + background-color: @accent-color; +} +#ToolPanelNotebook .entry:not(:focused):not(:insensitive) {/*Workaround*/ + color: @text-tbEntry; + background-color: transparent; +} +#ToolPanelNotebook .entry:not(:selected):not(:insensitive) { + color: @text-tbEntry; + background-color: rgba(255,255,255,.12); +} + +#MetaPanelNotebook .entry { + color: @text-color; + background-color: @bg-entry-IPTC; + border: none; + border-radius: 0; + padding: 2px 4px; + box-shadow: none; +} +#MetaPanelNotebook .entry:focused:selected { + color: @text-hl-color; + background-color: @accent-color; + box-shadow: none; +} +#MetaPanelNotebook .entry:not(:focused):not(:insensitive) {/*Workaround*/ + color: @text-color; + background-color: transparent; + box-shadow: none; +} +#MetaPanelNotebook .entry:not(:selected):not(:insensitive) { + color: @text-color; + background-color: @bg-entry-IPTC; + box-shadow: none; +} +/*** end ***/ + +/*** Buttons ***/ +.button { + background-color: transparent; + border: 1px solid @bg-button-border; + border-radius: 0; + padding: 3px 4px; + box-shadow: inset 0 1px rgba(242, 242, 242, 0.1), 0 1px rgba(242, 242, 242, 0.1); + background-image: linear-gradient(to bottom, rgba(0,0,0,.05), rgba(0,0,0,.14) 40%, rgba(0,0,0,.26)); +} +.message-dialog .dialog-action-area .button { + padding: 6px; + } + +.button.Left + .button:not(.image-button).Right { + border-left: none; +} +GtkComboBox .button { + padding: 4px 3px; +} +#ToolPanelNotebook .button, +GtkDialog .button, +#BatchQueueButtonsMainContainer .button { + padding: 0px 3px; +} +#BatchQueueButtons .button { + padding-top: 6px; + padding-bottom: 6px +} +#BeforeAfterContainer .button { + padding: 2px; +} + + /*** Fix: Space between first Retinex Comboboxes ***/ +GtkLabel + GtkComboBox + GtkComboBox { + padding-left: 4px; +} + +.text-button { + padding: 0 2px 0 0; +} +#PartialPaste .text-button { + padding: 0 8px 0 2px; + -GtkCheckButton-indicator-spacing: 1; +} +#ToolPanelNotebook GtkFrame > .text-button { + padding: 0 3px 0 0; +} + +.button.text-button { + padding: 5px 12px; +} +#ToolPanelNotebook .button.text-button, +#PrefNotebook .button.text-button, +GtkFileChooserWidget .button.text-button, +#RightNotebook .button.text-button { + padding: 3px 4px; +} +GtkPopover .button.text-button { + padding: 2px 4px; +} + +.spinbutton .button { + background-image: none; + background-color: transparent; + border: none; + border-radius: 0; + padding: 2px; + box-shadow: none; +} +#ToolPanelNotebook .spinbutton .button { + padding: 0; +} + +.button:hover { + background-color: rgba(0, 0, 0,.18); +} +#ToolPanelNotebook .spinbutton .button:hover { + background-color: @bg-spin-button-hover; +} + +.button:active, +.button:checked { + background-image: linear-gradient(to bottom, rgb(41,41,41), rgb(37,37,37) 40%, rgb(25,25,25)); + background-color: transparent; + border-color: black; +} + +#MainNotebook > GtkGrid .button { + padding: 2px; + border: 4px solid @bg-dark-grey; + background-color: transparent; + background-image: none; + box-shadow: none; +} +#MainNotebook tab .button { + padding: 1px; + border-top: 4px solid @bg-dark-grey; + border-bottom: 4px solid @bg-dark-grey; + border-left: none; + border-right: none; + background-color: transparent; + background-image: none; + box-shadow: none; +} +#MainNotebook > GtkGrid .button:hover, +#MainNotebook tab .button:hover { + background-color: rgba(255,255,255,.20); + box-shadow: inset 0 1px rgba(255, 255, 255, 0.12); + background-image: linear-gradient(to bottom, rgba(0,0,0,.05), rgba(0,0,0,.12) 40%, rgba(0,0,0,.24)); +} +#MainNotebook > GtkGrid .button:active, +#MainNotebook tab .button:active { + background-color: rgba(255,255,255,.27); + box-shadow: inset 0 1px rgba(255, 255, 255, 0.12); + background-image: linear-gradient(to bottom, rgba(0,0,0,.05), rgba(0,0,0,.12) 40%, rgba(0,0,0,.24)); +} +.view .button { + background-color: rgb(20,20,20); + padding: 1px 5px 2px; + background-image: none; + border-color: black; + box-shadow: none; +} +.menu .button.bottom, +.menu .button.bottom:insensitive { + background-color: rgb(20,20,20); + border-color: @accent-color; + border-width: 0 1px 1px 1px; + background-image: none; + box-shadow: none; +} +.menu .button.top, +.menu .button.top:insensitive { + background-color: rgb(20,20,20); + border-color: @accent-color; + border-width: 1px 1px 0 1px; + background-image: none; + box-shadow: none; +} +#fullButton, +#histButton { + padding: 5px; + border: none; + background-color: @bg-dark-grey; + background-image: none; + box-shadow: none; +} +/*** end ***/ + +/*** Check & Radio buttons ***/ +.check, +.check row { + -gtk-icon-source: url("images/twb/checkbox-unchecked.png"); +} +.check:checked, +.check row:checked { + -gtk-icon-source: url("images/twb/checkbox-checked.png"); +} +.check:insensitive, +.check row:insensitive { + -gtk-icon-source: url("images/twb/checkbox-unchecked-disabled.png"); +} +.check:checked:insensitive, +.check row:checked:insensitive { + -gtk-icon-source: url("images/twb/checkbox-checked-disabled.png"); +} +.check:inconsistent, +.check row:inconsistent { + -gtk-icon-source: url("images/twb/checkbox-inconsistent.png"); +} +.check:inconsistent:insensitive, +.check row:inconsistent:insensitive { + -gtk-icon-source: url("images/twb/checkbox-inconsistent-disabled.png"); +} + +.radio, +.radio row { + -gtk-icon-source: url("images/twb/radio-unchecked.png"); +} +.radio:checked, +.radio row:checked { + -gtk-icon-source: url("images/twb/radio-checked.png"); +} +.radio:insensitive, +.radio row:insensitive { + -gtk-icon-source: url("images/twb/radio-unchecked-disabled.png"); +} +.radio:checked:insensitive, +.radio row:checked:insensitive { + -gtk-icon-source: url("images/twb/radio-checked-disabled.png"); +} +.radio:inconsistent, +.radio row:inconsistent { + -gtk-icon-source: url("images/twb/radio-inconsistent.png"); +} +.radio:inconsistent:insensitive, +.radio row:inconsistent:insensitive { + -gtk-icon-source: url("images/twb/radio-inconsistent-disabled.png"); +} +/*** end ***/ + +/*** Disabled Items ***/ + +*:insensitive, +#ToolPanelNotebook *:insensitive { + color: rgb(128,128,128); + box-shadow: none; +} +#ToolPanelNotebook .entry:insensitive { + color: rgb(144,144,144); + background-color: rgba(255,255,255,.06); + box-shadow: none; +} +.button:insensitive { + background-image: none; + background-color: rgba(0,0,0,.10); + border-color: rgba(0,0,0,.30); + box-shadow: none; +} +.spinbutton .button:insensitive { + background-image: none; + background-color: transparent; + border: none; + box-shadow: none; +} +.scale.slider:insensitive, +.scale.trough.highlight:insensitive, +.scale.trough:insensitive, +#ToolPanelNotebook .scale.slider:insensitive, +#ToolPanelNotebook .scale.trough.highlight:insensitive, +#ToolPanelNotebook .scale.trough:insensitive { + background-color: rgb(65,65,65); + box-shadow: none; + background-image: none; +} +/*** end ***/ diff --git a/rtdata/themes/images/svg/twb/checkbox-checked-disabled.svg b/rtdata/themes/images/svg/twb/checkbox-checked-disabled.svg new file mode 100644 index 000000000..1103ee917 --- /dev/null +++ b/rtdata/themes/images/svg/twb/checkbox-checked-disabled.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/checkbox-checked.svg b/rtdata/themes/images/svg/twb/checkbox-checked.svg new file mode 100644 index 000000000..c7d28d45d --- /dev/null +++ b/rtdata/themes/images/svg/twb/checkbox-checked.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/checkbox-inconsistent-disabled.svg b/rtdata/themes/images/svg/twb/checkbox-inconsistent-disabled.svg new file mode 100644 index 000000000..ee55c4f6f --- /dev/null +++ b/rtdata/themes/images/svg/twb/checkbox-inconsistent-disabled.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/checkbox-inconsistent.svg b/rtdata/themes/images/svg/twb/checkbox-inconsistent.svg new file mode 100644 index 000000000..e0f5bd362 --- /dev/null +++ b/rtdata/themes/images/svg/twb/checkbox-inconsistent.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/checkbox-unchecked-disabled.svg b/rtdata/themes/images/svg/twb/checkbox-unchecked-disabled.svg new file mode 100644 index 000000000..635dae59b --- /dev/null +++ b/rtdata/themes/images/svg/twb/checkbox-unchecked-disabled.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/checkbox-unchecked.svg b/rtdata/themes/images/svg/twb/checkbox-unchecked.svg new file mode 100644 index 000000000..0adfe66cc --- /dev/null +++ b/rtdata/themes/images/svg/twb/checkbox-unchecked.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/radio-checked-disabled.svg b/rtdata/themes/images/svg/twb/radio-checked-disabled.svg new file mode 100644 index 000000000..f415b4be7 --- /dev/null +++ b/rtdata/themes/images/svg/twb/radio-checked-disabled.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/radio-checked.svg b/rtdata/themes/images/svg/twb/radio-checked.svg new file mode 100644 index 000000000..c6f9b4ee8 --- /dev/null +++ b/rtdata/themes/images/svg/twb/radio-checked.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/radio-inconsistent-disabled.svg b/rtdata/themes/images/svg/twb/radio-inconsistent-disabled.svg new file mode 100644 index 000000000..e41f3ff9c --- /dev/null +++ b/rtdata/themes/images/svg/twb/radio-inconsistent-disabled.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/radio-inconsistent.svg b/rtdata/themes/images/svg/twb/radio-inconsistent.svg new file mode 100644 index 000000000..65ea2a8e8 --- /dev/null +++ b/rtdata/themes/images/svg/twb/radio-inconsistent.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/radio-unchecked-disabled.svg b/rtdata/themes/images/svg/twb/radio-unchecked-disabled.svg new file mode 100644 index 000000000..60098048f --- /dev/null +++ b/rtdata/themes/images/svg/twb/radio-unchecked-disabled.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/rtdata/themes/images/svg/twb/radio-unchecked.svg b/rtdata/themes/images/svg/twb/radio-unchecked.svg new file mode 100644 index 000000000..8b448f3cf --- /dev/null +++ b/rtdata/themes/images/svg/twb/radio-unchecked.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/rtdata/themes/images/twb/checkbox-checked-disabled.png b/rtdata/themes/images/twb/checkbox-checked-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..8458b5987ff7050bfa6fa4733ac1fdb6c00b8092 GIT binary patch literal 378 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4Xgt=Z zV||aM?)TSwXR^xFPBI=>QOdNvdN%rpwJJlJ?MHEJ;>XkBwCQX}Er=siLBrCK`?fspE_9wcm zhaYe`b58L8dXo3wq<{V~9=EtHo{OcKiOslqTv7OUf%*-G literal 0 HcmV?d00001 diff --git a/rtdata/themes/images/twb/checkbox-checked.png b/rtdata/themes/images/twb/checkbox-checked.png new file mode 100644 index 0000000000000000000000000000000000000000..83d3744d3c627a13cc04fab355088f9547c3f4cb GIT binary patch literal 428 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4nhK;|bxBQuX(3GB>SSHDk)AewS05Vq|9(YNpQbs0(6Zi2QsZsz0eG`2Ans z$Z6X5cqEdipR=63>CE%b-0%NNH!uqBWst~c1q!WNwNO^$|D07^ch`f#=KW!>m5H&}12s)^IIUDHw(Q*O*#5+pmAN|n#&iY=`C01H zb0+07E4uh=mWl{CeR1N*b>w(BxucJ(ERo^Cu^GKnKK-e0{h!oxbIz%fXX3VXJqlm0 S1bYHQmci52&t;ucLK6TJt)}Jx literal 0 HcmV?d00001 diff --git a/rtdata/themes/images/twb/checkbox-inconsistent-disabled.png b/rtdata/themes/images/twb/checkbox-inconsistent-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..96c5fbe5f2a09eb89d3eb9b25ab3b0e545de3067 GIT binary patch literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4f;?skDA$93k5ia$#`{n=>KoF^QW144 zE@uvy9VuVLx?rM-%ua?WlWxWMGk7we{Kw%?#Azd09)2);(jSYxhi3n^KFG~b?Oh`N zEr*HW=`W8v;+IwP7(ajhvvj8=^P;8wg`pqY(pT#roTYhPyLh?~&_xWMu6{1-oD!M< DHcDHP literal 0 HcmV?d00001 diff --git a/rtdata/themes/images/twb/checkbox-inconsistent.png b/rtdata/themes/images/twb/checkbox-inconsistent.png new file mode 100644 index 0000000000000000000000000000000000000000..373f218be58be281a9fe270ec7d946e83f556ef2 GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4<` zTx6M>^h_u@#M?z!$*zjgrG&ZR=({$v~Fd+PR-U-&MYEzjb@P^dH6ryN;}G{kyHPIL}AZl=-%59aBiDUHpxy=YU>3eJ1s{ hL~PQtOS4zLVqI2d+!}eeM;Pc{22WQ%mvv4FO#s^ZYrOyf literal 0 HcmV?d00001 diff --git a/rtdata/themes/images/twb/checkbox-unchecked-disabled.png b/rtdata/themes/images/twb/checkbox-unchecked-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..985dd07cc239709ac9f75c1a3c37ac9c54ae0d41 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4b|U3J0F9t_qWH*PQRaU$~!nfzl=K-8KxfOl|fv z@F+d2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR43D3D49S*8GfEG9~WazOPL#Cay<{&iFof7p zHAQnoP3*`Bx|)}e|7g2{(zN2kb%lJ)3@OH|e<$-Krj?o$pJbnWO>d6Y6ebs-!x%hW L{an^LB{Ts5)@5O6 literal 0 HcmV?d00001 diff --git a/rtdata/themes/images/twb/radio-checked-disabled.png b/rtdata/themes/images/twb/radio-checked-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..0947a5e06a5a9b67e40811f66ce3071b45f5e41c GIT binary patch literal 524 zcmV+n0`vWeP)ZQcDvI+1*ie1z?P)J_*|TV zwSXDmqojUH{{`$h=MKF0?U487RRy8!ePBUSUs4rl0Q0~N(3EuOoXdOfe*hcfb|Qe# zvy;@f)~*5_;1e(fECL;C?OKu~&&C*+t{@7&3>*WDMx%OmP(iN+e*%2Y0zLqbA)fme zAhbiFQ1~74UjhEcaXcO3y9t0>fL^ax0{&zHXM@3D1;7}i2>=Ta^3Jk=9iZl%%QqU0 zBV$YzxCZ*bl`*C&>DW1!2a+g?cE^D9NBR!T=5o39BuSpL*M}!;1NV|P$9noBZ2>Ls z{ZDJ{c9`}9Py#C6`vf=wzNNu$c0tk-kluwy;5>?=-Fm%#IblBk(Ov)m=$0F&t&1f9 O0000Vr3`+raI1IeaGTNO-LsOZhCe4?)lz3 z-N8SGEGE)4ZHvgJst%oZt4(-$Igr7X*PQ52mmIxxmGJljM8Dr}EEbD2v=ZhUgh7DjJAkXuzaStn%$_ntv_>SQL zaII``4mh#=qT#UJZvRS>2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR42P&@K&#R-R_+gPNut)-({q`okIk@Ru6 z!sfedC&SseP33G(NssU67+L?{Zfw2#gS+cdhvk=7uD$+RdI8&!1MCLOzmz_05mrzV zd%-B~a6QVp?{S6U{PWrlvKdUm3lx`jAG3KY?xdgFax>@Hfl9#w79D=Z zDW{*7&!5j+6Pc~u&JeabRP=`q)3VH2adJ!_DlaQ7;5V6DytFoL|9pvLHp>S2lP;m{ zyA|qMoD;5OZJoEd;>QFj2mjFc+i%OR-~Yz6f~hprw?VK#x~cvztDq(Gq5T_J(vHn= etoZc*q8RU^pm3E32rm#Lxr37|cP{e) zL9)`pBS4FwNtKSq&B}K%ohAM}K=KSJ-~v^A=f;|)@gbihEK4-}s?lhF-^^-e;Ej^i zM3N+J5jhMYw1E%6UlF-c)$?w*d;2P2GMTtM&(DB;;AB3Zk6W$QeU@e0su}~wz*Q7Q zgHES2FMX~I7UqvdQGDw6`_rW&e}M1a`%CBCaPjVIrGq3%+Q5&ZD0WxO6?yNQ*4keo zgfHcH41kCn0;lWD0KH!CpNO1_$V&$XAcW91#{67oE~TntV6OrIwx-i*wh6#m`v7dM z0-kEM+V&=Z5W)`dSOJL0wR7%Z6M(870M`|Os-6SK-uvb{v-iF!B1guUiwa;dk}K!j z@HL3{zUiDBh7i&?j_=C+%OXWlG|2P(%v$?9P16%q9nWU7`+B{;1H>Y7q^fD7(fGCu t{_hq>qtWNZUX-_x0XN2&i{;AiN6)!|l0CFKsgM8w002ovPDHLkV1jeD;Q{~v literal 0 HcmV?d00001 From 8ef3005a54543a0699bec4a4be5e93216d65eea5 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Tue, 31 Jan 2017 22:44:48 +0100 Subject: [PATCH 19/42] TooWaBlue theme bumped to 2.42, closes #3651 --- rtdata/themes/TooWaBlue-Dark-GTK3-20_.css | 267 +++++++++++----------- rtdata/themes/TooWaBlue-GTK3-20_.css | 267 +++++++++++----------- 2 files changed, 266 insertions(+), 268 deletions(-) diff --git a/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css b/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css index 8cfce4f75..43d9a3035 100644 --- a/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-Dark-GTK3-20_.css @@ -2,7 +2,7 @@ This file is part of RawTherapee. Copyright (c) 2016-2017 TooWaBoo - Version 2.40 - requires RT 5.0 + Version 2.42 - requires RT 5.0 RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -69,7 +69,6 @@ outline-style: none; /* removes the ugly dashed focus line */ border-image: none; transition: none; - /* -gtk-dpi: 120; */ } *:disabled { @@ -77,10 +76,10 @@ } #ToolPanelNotebook { - min-width: 23em + min-width: 23em; } #HistoryPanel { - min-width: 17.83333em + min-width: 17.83334em; } window.background { @@ -107,7 +106,7 @@ messagedialog { tooltip { background-color: @bg-tooltip; border: 1px solid @border-tooltip; - border-radius: 0.33333em; + border-radius: 0.33334em; padding: 0; margin: 0; box-shadow: none; @@ -205,7 +204,7 @@ dialog frame > label { padding: 0.16667em 0.5em; } #BatchQueueButtonsMainContainer frame > border { - margin-bottom: 0.8334em; + margin-bottom: 0.83334em; } #BatchQueueButtonsMainContainer frame:nth-child(3) > border { padding-left: 0.91667em; @@ -232,10 +231,6 @@ textview.view, treeview.view { padding: 0.16667em; margin: 0; } -#RightNotebook > stack > :nth-child(3) treeview { - border: 1px solid @bg-dark-grey; - border-bottom: none; -} textview:hover, treeview:hover { background-color: @bg-list-hover; } @@ -245,8 +240,13 @@ textview:selected, treeview:selected { border-top-color: transparent; } +#RightNotebook > stack > :nth-child(3) treeview { + border: 1px solid @bg-dark-grey; + border-bottom: none; +} + #PlacesPaned > :nth-child(1) treeview { - padding: 0.0834em 0 0.0834em 0.5em; + padding: 0.08334em 0 0.08334em 0.5em; -gtk-icon-style: symbolic; } @@ -257,7 +257,7 @@ textview:selected, treeview:selected { margin-top: 1.75em; } #HistoryPanel > label { - margin: 0 0 -1.3334em 0; + margin: 0 0 -1.33334em 0; padding: 0; } @@ -285,7 +285,7 @@ textview:selected, treeview:selected { /*Corrects the space for the snapshot view of the paned separator*/ #Snapshots { - margin-top: -0.3334em; + margin-top: -0.33334em; } /**/ @@ -381,7 +381,7 @@ filechooser list row:selected { border-radius: 0; } #fullButton { - padding: 0.47em 0.41667em 0.58333em; + padding: 0.47em 0.41667em 0.58334em; } #EditorLeftPaned #fullButton, #EditorLeftPaned #histButton { @@ -433,7 +433,7 @@ paned.vertical > separator { dialog paned.horizontal > separator { background-color: @bg-grey; border-color: @bg-grey; - min-width: 0.33333em; + min-width: 0.33334em; } menu separator { @@ -451,13 +451,13 @@ menu separator { #IopsPanel separator, #FileBrowser separator { background-color: shade(@bg-light-grey,.75); - margin-top: 0.33333em; - margin-bottom: 0.33333em; + margin-top: 0.33334em; + margin-bottom: 0.33334em; } #MyExpander separator { background-color: shade(@bg-grey,.7); - margin: 0.33333em 0.66667em; + margin: 0.33334em 0.66667em; } #PlacesPaned .view.separator { @@ -474,7 +474,7 @@ menu separator { } #PartialPaste separator.vertical { - margin: 0 0.33333em; + margin: 0 0.33334em; padding: 0; } @@ -498,7 +498,7 @@ menu separator { /*** Scrollbar *********************************************************************************/ scrollbar { - background-color: rgba(0,0,0,.45); + background-color: rgba(0,0,0,.40); border: none; margin: 0; padding: 0; @@ -542,7 +542,7 @@ scrollbar.horizontal.hovering.fine-tune slider { scrollbar.horizontal.overlay-indicator:not(.hovering) slider { min-width: 2em; min-height: 0.25em; - border-width: 0.0834em; + border-width: 0.08334em; border-radius: 0.25em; margin: 0 0.16667em; } @@ -562,7 +562,7 @@ scrollbar.vertical.hovering.fine-tune slider { scrollbar.vertical.overlay-indicator:not(.hovering) slider { min-width: 0.25em; min-height: 2em; - border-width: 0.0834em; + border-width: 0.08334em; border-radius: 0.5em; margin: 0.16667em 0; } @@ -573,11 +573,8 @@ scrollbar slider:hover { } /* Scrollbar stuck workaround */ -scrollbar:not(.overlay-indicator).horizontal:hover slider { - min-width: calc(2em - 0.0001px); -} -scrollbar:not(.overlay-indicator).vertical:hover slider { - min-height: calc(2em - 0.0001px); +scrollbar:not(.overlay-indicator):hover { + min-width: 1px; } /*** end ***************************************************************************************/ @@ -585,7 +582,7 @@ scrollbar:not(.overlay-indicator).vertical:hover slider { /*** Scale**************************************************************************************/ scale { padding: 0; - min-height: 1.83333em; + min-height: 1.83334em; margin: 0 0.25em; } @@ -593,8 +590,8 @@ scale slider { /* Slider size is min-width x min-height; margin have to be half of those values, but negative */ min-width: 1em; min-height: 1em; - margin: calc(-0.3334em - 1px); - border-radius: 0.83333em; + margin: calc(-0.33334em - 1px); + border-radius: 0.83334em; background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); border: 1px solid @bg-dark-grey; box-shadow: none; @@ -637,12 +634,10 @@ scale:disabled trough { /*** Progressbar *******************************************************************************/ progressbar.vertical { min-width: 0; - margin-right: 0.58333em; + min-height: 9em; } progressbar.vertical text { color: transparent; - margin-right: -0.83333em; - min-width: 0; } progressbar.vertical trough { @@ -663,7 +658,7 @@ progressbar.horizontal trough { background-color: transparent; border: none; border-radius: 0.5em; - margin-top: 0.58333em; + margin-top: 0.58334em; } progressbar.horizontal trough progress { min-height: 0.41667em; @@ -716,25 +711,25 @@ notebook tabs { notebook header tab { background-color: transparent; margin: 0.41667em 0.25em; - padding: 0 0.3334em; + padding: 0 0.33334em; } notebook header.left tab { margin: 0.25em 0.41667em; - padding: 0.3334em 0; + padding: 0.33334em 0; } notebook header tab > grid > image { - min-height: 2.33333em; + min-height: 2.33334em; min-width: 0; padding: 0 0.16667em 0 0; margin: 0; } notebook header.left tab > grid > image { min-height: 0; - min-width: 2.33333em; + min-width: 2.33334em; padding: 0.16667em 0 0; } notebook header tab label { - margin: 0.33333em; + margin: 0.33334em; } notebook header tab:hover label { color: @headline-hl; @@ -747,7 +742,7 @@ notebook header.left tab:checked { } notebook > header > tabs > arrow { background-color: transparent; - border-radius: 0.16667em; + border-radius: 0.2em; min-width: 0; min-height: 0; padding: 0 0.16667em; @@ -776,7 +771,7 @@ dialog notebook stack { padding: 0.41667em; } #MainNotebook > stack > :nth-child(2) > :nth-child(2) { - margin-bottom: 0.3334em; + margin-bottom: 0.33334em; } @@ -784,17 +779,17 @@ dialog notebook stack { dialog.csd #PrefNotebook > header, dialog.csd #AboutNotebook > header, window.csd:not(.fullscreen) #MainNotebook > header.top { - border-top: 0.083333em solid rgba(200,200,200,.18); + border-top: 0.083334em solid rgba(200,200,200,.18); } /**/ #ToolPanelNotebook > header tabs { - margin-bottom: 0.33333em; + margin-bottom: 0.33334em; } #ToolPanelNotebook > header tab image{ min-height: 2.5em; - min-width: 2em; + min-width: calc(1.66667em + 6px); padding: 0; margin: 0; } @@ -813,7 +808,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } #PrefNotebook header { - margin: -0.66667em -0.66667em 0.3334em; + margin: -0.66667em -0.66667em 0.33334em; } #AboutNotebook header { margin: -0.66667em -0.66667em 0.66667em; @@ -827,14 +822,15 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #MetaPanelNotebook header { background-color: @bg-grey; - padding: 0.33333em; + padding: 0.33334em; margin: 0 0.5em 0; } #MetaPanelNotebook > header > tabs { background-color: @bg-dark-grey; + padding-left: 0.33334em; } -#MetaPanelNotebook > header > tab { - background-color: @bg-dark-grey; +#MetaPanelNotebook > header tab label{ + margin: 0.08334em; } #MetaPanelNotebook > stack > box { @@ -842,11 +838,11 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { background-color: @bg-grey; border-radius: 0; border-top-style: none; - padding: 0 0.33333em 0.25em; + padding: 0 0.33334em 0.25em; margin: 0 0.5em -0.5em; } #MetaPanelNotebook > stack > box:nth-child(1) > scrolledwindow { - margin: 0 0 0.33333em; + margin: 0 0 0.33334em; padding: 0; } @@ -862,10 +858,10 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin-top: 0; margin-bottom: 0; min-height: 1.66667em; - min-width: 0.83333em; + min-width: 0.83334em; } #MetaPanelNotebook entry { - padding: 0 0.33333em; + padding: 0 0.33334em; background-color: @bg-dark-grey; margin: 0; border-radius: 0; @@ -883,7 +879,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } #MetaPanelNotebook textview.view { background-color: @bg-dark-grey; - padding: 0.08333em 0.33333em; + padding: 0.08334em 0.33334em; margin: 0; } #MetaPanelNotebook text { @@ -904,7 +900,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } #MetaPanelNotebook label { - padding: 0.0834em 0; + padding: 0.08334em 0; } /*** end ***************************************************************************************/ @@ -934,7 +930,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #ToolBarPanelFileBrowser > box > button, #ToolBarPanelFileBrowser > button { - margin: 0 0.0834em; + margin: 0 0.08334em; } #ToolBarPanelFileBrowser > box > box > button { min-height: 0.91667em; @@ -952,7 +948,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-height: 1.66667em; min-width: 1.66667em; margin: 0 0 0 -1.66667em; - border-radius: 0 0.16667em 0.16667em 0; + border-radius: 0 0.2em 0.2em 0; border: 1px solid transparent; padding: 0; } @@ -961,11 +957,11 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-height: 1.66667em; min-width: 12em; margin: 0 -2px 0 0; - padding: 0 2em 0 0.33333em; + padding: 0 2em 0 0.33334em; } #ToolBarPanelFileBrowser label, #FileBrowser label { - margin: 0 0.33333em 0 0.5em; + margin: 0 0.33334em 0 0.5em; } /*** end ***************************************************************************************/ @@ -1005,8 +1001,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #BeforeAfterContainer button { min-height: 1.66667em; min-width: 1.66667em; - margin: 0.25em 0 0.3334em; - padding: 0 0 0 0.0834em; + margin: 0.25em 0 0.33334em; + padding: 0 0 0 0.08334em; } /**/ @@ -1016,7 +1012,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-height: 0; } #EditorTopPanel button { - margin: 0 0.0834em; + margin: 0 0.08334em; min-height: 2.16667em; min-width: 2.16667em; } @@ -1027,14 +1023,14 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #EditorTopPanel > box > button.image-button:not(:nth-child(6)) { min-width: 0; - padding-left: 0.33333em; - padding-right: 0.33333em; + padding-left: 0.33334em; + padding-right: 0.33334em; } #EditorTopPanel > box > button.image-button:nth-child(6) { -gtk-icon-shadow: none; } #EditorTopPanel > box > box > button { - min-height: 0.64em; + min-height: 0.625em; min-width: 0; margin: 0 0.16667em; padding: 0 0.16667em; @@ -1052,7 +1048,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #EditorTopPanel > box > box > button:checked { background-color: transparent; background-image: none; - border: 1px solid @bg-dark-grey; + border: 1px solid @bg-button-border; box-shadow: none; } @@ -1065,8 +1061,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { padding: 0 2px 0 3px; } #EditorZoomPanel button { - margin-left: 0.0834em; - margin-right: 0.0834em; + margin-left: 0.08334em; + margin-right: 0.08334em; } /*** end ***************************************************************************************/ @@ -1126,7 +1122,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #MyExpanderTitle > box { margin: 0; - padding: 0.33333em 0; + padding: 0.33334em 0; } #MyExpanderTitle label { @@ -1167,7 +1163,7 @@ menu > .bottom:hover { } menuitem { - padding: 0 0.33333em; + padding: 0 0.33334em; margin: 1px; min-height: 2em; } @@ -1182,7 +1178,7 @@ menuitem:hover > * { menu image { min-height: 2em; padding: 0; - margin: 0 0.33333em 0 0; + margin: 0 0.33334em 0 0; } /*** Selection popup list (used in filechooser) ***/ @@ -1239,7 +1235,7 @@ button { min-width: 2.16667em; margin: 0; padding: 0; /* x */ - border-radius: 0.16667em; + border-radius: 0.2em; border: 1px solid @bg-button-border; background-color: transparent; box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); @@ -1262,19 +1258,19 @@ button.flat { /* Resetbutton Queue & Save as*/ dialog scale + button.flat, scale + button.flat { - min-height: 1.33333em; + min-height: 1.33334em; min-width: 1.25em; margin: 0.25em 0 0.16667em 0.16667em; - padding: 0 0 0 0.0834em; + padding: 0 0 0 0.08334em; -gtk-icon-shadow: none; } /* Resetbutton */ #MyExpander button.flat { - min-height: 1.33333em; + min-height: 1.33334em; min-width: 1.25em; - margin: 0.08333em 0 0.08333em 0.16667em; - padding: 0 0 0 0.0834em; + margin: 0.08334em 0 0.08334em 0.16667em; + padding: 0 0 0 0.08334em; -gtk-icon-shadow: none; } @@ -1286,7 +1282,7 @@ scale + button.flat { } #MyExpander spinbutton + button.flat { margin: 0 0 0 0.16667em; - padding-top: 0.08333em; + padding-top: 0.08334em; } /**/ @@ -1295,7 +1291,7 @@ scale + button.flat { #MyExpander button.flat:first-child { min-height: 2.16667em; min-width: 2.16667em; - margin: 0.08333em; + margin: 0.08334em; padding: 0; } /**/ @@ -1304,7 +1300,7 @@ scale + button.flat { #FileBrowser entry + button:hover, button.flat:hover, button:hover { - border: 1px solid @bg-button-border; + border-color: @bg-button-border; box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-hover; @@ -1316,8 +1312,8 @@ button.flat:active, button.flat:checked, button:active, button:checked { - border-color: black; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + border-color: @bg-button-border; + box-shadow: inset 0 1px rgba(242, 242, 242, 0.08); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-active; } @@ -1333,7 +1329,7 @@ button.MiddleH { /* Applies special styles in main notebook */ #ProfilePanel { margin-bottom: -2px; - padding-bottom: 0.41667em + padding-bottom: 0.41667em; } #ProfilePanel combobox { margin-left: 0.16667em; @@ -1359,7 +1355,7 @@ combobox .combo, dialog combobox .combo, #ToolPanelNotebook combobox .combo, #BatchQueueButtonsMainContainer combobox .combo { - padding: 0 0.20833em; + padding: 0 0.208334em; } /**/ @@ -1377,7 +1373,7 @@ dialog combobox .combo, #MyExpander label + * > button:not(.flat).Left, #MyExpander label + combobox:not(:first-child):not(:only-child), #MyExpander label + button:not(.flat):not(spinbutton) { - margin-left: 0.33333em; + margin-left: 0.33334em; } /* Arrow toggle combo button */ @@ -1385,8 +1381,8 @@ dialog combobox .combo, #MyExpander button:not(.flat).Left + button:not(.flat).Right { border-left: none; margin-left: 0; - padding-left: 0.33333em; - padding-right: 0.33333em; + padding-left: 0.33334em; + padding-right: 0.33334em; border-top-left-radius: 0; border-bottom-left-radius: 0; } @@ -1394,7 +1390,7 @@ dialog combobox .combo, #MyExpander button:not(.flat).Left { border-top-right-radius: 0; border-bottom-right-radius: 0; - min-width: 2.33333em; + min-width: 2.16667em; } /**/ @@ -1402,8 +1398,8 @@ dialog combobox .combo, #PrefNotebook stack > box:nth-child(4) combobox, #MyExpander button.flat, #MyExpander button { - margin-top: 0.115em; - margin-bottom: 0.115em; + margin-top: 0.08334em; + margin-bottom: 0.08334em; } /**/ #MyExpander button.text-button label { @@ -1429,11 +1425,11 @@ button.color { /* Save, Cancel, OK ... buttons */ .dialog-action-area button { min-height: 2.16667em; - margin-top: 0.33333em; + margin-top: 0.33334em; } messagedialog .dialog-action-area button { margin: 0 0.66667em 0.66667em 0.66667em; - min-height: 1.83333em; + min-height: 1.83334em; } messagedialog .dialog-action-area button:not(:only-child):nth-child(1) { margin-right: 0.25em; @@ -1457,7 +1453,8 @@ window .view button { background-image: none; box-shadow: none; min-height: 2em; - padding: 0 0.33333em; + min-width: 1.33334em; + padding: 0 0.33334em; } dialog .view button.text-button label, window .view button.text-button label { @@ -1497,22 +1494,22 @@ window .view header button, padding: 0; } .path-bar button:first-child { - border-top-left-radius: 0.16667em; - border-bottom-left-radius: 0.16667em; + border-top-left-radius: 0.2em; + border-bottom-left-radius: 0.2em; min-width: 2em; margin: 0; padding: 0; } .path-bar button:last-child { - border-top-right-radius: 0.16667em; - border-bottom-right-radius: 0.16667em; + border-top-right-radius: 0.2em; + border-bottom-right-radius: 0.2em; min-width: 2em; margin: 0; padding: 0; } .path-bar button label { margin: 0; - padding: 0 0.33333em; + padding: 0 0.33334em; } /**/ @@ -1560,13 +1557,13 @@ headerbar button.titlebutton image { margin: 0; } headerbar button.titlebutton { - margin: 0 0 0 0.33333em; + margin: 0 0 0 0.33334em; background-image: none; border: 1px solid transparent; background-color: transparent; box-shadow: none; - min-width: 1.5em; - min-height: 1.5em; + min-width: 1.55em; + min-height: 1.55em; padding: 0; } messagedialog headerbar button.titlebutton { @@ -1577,7 +1574,7 @@ messagedialog headerbar button.titlebutton { #MainNotebook tab #CloseButton { padding: 0; - margin: 0.3334em -3px 0.3334em 0.0834em; + margin: 0.33334em -3px 0.33334em 0.08334em; min-width: 1.5em; min-height: 1.5em; } @@ -1585,26 +1582,26 @@ messagedialog headerbar button.titlebutton { #MainNotebook tab #CloseButton:hover, headerbar button.titlebutton:hover{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 1px rgba(242, 242, 242, 0.11); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); - background-color: rgba(128, 128, 128,.15); + background-color: rgba(128, 128, 128,.20); } #MainNotebook > header > grid > button:active, headerbar button.titlebutton:active{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 1px rgba(242, 242, 242, 0.15); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); - background-color: rgba(128, 128, 128,.30); + background-color: rgba(128, 128, 128,.40); } #MainNotebook tab #CloseButton:hover, headerbar button.titlebutton.close:hover{ - border-color: rgba(0,0,0,.9); + border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(180,0,0), rgb(160,0,0) 40%, rgb(130,0,0)); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.3); + box-shadow: inset 0 1px rgba(242, 242, 242, 0.32); } #MainNotebook tab #CloseButton:active, headerbar button.titlebutton.close:active{ - border-color: rgba(0,0,0,.9); + border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(215,0,0), rgb(185,0,0) 40%, rgb(150,0,0)); box-shadow: inset 0 1px rgba(242, 242, 242, 0.4); } @@ -1616,17 +1613,17 @@ headerbar button.titlebutton.close:active{ checkbox { padding:0; margin:0; - min-height: 1.16667em; + min-height: 2em; } checkbutton, radiobutton { - padding: 0.41667em 0; + padding: 0; margin: 0; - min-height: 1.16667em; + min-height: 2em; } check, radio { - border: calc(0.08334em + 0.18px) solid shade(@text-color, .9); + border: calc(0.083334em + 0.18px) solid shade(@text-color, .9); background-image: none; background-color: transparent; margin: 0; @@ -1667,24 +1664,26 @@ frame > checkbutton check{ } #PartialPaste checkbutton:not(#PartialPasteHeader) { - padding: 0.0834em 0; + min-height: 1.4em; margin-left: 1.16667em; } #PartialPasteHeader { - padding: 0.0834em 0; + min-height: 1.4em; margin-left: 0.5em; } #PrefNotebook checkbutton { - padding: 0; + min-height: 1.16667em; } -#PrefNotebook radiobutton, #PrefNotebook stack > box:nth-child(3) checkbutton, #PrefNotebook stack > box:nth-child(4) checkbutton { - padding: 0.25em 0; + min-height: 2em; +} +#PrefNotebook radiobutton { + min-height: 2em; } #MyExpander button + checkbutton:last-child { - margin-left: 0.33333em; + margin-left: 0.33334em; } /*** end ***************************************************************************************/ @@ -1693,11 +1692,11 @@ frame > checkbutton check{ #MyExpander entry, entry { margin: 0; - padding: 0 0.33333em; + padding: 0 0.33334em; min-height: 1.66667em; min-width: 0; - border-radius: 0.16667em; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242 , 242, 242, 0.1); + border-radius: 0.2em; + box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); border: 1px solid @bg-entry-border; background-color: @bg-scale-entry; } @@ -1707,29 +1706,29 @@ spinbutton { padding: 0; min-height: 1.66667em; min-width: 0; - border-radius: 0.16667em; + border-radius: 0.2em; background-color: @bg-scale-entry; border: 1px solid @bg-entry-border; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242 , 242, 242, 0.1); + box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); } #MyExpander spinbutton { margin: 0.16667em 0; padding: 0; - min-height: 1.35em; + min-height: 1.33334em; min-width: 0; - border-top-left-radius: 1.83333em; - border-bottom-left-radius: 1.83333em; + border-top-left-radius: 1.83334em; + border-bottom-left-radius: 1.83334em; background-color: shade(@bg-grey, 1.33); border: 1px solid @bg-button-border; color: @text-tbEntry; - box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255 , 255, 255, 0.12); + box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255, 255, 255, 0.12); } #MyExpander button + label + spinbutton { - margin: 0.29em 0; /* Needed for Reset & and Auto button height*/ + margin: 0.25em 0; /* Needed for Reset & and Auto button height*/ } #MyExpander checkbutton + label + spinbutton { - margin: 0.41667em 0; /* Needed for Reset & and Auto checkbox button height*/ + margin: 0.33334em 0; /* Needed for Reset & and Auto checkbox button height*/ } #MyExpander image + spinbutton { @@ -1742,7 +1741,7 @@ spinbutton button { padding: 0; margin: 0; min-height: 0; - min-width: 1.33333em; + min-width: 1.33334em; background-image: none; background-color: transparent; border: none; @@ -1752,7 +1751,7 @@ spinbutton button { } #MyExpander spinbutton entry, spinbutton entry { - padding: 0 0.33333em; + padding: 0 0.33334em; margin: 0; min-height: 0; min-width: 0; @@ -1761,7 +1760,7 @@ spinbutton entry { background-color: transparent; } #MyExpander spinbutton entry { - padding: 0 0.33333em 0 0.83333em; + padding: 0 0.33334em 0 0.83334em; } #BatchQueueButtonsMainContainer spinbutton button:hover, @@ -1824,7 +1823,7 @@ entry:focus > selection { border: none; padding: 0; box-shadow: 0 0.25em 0.75em 1px rgba(0, 0, 0, 0.5), 0 0 0 1px @bg-dark-grey; - margin: 0.83333em; + margin: 0.83334em; } headerbar { background-color: shade(@winHeaderbar,1.12); @@ -1833,7 +1832,7 @@ headerbar { border-bottom: 1px solid @bg-dark-grey; border-radius: 0.41667em 0.41667em 0 0; min-height: 2.16667em; - padding: 0.08333em 0.41667em 0; + padding: 0.08334em 0.41667em 0; margin: 0; } messagedialog headerbar { diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index 55bc4abcf..e1a7e84c2 100644 --- a/rtdata/themes/TooWaBlue-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-GTK3-20_.css @@ -2,7 +2,7 @@ This file is part of RawTherapee. Copyright (c) 2016-2017 TooWaBoo - Version 2.40 - requires RT 5.0 + Version 2.42 - requires RT 5.0 RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -69,7 +69,6 @@ outline-style: none; /* removes the ugly dashed focus line */ border-image: none; transition: none; - /* -gtk-dpi: 120; */ } *:disabled { @@ -77,10 +76,10 @@ } #ToolPanelNotebook { - min-width: 23em + min-width: 23em; } #HistoryPanel { - min-width: 17.83333em + min-width: 17.83334em; } window.background { @@ -107,7 +106,7 @@ messagedialog { tooltip { background-color: @bg-tooltip; border: 1px solid @border-tooltip; - border-radius: 0.33333em; + border-radius: 0.33334em; padding: 0; margin: 0; box-shadow: none; @@ -205,7 +204,7 @@ dialog frame > label { padding: 0.16667em 0.5em; } #BatchQueueButtonsMainContainer frame > border { - margin-bottom: 0.8334em; + margin-bottom: 0.83334em; } #BatchQueueButtonsMainContainer frame:nth-child(3) > border { padding-left: 0.91667em; @@ -232,10 +231,6 @@ textview.view, treeview.view { padding: 0.16667em; margin: 0; } -#RightNotebook > stack > :nth-child(3) treeview { - border: 1px solid @bg-dark-grey; - border-bottom: none; -} textview:hover, treeview:hover { background-color: @bg-list-hover; } @@ -245,8 +240,13 @@ textview:selected, treeview:selected { border-top-color: transparent; } +#RightNotebook > stack > :nth-child(3) treeview { + border: 1px solid @bg-dark-grey; + border-bottom: none; +} + #PlacesPaned > :nth-child(1) treeview { - padding: 0.0834em 0 0.0834em 0.5em; + padding: 0.08334em 0 0.08334em 0.5em; -gtk-icon-style: symbolic; } @@ -257,7 +257,7 @@ textview:selected, treeview:selected { margin-top: 1.75em; } #HistoryPanel > label { - margin: 0 0 -1.3334em 0; + margin: 0 0 -1.33334em 0; padding: 0; } @@ -285,7 +285,7 @@ textview:selected, treeview:selected { /*Corrects the space for the snapshot view of the paned separator*/ #Snapshots { - margin-top: -0.3334em; + margin-top: -0.33334em; } /**/ @@ -381,7 +381,7 @@ filechooser list row:selected { border-radius: 0; } #fullButton { - padding: 0.47em 0.41667em 0.58333em; + padding: 0.47em 0.41667em 0.58334em; } #EditorLeftPaned #fullButton, #EditorLeftPaned #histButton { @@ -433,7 +433,7 @@ paned.vertical > separator { dialog paned.horizontal > separator { background-color: @bg-grey; border-color: @bg-grey; - min-width: 0.33333em; + min-width: 0.33334em; } menu separator { @@ -451,13 +451,13 @@ menu separator { #IopsPanel separator, #FileBrowser separator { background-color: shade(@bg-light-grey,.75); - margin-top: 0.33333em; - margin-bottom: 0.33333em; + margin-top: 0.33334em; + margin-bottom: 0.33334em; } #MyExpander separator { background-color: shade(@bg-grey,.7); - margin: 0.33333em 0.66667em; + margin: 0.33334em 0.66667em; } #PlacesPaned .view.separator { @@ -474,7 +474,7 @@ menu separator { } #PartialPaste separator.vertical { - margin: 0 0.33333em; + margin: 0 0.33334em; padding: 0; } @@ -498,7 +498,7 @@ menu separator { /*** Scrollbar *********************************************************************************/ scrollbar { - background-color: rgba(0,0,0,.45); + background-color: rgba(0,0,0,.40); border: none; margin: 0; padding: 0; @@ -542,7 +542,7 @@ scrollbar.horizontal.hovering.fine-tune slider { scrollbar.horizontal.overlay-indicator:not(.hovering) slider { min-width: 2em; min-height: 0.25em; - border-width: 0.0834em; + border-width: 0.08334em; border-radius: 0.25em; margin: 0 0.16667em; } @@ -562,7 +562,7 @@ scrollbar.vertical.hovering.fine-tune slider { scrollbar.vertical.overlay-indicator:not(.hovering) slider { min-width: 0.25em; min-height: 2em; - border-width: 0.0834em; + border-width: 0.08334em; border-radius: 0.5em; margin: 0.16667em 0; } @@ -573,11 +573,8 @@ scrollbar slider:hover { } /* Scrollbar stuck workaround */ -scrollbar:not(.overlay-indicator).horizontal:hover slider { - min-width: calc(2em - 0.0001px); -} -scrollbar:not(.overlay-indicator).vertical:hover slider { - min-height: calc(2em - 0.0001px); +scrollbar:not(.overlay-indicator):hover { + min-width: 1px; } /*** end ***************************************************************************************/ @@ -585,7 +582,7 @@ scrollbar:not(.overlay-indicator).vertical:hover slider { /*** Scale**************************************************************************************/ scale { padding: 0; - min-height: 1.83333em; + min-height: 1.83334em; margin: 0 0.25em; } @@ -593,8 +590,8 @@ scale slider { /* Slider size is min-width x min-height; margin have to be half of those values, but negative */ min-width: 1em; min-height: 1em; - margin: calc(-0.3334em - 1px); - border-radius: 0.83333em; + margin: calc(-0.33334em - 1px); + border-radius: 0.83334em; background-image: linear-gradient(to bottom, shade (@accent-color4,1.15), shade (@accent-color4,.85)); border: 1px solid @bg-dark-grey; box-shadow: none; @@ -637,12 +634,10 @@ scale:disabled trough { /*** Progressbar *******************************************************************************/ progressbar.vertical { min-width: 0; - margin-right: 0.58333em; + min-height: 9em; } progressbar.vertical text { color: transparent; - margin-right: -0.83333em; - min-width: 0; } progressbar.vertical trough { @@ -663,7 +658,7 @@ progressbar.horizontal trough { background-color: transparent; border: none; border-radius: 0.5em; - margin-top: 0.58333em; + margin-top: 0.58334em; } progressbar.horizontal trough progress { min-height: 0.41667em; @@ -716,25 +711,25 @@ notebook tabs { notebook header tab { background-color: transparent; margin: 0.41667em 0.25em; - padding: 0 0.3334em; + padding: 0 0.33334em; } notebook header.left tab { margin: 0.25em 0.41667em; - padding: 0.3334em 0; + padding: 0.33334em 0; } notebook header tab > grid > image { - min-height: 2.33333em; + min-height: 2.33334em; min-width: 0; padding: 0 0.16667em 0 0; margin: 0; } notebook header.left tab > grid > image { min-height: 0; - min-width: 2.33333em; + min-width: 2.33334em; padding: 0.16667em 0 0; } notebook header tab label { - margin: 0.33333em; + margin: 0.33334em; } notebook header tab:hover label { color: @headline-hl; @@ -747,7 +742,7 @@ notebook header.left tab:checked { } notebook > header > tabs > arrow { background-color: transparent; - border-radius: 0.16667em; + border-radius: 0.2em; min-width: 0; min-height: 0; padding: 0 0.16667em; @@ -776,7 +771,7 @@ dialog notebook stack { padding: 0.41667em; } #MainNotebook > stack > :nth-child(2) > :nth-child(2) { - margin-bottom: 0.3334em; + margin-bottom: 0.33334em; } @@ -784,17 +779,17 @@ dialog notebook stack { dialog.csd #PrefNotebook > header, dialog.csd #AboutNotebook > header, window.csd:not(.fullscreen) #MainNotebook > header.top { - border-top: 0.083333em solid rgba(200,200,200,.18); + border-top: 0.083334em solid rgba(200,200,200,.18); } /**/ #ToolPanelNotebook > header tabs { - margin-bottom: 0.33333em; + margin-bottom: 0.33334em; } #ToolPanelNotebook > header tab image{ min-height: 2.5em; - min-width: 2em; + min-width: calc(1.66667em + 6px); padding: 0; margin: 0; } @@ -813,7 +808,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } #PrefNotebook header { - margin: -0.66667em -0.66667em 0.3334em; + margin: -0.66667em -0.66667em 0.33334em; } #AboutNotebook header { margin: -0.66667em -0.66667em 0.66667em; @@ -827,14 +822,15 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #MetaPanelNotebook header { background-color: @bg-grey; - padding: 0.33333em; + padding: 0.33334em; margin: 0 0.5em 0; } #MetaPanelNotebook > header > tabs { background-color: @bg-dark-grey; + padding-left: 0.33334em; } -#MetaPanelNotebook > header > tab { - background-color: @bg-dark-grey; +#MetaPanelNotebook > header tab label{ + margin: 0.08334em; } #MetaPanelNotebook > stack > box { @@ -842,11 +838,11 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { background-color: @bg-grey; border-radius: 0; border-top-style: none; - padding: 0 0.33333em 0.25em; + padding: 0 0.33334em 0.25em; margin: 0 0.5em -0.5em; } #MetaPanelNotebook > stack > box:nth-child(1) > scrolledwindow { - margin: 0 0 0.33333em; + margin: 0 0 0.33334em; padding: 0; } @@ -862,10 +858,10 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { margin-top: 0; margin-bottom: 0; min-height: 1.66667em; - min-width: 0.83333em; + min-width: 0.83334em; } #MetaPanelNotebook entry { - padding: 0 0.33333em; + padding: 0 0.33334em; background-color: @bg-dark-grey; margin: 0; border-radius: 0; @@ -883,7 +879,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } #MetaPanelNotebook textview.view { background-color: @bg-dark-grey; - padding: 0.08333em 0.33333em; + padding: 0.08334em 0.33334em; margin: 0; } #MetaPanelNotebook text { @@ -904,7 +900,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { } #MetaPanelNotebook label { - padding: 0.0834em 0; + padding: 0.08334em 0; } /*** end ***************************************************************************************/ @@ -934,7 +930,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #ToolBarPanelFileBrowser > box > button, #ToolBarPanelFileBrowser > button { - margin: 0 0.0834em; + margin: 0 0.08334em; } #ToolBarPanelFileBrowser > box > box > button { min-height: 0.91667em; @@ -952,7 +948,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-height: 1.66667em; min-width: 1.66667em; margin: 0 0 0 -1.66667em; - border-radius: 0 0.16667em 0.16667em 0; + border-radius: 0 0.2em 0.2em 0; border: 1px solid transparent; padding: 0; } @@ -961,11 +957,11 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-height: 1.66667em; min-width: 12em; margin: 0 -2px 0 0; - padding: 0 2em 0 0.33333em; + padding: 0 2em 0 0.33334em; } #ToolBarPanelFileBrowser label, #FileBrowser label { - margin: 0 0.33333em 0 0.5em; + margin: 0 0.33334em 0 0.5em; } /*** end ***************************************************************************************/ @@ -1005,8 +1001,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #BeforeAfterContainer button { min-height: 1.66667em; min-width: 1.66667em; - margin: 0.25em 0 0.3334em; - padding: 0 0 0 0.0834em; + margin: 0.25em 0 0.33334em; + padding: 0 0 0 0.08334em; } /**/ @@ -1016,7 +1012,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { min-height: 0; } #EditorTopPanel button { - margin: 0 0.0834em; + margin: 0 0.08334em; min-height: 2.16667em; min-width: 2.16667em; } @@ -1027,14 +1023,14 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #EditorTopPanel > box > button.image-button:not(:nth-child(6)) { min-width: 0; - padding-left: 0.33333em; - padding-right: 0.33333em; + padding-left: 0.33334em; + padding-right: 0.33334em; } #EditorTopPanel > box > button.image-button:nth-child(6) { -gtk-icon-shadow: none; } #EditorTopPanel > box > box > button { - min-height: 0.64em; + min-height: 0.625em; min-width: 0; margin: 0 0.16667em; padding: 0 0.16667em; @@ -1052,7 +1048,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #EditorTopPanel > box > box > button:checked { background-color: transparent; background-image: none; - border: 1px solid @bg-dark-grey; + border: 1px solid @bg-button-border; box-shadow: none; } @@ -1065,8 +1061,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { padding: 0 2px 0 3px; } #EditorZoomPanel button { - margin-left: 0.0834em; - margin-right: 0.0834em; + margin-left: 0.08334em; + margin-right: 0.08334em; } /*** end ***************************************************************************************/ @@ -1126,7 +1122,7 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #MyExpanderTitle > box { margin: 0; - padding: 0.33333em 0; + padding: 0.33334em 0; } #MyExpanderTitle label { @@ -1167,7 +1163,7 @@ menu > .bottom:hover { } menuitem { - padding: 0 0.33333em; + padding: 0 0.33334em; margin: 1px; min-height: 2em; } @@ -1182,7 +1178,7 @@ menuitem:hover > * { menu image { min-height: 2em; padding: 0; - margin: 0 0.33333em 0 0; + margin: 0 0.33334em 0 0; } /*** Selection popup list (used in filechooser) ***/ @@ -1239,7 +1235,7 @@ button { min-width: 2.16667em; margin: 0; padding: 0; /* x */ - border-radius: 0.16667em; + border-radius: 0.2em; border: 1px solid @bg-button-border; background-color: transparent; box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); @@ -1262,19 +1258,19 @@ button.flat { /* Resetbutton Queue & Save as*/ dialog scale + button.flat, scale + button.flat { - min-height: 1.33333em; + min-height: 1.33334em; min-width: 1.25em; margin: 0.25em 0 0.16667em 0.16667em; - padding: 0 0 0 0.0834em; + padding: 0 0 0 0.08334em; -gtk-icon-shadow: none; } /* Resetbutton */ #MyExpander button.flat { - min-height: 1.33333em; + min-height: 1.33334em; min-width: 1.25em; - margin: 0.08333em 0 0.08333em 0.16667em; - padding: 0 0 0 0.0834em; + margin: 0.08334em 0 0.08334em 0.16667em; + padding: 0 0 0 0.08334em; -gtk-icon-shadow: none; } @@ -1286,7 +1282,7 @@ scale + button.flat { } #MyExpander spinbutton + button.flat { margin: 0 0 0 0.16667em; - padding-top: 0.08333em; + padding-top: 0.08334em; } /**/ @@ -1295,7 +1291,7 @@ scale + button.flat { #MyExpander button.flat:first-child { min-height: 2.16667em; min-width: 2.16667em; - margin: 0.08333em; + margin: 0.08334em; padding: 0; } /**/ @@ -1304,7 +1300,7 @@ scale + button.flat { #FileBrowser entry + button:hover, button.flat:hover, button:hover { - border: 1px solid @bg-button-border; + border-color: @bg-button-border; box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-hover; @@ -1316,8 +1312,8 @@ button.flat:active, button.flat:checked, button:active, button:checked { - border-color: black; - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + border-color: @bg-button-border; + box-shadow: inset 0 1px rgba(242, 242, 242, 0.08); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); background-color: @bg-button-active; } @@ -1333,7 +1329,7 @@ button.MiddleH { /* Applies special styles in main notebook */ #ProfilePanel { margin-bottom: -2px; - padding-bottom: 0.41667em + padding-bottom: 0.41667em; } #ProfilePanel combobox { margin-left: 0.16667em; @@ -1359,7 +1355,7 @@ combobox .combo, dialog combobox .combo, #ToolPanelNotebook combobox .combo, #BatchQueueButtonsMainContainer combobox .combo { - padding: 0 0.20833em; + padding: 0 0.208334em; } /**/ @@ -1377,7 +1373,7 @@ dialog combobox .combo, #MyExpander label + * > button:not(.flat).Left, #MyExpander label + combobox:not(:first-child):not(:only-child), #MyExpander label + button:not(.flat):not(spinbutton) { - margin-left: 0.33333em; + margin-left: 0.33334em; } /* Arrow toggle combo button */ @@ -1385,8 +1381,8 @@ dialog combobox .combo, #MyExpander button:not(.flat).Left + button:not(.flat).Right { border-left: none; margin-left: 0; - padding-left: 0.33333em; - padding-right: 0.33333em; + padding-left: 0.33334em; + padding-right: 0.33334em; border-top-left-radius: 0; border-bottom-left-radius: 0; } @@ -1394,7 +1390,7 @@ dialog combobox .combo, #MyExpander button:not(.flat).Left { border-top-right-radius: 0; border-bottom-right-radius: 0; - min-width: 2.33333em; + min-width: 2.16667em; } /**/ @@ -1402,8 +1398,8 @@ dialog combobox .combo, #PrefNotebook stack > box:nth-child(4) combobox, #MyExpander button.flat, #MyExpander button { - margin-top: 0.115em; - margin-bottom: 0.115em; + margin-top: 0.08334em; + margin-bottom: 0.08334em; } /**/ #MyExpander button.text-button label { @@ -1429,11 +1425,11 @@ button.color { /* Save, Cancel, OK ... buttons */ .dialog-action-area button { min-height: 2.16667em; - margin-top: 0.33333em; + margin-top: 0.33334em; } messagedialog .dialog-action-area button { margin: 0 0.66667em 0.66667em 0.66667em; - min-height: 1.83333em; + min-height: 1.83334em; } messagedialog .dialog-action-area button:not(:only-child):nth-child(1) { margin-right: 0.25em; @@ -1457,7 +1453,8 @@ window .view button { background-image: none; box-shadow: none; min-height: 2em; - padding: 0 0.33333em; + min-width: 1.33334em; + padding: 0 0.33334em; } dialog .view button.text-button label, window .view button.text-button label { @@ -1497,22 +1494,22 @@ window .view header button, padding: 0; } .path-bar button:first-child { - border-top-left-radius: 0.16667em; - border-bottom-left-radius: 0.16667em; + border-top-left-radius: 0.2em; + border-bottom-left-radius: 0.2em; min-width: 2em; margin: 0; padding: 0; } .path-bar button:last-child { - border-top-right-radius: 0.16667em; - border-bottom-right-radius: 0.16667em; + border-top-right-radius: 0.2em; + border-bottom-right-radius: 0.2em; min-width: 2em; margin: 0; padding: 0; } .path-bar button label { margin: 0; - padding: 0 0.33333em; + padding: 0 0.33334em; } /**/ @@ -1560,13 +1557,13 @@ headerbar button.titlebutton image { margin: 0; } headerbar button.titlebutton { - margin: 0 0 0 0.33333em; + margin: 0 0 0 0.33334em; background-image: none; border: 1px solid transparent; background-color: transparent; box-shadow: none; - min-width: 1.5em; - min-height: 1.5em; + min-width: 1.55em; + min-height: 1.55em; padding: 0; } messagedialog headerbar button.titlebutton { @@ -1577,7 +1574,7 @@ messagedialog headerbar button.titlebutton { #MainNotebook tab #CloseButton { padding: 0; - margin: 0.3334em -3px 0.3334em 0.0834em; + margin: 0.33334em -3px 0.33334em 0.08334em; min-width: 1.5em; min-height: 1.5em; } @@ -1585,26 +1582,26 @@ messagedialog headerbar button.titlebutton { #MainNotebook tab #CloseButton:hover, headerbar button.titlebutton:hover{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 1px rgba(242, 242, 242, 0.11); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); - background-color: rgba(128, 128, 128,.15); + background-color: rgba(128, 128, 128,.20); } #MainNotebook > header > grid > button:active, headerbar button.titlebutton:active{ border-color: rgba(0,0,0,.8); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.1); + box-shadow: inset 0 1px rgba(242, 242, 242, 0.15); background-image: linear-gradient(to bottom, rgba(100,100,100,.3), rgba(30,30,30,.3)); - background-color: rgba(128, 128, 128,.30); + background-color: rgba(128, 128, 128,.40); } #MainNotebook tab #CloseButton:hover, headerbar button.titlebutton.close:hover{ - border-color: rgba(0,0,0,.9); + border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(180,0,0), rgb(160,0,0) 40%, rgb(130,0,0)); - box-shadow: inset 0 1px rgba(242, 242, 242, 0.3); + box-shadow: inset 0 1px rgba(242, 242, 242, 0.32); } #MainNotebook tab #CloseButton:active, headerbar button.titlebutton.close:active{ - border-color: rgba(0,0,0,.9); + border-color: rgba(0,0,0,.8); background-image: linear-gradient(to bottom, rgb(215,0,0), rgb(185,0,0) 40%, rgb(150,0,0)); box-shadow: inset 0 1px rgba(242, 242, 242, 0.4); } @@ -1616,17 +1613,17 @@ headerbar button.titlebutton.close:active{ checkbox { padding:0; margin:0; - min-height: 1.16667em; + min-height: 2em; } checkbutton, radiobutton { - padding: 0.41667em 0; + padding: 0; margin: 0; - min-height: 1.16667em; + min-height: 2em; } check, radio { - border: calc(0.08334em + 0.18px) solid shade(@text-color, .9); + border: calc(0.083334em + 0.18px) solid shade(@text-color, .9); background-image: none; background-color: transparent; margin: 0; @@ -1667,24 +1664,26 @@ frame > checkbutton check{ } #PartialPaste checkbutton:not(#PartialPasteHeader) { - padding: 0.0834em 0; + min-height: 1.4em; margin-left: 1.16667em; } #PartialPasteHeader { - padding: 0.0834em 0; + min-height: 1.4em; margin-left: 0.5em; } #PrefNotebook checkbutton { - padding: 0; + min-height: 1.16667em; } -#PrefNotebook radiobutton, #PrefNotebook stack > box:nth-child(3) checkbutton, #PrefNotebook stack > box:nth-child(4) checkbutton { - padding: 0.25em 0; + min-height: 2em; +} +#PrefNotebook radiobutton { + min-height: 2em; } #MyExpander button + checkbutton:last-child { - margin-left: 0.33333em; + margin-left: 0.33334em; } /*** end ***************************************************************************************/ @@ -1693,11 +1692,11 @@ frame > checkbutton check{ #MyExpander entry, entry { margin: 0; - padding: 0 0.33333em; + padding: 0 0.33334em; min-height: 1.66667em; min-width: 0; - border-radius: 0.16667em; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242 , 242, 242, 0.1); + border-radius: 0.2em; + box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); border: 1px solid @bg-entry-border; background-color: @bg-scale-entry; } @@ -1707,29 +1706,29 @@ spinbutton { padding: 0; min-height: 1.66667em; min-width: 0; - border-radius: 0.16667em; + border-radius: 0.2em; background-color: @bg-scale-entry; border: 1px solid @bg-entry-border; - box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242 , 242, 242, 0.1); + box-shadow: inset 1px 1px rgba(0, 0, 0, 0.08), 0 1px rgba(242, 242, 242, 0.1); } #MyExpander spinbutton { margin: 0.16667em 0; padding: 0; - min-height: 1.35em; + min-height: 1.33334em; min-width: 0; - border-top-left-radius: 1.83333em; - border-bottom-left-radius: 1.83333em; + border-top-left-radius: 1.83334em; + border-bottom-left-radius: 1.83334em; background-color: shade(@bg-grey, 1.33); border: 1px solid @bg-button-border; color: @text-tbEntry; - box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255 , 255, 255, 0.12); + box-shadow: inset 1px 1px rgba(0, 0, 0, .12), 0 1px rgba(255, 255, 255, 0.12); } #MyExpander button + label + spinbutton { - margin: 0.29em 0; /* Needed for Reset & and Auto button height*/ + margin: 0.25em 0; /* Needed for Reset & and Auto button height*/ } #MyExpander checkbutton + label + spinbutton { - margin: 0.41667em 0; /* Needed for Reset & and Auto checkbox button height*/ + margin: 0.33334em 0; /* Needed for Reset & and Auto checkbox button height*/ } #MyExpander image + spinbutton { @@ -1742,7 +1741,7 @@ spinbutton button { padding: 0; margin: 0; min-height: 0; - min-width: 1.33333em; + min-width: 1.33334em; background-image: none; background-color: transparent; border: none; @@ -1752,7 +1751,7 @@ spinbutton button { } #MyExpander spinbutton entry, spinbutton entry { - padding: 0 0.33333em; + padding: 0 0.33334em; margin: 0; min-height: 0; min-width: 0; @@ -1761,7 +1760,7 @@ spinbutton entry { background-color: transparent; } #MyExpander spinbutton entry { - padding: 0 0.33333em 0 0.83333em; + padding: 0 0.33334em 0 0.83334em; } #BatchQueueButtonsMainContainer spinbutton button:hover, @@ -1824,7 +1823,7 @@ entry:focus > selection { border: none; padding: 0; box-shadow: 0 0.25em 0.75em 1px rgba(0, 0, 0, 0.5), 0 0 0 1px @bg-dark-grey; - margin: 0.83333em; + margin: 0.83334em; } headerbar { background-color: shade(@winHeaderbar,1.12); @@ -1833,7 +1832,7 @@ headerbar { border-bottom: 1px solid @bg-dark-grey; border-radius: 0.41667em 0.41667em 0 0; min-height: 2.16667em; - padding: 0.08333em 0.41667em 0; + padding: 0.08334em 0.41667em 0; margin: 0; } messagedialog headerbar { From 79fc6552b8b6510e3ca61ac871ca617c663909ef Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 1 Feb 2017 16:12:49 +0100 Subject: [PATCH 20/42] Added newline into tooltip PREFERENCES_OUTDIRTEMPLATEHINT --- rtdata/languages/default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 5acc40764..01f8a70b1 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1016,7 +1016,7 @@ PREFERENCES_OUTDIR;Output Directory PREFERENCES_OUTDIRFOLDER;Save to folder PREFERENCES_OUTDIRFOLDERHINT;Save images to the selected folder. PREFERENCES_OUTDIRTEMPLATE;Use template -PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f +PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named\n"/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails in the file browser PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Overlay filenames on thumbnails in the editor pannel PREFERENCES_OVERWRITEOUTPUTFILE;Overwrite existing output files From 1077c4ba2e2dbe249884e6974c6050db8eb5e9c2 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 1 Feb 2017 16:14:26 +0100 Subject: [PATCH 21/42] Translation files updated. --- rtdata/languages/English (UK) | 2 +- rtdata/languages/English (US) | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index af9988062..bf4734453 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -1082,7 +1082,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PREFERENCES_OUTDIRFOLDER;Save to folder !PREFERENCES_OUTDIRFOLDERHINT;Save images to the selected folder. !PREFERENCES_OUTDIRTEMPLATE;Use template -!PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f +!PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named\n"/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f !PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails in the file browser !PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Overlay filenames on thumbnails in the editor pannel !PREFERENCES_OVERWRITEOUTPUTFILE;Overwrite existing output files diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 7a1d87a4a..d5a0e16f2 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -1017,7 +1017,7 @@ !PREFERENCES_OUTDIRFOLDER;Save to folder !PREFERENCES_OUTDIRFOLDERHINT;Save images to the selected folder. !PREFERENCES_OUTDIRTEMPLATE;Use template -!PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f +!PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named\n"/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f !PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails in the file browser !PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Overlay filenames on thumbnails in the editor pannel !PREFERENCES_OVERWRITEOUTPUTFILE;Overwrite existing output files From c4a0604835786ac360a149619304c06d08ec4738 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Fri, 3 Feb 2017 11:40:57 +0100 Subject: [PATCH 22/42] Updated release notes to describe development versions. --- RELEASE_NOTES.txt | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 725844203..aed4cce33 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,9 +1,18 @@ -RAWTHERAPEE 5 RELEASE NOTES ---------------------------- +RAWTHERAPEE 5 DEVELOPMENT RELEASE NOTES +--------------------------------------- RawTherapee provides you with a selection of powerful tools with which you can practice the art of developing raw photos. Be sure to read RawPedia to understand how each tool works so that you may make the most of it. http://rawpedia.rawtherapee.com/ A great place to start is the "Getting Started" article. Click on "Main page" in the top-left corner when you have finished reading that article to see all other articles. +This is a development version of RawTherapee. We update the code almost daily. Every few months, once enough changes have accumulated and the code is stabilized, we make a new official release. Every code change between these releases is known as a "development" version, and this is one of them. + +While we only commit tested and relatively stable code and so the development versions should be fairly stable, you should be aware that: +- Development versions only had limited testing, so there may be bugs unknown to us. +- You should report these bugs so that they get fixed for the next stable release. See + www.rawpedia.rawtherapee.com/How_to_write_useful_bug_reports +- The way new tools work in the development versions is likely to change as we tweak and tune them, so your processing profiles may produce different results when used in a future stable version. +- Bugs present in the stable versions get fixed in the development versions, and make it into the next stable version when we make a new official release. That means that in some ways the development versions can be "more stable" than the latest stable release. At the same time, new features may introduce new bugs. This is a trade-off you should be aware of. + News Relevant to Photographers ------------------------------ - RawTherapee 5 supports most raw formats, including some unusual ones like those from cameras using Foveon and X-Trans sensors. If you're wondering whether it supports your camera's raw format, first download RawTherapee 5 and try for yourself. If a raw format is not supported it will either not open, or the preview in the Editor tab will appear black, white, or have a strong color cast - usually magenta. In that case, read the "Adding Support for New Raw Formats" RawPedia article. @@ -15,32 +24,18 @@ In order to use RawTherapee efficiently you should know that: - All curves support the Shift and Ctrl keys while dragging a point. Shift+drag makes the point snap to meaningful axes (top, bottom, diagonal, other), while Ctrl+drag makes your mouse movement super-fine for precise point positioning. - There are many keyboard shortcuts which make working with RawTherapee much faster and give you greater control. Make sure you familiarize yourself with them on RawPedia's "Keyboard Shortcuts" page! -New Features: -- Wavelets tool. -- Retinex tool. -- Monitor profile and rendering intent support. -- Print soft-proofing support. -- Automatic chroma noise reduction, manual luminance noise reduction using sliders and curves. -- The "Inspect" tab in the File Browser lets you see a 100% preview of the image whose thumbnail your mouse cursor hovers over, which is either the largest JPEG image embedded in the raw file or the image itself when hovering over non-raw images. -- The curve pipette allows you to pick the right point of a curve by clicking in the preview, and input/output values so that you can set the desired output value for a given input value. -- Post-resize sharpening, to give your photos that subtle crispness after resizing them. -- Dual-illuminant DCP support with curves, base tables, look tables and baseline exposure. -- New exposure tone curve modes "Luminance" and "Perceptual". -- Queue processing will stop if an error is encountered while saving, e.g. if you run out of disk space. -- The Contrast by Detail Levels tool received the "Process Locate Before/After Black-and-White" option. -- Rec. 2020 ICC profile added. -- The Navigator can show RGB, HSV and L*a*b* values in a range of 0-255, 0-1 or %. -- The Lockable Color Picker allows you to place multiple sample points over the preview to measure colors and see them change in real time as you manipulate the image. They support the same ranges as the Navigator. -- Grayscale JPEG and TIFF images are now supported. -- 32-bit TIFF files are supported. -- In addition to these new features, RawTherapee received over two years worth of amazing speedups, code cleanups and bug fixes, making it faster and more stable than ever before! +New features since 5.0-r1: +- News Relevant to Package Maintainers ------------------------------------ -- Branch "master" uses GTK2, branch "gtk3" requires GTK+ >=3.16. There are known bugs using GTK+ versions 3.20-3.22 where scrollbars may appear stuck (issue #3545) and where the Retinex tool's "Gain and Offset" panel may appear under the "Transmission" panel (issue #3525) until the user hovers the mouse cursor over a curve button. For this reason we recommend using GTK+ 3.16-3.18 if possible. +- To get the latest development version, use the "dev" branch. +- All development now uses GTK3, requiring version >=3.16. There are known bugs using GTK+ versions 3.20-3.22 where scrollbars may appear stuck (issue #3545) and where the Retinex tool's "Gain and Offset" panel may appear under the "Transmission" panel (issue #3525) until the user hovers the mouse cursor over a curve button. For this reason we recommend using GTK+ 3.16-3.18 if possible. +- GTK2 is no longer supported. Use branch "gtk2" if you want to compile a GTK2 version, but remember that there will be no improvements to it after 5.0-r1. +- Branches "master" and "gtk3" are dead, do not use them. - RawTherapee 5 requires GCC-4.9 or higher, or Clang. -- Do not use -ffast-math -- Use -o3 +- Do not use -ffast-math, it will not make RawTherapee faster but will introduce artifacts. +- Use -o3, it will make RawTherapee faster with no known side-effects. - For stable builds (RT5) use -DCACHE_NAME_SUFFIX="" - For development builds use -DCACHE_NAME_SUFFIX="5-dev" - Windows builders should compile on a drive letter which users are most unlikely to have, such as Y:, due to the "There is no disk in the drive" error (issue #3544). @@ -51,9 +46,6 @@ News Relevant to Developers - Code must be run through astyle. - Commits automatically trigger a compilation using Travis CI. -Complete revision history available on GitHub: -https://github.com/Beep6581/RawTherapee/commits/ - DOCUMENTATION ------------- http://rawtherapee.com/blog/documentation From 65587348300ade04c96d9d0cd069ae72c4d276db Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 6 Feb 2017 22:14:40 +0100 Subject: [PATCH 23/42] CMake indentation cleanup. --- CMakeLists.txt | 122 ++++++++++++------------- cmake/modules/FindMacIntegration.cmake | 4 +- rtdata/CMakeLists.txt | 10 +- rtgui/CMakeLists.txt | 4 +- 4 files changed, 69 insertions(+), 71 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f3546364..b2fb88ec9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,21 +1,21 @@ if (WIN32) - cmake_minimum_required(VERSION 2.8.4) + cmake_minimum_required(VERSION 2.8.4) else (WIN32) - cmake_minimum_required(VERSION 2.6) + cmake_minimum_required(VERSION 2.6) endif (WIN32) # must stay before the 'project' command if(${CMAKE_EXTRA_GENERATOR} MATCHES "Eclipse CDT4") - set(CMAKE_CXX_COMPILER_ARG1 "-std=c++11" CACHE STRING "C++ version for eclipse" FORCE) - # users building with Eclipse should set CMAKE_ECLIPSE_VERSION through the command line to their current version of Eclipse - #set(CMAKE_ECLIPSE_VERSION "4.6.0" CACHE STRING "Eclipse version" FORCE) + set(CMAKE_CXX_COMPILER_ARG1 "-std=c++11" CACHE STRING "C++ version for eclipse" FORCE) + # users building with Eclipse should set CMAKE_ECLIPSE_VERSION through the command line to their current version of Eclipse + #set(CMAKE_ECLIPSE_VERSION "4.6.0" CACHE STRING "Eclipse version" FORCE) endif() PROJECT(RawTherapee) # the default target is 'Debug' if (CMAKE_BUILD_TYPE STREQUAL "") - set (CMAKE_BUILD_TYPE Debug CACHE STRING "One of: None Debug Release RelWithDebInfo MinSizeRel." FORCE) + set (CMAKE_BUILD_TYPE Debug CACHE STRING "One of: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif () string (TOUPPER ${CMAKE_BUILD_TYPE} UPPER_CMAKE_BUILD_TYPE) @@ -25,19 +25,19 @@ SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9") - message(FATAL_ERROR "Building RawTherapee requires using GCC version 4.9 or higher!") + message(FATAL_ERROR "Building RawTherapee requires using GCC version 4.9 or higher!") endif() # We might want to build using the old C++ ABI, even when using a new GCC version if (USE_OLD_CXX_ABI) - add_definitions (-D_GLIBCXX_USE_CXX11_ABI=0) + add_definitions (-D_GLIBCXX_USE_CXX11_ABI=0) endif() if (UPPER_CMAKE_BUILD_TYPE STREQUAL "DEBUG") - add_definitions (-D_DEBUG) + add_definitions (-D_DEBUG) else () - add_definitions (-DNDEBUG) - add_definitions (-D_DNDEBUG) + add_definitions (-DNDEBUG) + add_definitions (-D_DNDEBUG) endif () message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") @@ -59,10 +59,10 @@ include (ProcessorTargets.cmake) set (PROC_LABEL "undefined" CACHE STRING "Target processor label, unused if PROC_TARGET_NUMBER = 0 or 2") set (PROC_FLAGS "" CACHE STRING "Target processor related build/link flags") if ((NOT(PROC_TARGET_NUMBER EQUAL 0)) AND (NOT(PROC_TARGET_NUMBER EQUAL 2))) - set (PROC_LABEL ${PROC_TARGET_${PROC_TARGET_NUMBER}_LABEL}) + set (PROC_LABEL ${PROC_TARGET_${PROC_TARGET_NUMBER}_LABEL}) endif () if (NOT(PROC_TARGET_NUMBER EQUAL 0)) - set (PROC_FLAGS ${PROC_TARGET_${PROC_TARGET_NUMBER}_FLAGS}) + set (PROC_FLAGS ${PROC_TARGET_${PROC_TARGET_NUMBER}_FLAGS}) endif () if (UNIX AND PROC_LABEL STREQUAL "undefined") execute_process(COMMAND uname -p OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE cpu) @@ -75,7 +75,7 @@ endif () # if it exists, the PROC_FORCED_LABEL value is loaded in PROC_LABEL to override the one of ProcessorTargets if (DEFINED PROC_FORCED_LABEL) - set (PROC_LABEL ${PROC_FORCED_LABEL}) + set (PROC_LABEL ${PROC_FORCED_LABEL}) endif (DEFINED PROC_FORCED_LABEL) # adding the proc flags to the build flags @@ -94,7 +94,7 @@ endif (WIN32) if (APPLE) if (CMAKE_CXX_COMPILER MATCHES "g\\+\\+-mp-4.[5-8]" OR - CMAKE_CXX_COMPILER_ARG1 MATCHES "g\\+\\+-mp-4.[5-8]") + CMAKE_CXX_COMPILER_ARG1 MATCHES "g\\+\\+-mp-4.[5-8]") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /usr/lib/libstdc++.6.dylib") message (STATUS "CMAKE_CXX_COMPILER is MacPorts GCC.\n CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}") endif () @@ -144,11 +144,11 @@ if (NOT DEFINED LIBDIR) else (BUILD_BUNDLE) # Respect CMAKE_INSTALL_LIBDIR if set if (DEFINED CMAKE_INSTALL_LIBDIR) - if (IS_ABSOLUTE "${LIBDIR}") - set (LIBDIR "${CMAKE_INSTALL_LIBDIR}") - else (IS_ABSOLUTE "${LIBDIR}") - set (LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") - endif (IS_ABSOLUTE "${LIBDIR}") + if (IS_ABSOLUTE "${LIBDIR}") + set (LIBDIR "${CMAKE_INSTALL_LIBDIR}") + else (IS_ABSOLUTE "${LIBDIR}") + set (LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + endif (IS_ABSOLUTE "${LIBDIR}") else (DEFINED CMAKE_INSTALL_LIBDIR) set (LIBDIR "${CMAKE_INSTALL_PREFIX}/lib") endif (DEFINED CMAKE_INSTALL_LIBDIR) @@ -198,9 +198,7 @@ if (NOT DEFINED APPDATADIR) endif (NOT DEFINED APPDATADIR) # non-bundle builds has to use absolute paths -if (NOT BUILD_BUNDLE AND - NOT (IS_ABSOLUTE "${BINDIR}" AND IS_ABSOLUTE "${DATADIR}" AND IS_ABSOLUTE "${LIBDIR}" AND - IS_ABSOLUTE "${DOCDIR}" AND IS_ABSOLUTE "${CREDITSDIR}" AND IS_ABSOLUTE "${LICENCEDIR}")) +if (NOT BUILD_BUNDLE AND NOT (IS_ABSOLUTE "${BINDIR}" AND IS_ABSOLUTE "${DATADIR}" AND IS_ABSOLUTE "${LIBDIR}" AND IS_ABSOLUTE "${DOCDIR}" AND IS_ABSOLUTE "${CREDITSDIR}" AND IS_ABSOLUTE "${LICENCEDIR}")) message (FATAL_ERROR "The paths has to be absolute or use -DBUILD_BUNDLE=ON") endif () @@ -242,7 +240,7 @@ if (WIN32) if (MINGW) add_definitions (-D__MINGW32__) endif (MINGW) - if (CMAKE_SIZEOF_VOID_P EQUAL 4) + if (CMAKE_SIZEOF_VOID_P EQUAL 4) add_definitions (-DWINVER=0x0501) endif (CMAKE_SIZEOF_VOID_P EQUAL 4) set (EXTRA_LIB "-lws2_32 -lshlwapi") @@ -259,12 +257,12 @@ find_package (ZLIB REQUIRED) # link witz bzip if (WITH_BZIP) - find_package(BZip2) - if (BZIP2_FOUND) - add_definitions (-DBZIP_SUPPORT) - set (EXTRA_INCDIR ${BZIP2_INCLUDE_DIR}) - set (EXTRA_LIB ${EXTRA_LIB} ${BZIP2_LIBRARIES}) - endif (BZIP2_FOUND) + find_package(BZip2) + if (BZIP2_FOUND) + add_definitions (-DBZIP_SUPPORT) + set (EXTRA_INCDIR ${BZIP2_INCLUDE_DIR}) + set (EXTRA_LIB ${EXTRA_LIB} ${BZIP2_LIBRARIES}) + endif (BZIP2_FOUND) endif (WITH_BZIP) #Check for libcanberra-gtk3 (sound events on Linux) @@ -273,7 +271,7 @@ if (UNIX AND (NOT APPLE)) endif (UNIX AND (NOT APPLE)) if (WITH_MYFILE_MMAP) - add_definitions (-DMYFILE_MMAP) + add_definitions (-DMYFILE_MMAP) endif (WITH_MYFILE_MMAP) if (WITH_LTO) @@ -327,26 +325,26 @@ if (OUT_OF_SOURCE_BUILD) foreach(f ${OOSB_FILES}) if (EXISTS "${f}") message (SEND_ERROR "Generated \"${f}\" found inside the source tree. Please remove it as it is a relic of the old build system and prevents valid compilation now.") - endif () + endif () endforeach(f) endif () ## BEGIN: Create AboutThisBuild.txt and other version-dependent files. # set the bit number information of the platform if (CMAKE_SIZEOF_VOID_P EQUAL 4) - set(PROC_BIT_DEPTH 32 bits) + set(PROC_BIT_DEPTH 32 bits) elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PROC_BIT_DEPTH 64 bits) + set(PROC_BIT_DEPTH 64 bits) endif (CMAKE_SIZEOF_VOID_P EQUAL 4) # Get comiler name and version # only cmake > 2.8.7 knows CMAKE_*_COMPILER_VERSION if (CMAKE_VERSION VERSION_GREATER 2.8.7) - get_filename_component(COMPILER_INFO ${CMAKE_C_COMPILER} NAME_WE) - set(COMPILER_INFO "${COMPILER_INFO} ${CMAKE_C_COMPILER_VERSION}") + get_filename_component(COMPILER_INFO ${CMAKE_C_COMPILER} NAME_WE) + set(COMPILER_INFO "${COMPILER_INFO} ${CMAKE_C_COMPILER_VERSION}") else () - execute_process(COMMAND gcc -dumpversion OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) - set(COMPILER_INFO "gcc ${GCC_VERSION}") + execute_process(COMMAND gcc -dumpversion OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + set(COMPILER_INFO "gcc ${GCC_VERSION}") endif () # Get c++ and linker flags for rtengine (the gui's c++ flags may have less flags) @@ -354,32 +352,32 @@ set(CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${UPPER_CMAKE_BUILD_TYPE}} $ set(LFLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${UPPER_CMAKE_BUILD_TYPE}}") set(ABOUT_COMMAND_WITH_ARGS ${CMAKE_COMMAND} - -DPROJECT_SOURCE_DIR:STRING=${PROJECT_SOURCE_DIR} - -DCACHE_NAME_SUFFIX:STRING=${CACHE_NAME_SUFFIX} - -DPROC_LABEL:STRING="${PROC_LABEL}" - -DPROC_BIT_DEPTH:STRING="${PROC_BIT_DEPTH}" - -DBUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DGTKMM_VERSION:STRING=${GTKMM_VERSION} - -DOPTION_OMP:STRING=${OPTION_OMP} - -DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP}) + -DPROJECT_SOURCE_DIR:STRING=${PROJECT_SOURCE_DIR} + -DCACHE_NAME_SUFFIX:STRING=${CACHE_NAME_SUFFIX} + -DPROC_LABEL:STRING="${PROC_LABEL}" + -DPROC_BIT_DEPTH:STRING="${PROC_BIT_DEPTH}" + -DBUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DGTKMM_VERSION:STRING=${GTKMM_VERSION} + -DOPTION_OMP:STRING=${OPTION_OMP} + -DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP}) if (WIN32) - list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Windows - -DCXX_FLAGS:STRING="${CXX_FLAGS}" - -DLFLAGS:STRING="${LFLAGS}" - -DCOMPILER_INFO:STRING="${COMPILER_INFO}" - -DCMAKE_INSTALL_PREFIX:STRING="${CMAKE_INSTALL_PREFIX}" - -DBIT_DEPTH:STRING="${CMAKE_SIZEOF_VOID_P}") + list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Windows + -DCXX_FLAGS:STRING="${CXX_FLAGS}" + -DLFLAGS:STRING="${LFLAGS}" + -DCOMPILER_INFO:STRING="${COMPILER_INFO}" + -DCMAKE_INSTALL_PREFIX:STRING="${CMAKE_INSTALL_PREFIX}" + -DBIT_DEPTH:STRING="${CMAKE_SIZEOF_VOID_P}") elseif (APPLE) - list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Apple - -DCXX_FLAGS:STRING=${CXX_FLAGS} - -DLFLAGS:STRING=${LFLAGS} - -DCOMPILER_INFO:STRING=${COMPILER_INFO}) + list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Apple + -DCXX_FLAGS:STRING=${CXX_FLAGS} + -DLFLAGS:STRING=${LFLAGS} + -DCOMPILER_INFO:STRING=${COMPILER_INFO}) else (WIN32) - list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Linux - -DCXX_FLAGS:STRING=${CXX_FLAGS} - -DLFLAGS:STRING=${LFLAGS} - -DCOMPILER_INFO:STRING=${COMPILER_INFO}) + list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Linux + -DCXX_FLAGS:STRING=${CXX_FLAGS} + -DLFLAGS:STRING=${LFLAGS} + -DCOMPILER_INFO:STRING=${COMPILER_INFO}) endif (WIN32) list(APPEND ABOUT_COMMAND_WITH_ARGS -P "${PROJECT_SOURCE_DIR}/UpdateInfo.cmake") @@ -398,8 +396,8 @@ if (WIN32) install (DIRECTORY "licenses" DESTINATION "${LICENCEDIR}") endif (WIN32) if (UNIX) - install (FILES "${PROJECT_SOURCE_DIR}/doc/manpage/rawtherapee.1" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1") - install (FILES rawtherapee.appdata.xml DESTINATION "${APPDATADIR}") + install (FILES "${PROJECT_SOURCE_DIR}/doc/manpage/rawtherapee.1" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1") + install (FILES rawtherapee.appdata.xml DESTINATION "${APPDATADIR}") endif (UNIX) add_subdirectory (rtexif) diff --git a/cmake/modules/FindMacIntegration.cmake b/cmake/modules/FindMacIntegration.cmake index d25841815..47cbc7f83 100644 --- a/cmake/modules/FindMacIntegration.cmake +++ b/cmake/modules/FindMacIntegration.cmake @@ -27,6 +27,6 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MACINTEGRATION DEFAULT_MSG MACINTEGRATION_LIBRARY MACINTEGRATION_INCLUDE_DIR) IF(MACINTEGRATION_FOUND) - SET(MacIntegration_LIBRARIES ${MACINTEGRATION_LIBRARY}) - SET(MacIntegration_INCLUDE_DIRS ${MACINTEGRATION_INCLUDE_DIR}) + SET(MacIntegration_LIBRARIES ${MACINTEGRATION_LIBRARY}) + SET(MacIntegration_INCLUDE_DIRS ${MACINTEGRATION_INCLUDE_DIR}) ENDIF(MACINTEGRATION_FOUND) diff --git a/rtdata/CMakeLists.txt b/rtdata/CMakeLists.txt index b3f44a68c..5967bd70a 100644 --- a/rtdata/CMakeLists.txt +++ b/rtdata/CMakeLists.txt @@ -49,16 +49,16 @@ install (DIRECTORY ${IMAGESDIR} DESTINATION "${DATADIR}" FILES_MATCHING PATTERN install (FILES ${OPTIONSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ RENAME options) if (WIN32) - install (FILES "${PROJECT_SOURCE_DIR}/doc/manpage/rawtherapee.1" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1") + install (FILES "${PROJECT_SOURCE_DIR}/doc/manpage/rawtherapee.1" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1") endif (WIN32) if (APPLE) # CMake escapes first item quote character. Do not remove 'DUMMY_VARIABLE='. set (MACOSX_BUNDLE_COMMAND DUMMY_VARIABLE= - PROJECT_NAME="${PROJECT_NAME}" - PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}" - CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" - GTK_PREFIX="${GTK_PREFIX}") + PROJECT_NAME="${PROJECT_NAME}" + PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}" + CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" + GTK_PREFIX="${GTK_PREFIX}") if (PROC_BIT_DEPTH MATCHES 32) list (APPEND MACOSX_BUNDLE_COMMAND PROC_BIT_DEPTH=32) elseif (PROC_BIT_DEPTH MATCHES 64) diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index be2186e63..021f6163f 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -68,7 +68,7 @@ set_target_properties (rth PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_ #target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} # ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES}) target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} - ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} - ${FFTW3F_LIBRARIES} ${IPTCDATA_LIBRARIES} ${CANBERRA-GTK_LIBRARIES} ${EXTRA_LIB_RTGUI}) + ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} + ${FFTW3F_LIBRARIES} ${IPTCDATA_LIBRARIES} ${CANBERRA-GTK_LIBRARIES} ${EXTRA_LIB_RTGUI}) install (TARGETS rth DESTINATION ${BINDIR}) From 737911141592940836f068c9c4800953309e6a08 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 6 Feb 2017 22:32:18 +0100 Subject: [PATCH 24/42] win.cmake cleanup, no functional changes yet. --- win.cmake | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/win.cmake b/win.cmake index 2259c144f..072061d8f 100644 --- a/win.cmake +++ b/win.cmake @@ -1,42 +1,40 @@ -# Use the 'Debug' build type to have a non optimized, with debugging information, with a console executable -# Use the 'Release' build type to have an optimized, without debugging information, console free executable -# Use the 'RelWithDebInfo' build type to have an optimized, without debugging information, with a console executable -# Use the 'MinSizeRel' build type to have the smallest possible, without debugging information, console free executable +# Use the 'Debug' build type to have a non optimized, with debugging information, with a console executable. +# Use the 'Release' build type to have an optimized, without debugging information, console-free executable. +# Use the 'RelWithDebInfo' build type to have an optimized, without debugging information, with a console executable. +# Use the 'MinSizeRel' build type to have the smallest possible, without debugging information, console-free executable. +# #set(CMAKE_BUILD_TYPE Release CACHE STRING "Between: None Debug Release RelWithDebInfo MinSizeRel.") -set(CMAKE_INSTALL_PREFIX ./Builds/${CMAKE_BUILD_TYPE} CACHE PATH "Libraries installation path") -set(DATADIR . CACHE PATH "Datas installation path") +set(CMAKE_INSTALL_PREFIX ./Builds/${CMAKE_BUILD_TYPE} CACHE PATH "Library installation path") +set(DATADIR . CACHE PATH "Data installation path") set(BINDIR . CACHE PATH "Binaries installation path") -set(LIBDIR . CACHE PATH "Libraries installation path") +set(LIBDIR . CACHE PATH "Library installation path") set(DOCDIR ./doc CACHE PATH "Documentation installation path") set(CREDITSDIR . CACHE PATH "Credit file installation path") set(LICENCEDIR . CACHE PATH "Licence file installation path") -set(BUILD_SHARED OFF CACHE BOOL "Should RT generate shared libraries") +set(BUILD_SHARED OFF CACHE BOOL "Should shared libraries be generated") set(OPTION_OMP ON CACHE BOOL "Use OpenMP to speedup the preview and batch processing") -# set WITH_MYFILE_MMAP to OFF if you experience crash with thumbnail creation (it should be slower, but more reliable) -set(WITH_MYFILE_MMAP ON CACHE BOOL "Use the MMAP mechanism to speedup thumbnail creations") +# set WITH_MYFILE_MMAP to OFF if you experience crashes caused by thumbnail creation (it will be slower but more reliable). +set(WITH_MYFILE_MMAP ON CACHE BOOL "Use the MMAP mechanism to speedup thumbnail creation") -set(CACHE_NAME_SUFFIX "" CACHE STRING "RawTherapee's cache folder suffix (leave empty to use the default suffix, i.e. latesttag)") +set(CACHE_NAME_SUFFIX "" CACHE STRING "RawTherapee's cache folder suffix (leave empty to use default from UpdateIndo.cmake)") -# This line will let you chose the target number, and the associated processor -set(PROC_TARGET_NUMBER 0 CACHE STRING "Target Processor") +# Choose the target processor's number from ProcessorTargets.cmake. +set(PROC_TARGET_NUMBER 0 CACHE STRING "Target processor") # If you want to force the target processor name when PROC_TARGET_NUMBER = 0 or 2, -# uncomment the next line and replace labelWithoutQuotes by its value -#set (PROC_LABEL labelWithoutQuotes CACHE STRING "Target Processor label") +# uncomment the next line and replace labelWithoutQuotes with a string. +#set (PROC_LABEL labelWithoutQuotes CACHE STRING "Target processor label") -# Important: MinGW-w64 user may need to specify the -m32 or -m64 flag in CMAKE_CXX_FLAGS, -# CMAKE_C_FLAGS and CMAKE_EXE_LINKER_FLAGS to select between 32/64bit build +# Important: MinGW-w64 users may need to specify the -m32 or -m64 flag in CMAKE_CXX_FLAGS, +# CMAKE_C_FLAGS and CMAKE_EXE_LINKER_FLAGS to select between 32-/64-bit builds. set(CMAKE_CXX_FLAGS "-mwin32 -mthreads" CACHE STRING "Compiler options for C++ source files") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g2" CACHE STRING "Compiler options for C++ source files and Debug target") set(CMAKE_CXX_FLAGS_RELEASE "-mwindows -DNDEBUG -O2" CACHE STRING "Compiler options for C++ source files and Release target") set(CMAKE_CXX_FLAGS_MINSIZEREL "-mwindows -DNDEBUG -Os" CACHE STRING "Compiler options for C++ source files and MinSizeRel target") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Compiler options for C++ source files and RelWithDebInfo target") -# Uncomment the next line and set the right value to override the default value (special compiling flags for RTEngine) -#set(RTENGINE_CXX_FLAGS "-funroll-loops" CACHE STRING "Special compilation flags for RTEngine") - set(CMAKE_C_FLAGS "-mwin32 -mthreads" CACHE STRING "Compiler options for C source files") set(CMAKE_C_FLAGS_DEBUG "-O0 -g2" CACHE STRING "Compiler options for C source files and Debug target") set(CMAKE_C_FLAGS_RELEASE "-mwindows -DNDEBUG -O2" CACHE STRING "Compiler options for C source files and Release target") From 88985c8cb7694f5a819dc59040b04c5e3faa8e10 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 7 Feb 2017 21:18:12 +0100 Subject: [PATCH 25/42] There is no disk in drive error messages with Windows gtk3 builds. fixes #3544 --- rtgui/main.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rtgui/main.cc b/rtgui/main.cc index 20cd626e9..d6b99fdc6 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -181,6 +181,9 @@ int main(int argc, char **argv) #ifdef WIN32 bool consoleOpened = false; + // suppression of annoying error boxes + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + if (argc > 1 || options.rtSettings.verbose) { if (options.rtSettings.verbose || ( !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_IS_DIR))) { bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); From 281982f329c6d151f81905082db1efd7a3a27d45 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 7 Feb 2017 21:43:10 +0100 Subject: [PATCH 26/42] DNG files from HdrMerge are decoded incorrectly when zlib 1.2.11 is used. fixes #3674 --- rtengine/dcraw.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index a3bd3e523..8623d26cd 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -9791,20 +9791,22 @@ void CLASS deflate_dng_load_raw() { } uLongf dstLen = tile_width * tile_length * 4; -#ifdef _OPENMP +#if defined(_OPENMP) && ZLIB_VER_REVISION == 8 #pragma omp parallel #endif { Bytef * cBuffer = new Bytef[maxCompressed]; Bytef * uBuffer = new Bytef[dstLen]; -#ifdef _OPENMP +#if defined(_OPENMP) && ZLIB_VER_REVISION == 8 #pragma omp for collapse(2) nowait #endif for (size_t y = 0; y < raw_height; y += tile_length) { for (size_t x = 0; x < raw_width; x += tile_width) { size_t t = (y / tile_length) * tilesWide + (x / tile_width); +#if defined(_OPENMP) && ZLIB_VER_REVISION == 8 #pragma omp critical +#endif { fseek(ifp, tileOffsets[t], SEEK_SET); fread(cBuffer, 1, tileBytes[t], ifp); From 824ecaed41dd6c02359180438627d261a7a4f5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Thu, 9 Feb 2017 20:25:58 +0100 Subject: [PATCH 27/42] Add `IdleRegister` to deal with destruction while idle func is queued This adds a little helper class to `guiutils.*` that unregisters in-flight idle functions queued by `IdleRegister::add()`. It's best to call `IdleRegister::destroy()` in the destructor of the class owning the `IdleRegister` instance. Otherwise make sure, it is the last member which will be deleted first. `Resize` now makes use of this new facility in `setDimensions()`, which also fixes #3673. --- rtgui/guiutils.cc | 47 ++++++++++++++++++ rtgui/guiutils.h | 32 ++++++++++--- rtgui/resize.cc | 118 +++++++++++++++++++++++++--------------------- rtgui/resize.h | 36 +++++++------- 4 files changed, 155 insertions(+), 78 deletions(-) diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 43bfc11b0..e8310ff0e 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -43,6 +43,53 @@ guint add_idle (GSourceFunc function, gpointer data) //gtk_main_iteration_do(false); } +IdleRegister::~IdleRegister() +{ + destroy(); +} + +void IdleRegister::add(GSourceFunc function, gpointer data) +{ + struct DataWrapper { + IdleRegister* const self; + GSourceFunc function; + gpointer data; + }; + + const auto dispatch = [](gpointer data) -> gboolean { + DataWrapper* const data_wrapper = static_cast(data); + + if (!data_wrapper->function(data_wrapper->data)) { + data_wrapper->self->mutex.lock(); + data_wrapper->self->ids.erase(data_wrapper); + data_wrapper->self->mutex.unlock(); + + delete data_wrapper; + return FALSE; + } + + return TRUE; + }; + + DataWrapper* const data_wrapper = new DataWrapper{ + this, + function, + data + }; + + mutex.lock(); + ids[data_wrapper] = add_idle(dispatch, data_wrapper); + mutex.unlock(); +} + +void IdleRegister::destroy() +{ + mutex.lock(); + for (const auto id : ids) { + g_source_remove(id.second); + } + mutex.unlock(); +} /* gboolean giveMeAGo(void* data) { diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index e5919c9e4..422a99a45 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -19,13 +19,19 @@ #ifndef __GUI_UTILS_ #define __GUI_UTILS_ -#include -#include -#include "../rtengine/rtengine.h" -#include "../rtengine/coord.h" -#include "rtimage.h" -#include #include +#include +#include + +#include + +#include + +#include "../rtengine/coord.h" +#include "../rtengine/noncopyable.h" +#include "../rtengine/rtengine.h" + +#include "rtimage.h" Glib::ustring escapeHtmlChars(const Glib::ustring &src); bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference = true); @@ -40,6 +46,20 @@ void setExpandAlignProperties(Gtk::Widget *widget, bool hExpand, bool vExpand, e guint add_idle (GSourceFunc function, gpointer data); +class IdleRegister final : + public rtengine::NonCopyable +{ +public: + ~IdleRegister(); + + void add(GSourceFunc function, gpointer data); + void destroy(); + +private: + std::map ids; + MyMutex mutex; +}; + // TODO: The documentation says gdk_threads_enter and gdk_threads_leave should be replaced // by g_main_context_invoke(), g_idle_add() and related functions, but this will require more extensive changes. // We silence those warnings until then so that we notice the others. diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 0504a3934..bf2d4ce67 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -118,7 +118,7 @@ Resize::Resize () : FoldableToolPanel(this, "resize", M("TP_RESIZE_LABEL"), fals Resize::~Resize () { - + idle_register.destroy(); delete scale; delete sizeBox; } @@ -352,68 +352,76 @@ void Resize::sizeChanged (int mw, int mh, int ow, int oh) void Resize::setDimensions () { + const auto func = [](gpointer data) -> gboolean { + Resize* const self = static_cast(data); - int refw, refh; + self->wconn.block(true); + self->hconn.block(true); + self->scale->block(true); - wconn.block (true); - hconn.block (true); - scale->block(true); + int refw, refh; - if (appliesTo->get_active_row_number() == 0 && cropw) { - // Applies to Cropped area - refw = cropw; - refh = croph; - } else { - // Applies to Full image or crop is disabled - refw = maxw; - refh = maxh; - } - - GThreadLock lock; - w->set_range (32, 4 * refw); - h->set_range (32, 4 * refh); - - double tmpScale; - - switch (spec->get_active_row_number()) { - case (0): // Scale mode - w->set_value((double)((int)( (double)(refw) * scale->getValue() + 0.5) )); - h->set_value((double)((int)( (double)(refh) * scale->getValue() + 0.5) )); - break; - - case (1): // Width mode - tmpScale = w->get_value() / (double)refw; - scale->setValue (tmpScale); - h->set_value((double)((int)( (double)(refh) * tmpScale + 0.5) )); - break; - - case (2): // Height mode - tmpScale = h->get_value() / (double)refh; - scale->setValue (tmpScale); - w->set_value((double)((int)( (double)(refw) * tmpScale + 0.5) )); - break; - - case (3): { // Bounding box mode - double wSliderValue = w->get_value(); - double hSliderValue = h->get_value(); - - if ( (wSliderValue / hSliderValue) < ((double)refw / (double)refh)) { - tmpScale = wSliderValue / (double)refw; + if (self->appliesTo->get_active_row_number() == 0 && self->cropw) { + // Applies to Cropped area + refw = self->cropw; + refh = self->croph; } else { - tmpScale = hSliderValue / (double)refh; + // Applies to Full image or crop is disabled + refw = self->maxw; + refh = self->maxh; } - scale->setValue (tmpScale); - break; - } + self->w->set_range(32, 4 * refw); + self->h->set_range(32, 4 * refh); - default: - break; - } + switch (self->spec->get_active_row_number()) { + case 0: { + // Scale mode + self->w->set_value(static_cast(static_cast(static_cast(refw) * self->scale->getValue() + 0.5))); + self->h->set_value(static_cast(static_cast(static_cast(refh) * self->scale->getValue() + 0.5))); + break; + } - scale->block(false); - wconn.block (false); - hconn.block (false); + case 1: { + // Width mode + const double tmp_scale = self->w->get_value() / static_cast(refw); + self->scale->setValue(tmp_scale); + self->h->set_value(static_cast(static_cast(static_cast(refh) * tmp_scale + 0.5))); + break; + } + + case 2: { + // Height mode + const double tmp_scale = self->h->get_value() / static_cast(refh); + self->scale->setValue(tmp_scale); + self->w->set_value(static_cast(static_cast(static_cast(refw) * tmp_scale + 0.5))); + break; + } + + case 3: { + // Bounding box mode + const double tmp_scale = + self->w->get_value() / self->h->get_value() < static_cast(refw) / static_cast(refh) + ? self->w->get_value() / static_cast(refw) + : self->h->get_value() / static_cast(refh); + + self->scale->setValue(tmp_scale); + break; + } + + default: { + break; + } + } + + self->scale->block(false); + self->wconn.block(false); + self->hconn.block(false); + + return FALSE; + }; + + idle_register.add(func, this); } void Resize::fitBoxScale() diff --git a/rtgui/resize.h b/rtgui/resize.h index cf640c281..acba5b478 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -25,25 +25,13 @@ #include "toolpanel.h" #include "guiutils.h" -class Resize : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::SizeListener +class Resize final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::SizeListener { - -protected: - Adjuster* scale; - Gtk::VBox* sizeBox; - MyComboBoxText* appliesTo; - MyComboBoxText* method; - MyComboBoxText* spec; - MySpinButton* w; - MySpinButton* h; - int maxw, maxh; - int cropw, croph; - sigc::connection sconn, aconn, wconn, hconn; - bool wDirty, hDirty; - ToolParamBlock* packBox; - public: - Resize (); ~Resize (); @@ -75,6 +63,20 @@ private: int getComputedHeight (); void notifyBBox (); void updateGUI (); + + Adjuster* scale; + Gtk::VBox* sizeBox; + MyComboBoxText* appliesTo; + MyComboBoxText* method; + MyComboBoxText* spec; + MySpinButton* w; + MySpinButton* h; + int maxw, maxh; + int cropw, croph; + sigc::connection sconn, aconn, wconn, hconn; + bool wDirty, hDirty; + ToolParamBlock* packBox; + IdleRegister idle_register; }; #endif From f9bd9956c0a5c0a341a8924b1cc6704c46345074 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 10 Feb 2017 01:29:02 +0100 Subject: [PATCH 28/42] Removed clang related restriction. Should give a speedup for some parts of rt (denoise for example) when clang is used to build rt --- rtengine/opthelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h index bee97f6b2..4b34fc58f 100644 --- a/rtengine/opthelper.h +++ b/rtengine/opthelper.h @@ -69,7 +69,7 @@ #define ALIGNED64 #define ALIGNED16 #endif - #if !defined(__clang__) && defined _OPENMP + #if defined _OPENMP #define _RT_NESTED_OPENMP #endif #endif From 5202f451376b69924872eec54bd19c34558bb254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Fri, 10 Feb 2017 20:06:35 +0100 Subject: [PATCH 29/42] Protect all `Crop` accesses with `cropMutex` (fixes #3306) --- rtengine/dcrop.cc | 51 ++++++++++++++++++++++++++++++++++++++--------- rtengine/dcrop.h | 43 ++++++++------------------------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index a90c78069..bf4d1b194 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -22,8 +22,18 @@ #include "mytime.h" #include "refreshmap.h" #include "rt_math.h" -// "ceil" rounding -#define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0)) + +namespace +{ + + // "ceil" rounding + template + constexpr T skips(T a, T b) + { + return a / b + static_cast(a % b); + } + +} namespace rtengine { @@ -33,7 +43,7 @@ extern const Settings* settings; Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow) : PipetteBuffer(editDataProvider), origCrop(nullptr), laboCrop(nullptr), labnCrop(nullptr), cropImg(nullptr), cbuf_real(nullptr), cshmap(nullptr), transCrop(nullptr), cieCrop(nullptr), cbuffer(nullptr), - updating(false), newUpdatePending(false), skip(10), padding(0), + updating(false), newUpdatePending(false), skip(10), cropx(0), cropy(0), cropw(-1), croph(-1), trafx(0), trafy(0), trafw(-1), trafh(-1), rqcropx(0), rqcropy(0), rqcropw(-1), rqcroph(-1), @@ -111,6 +121,12 @@ void Crop::setEditSubscriber(EditSubscriber* newSubscriber) // If oldSubscriber == NULL && newSubscriber != NULL && newSubscriber->getEditingType() == ET_PIPETTE-> the image will be allocated when necessary } +bool Crop::hasListener() +{ + MyMutex::MyLock cropLock(cropMutex); + return cropImageListener; +} + void Crop::update (int todo) { MyMutex::MyLock cropLock(cropMutex); @@ -684,7 +700,7 @@ void Crop::update (int todo) } if (needstransform) - parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, SKIPS(parent->fw, skip), SKIPS(parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), + parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, skips(parent->fw, skip), skips(parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(), parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false); else @@ -714,7 +730,7 @@ void Crop::update (int todo) // blurmap for shadow & highlights if ((todo & M_BLURMAP) && params.sh.enabled) { - double radius = sqrt (double(SKIPS(parent->fw, skip) * SKIPS(parent->fw, skip) + SKIPS(parent->fh, skip) * SKIPS(parent->fh, skip))) / 2.0; + double radius = sqrt (double(skips(parent->fw, skip) * skips(parent->fw, skip) + skips(parent->fh, skip) * skips(parent->fh, skip))) / 2.0; double shradius = params.sh.radius; if (!params.sh.hq) { @@ -1114,11 +1130,11 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte int orW, orH; parent->imgsrc->getSize (cp, orW, orH); - int cw = SKIPS(bw, skip); - int ch = SKIPS(bh, skip); + int cw = skips(bw, skip); + int ch = skips(bh, skip); - leftBorder = SKIPS(rqx1 - bx1, skip); - upperBorder = SKIPS(rqy1 - by1, skip); + leftBorder = skips(rqx1 - bx1, skip); + upperBorder = skips(rqy1 - by1, skip); if (settings->verbose) { printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh, cw, ch); @@ -1286,5 +1302,22 @@ void Crop::fullUpdate () parent->updaterThreadStart.unlock (); } +int Crop::get_skip() +{ + MyMutex::MyLock lock(cropMutex); + return skip; } +int Crop::getLeftBorder() +{ + MyMutex::MyLock lock(cropMutex); + return leftBorder; +} + +int Crop::getUpperBorder() +{ + MyMutex::MyLock lock(cropMutex); + return upperBorder; +} + +} diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index 450c659f0..fcdfcf001 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -16,8 +16,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _CROP_H_ -#define _CROP_H_ +#pragma once #include "improccoordinator.h" #include "rtengine.h" @@ -57,19 +56,18 @@ protected: bool updating; /// Flag telling if an updater thread is currently processing bool newUpdatePending; /// Flag telling the updater thread that a new update is pending int skip; - int padding; /// Minimum space allowed around image in the display area int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border) - int borderRequested; /// requested extra border size for image processing + const int borderRequested; /// requested extra border size for image processing int upperBorder, leftBorder; /// extra border size really allocated for image processing bool cropAllocated; DetailedCropListener* cropImageListener; MyMutex cropMutex; - ImProcCoordinator* parent; - bool isDetailWindow; + ImProcCoordinator* const parent; + const bool isDetailWindow; EditUniqueID getCurrEditID(); bool setCropSizes (int cropX, int cropY, int cropW, int cropH, int skip, bool internal); void freeAll (); @@ -78,19 +76,8 @@ public: Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow); virtual ~Crop (); - void mLock () - { - cropMutex.lock(); - } - void mUnlock () - { - cropMutex.lock(); - } void setEditSubscriber(EditSubscriber* newSubscriber); - bool hasListener () - { - return cropImageListener; - } + bool hasListener(); void update (int todo); void setWindow (int cropX, int cropY, int cropW, int cropH, int skip) { @@ -106,22 +93,8 @@ public: void setListener (DetailedCropListener* il); void destroy (); - int get_skip () - { - return skip; - } - int getPadding () - { - return padding; - } - int getLeftBorder () - { - return leftBorder; - } - int getUpperBorder () - { - return upperBorder; - } + int get_skip(); + int getLeftBorder(); + int getUpperBorder(); }; } -#endif From 242b7a86cf4700de4356f113f58dc157eb58edbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Fri, 10 Feb 2017 20:20:48 +0100 Subject: [PATCH 30/42] Fix FreeBSD compile error (fixes #3566) --- rtgui/cachemanager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 7421711eb..c0cc3e30f 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -35,8 +35,8 @@ namespace { -constexpr auto cacheDirMode = 511; -constexpr auto cacheDirs = { "profiles", "images", "aehistograms", "embprofiles", "data" }; +constexpr int cacheDirMode = 0777; +constexpr const char* cacheDirs[] = { "profiles", "images", "aehistograms", "embprofiles", "data" }; } From 79ff7f5997c2f0f99dfb01b2e22fe0bb14fba46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Fri, 10 Feb 2017 21:22:42 +0100 Subject: [PATCH 31/42] Replace all `add_idle()`s with `IdleRegister` --- rtgui/batchqueue.cc | 6 +- rtgui/batchqueue.h | 59 +++++++------ rtgui/blackwhite.cc | 16 ++-- rtgui/blackwhite.h | 108 ++++++++++++----------- rtgui/cachemanager.cc | 1 + rtgui/colorappearance.cc | 30 ++++--- rtgui/colorappearance.h | 103 +++++++++++----------- rtgui/colortoning.cc | 17 ++-- rtgui/colortoning.h | 67 ++++++++------- rtgui/crop.cc | 113 ++++++++++++------------ rtgui/crop.h | 68 ++++++++------- rtgui/crophandler.cc | 172 ++++++++++++++++++------------------- rtgui/crophandler.h | 87 ++++++++++--------- rtgui/dirbrowser.cc | 1 + rtgui/dirpyrdenoise.cc | 49 ++++++----- rtgui/dirpyrdenoise.h | 97 +++++++++++---------- rtgui/editorpanel.cc | 77 +++++++++-------- rtgui/editorpanel.h | 179 ++++++++++++++++++++------------------- rtgui/filepanel.cc | 16 ++-- rtgui/filepanel.h | 58 ++++++------- rtgui/guiutils.h | 4 +- 21 files changed, 691 insertions(+), 637 deletions(-) diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index fbe2be4c6..7bd53c444 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -85,6 +85,8 @@ BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(nullptr), fileCa BatchQueue::~BatchQueue () { + idle_register.destroy(); + MYWRITERLOCK(l, entryRW); // The listener merges parameters with old values, so delete afterwards @@ -937,7 +939,7 @@ void BatchQueue::notifyListener (bool queueEmptied) } params->queueEmptied = queueEmptied; params->queueError = false; - add_idle (bqnotifylistenerUI, params); + idle_register.add(bqnotifylistenerUI, params); } } @@ -967,6 +969,6 @@ void BatchQueue::error (Glib::ustring msg) params->queueEmptied = false; params->queueError = true; params->queueErrorMessage = msg; - add_idle (bqnotifylistenerUI, params); + idle_register.add(bqnotifylistenerUI, params); } } diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index f7376680b..68373838e 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -36,37 +36,12 @@ public: }; class FileCatalog; -class BatchQueue : public ThumbBrowserBase, + +class BatchQueue final : + public ThumbBrowserBase, public rtengine::BatchProcessingListener, public LWButtonListener { - -protected: - int getMaxThumbnailHeight() const; - void saveThumbnailHeight (int height); - int getThumbnailHeight (); - - BatchQueueEntry* processing; // holds the currently processed image - FileCatalog* fileCatalog; - int sequence; // holds the current sequence index - - Glib::ustring nameTemplate; - - MyImageMenuItem* cancel; - MyImageMenuItem* head; - MyImageMenuItem* tail; - Gtk::MenuItem* selall; - Gtk::MenuItem* open; - Glib::RefPtr pmaccelgroup; - Gtk::Menu pmenu; - - BatchQueueListener* listener; - - Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); - Glib::ustring getTempFilenameForParams( const Glib::ustring &filename ); - bool saveBatchQueue (); - void notifyListener (bool queueEmptied); - public: explicit BatchQueue (FileCatalog* aFileCatalog); ~BatchQueue (); @@ -106,6 +81,34 @@ public: static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence = 0); static int calcMaxThumbnailHeight(); + +protected: + int getMaxThumbnailHeight() const; + void saveThumbnailHeight (int height); + int getThumbnailHeight (); + + Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); + Glib::ustring getTempFilenameForParams( const Glib::ustring &filename ); + bool saveBatchQueue (); + void notifyListener (bool queueEmptied); + + BatchQueueEntry* processing; // holds the currently processed image + FileCatalog* fileCatalog; + int sequence; // holds the current sequence index + + Glib::ustring nameTemplate; + + MyImageMenuItem* cancel; + MyImageMenuItem* head; + MyImageMenuItem* tail; + Gtk::MenuItem* selall; + Gtk::MenuItem* open; + Glib::RefPtr pmaccelgroup; + Gtk::Menu pmenu; + + BatchQueueListener* listener; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index dab459a14..67dd9f64a 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -364,23 +364,25 @@ BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LAB } BlackWhite::~BlackWhite () { + idle_register.destroy(); + delete luminanceCEG; delete beforeCurveCEG; delete afterCurveCEG; } -int BWChangedUI (void* data) -{ - (static_cast(data))->BWComputed_ (); - return 0; -} - void BlackWhite::BWChanged (double redbw, double greenbw, double bluebw) { nextredbw = redbw; nextgreenbw = greenbw; nextbluebw = bluebw; - add_idle (BWChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->BWComputed_(); + return FALSE; + }; + + idle_register.add(func, this); } bool BlackWhite::BWComputed_ () diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index e38258b04..5f0ffec44 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -28,10 +28,64 @@ #include "mycurve.h" #include "colorprovider.h" -class BlackWhite : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoBWListener, public CurveListener, public ColorProvider +class BlackWhite final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoBWListener, + public CurveListener, + public ColorProvider { +public: + + BlackWhite (); + ~BlackWhite (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void autoOpenCurve (); + void setEditProvider (EditDataProvider *provider); + + void autoch_toggled (); + void neutral_pressed (); + + void updateRGBLabel (); + void adjusterChanged (Adjuster* a, double newval); + void setAdjusterBehavior (bool bwadd, bool bwgadd); + void trimValues (rtengine::procparams::ProcParams* pp); + void enabledcc_toggled (); + void enabledChanged (); + void methodChanged (); + void filterChanged (); + void settingChanged (); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void BWChanged (double redbw, double greenbw, double bluebw); + bool BWComputed_ (); + void curveChanged (CurveEditor* ce); + void curveMode1Changed (); + bool curveMode1Changed_ (); + void curveMode1Changed2 (); + bool curveMode1Changed2_ (); + void algoChanged (); + + Glib::ustring getSettingString (); + Glib::ustring getFilterString (); + Glib::ustring getalgoString (); + +private: + void showLuminance(); + void hideLuminance(); + void showFilter(); + void hideFilter(); + void showEnabledCC(); + void hideEnabledCC(); + void showMixer(int nChannels, bool RGBIsSensitive = true); + void hideMixer(); + void showGamma(); + void hideGamma(); -protected: FlatCurveEditor* luminanceCurve; Gtk::HSeparator* luminanceSep; CurveEditorGroup* luminanceCEG; @@ -85,55 +139,7 @@ protected: double nextgreenbw; double nextbluebw; - void showLuminance(); - void hideLuminance(); - void showFilter(); - void hideFilter(); - void showEnabledCC(); - void hideEnabledCC(); - void showMixer(int nChannels, bool RGBIsSensitive = true); - void hideMixer(); - void showGamma(); - void hideGamma(); - -public: - - BlackWhite (); - ~BlackWhite (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void autoOpenCurve (); - void setEditProvider (EditDataProvider *provider); - - void autoch_toggled (); - void neutral_pressed (); - - void updateRGBLabel (); - void adjusterChanged (Adjuster* a, double newval); - void setAdjusterBehavior (bool bwadd, bool bwgadd); - void trimValues (rtengine::procparams::ProcParams* pp); - void enabledcc_toggled (); - void enabledChanged (); - void methodChanged (); - void filterChanged (); - void settingChanged (); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - void BWChanged (double redbw, double greenbw, double bluebw); - bool BWComputed_ (); - void curveChanged (CurveEditor* ce); - void curveMode1Changed (); - bool curveMode1Changed_ (); - void curveMode1Changed2 (); - bool curveMode1Changed2_ (); - void algoChanged (); - - Glib::ustring getSettingString (); - Glib::ustring getFilterString (); - Glib::ustring getalgoString (); - + IdleRegister idle_register; }; #endif diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 7421711eb..68ab74d95 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -19,6 +19,7 @@ #include "cachemanager.h" #include +#include #include #include diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index 528047a22..a198dd1f5 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -424,6 +424,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", ColorAppearance::~ColorAppearance () { + idle_register.destroy(); + delete curveEditorG; delete curveEditorG2; delete curveEditorG3; @@ -1002,15 +1004,17 @@ void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdit } } -int autoCamChangedUI (void* data) -{ - (static_cast(data))->autoCamComputed_ (); - return 0; -} + void ColorAppearance::autoCamChanged (double ccam) { nextCcam = ccam; - add_idle (autoCamChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->autoCamComputed_(); + return FALSE; + }; + + idle_register.add(func, this); } bool ColorAppearance::autoCamComputed_ () @@ -1023,15 +1027,17 @@ bool ColorAppearance::autoCamComputed_ () return false; } -int adapCamChangedUI (void* data) -{ - (static_cast(data))->adapCamComputed_ (); - return 0; -} + void ColorAppearance::adapCamChanged (double cadap) { nextCadap = cadap; - add_idle (adapCamChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->adapCamComputed_(); + return FALSE; + }; + + idle_register.add(func, this); } bool ColorAppearance::adapCamComputed_ () diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index 1560e275e..e7b7e072d 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -28,10 +28,61 @@ #include "guiutils.h" #include "colorprovider.h" -class ColorAppearance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoCamListener, public CurveListener, public ColorProvider +class ColorAppearance final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoCamListener, + public CurveListener, + public ColorProvider { +public: + ColorAppearance (); + ~ColorAppearance (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void adjusterChanged (Adjuster* a, double newval); + void adjusterAutoToggled (Adjuster* a, bool newval); +// void adjusterAdapToggled (Adjuster* a, bool newval); + void enabledChanged (); + void surroundChanged (); + void wbmodelChanged (); + void algoChanged (); + void surrsource_toggled (); + void gamut_toggled (); +// void badpix_toggled (); + void datacie_toggled (); + void tonecie_toggled (); +// void sharpcie_toggled (); + void autoCamChanged (double ccam); + bool autoCamComputed_ (); + void adapCamChanged (double cadap); + bool adapCamComputed_ (); + + void curveChanged (CurveEditor* ce); + void curveMode1Changed (); + bool curveMode1Changed_ (); + void curveMode2Changed (); + bool curveMode2Changed_ (); + void curveMode3Changed (); + bool curveMode3Changed_ (); + + void expandCurve (bool isExpanded); + bool isCurveExpanded (); + void autoOpenCurve (); + + void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd); + void trimValues (rtengine::procparams::ProcParams* pp); + void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller); + +private: + bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); + bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); -protected: Glib::RefPtr bgTTips; Glib::RefPtr srTTips; Glib::RefPtr bgPixbuf; @@ -83,56 +134,10 @@ protected: bool lastAutoAdapscen; bool lastsurr; bool lastgamut; -// bool lastbadpix; bool lastdatacie; bool lasttonecie; -// bool lastsharpcie; - bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); - bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); -public: - - ColorAppearance (); - ~ColorAppearance (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void adjusterChanged (Adjuster* a, double newval); - void adjusterAutoToggled (Adjuster* a, bool newval); -// void adjusterAdapToggled (Adjuster* a, bool newval); - void enabledChanged (); - void surroundChanged (); - void wbmodelChanged (); - void algoChanged (); - void surrsource_toggled (); - void gamut_toggled (); -// void badpix_toggled (); - void datacie_toggled (); - void tonecie_toggled (); -// void sharpcie_toggled (); - void autoCamChanged (double ccam); - bool autoCamComputed_ (); - void adapCamChanged (double cadap); - bool adapCamComputed_ (); - - void curveChanged (CurveEditor* ce); - void curveMode1Changed (); - bool curveMode1Changed_ (); - void curveMode2Changed (); - bool curveMode2Changed_ (); - void curveMode3Changed (); - bool curveMode3Changed_ (); - - void expandCurve (bool isExpanded); - bool isCurveExpanded (); - void autoOpenCurve (); - - void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd); - void trimValues (rtengine::procparams::ProcParams* pp); - void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller); + IdleRegister idle_register; }; #endif diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index ceec0092f..d471ef787 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -324,6 +324,8 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR ColorToning::~ColorToning() { + idle_register.destroy(); + delete colorCurveEditorG; delete opacityCurveEditorG; delete clCurveEditorG; @@ -650,19 +652,18 @@ void ColorToning::adjusterChanged (ThresholdAdjuster* a, double newBottom, doubl Glib::ustring::compose(Glib::ustring(M("TP_COLORTONING_HUE") + ": %1" + "\n" + M("TP_COLORTONING_STRENGTH") + ": %2"), int(newTop), int(newBottom))); } -int CTChanged_UI (void* data) -{ - (static_cast(data))->CTComp_ (); - return 0; -} - - void ColorToning::autoColorTonChanged(int bwct, int satthres, int satprot) { nextbw = bwct; nextsatth = satthres; nextsatpr = satprot; - add_idle (CTChanged_UI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->CTComp_(); + return FALSE; + }; + + idle_register.add(func, this); } bool ColorToning::CTComp_ () diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index e34447301..7f1290bf6 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -13,12 +13,43 @@ #include "thresholdadjuster.h" #include "colorprovider.h" -class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rtengine::AutoColorTonListener, public CurveListener, public ColorProvider, - public ThresholdAdjusterListener, public AdjusterListener +class ColorToning final : + public ToolParamBlock, + public FoldableToolPanel, + public rtengine::AutoColorTonListener, + public CurveListener, + public ColorProvider, + public ThresholdAdjusterListener, + public AdjusterListener { +public: + ColorToning (); + ~ColorToning(); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void trimValues (rtengine::procparams::ProcParams* pp); + void adjusterChanged (Adjuster* a, double newval); + void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); + void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); + void neutral_pressed (); + //void neutralCurves_pressed (); + void autoColorTonChanged (int bwct, int satthres, int satprot); + bool CTComp_ (); -protected: - //Gtk::HSeparator* splitSep; + void enabledChanged (); + void curveChanged (CurveEditor* ce); + void autosatChanged (); + void autoOpenCurve (); + void methodChanged (); + void twocolorChanged (bool changedbymethod); + void twoColorChangedByGui (); + void lumamodeChanged (); + + void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + +private: Gtk::HSeparator* satLimiterSep; Gtk::HSeparator* colorSep; CurveEditorGroup* colorCurveEditorG; @@ -57,7 +88,6 @@ protected: Gtk::Image* irg; Gtk::Button* neutral; - //Gtk::Button* neutralCurves; Gtk::HBox* neutrHBox; Gtk::HBox* chromaHbox; Gtk::Label* chroLabel; @@ -75,32 +105,7 @@ protected: bool lastLumamode; sigc::connection lumamodeConn; -public: - ColorToning (); - ~ColorToning(); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void trimValues (rtengine::procparams::ProcParams* pp); - void adjusterChanged (Adjuster* a, double newval); - void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); - void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); - void neutral_pressed (); - //void neutralCurves_pressed (); - void autoColorTonChanged (int bwct, int satthres, int satprot); - bool CTComp_ (); - - void enabledChanged (); - void curveChanged (CurveEditor* ce); - void autosatChanged (); - void autoOpenCurve (); - void methodChanged (); - void twocolorChanged (bool changedbymethod); - void twoColorChangedByGui (); - void lumamodeChanged (); - - void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + IdleRegister idle_register; }; #endif diff --git a/rtgui/crop.cc b/rtgui/crop.cc index a69c71ed8..83efb6a37 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -25,6 +25,9 @@ using namespace rtengine::procparams; extern Options options; +namespace +{ + class RefreshSpinHelper { @@ -35,6 +38,22 @@ public: : crop(_crop), notify(_notify) {} }; +int refreshSpinsUI (void* data) +{ + RefreshSpinHelper* rsh = static_cast(data); + rsh->crop->refreshSpins (rsh->notify); + delete rsh; + return 0; +} + +int notifyListenerUI (void* data) +{ + static_cast(data)->notifyListener(); + return 0; +} + +} + Crop::Crop (): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true) { @@ -252,6 +271,11 @@ Crop::Crop (): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true) show_all (); } +Crop::~Crop() +{ + idle_register.destroy(); +} + void Crop::writeOptions () { @@ -508,32 +532,18 @@ void Crop::enabledChanged () } } -int notifyListenerUI (void* data) -{ - (static_cast(data))->notifyListener (); - return 0; -} - -int refreshSpinsUI (void* data) -{ - RefreshSpinHelper* rsh = static_cast(data); - rsh->crop->refreshSpins (rsh->notify); - delete rsh; - return 0; -} - void Crop::hFlipCrop () { nx = maxw - nx - nw; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::vFlipCrop () { ny = maxh - ny - nh; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::rotateCrop (int deg, bool hflip, bool vflip) @@ -573,7 +583,7 @@ void Crop::rotateCrop (int deg, bool hflip, bool vflip) } lastRotationDeg = deg; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::positionChanged () @@ -587,7 +597,7 @@ void Crop::positionChanged () int W = nw; int H = nh; cropMoved (X, Y, W, H); - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } void Crop::widthChanged () @@ -600,7 +610,7 @@ void Crop::widthChanged () int W = (int)w->get_value (); int H = nh; cropWidth2Resized (X, Y, W, H); - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } void Crop::heightChanged () @@ -613,7 +623,7 @@ void Crop::heightChanged () int W = nw; int H = (int)h->get_value (); cropHeight2Resized (X, Y, W, H); - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } // Fixed ratio toggle button @@ -665,7 +675,7 @@ void Crop::adjustCropToRatio() } // This will save the options - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, true)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, true)); } void Crop::refreshSize () @@ -737,28 +747,28 @@ void Crop::setDimensions (int mw, int mh) refreshSize (); } -struct setdimparams { - Crop* crop; - int x; - int y; -}; - -int sizeChangedUI (void* data) -{ - setdimparams* params = static_cast(data); - params->crop->setDimensions (params->x, params->y); - delete params; - return 0; -} - void Crop::sizeChanged (int x, int y, int ow, int oh) { + struct Params { + Crop* crop; + int x; + int y; + }; - setdimparams* params = new setdimparams; - params->x = x; - params->y = y; - params->crop = this; - add_idle (sizeChangedUI, params); + Params* const params = new Params{ + this, + x, + y + }; + + const auto func = [](gpointer data) -> gboolean { + Params* const params = static_cast(data); + params->crop->setDimensions(params->x, params->y); + delete params; + return FALSE; + }; + + idle_register.add(func, params); } bool Crop::refreshSpins (bool notify) @@ -822,7 +832,7 @@ void Crop::cropMoved (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -866,7 +876,7 @@ void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) @@ -906,7 +916,7 @@ void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) @@ -949,7 +959,7 @@ void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) @@ -989,7 +999,7 @@ void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) @@ -1031,7 +1041,7 @@ void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) @@ -1071,7 +1081,7 @@ void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) @@ -1111,7 +1121,7 @@ void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) @@ -1148,7 +1158,7 @@ void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropInit (int &x, int &y, int &w, int &h) @@ -1266,13 +1276,12 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) nw = W; nh = H; - add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false)); + idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false)); } void Crop::cropManipReady () { - - add_idle (notifyListenerUI, this); + idle_register.add(notifyListenerUI, this); } double Crop::getRatio () diff --git a/rtgui/crop.h b/rtgui/crop.h index 077903836..e0bad8b36 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -33,44 +33,20 @@ public: virtual void cropSelectRequested() = 0; }; -class CropRatio -{ - -public: +struct CropRatio { Glib::ustring label; double value; }; -class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolPanel, public rtengine::SizeListener +class Crop final : + public ToolParamBlock, + public CropGUIListener, + public FoldableToolPanel, + public rtengine::SizeListener { -protected: - Gtk::CheckButton* fixr; - MyComboBoxText* ratio; - MyComboBoxText* orientation; - MyComboBoxText* guide; - Gtk::Button* selectCrop; - CropPanelListener* clistener; - int opt; - MySpinButton* x; - MySpinButton* y; - MySpinButton* w; - MySpinButton* h; - MySpinButton* ppi; - Gtk::Label* sizecm; - Gtk::Label* sizein; - Gtk::VBox* ppibox; - Gtk::VBox* sizebox; - int maxw, maxh; - double nx, ny; - int nw, nh; - int lastRotationDeg; - sigc::connection xconn, yconn, wconn, hconn, fconn, rconn, oconn, gconn; - bool wDirty, hDirty, xDirty, yDirty, lastFixRatio; - void adjustCropToRatio(); - std::vector cropratio; - public: - Crop (); + Crop(); + ~Crop(); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); @@ -116,6 +92,34 @@ public: void hFlipCrop (); void vFlipCrop (); void rotateCrop (int deg, bool hflip, bool vflip); + +private: + Gtk::CheckButton* fixr; + MyComboBoxText* ratio; + MyComboBoxText* orientation; + MyComboBoxText* guide; + Gtk::Button* selectCrop; + CropPanelListener* clistener; + int opt; + MySpinButton* x; + MySpinButton* y; + MySpinButton* w; + MySpinButton* h; + MySpinButton* ppi; + Gtk::Label* sizecm; + Gtk::Label* sizein; + Gtk::VBox* ppibox; + Gtk::VBox* sizebox; + int maxw, maxh; + double nx, ny; + int nw, nh; + int lastRotationDeg; + sigc::connection xconn, yconn, wconn, hconn, fconn, rconn, oconn, gconn; + bool wDirty, hDirty, xDirty, yDirty, lastFixRatio; + void adjustCropToRatio(); + std::vector cropratio; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index bb59efe13..42c6eb756 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -38,14 +38,15 @@ CropHandler::CropHandler () displayHandler(nullptr) { - chi = new CropHandlerIdleHelper; - chi->destroyed = false; - chi->pending = 0; - chi->cropHandler = this; + idle_helper = new IdleHelper; + idle_helper->destroyed = false; + idle_helper->pending = 0; + idle_helper->cropHandler = this; } CropHandler::~CropHandler () { + idle_register.destroy(); if (ipc) { ipc->delSizeListener (this); @@ -61,10 +62,10 @@ CropHandler::~CropHandler () cimg.lock (); - if (chi->pending) { - chi->destroyed = true; + if (idle_helper->pending) { + idle_helper->destroyed = true; } else { - delete chi; + delete idle_helper; } cimg.unlock (); @@ -292,83 +293,6 @@ void CropHandler::getPosition (int& x, int& y) } -int createpixbufs (void* data) -{ - - CropHandlerIdleHelper* chi = static_cast(data); - - if (chi->destroyed) { - if (chi->pending == 1) { - delete chi; - } else { - chi->pending--; - } - - return 0; - } - - CropHandler* ch = chi->cropHandler; - - ch->cimg.lock (); - ch->cropPixbuf.clear (); - - if (!ch->enabled) { - delete [] ch->cropimg; - ch->cropimg = nullptr; - delete [] ch->cropimgtrue; - ch->cropimgtrue = nullptr; - ch->cimg.unlock (); - return 0; - } - - if (ch->cropimg) { - if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) { - // calculate final image size - int czoom = ch->zoom < 1000 ? 1000 : ch->zoom; - int imw = ch->cropimg_width * czoom / 1000; - int imh = ch->cropimg_height * czoom / 1000; - - if (imw > ch->ww) { - imw = ch->ww; - } - - if (imh > ch->wh) { - imh = ch->wh; - } - - Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); - ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); - tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); - tmpPixbuf.clear (); - - Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); - ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); - tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); - tmpPixbuftrue.clear (); - } - - delete [] ch->cropimg; - ch->cropimg = nullptr; - delete [] ch->cropimgtrue; - ch->cropimgtrue = nullptr; - } - - ch->cimg.unlock (); - - if (ch->displayHandler) { - ch->displayHandler->cropImageUpdated (); - - if (ch->initial) { - ch->displayHandler->initialImageArrived (); - ch->initial = false; - } - } - - chi->pending--; - - return 0; -} - void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procparams::ColorManagementParams cmp, rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) { @@ -408,8 +332,84 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp ciw = aw; cih = ah; cis = askip; - chi->pending++; - add_idle (createpixbufs, chi); + idle_helper->pending++; + + const auto func = [](gpointer data) -> gboolean { + IdleHelper* const idle_helper = static_cast(data); + + if (idle_helper->destroyed) { + if (idle_helper->pending == 1) { + delete idle_helper; + } else { + idle_helper->pending--; + } + + return FALSE; + } + + CropHandler* ch = idle_helper->cropHandler; + + ch->cimg.lock (); + ch->cropPixbuf.clear (); + + if (!ch->enabled) { + delete [] ch->cropimg; + ch->cropimg = nullptr; + delete [] ch->cropimgtrue; + ch->cropimgtrue = nullptr; + ch->cimg.unlock (); + return FALSE; + } + + if (ch->cropimg) { + if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) { + // calculate final image size + int czoom = ch->zoom < 1000 ? 1000 : ch->zoom; + int imw = ch->cropimg_width * czoom / 1000; + int imh = ch->cropimg_height * czoom / 1000; + + if (imw > ch->ww) { + imw = ch->ww; + } + + if (imh > ch->wh) { + imh = ch->wh; + } + + Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); + ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); + tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); + tmpPixbuf.clear (); + + Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); + ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); + tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); + tmpPixbuftrue.clear (); + } + + delete [] ch->cropimg; + ch->cropimg = nullptr; + delete [] ch->cropimgtrue; + ch->cropimgtrue = nullptr; + } + + ch->cimg.unlock (); + + if (ch->displayHandler) { + ch->displayHandler->cropImageUpdated (); + + if (ch->initial) { + ch->displayHandler->initialImageArrived (); + ch->initial = false; + } + } + + idle_helper->pending--; + + return FALSE; + }; + + idle_register.add(func, idle_helper); } cimg.unlock (); diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 3bf7e58da..0492aea2a 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -36,56 +36,15 @@ public: virtual void setDisplayPosition (int x, int y) {} }; -class CropHandler; -struct CropHandlerIdleHelper { - CropHandler* cropHandler; - bool destroyed; - int pending; -}; - /** * This class handle the displayed part of the image, ask for the initial data and process it so it can display it. * Its position on the preview is handled not set by this class but by the CropHandlerListener (i.e. CropWindow) with which it works closely. */ -class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener +class CropHandler final : + public rtengine::DetailedCropListener, + public rtengine::SizeListener { - - friend int createpixbufs (void* data); - -protected: - int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) - int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller - int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters - int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image - int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size - int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds - bool enabled; - unsigned char* cropimg; - unsigned char* cropimgtrue; - int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; - bool initial; - bool isLowUpdatePriority; - - rtengine::StagedImageProcessor* ipc; - rtengine::DetailedCrop* crop; - - CropDisplayHandler* displayHandler; - CropHandlerIdleHelper* chi; - - void compDim (); - public: - - void update (); - - - rtengine::procparams::CropParams cropParams; - rtengine::procparams::ColorManagementParams colorParams; - Glib::RefPtr cropPixbuf; - Glib::RefPtr cropPixbuftrue; - - MyMutex cimg; - CropHandler (); ~CropHandler (); @@ -127,6 +86,46 @@ public: bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip); // SizeListener interface void sizeChanged (int w, int h, int ow, int oh); + + void update (); + + + rtengine::procparams::CropParams cropParams; + rtengine::procparams::ColorManagementParams colorParams; + Glib::RefPtr cropPixbuf; + Glib::RefPtr cropPixbuftrue; + + MyMutex cimg; + +private: + struct IdleHelper { + CropHandler* cropHandler; + bool destroyed; + int pending; + }; + + void compDim (); + + int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) + int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller + int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters + int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image + int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size + int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds + bool enabled; + unsigned char* cropimg; + unsigned char* cropimgtrue; + int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; + bool initial; + bool isLowUpdatePriority; + + rtengine::StagedImageProcessor* ipc; + rtengine::DetailedCrop* crop; + + CropDisplayHandler* displayHandler; + IdleHelper* idle_helper; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index eafaa477a..7b5adade2 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -18,6 +18,7 @@ */ #include "dirbrowser.h" +#include #include #ifdef WIN32 diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index a5611cc45..bd673e5c3 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -327,22 +327,24 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP DirPyrDenoise::~DirPyrDenoise () { + idle_register.destroy(); + delete NoiscurveEditorG; delete CCcurveEditorG; +} -} -int chromaChangedUI (void* data) -{ - (static_cast(data))->chromaComputed_ (); - return 0; -} void DirPyrDenoise::chromaChanged (double autchroma, double autred, double autblue) { nextchroma = autchroma; -// printf("CHROM=%f\n",nextchroma); nextred = autred; nextblue = autblue; - add_idle(chromaChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->chromaComputed_(); + return false; + }; + + idle_register.add(func, this); } bool DirPyrDenoise::chromaComputed_ () @@ -356,12 +358,6 @@ bool DirPyrDenoise::chromaComputed_ () updateNoiseLabel (); return false; } -int TilePrevChangedUI (void* data) -{ - (static_cast(data))->TilePrevComputed_ (); - return 0; -} - void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) { @@ -372,10 +368,14 @@ void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, i nextsizeT = sizeT; nextsizeP = sizeP; - add_idle(TilePrevChangedUI, this); - + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->TilePrevComputed_(); + return false; + }; + idle_register.add(func, this); } + bool DirPyrDenoise::TilePrevComputed_ () { @@ -385,6 +385,7 @@ bool DirPyrDenoise::TilePrevComputed_ () updatePrevLabel (); return false; } + void DirPyrDenoise::updateTileLabel () { if (!batchMode) { @@ -422,19 +423,17 @@ void DirPyrDenoise::updatePrevLabel () } } - -int noiseChangedUI (void* data) -{ - (static_cast(data))->noiseComputed_ (); - return 0; -} - - void DirPyrDenoise::noiseChanged (double nresid, double highresid) { nextnresid = nresid; nexthighresid = highresid; - add_idle(noiseChangedUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->noiseComputed_(); + return false; + }; + + idle_register.add(func, this); } bool DirPyrDenoise::noiseComputed_ () diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index e81bf263e..9745b374b 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -28,10 +28,58 @@ #include "guiutils.h" #include "options.h" -class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoChromaListener, public CurveListener, public ColorProvider +class DirPyrDenoise final : + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public rtengine::AutoChromaListener, + public CurveListener, + public ColorProvider { +public: + DirPyrDenoise (); + ~DirPyrDenoise (); -protected: + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void setBatchMode (bool batchMode); + void curveChanged (CurveEditor* ce); + void setEditProvider (EditDataProvider *provider); + void autoOpenCurve (); + + void adjusterChanged (Adjuster* a, double newval); + void enabledChanged (); + void enhanceChanged (); + void medianChanged (); + void autochromaChanged (); + void chromaChanged (double autchroma, double autred, double autblue); + bool chromaComputed_ (); + void noiseChanged (double nresid, double highresid); + bool noiseComputed_ (); + void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP); + bool TilePrevComputed_ (); + +// void perform_toggled (); + void updateNoiseLabel (); + void LmethodChanged (); + void CmethodChanged (); + void C2methodChanged (); + void updateTileLabel (); + void updatePrevLabel (); + + void dmethodChanged (); + void medmethodChanged (); + void methodmedChanged (); + void rgbmethodChanged (); + void smethodChanged (); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + + void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd); + void trimValues (rtengine::procparams::ProcParams* pp); + Glib::ustring getSettingString (); + +private: CurveEditorGroup* NoiscurveEditorG; CurveEditorGroup* CCcurveEditorG; Adjuster* luma; @@ -92,50 +140,7 @@ protected: int nextsizeT; int nextsizeP; -public: - - DirPyrDenoise (); - ~DirPyrDenoise (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void curveChanged (CurveEditor* ce); - void setEditProvider (EditDataProvider *provider); - void autoOpenCurve (); - - void adjusterChanged (Adjuster* a, double newval); - void enabledChanged (); - void enhanceChanged (); - void medianChanged (); - void autochromaChanged (); - void chromaChanged (double autchroma, double autred, double autblue); - bool chromaComputed_ (); - void noiseChanged (double nresid, double highresid); - bool noiseComputed_ (); - void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP); - bool TilePrevComputed_ (); - -// void perform_toggled (); - void updateNoiseLabel (); - void LmethodChanged (); - void CmethodChanged (); - void C2methodChanged (); - void updateTileLabel (); - void updatePrevLabel (); - - void dmethodChanged (); - void medmethodChanged (); - void methodmedChanged (); - void rgbmethodChanged (); - void smethodChanged (); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - - void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd); - void trimValues (rtengine::procparams::ProcParams* pp); - Glib::ustring getSettingString (); - + IdleRegister idle_register; }; #endif diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 0783efe14..8da176fc3 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -35,6 +35,44 @@ using namespace rtengine::procparams; +namespace +{ + +struct spparams { + double val; + Glib::ustring str; + MyProgressBar *pProgress; + Glib::RefPtr cssProvider; +}; + +int setprogressStrUI ( void *p ) +{ + spparams *s = static_cast (p); + + if ( ! s->str.empty() ) { + s->pProgress->set_text ( M (s->str) ); + } + + if ( s->val >= 0 ) { + s->pProgress->set_fraction ( s->val ); + + if (s->cssProvider) { + if ( s->val < 1.0 ) { + s->cssProvider->load_from_data ("ProgressBar { background-color: red }"); + } else { + s->cssProvider->load_from_data ("ProgressBar { background-color: grey }"); + } + + s->pProgress->get_style_context()->set_background (s->pProgress->get_window()); + } + } + + delete s; + return FALSE; +} + +} + class EditorPanel::ColorManagementToolbar { private: @@ -683,6 +721,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) EditorPanel::~EditorPanel () { + idle_register.destroy(); history->setHistoryBeforeLineListener (nullptr); // the order is important! @@ -1017,46 +1056,12 @@ void EditorPanel::setProgressState (bool inProcessing) g_idle_add (setProgressStateUIThread, p); } -struct spparams { - double val; - Glib::ustring str; - MyProgressBar *pProgress; - Glib::RefPtr cssProvider; - -}; - -int setprogressStrUI ( void *p ) -{ - spparams *s = static_cast (p); - - if ( ! s->str.empty() ) { - s->pProgress->set_text ( M (s->str) ); - } - - if ( s->val >= 0 ) { - s->pProgress->set_fraction ( s->val ); - - if (s->cssProvider) { - if ( s->val < 1.0 ) { - s->cssProvider->load_from_data ("ProgressBar { background-color: red }"); - } else { - s->cssProvider->load_from_data ("ProgressBar { background-color: grey }"); - } - - s->pProgress->get_style_context()->set_background (s->pProgress->get_window()); - } - } - - delete s; - return 0; -} - void EditorPanel::setProgress (double p) { spparams *s = new spparams; s->val = p; s->pProgress = progressLabel; - add_idle (setprogressStrUI, s); + idle_register.add(setprogressStrUI, s); } void EditorPanel::setProgressStr (Glib::ustring str) @@ -1065,7 +1070,7 @@ void EditorPanel::setProgressStr (Glib::ustring str) s->str = str; s->val = -1; s->pProgress = progressLabel; - add_idle (setprogressStrUI, s); + idle_register.add(setprogressStrUI, s); } // This is only called from the ThreadUI, so within the gtk thread diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index d87f12c23..609df5236 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -45,102 +45,17 @@ struct EditorPanelIdleHelper { }; class RTWindow; -class EditorPanel : public Gtk::VBox, +class EditorPanel final : + public Gtk::VBox, public PParamsChangeListener, public rtengine::ProgressListener, public ThumbnailListener, public HistoryBeforeLineListener, public rtengine::HistogramListener { -private: - - Glib::ustring lastSaveAsFileName; - bool realized; - -protected: - MyProgressBar *progressLabel; - Gtk::ToggleButton* info; - Gtk::ToggleButton* hidehp; - Gtk::ToggleButton* tbShowHideSidePanels; - Gtk::ToggleButton* tbTopPanel_1; - Gtk::ToggleButton* tbRightPanel_1; - Gtk::ToggleButton* tbBeforeLock; - //bool bAllSidePanelsVisible; - Gtk::ToggleButton* beforeAfter; - Gtk::Paned* hpanedl; - Gtk::Paned* hpanedr; - Gtk::Image *iHistoryShow, *iHistoryHide; - Gtk::Image *iTopPanel_1_Show, *iTopPanel_1_Hide; - Gtk::Image *iRightPanel_1_Show, *iRightPanel_1_Hide; - Gtk::Image *iShowHideSidePanels; - Gtk::Image *iShowHideSidePanels_exit; - Gtk::Image *iBeforeLockON, *iBeforeLockOFF; - Gtk::VBox *leftbox; - Gtk::VBox *vboxright; - - Gtk::Button* queueimg; - Gtk::Button* saveimgas; - Gtk::Button* sendtogimp; - Gtk::Button* navSync; - Gtk::Button* navNext; - Gtk::Button* navPrev; - - class ColorManagementToolbar; - std::unique_ptr colorMgmtToolBar; - - ImageAreaPanel* iareapanel; - PreviewHandler* previewHandler; - PreviewHandler* beforePreviewHandler; // for the before-after view - Navigator* navigator; - ImageAreaPanel* beforeIarea; // for the before-after view - Gtk::VBox* beforeBox; - Gtk::VBox* afterBox; - Gtk::Label* beforeLabel; - Gtk::Label* afterLabel; - Gtk::HBox* beforeAfterBox; - Gtk::HBox* beforeHeaderBox; - Gtk::HBox* afterHeaderBox; - - Gtk::Frame* ppframe; - ProfilePanel* profilep; - History* history; - HistogramPanel* histogramPanel; - ToolPanelCoordinator* tpc; - RTWindow* parent; - //SaveAsDialog* saveAsDialog; - BatchToolPanelCoordinator* btpCoordinator; - FilePanel* fPanel; - - bool firstProcessingDone; - - Thumbnail* openThm; // may get invalid on external delete event - Glib::ustring fname; // must be saved separately - - rtengine::InitialImage* isrc; - rtengine::StagedImageProcessor* ipc; - rtengine::StagedImageProcessor* beforeIpc; // for the before-after view - - EditorPanelIdleHelper* epih; - - void close (); - - BatchQueueEntry* createBatchQueueEntry (); - bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf); - bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf); - bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname); - bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename); - int err; - - time_t processingStartedTime; - - sigc::connection ShowHideSidePanelsconn; - - bool isProcessing; - - public: explicit EditorPanel (FilePanel* filePanel = nullptr); - virtual ~EditorPanel (); + ~EditorPanel (); void open (Thumbnail* tmb, rtengine::InitialImage* isrc); void setAspect (); @@ -214,7 +129,93 @@ public: void updateTabsUsesIcons (bool useIcons); void updateHistogramPosition (int oldPosition, int newPosition); - Gtk::Paned *catalogPane; + Gtk::Paned* catalogPane; + +private: + void close (); + + BatchQueueEntry* createBatchQueueEntry (); + bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf); + bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf); + bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname); + bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename); + + Glib::ustring lastSaveAsFileName; + bool realized; + + MyProgressBar *progressLabel; + Gtk::ToggleButton* info; + Gtk::ToggleButton* hidehp; + Gtk::ToggleButton* tbShowHideSidePanels; + Gtk::ToggleButton* tbTopPanel_1; + Gtk::ToggleButton* tbRightPanel_1; + Gtk::ToggleButton* tbBeforeLock; + //bool bAllSidePanelsVisible; + Gtk::ToggleButton* beforeAfter; + Gtk::Paned* hpanedl; + Gtk::Paned* hpanedr; + Gtk::Image *iHistoryShow, *iHistoryHide; + Gtk::Image *iTopPanel_1_Show, *iTopPanel_1_Hide; + Gtk::Image *iRightPanel_1_Show, *iRightPanel_1_Hide; + Gtk::Image *iShowHideSidePanels; + Gtk::Image *iShowHideSidePanels_exit; + Gtk::Image *iBeforeLockON, *iBeforeLockOFF; + Gtk::VBox *leftbox; + Gtk::VBox *vboxright; + + Gtk::Button* queueimg; + Gtk::Button* saveimgas; + Gtk::Button* sendtogimp; + Gtk::Button* navSync; + Gtk::Button* navNext; + Gtk::Button* navPrev; + + class ColorManagementToolbar; + std::unique_ptr colorMgmtToolBar; + + ImageAreaPanel* iareapanel; + PreviewHandler* previewHandler; + PreviewHandler* beforePreviewHandler; // for the before-after view + Navigator* navigator; + ImageAreaPanel* beforeIarea; // for the before-after view + Gtk::VBox* beforeBox; + Gtk::VBox* afterBox; + Gtk::Label* beforeLabel; + Gtk::Label* afterLabel; + Gtk::HBox* beforeAfterBox; + Gtk::HBox* beforeHeaderBox; + Gtk::HBox* afterHeaderBox; + + Gtk::Frame* ppframe; + ProfilePanel* profilep; + History* history; + HistogramPanel* histogramPanel; + ToolPanelCoordinator* tpc; + RTWindow* parent; + //SaveAsDialog* saveAsDialog; + BatchToolPanelCoordinator* btpCoordinator; + FilePanel* fPanel; + + bool firstProcessingDone; + + Thumbnail* openThm; // may get invalid on external delete event + Glib::ustring fname; // must be saved separately + + rtengine::InitialImage* isrc; + rtengine::StagedImageProcessor* ipc; + rtengine::StagedImageProcessor* beforeIpc; // for the before-after view + + EditorPanelIdleHelper* epih; + + int err; + + time_t processingStartedTime; + + sigc::connection ShowHideSidePanelsconn; + + bool isProcessing; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 8c7bae0fa..ed9b70e8d 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -22,12 +22,6 @@ #include "inspector.h" #include "placesbrowser.h" -int FilePanelInitUI (void* data) -{ - (static_cast(data))->init (); - return 0; -} - FilePanel::FilePanel () : parent(nullptr) { @@ -143,13 +137,21 @@ FilePanel::FilePanel () : parent(nullptr) fileCatalog->setFileSelectionChangeListener (tpc); fileCatalog->setFileSelectionListener (this); - add_idle (FilePanelInitUI, this); + + const auto func = [](gpointer data) -> gboolean { + static_cast(data)->init(); + return FALSE; + }; + + idle_register.add(func, this); show_all (); } FilePanel::~FilePanel () { + idle_register.destroy(); + rightNotebookSwitchConn.disconnect(); if (inspectorPanel) { diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index 68f021043..d54f5f75a 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -33,38 +33,12 @@ #include "progressconnector.h" class RTWindow; -class FilePanel : public Gtk::HPaned, + +class FilePanel final : + public Gtk::HPaned, public FileSelectionListener, public PParamsChangeListener { - -protected: - //DirBrowser* dirBrowser; - PlacesBrowser* placesBrowser; - RecentBrowser* recentBrowser; - // FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it - - Inspector* inspectorPanel; - Gtk::VPaned* tpcPaned; - BatchToolPanelCoordinator* tpc; - History* history; - //FilterPanel* filterPanel; - RTWindow* parent; - Gtk::Notebook* rightNotebook; - sigc::connection rightNotebookSwitchConn; - - struct pendingLoad { - bool complete; - ProgressConnector *pc; - Thumbnail *thm; - }; - MyMutex pendingLoadMutex; - std::vector pendingLoads; - - int error; - - void on_NB_switch_page(Gtk::Widget* page, guint page_num); - public: FilePanel (); ~FilePanel (); @@ -107,6 +81,32 @@ public: bool handleShortcutKey (GdkEventKey* event); void updateTPVScrollbar (bool hide); void updateTabsUsesIcons (bool useIcons); + +private: + void on_NB_switch_page(Gtk::Widget* page, guint page_num); + + PlacesBrowser* placesBrowser; + RecentBrowser* recentBrowser; + + Inspector* inspectorPanel; + Gtk::VPaned* tpcPaned; + BatchToolPanelCoordinator* tpc; + History* history; + RTWindow* parent; + Gtk::Notebook* rightNotebook; + sigc::connection rightNotebookSwitchConn; + + struct pendingLoad { + bool complete; + ProgressConnector *pc; + Thumbnail *thm; + }; + MyMutex pendingLoadMutex; + std::vector pendingLoads; + + int error; + + IdleRegister idle_register; }; #endif diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index 422a99a45..12370a571 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -19,9 +19,7 @@ #ifndef __GUI_UTILS_ #define __GUI_UTILS_ -#include -#include -#include +#include #include From d5d8747e5ab436995fe258a1ec8d9f165cce369f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 11 Feb 2017 17:48:59 +0100 Subject: [PATCH 32/42] decode compressed xtrans files --- rtengine/dcraw.cc | 8 + rtengine/dcraw.h | 62 +++ rtengine/rawimage.cc | 6 + rtengine/xtranscompressed.cc | 775 +++++++++++++++++++++++++++++++++++ 4 files changed, 851 insertions(+) create mode 100644 rtengine/xtranscompressed.cc diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 8623d26cd..a35e3454d 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -11,6 +11,8 @@ /*RT*/#define DJGPP #include "opthelper.h" +#include +#include /* dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net @@ -6264,6 +6266,7 @@ void CLASS apply_tiff() tile_width = tiff_ifd[i].tile_width; tile_length = tiff_ifd[i].tile_length; shutter = tiff_ifd[i].shutter; + raw_size = tiff_ifd[i].bytes; raw = i; } } @@ -9016,6 +9019,9 @@ canon_a5: if (filters == 9) FORC(36) ((char *)xtrans)[c] = xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6]; + if(filters == 9 && raw_height * raw_width * 2 != raw_size) { + xtransCompressed = true; + } } else if (!strcmp(model,"KD-400Z")) { height = 1712; width = 2312; @@ -9865,6 +9871,8 @@ struct tiff_hdr { char desc[512], make[64], model[64], soft[32], date[20], artist[64]; }; +#include "xtranscompressed.cc" + /* RT: Delete from here */ /*RT*/#undef SQR /*RT*/#undef MAX diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 0a68b02cc..1ea938cc7 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -89,8 +89,51 @@ protected: unsigned black, cblack[4102], maximum, mix_green, raw_color, zero_is_bad; unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; unsigned tile_width, tile_length, gpsdata[32], load_flags; + bool xtransCompressed = false; + struct xtrans_params + { + char *q_table; /* quantization table */ + int q_point[5]; /* quantization points */ + int max_bits; + int min_value; + int raw_bits; + int total_values; + int maxDiff; + ushort line_width; + }; + + struct int_pair { + int value1; + int value2; + }; + + enum _xt_lines + { + _R0=0,_R1,_R2,_R3,_R4, + _G0,_G1,_G2,_G3,_G4,_G5,_G6,_G7, + _B0,_B1,_B2,_B3,_B4, + _ltotal + }; + + struct xtrans_block { + int cur_bit; // current bit being read (from left to right) + int cur_pos; // current position in a buffer + INT64 cur_buf_offset; // offset of this buffer in a file + unsigned max_read_size; // Amount of data to be read + int cur_buf_size; // buffer size + uchar *cur_buf; // currently read block + IMFILE *input; + struct int_pair grad_even[3][41]; // tables of gradients + struct int_pair grad_odd[3][41]; + ushort *linealloc; + ushort *linebuf[_ltotal]; + }; + + int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits; + ushort raw_height, raw_width, height, width, top_margin, left_margin; ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; + unsigned raw_size; ushort *raw_image; float * float_raw_image; ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; @@ -226,6 +269,25 @@ void adobe_copy_pixel (unsigned row, unsigned col, ushort **rp); void lossless_dng_load_raw(); void packed_dng_load_raw(); void deflate_dng_load_raw(); +void init_xtrans(struct xtrans_params* info); +void fuji_fill_buffer(struct xtrans_block *info); +void init_xtrans_block(struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize); +void copy_line_to_xtrans(struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width); +void fuji_zerobits(struct xtrans_block* info, int *count); +void fuji_read_code(struct xtrans_block* info, int *data, int bits_to_read); +int bitDiff(int value1, int value2); +int fuji_decode_sample_even(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads); +int fuji_decode_sample_odd(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads); +void fuji_decode_interpolation_even(int line_width, ushort* line_buf, int pos); +void xtrans_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end); +void xtrans_extend_red(ushort *linebuf[_ltotal], int line_width); +void xtrans_extend_green(ushort *linebuf[_ltotal], int line_width); +void xtrans_extend_blue(ushort *linebuf[_ltotal], int line_width); +void xtrans_decode_block(struct xtrans_block* info, const struct xtrans_params *params, int cur_line); +void xtrans_decode_strip(const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize); +void xtrans_compressed_load_raw(); +void xtrans_decode_loop(const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes); +void parse_xtrans_header(); void pentax_load_raw(); void nikon_load_raw(); int nikon_is_compressed(); diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index dc91da64d..c10cc5abd 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -14,6 +14,8 @@ #include #endif +#include + namespace rtengine { @@ -435,6 +437,10 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene return 2; } + if(xtransCompressed) { + parse_xtrans_header(); + } + if (flip == 5) { this->rotate_deg = 270; } else if (flip == 3) { diff --git a/rtengine/xtranscompressed.cc b/rtengine/xtranscompressed.cc new file mode 100644 index 000000000..ed91df841 --- /dev/null +++ b/rtengine/xtranscompressed.cc @@ -0,0 +1,775 @@ +/* -*- C++ -*- + * File: xtranscompressed.cpp + * Copyright (C) 2016 Alexey Danilchenko + * + * Adopted to LibRaw by Alex Tutubalin, lexa@lexa.ru + * LibRaw Fujifilm/compressed decoder + + * Adopted to RawTherapee by Ingo Weyrich +LibRaw is free software; you can redistribute it and/or modify +it under the terms of the one of three licenses as you choose: + +1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 + (See file LICENSE.LGPL provided in LibRaw distribution archive for details). + +2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 + (See file LICENSE.CDDL provided in LibRaw distribution archive for details). + + */ + +void CLASS init_xtrans(struct xtrans_params* info) +{ + int cur_val, i; + char *qt; + + if (fuji_block_width % 3) + derror(); + + info->q_table = (char *) malloc(32768); + merror(info->q_table, "init_xtrans()"); + + info->line_width = (fuji_block_width*2)/3; + + info->q_point[0] = 0; + info->q_point[1] = 0x12; + info->q_point[2] = 0x43; + info->q_point[3] = 0x114; + info->q_point[4] = (1 << fuji_bits) - 1; + info->min_value = 0x40; + + cur_val = -info->q_point[4]; + for (qt = info->q_table; cur_val<=info->q_point[4]; ++qt, ++cur_val) + { + if (cur_val<= -info->q_point[3]) + *qt = -4; + else if (cur_val<= -info->q_point[2]) + *qt = -3; + else if (cur_val<= -info->q_point[1]) + *qt = -2; + else if (cur_val< 0) + *qt = -1; + else if (cur_val== 0) + *qt = 0; + else if (cur_val< info->q_point[1]) + *qt = 1; + else if (cur_val< info->q_point[2]) + *qt = 2; + else if (cur_val< info->q_point[3]) + *qt = 3; + else + *qt = 4; + } + + // populting gradients + if (info->q_point[4] == 0x3FFF) + { + info->total_values = 0x4000; + info->raw_bits = 14; + info->max_bits = 56; + info->maxDiff = 256; + } + else if (info->q_point[4] == 0xFFF) + { + info->total_values = 4096; + info->raw_bits = 12; + info->max_bits = 48; + info->maxDiff = 64; + } + else + derror(); +} + +#define XTRANS_BUF_SIZE 0x10000u + +void CLASS fuji_fill_buffer(struct xtrans_block *info) +{ + if (info->cur_pos >= info->cur_buf_size) + { + info->cur_pos = 0; + info->cur_buf_offset += info->cur_buf_size; +#ifdef _OPENMP +#pragma omp critical +#endif + { + fseek(info->input, info->cur_buf_offset, SEEK_SET); + info->cur_buf_size = fread(info->cur_buf, 1, std::min(info->max_read_size,XTRANS_BUF_SIZE), info->input); + if(info->cur_buf_size<1) // nothing read + ;//throw LIBRAW_EXCEPTION_IO_EOF; + info->max_read_size -= info->cur_buf_size; + + } + } +} + +#define _min(a,b) ((a) < (b) ? (a) : (b)) + +void CLASS init_xtrans_block(struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize) +{ + info->linealloc = (ushort*)calloc(sizeof(ushort),_ltotal*(params->line_width+2)); + merror(info->linealloc, "init_xtrans_block()"); + + info->input = ifp; + INT64 fsize = info->input->size; + info->max_read_size = _min(unsigned(fsize-raw_offset),dsize+16); // Data size may be incorrect? + + info->linebuf[_R0] = info->linealloc; + for(int i = _R1; i<=_B4;i++) + info->linebuf[i] = info->linebuf[i-1] + params->line_width + 2; + + // init buffer + info->cur_buf = (uchar*)malloc(XTRANS_BUF_SIZE); + merror(info->cur_buf, "init_xtrans_block()"); + info->cur_bit = 0; + info->cur_pos = 0; + info->cur_buf_offset = raw_offset; + for(int j=0; j < 3; j++) + for (int i=0; i<41; i++) + { + info->grad_even[j][i].value1 = params->maxDiff; + info->grad_even[j][i].value2 = 1; + info->grad_odd[j][i].value1 = params->maxDiff; + info->grad_odd[j][i].value2 = 1; + } + + info->cur_buf_size = 0; + fuji_fill_buffer(info); +} + +void CLASS copy_line_to_xtrans(struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width) +{ + ushort *lineBufB[3]; + ushort *lineBufG[6]; + ushort *lineBufR[3]; + unsigned pixel_count; + ushort* line_buf; + int index; + + int offset = fuji_block_width*cur_block + 6 * raw_width * cur_line; + ushort* raw_block_data = raw_image + offset; + int row_count = 0; + + for(int i = 0; i<3; i++) + { + lineBufR[i] = info->linebuf[_R2+i] + 1; + lineBufB[i] = info->linebuf[_B2+i] + 1; + } + for(int i = 0; i<6; i++) + lineBufG[i] = info->linebuf[_G2+i] + 1; + + while (row_count < 6) + { + pixel_count = 0; + while (pixel_count < cur_block_width) + { + switch (xtrans_abs[row_count][(pixel_count % 6)]) + { + case 0: // red + line_buf = lineBufR[row_count >> 1]; + break; + case 1: // green + line_buf = lineBufG[row_count]; + break; + case 2: // blue + line_buf = lineBufB[row_count >> 1]; + break; + } + + index = (((pixel_count*2/3) & 0x7FFFFFFE) | (pixel_count % 3) & 1) + ((pixel_count % 3) >> 1); + raw_block_data[pixel_count] = line_buf[index]; + + ++pixel_count; + } + ++row_count; + raw_block_data += raw_width; + } +} + +#define fuji_quant_gradient(i,v1,v2) (9*i->q_table[i->q_point[4]+(v1)] + i->q_table[i->q_point[4]+(v2)]) + +void CLASS fuji_zerobits(struct xtrans_block* info, int *count) +{ + uchar zero = 0; + *count = 0; + while (zero == 0) + { + zero = (info->cur_buf[info->cur_pos] >> (7 - info->cur_bit)) & 1; + info->cur_bit++; + info->cur_bit &= 7; + if (!info->cur_bit) + { + ++info->cur_pos; + fuji_fill_buffer(info); + } + if (zero) + break; + ++*count; + } +} + +void CLASS fuji_read_code(struct xtrans_block* info, int *data, int bits_to_read) +{ + uchar bits_left = bits_to_read; + uchar bits_left_in_byte = 8 - (info->cur_bit & 7); + *data = 0; + if (!bits_to_read) + return; + if (bits_to_read >= bits_left_in_byte) + { + do + { + *data <<= bits_left_in_byte; + bits_left -= bits_left_in_byte; + *data |= info->cur_buf[info->cur_pos] & ((1 << bits_left_in_byte) - 1); + ++info->cur_pos; + fuji_fill_buffer(info); + bits_left_in_byte = 8; + } + while (bits_left >= 8); + } + if (!bits_left) + { + info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7; + return; + } + *data <<= bits_left; + bits_left_in_byte -= bits_left; + *data |= ((1 << bits_left) - 1) & ((unsigned)info->cur_buf[info->cur_pos] >> bits_left_in_byte); + info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7; +} + +int CLASS bitDiff(int value1, int value2) +{ + int decBits = 0; + if ( value2 < value1 ) + while (decBits <= 12 && + (value2 << ++decBits) + < value1) + ; + return decBits; +} + +#define _abs(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) + +int CLASS fuji_decode_sample_even(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads) +{ + int interp_val = 0; + //ushort decBits; + int errcnt=0; + + int sample=0, code=0; + ushort* line_buf_cur = line_buf + pos; + int Rb = line_buf_cur[-2 - params->line_width]; + int Rc = line_buf_cur[-3 - params->line_width]; + int Rd = line_buf_cur[-1 - params->line_width]; + int Rf = line_buf_cur[-4 - 2*params->line_width]; + + int grad, gradient, diffRcRb, diffRfRb, diffRdRb; + + grad = fuji_quant_gradient(params, Rb - Rf, Rc - Rb); + gradient = _abs(grad); + diffRcRb = _abs(Rc - Rb); + diffRfRb = _abs(Rf - Rb); + diffRdRb = _abs(Rd - Rb); + + if ( diffRcRb > diffRfRb && diffRcRb > diffRdRb ) + interp_val = Rf + Rd + 2 * Rb; + else if ( diffRdRb > diffRcRb && diffRdRb > diffRfRb ) + interp_val = Rf + Rc + 2 * Rb; + else + interp_val = Rd + Rc + 2 * Rb; + + + fuji_zerobits(info, &sample); + + if (sample < params->max_bits - params->raw_bits - 1) + { + int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2); + fuji_read_code(info, &code, decBits); + code += sample << decBits; + } + else + { + fuji_read_code(info, &code, params->raw_bits); + code++; + } + + if (code < 0 || code >= params->total_values) + errcnt++; + + if (code & 1) + code = -1 - code/2; + else + code /= 2; + + grads[gradient].value1 += _abs(code); + if (grads[gradient].value2 == params->min_value ) + { + grads[gradient].value1 >>= 1; + grads[gradient].value2 >>= 1; + } + grads[gradient].value2++; + if (grad < 0) + interp_val = (interp_val >> 2) - code; + else + interp_val = (interp_val >> 2) + code; + if ( interp_val < 0 ) + interp_val += params->total_values; + else if (interp_val > params->q_point[4]) + interp_val -= params->total_values; + + if ( interp_val >= 0 ) + line_buf_cur[0] = _min(interp_val, params->q_point[4]); + else + line_buf_cur[0] = 0; + return errcnt; +} + +int CLASS fuji_decode_sample_odd(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads) +{ + int interp_val = 0; + int errcnt = 0; + + int sample=0, code=0; + ushort* line_buf_cur = line_buf + pos; + int Ra = line_buf_cur[-1]; + int Rb = line_buf_cur[-2 - params->line_width]; + int Rc = line_buf_cur[-3 - params->line_width]; + int Rd = line_buf_cur[-1 - params->line_width]; + int Rg = line_buf_cur[1]; + + int grad, gradient; + + grad = fuji_quant_gradient(params, Rb - Rc, Rc - Ra); + gradient = _abs(grad); + + if ((Rb > Rc && Rb > Rd) || (Rb < Rc && Rb < Rd)) + interp_val = (Rg + Ra + 2 * Rb) >> 2; + else + interp_val = (Ra + Rg) >> 1; + + fuji_zerobits(info, &sample); + + if (sample < params->max_bits - params->raw_bits - 1) + { + int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2); + fuji_read_code(info, &code, decBits); + code += sample << decBits; + } + else + { + fuji_read_code(info, &code, params->raw_bits); + code++; + } + + if (code < 0 || code >= params->total_values) + errcnt++; + + if (code & 1) + code = -1 - code/2; + else + code /= 2; + + grads[gradient].value1 += _abs(code); + if (grads[gradient].value2 == params->min_value) + { + grads[gradient].value1 >>= 1; + grads[gradient].value2 >>= 1; + } + grads[gradient].value2++; + if (grad < 0) + interp_val -= code; + else + interp_val += code; + if ( interp_val < 0 ) + interp_val += params->total_values; + else if (interp_val > params->q_point[4]) + interp_val -= params->total_values; + + if ( interp_val >= 0 ) + line_buf_cur[0] = _min(interp_val, params->q_point[4]); + else + line_buf_cur[0] = 0; + return errcnt; +} + +void CLASS fuji_decode_interpolation_even(int line_width, ushort* line_buf, int pos) +{ + ushort* line_buf_cur = line_buf + pos; + int Rb = line_buf_cur[-2 - line_width]; + int Rc = line_buf_cur[-3 - line_width]; + int Rd = line_buf_cur[-1 - line_width]; + int Rf = line_buf_cur[-4 - 2*line_width]; + int diffRcRb = _abs(Rc - Rb); + int diffRfRb = _abs(Rf - Rb); + int diffRdRb = _abs(Rd - Rb); + if ( diffRcRb > diffRfRb && diffRcRb > diffRdRb ) + *line_buf_cur = (Rf + Rd + 2 * Rb) >> 2; + else if ( diffRdRb > diffRcRb && diffRdRb > diffRfRb ) + *line_buf_cur = (Rf + Rc + 2 * Rb) >> 2; + else + *line_buf_cur = (Rd + Rc + 2 * Rb) >> 2; +} + +void CLASS xtrans_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end) +{ + for(int i = start; i<= end; i++) + { + linebuf[i][0] = linebuf[i-1][1]; + linebuf[i][line_width + 1] = linebuf[i-1][line_width]; + } +} + +void CLASS xtrans_extend_red(ushort *linebuf[_ltotal], int line_width) +{ + xtrans_extend_generic(linebuf,line_width,_R2,_R4); +} + +void CLASS xtrans_extend_green(ushort *linebuf[_ltotal], int line_width) +{ + xtrans_extend_generic(linebuf,line_width,_G2,_G7); +} + +void CLASS xtrans_extend_blue(ushort *linebuf[_ltotal], int line_width) +{ + xtrans_extend_generic(linebuf,line_width,_B2,_B4); +} + +void CLASS xtrans_decode_block(struct xtrans_block* info, const struct xtrans_params *params, int cur_line) +{ + int r_even_pos = 0, r_odd_pos = 1; + int g_even_pos = 0, g_odd_pos = 1; + int b_even_pos = 0, b_odd_pos = 1; + + int errcnt = 0; + + const int line_width = params->line_width; + + while (g_even_pos < line_width || g_odd_pos < line_width) + { + if (g_even_pos < line_width) + { + fuji_decode_interpolation_even(line_width, info->linebuf[_R2] + 1, r_even_pos); + r_even_pos += 2; + errcnt+=fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, info->grad_even[0]); + g_even_pos += 2; + } + if (g_even_pos > 8) + { + errcnt+=fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, info->grad_odd[0]); + r_odd_pos += 2; + errcnt+=fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, info->grad_odd[0]); + g_odd_pos += 2; + } + } + + xtrans_extend_red(info->linebuf,line_width); + xtrans_extend_green(info->linebuf,line_width); + + g_even_pos = 0, g_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) + { + if (g_even_pos < line_width) + { + errcnt+=fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, info->grad_even[1]); + g_even_pos += 2; + fuji_decode_interpolation_even(line_width,info->linebuf[_B2] + 1, b_even_pos); + b_even_pos += 2; + } + if (g_even_pos > 8) + { + errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_G3] + 1, g_odd_pos, info->grad_odd[1]); + g_odd_pos += 2; + errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_B2] + 1, b_odd_pos, info->grad_odd[1]); + b_odd_pos += 2; + } + } + + xtrans_extend_green(info->linebuf,line_width); + xtrans_extend_blue(info->linebuf,line_width); + + r_even_pos = 0, r_odd_pos = 1; + g_even_pos = 0, g_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) + { + if (g_even_pos < line_width) + { + if (r_even_pos & 3) + errcnt+=fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, info->grad_even[2]); + else + fuji_decode_interpolation_even(line_width, info->linebuf[_R3] + 1, r_even_pos); + r_even_pos += 2; + fuji_decode_interpolation_even(line_width, info->linebuf[_G4] + 1, g_even_pos); + g_even_pos += 2; + } + if (g_even_pos > 8) + { + errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_R3] + 1, r_odd_pos, info->grad_odd[2]); + r_odd_pos += 2; + errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_G4] + 1, g_odd_pos, info->grad_odd[2]); + g_odd_pos += 2; + } + } + + xtrans_extend_red(info->linebuf,line_width); + xtrans_extend_green(info->linebuf,line_width); + + g_even_pos = 0, g_odd_pos = 1; + b_even_pos = 0, b_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) + { + if (g_even_pos < line_width) + { + errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_G5] + 1, g_even_pos, info->grad_even[0]); + g_even_pos += 2; + if ((b_even_pos & 3) == 2) + fuji_decode_interpolation_even(line_width, info->linebuf[_B3] + 1, b_even_pos); + else + errcnt+=fuji_decode_sample_even(info, params,info->linebuf[_B3] + 1, b_even_pos, info->grad_even[0]); + b_even_pos += 2; + } + if (g_even_pos > 8) + { + errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_G5] + 1, g_odd_pos, info->grad_odd[0]); + g_odd_pos += 2; + errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_B3] + 1, b_odd_pos, info->grad_odd[0]); + b_odd_pos += 2; + } + } + + xtrans_extend_green(info->linebuf,line_width); + xtrans_extend_blue(info->linebuf,line_width); + + r_even_pos = 0, r_odd_pos = 1; + g_even_pos = 0, g_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) + { + if (g_even_pos < line_width) + { + if ((r_even_pos & 3) == 2) + fuji_decode_interpolation_even(line_width, info->linebuf[_R4] + 1, r_even_pos); + else + errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_R4] + 1, r_even_pos, info->grad_even[1]); + r_even_pos += 2; + errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_G6] + 1, g_even_pos, info->grad_even[1]); + g_even_pos += 2; + } + if (g_even_pos > 8) + { + errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_R4] + 1, r_odd_pos, info->grad_odd[1]); + r_odd_pos += 2; + errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_G6] + 1, g_odd_pos, info->grad_odd[1]); + g_odd_pos += 2; + } + } + + xtrans_extend_red(info->linebuf,line_width); + xtrans_extend_green(info->linebuf,line_width); + + g_even_pos = 0, g_odd_pos = 1; + b_even_pos = 0, b_odd_pos = 1; + + while (g_even_pos < line_width || g_odd_pos < line_width) + { + if (g_even_pos < line_width) + { + fuji_decode_interpolation_even(line_width, info->linebuf[_G7] + 1, g_even_pos); + g_even_pos += 2; + if (b_even_pos & 3) + errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_B4] + 1, b_even_pos, info->grad_even[2]); + else + fuji_decode_interpolation_even(line_width, info->linebuf[_B4] + 1, b_even_pos); + b_even_pos += 2; + } + if (g_even_pos > 8) + { + errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_G7] + 1, g_odd_pos, info->grad_odd[2]); + g_odd_pos += 2; + errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_B4] + 1, b_odd_pos, info->grad_odd[2]); + b_odd_pos += 2; + } + } + + xtrans_extend_green(info->linebuf,line_width); + xtrans_extend_blue(info->linebuf,line_width); + + if(errcnt) + derror(); +} + +void CLASS xtrans_decode_strip(const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize) +{ + int cur_block_width, cur_line; + unsigned line_size; + struct xtrans_block info; + + init_xtrans_block(&info, info_common, raw_offset,dsize); + line_size = sizeof(ushort)*(info_common->line_width+2); + + cur_block_width = fuji_block_width; + if (cur_block+1 == fuji_total_blocks) + cur_block_width = raw_width % fuji_block_width; + + struct i_pair + { + int a,b; + }; + const i_pair mtable[6] = { {_R0,_R3},{_R1,_R4},{_G0,_G6},{_G1,_G7},{_B0,_B3},{_B1,_B4}}, + ztable[3]= {{_R2,3},{_G2,6},{_B2,3}}; + for (cur_line = 0; cur_line < fuji_total_lines; cur_line++) + { + xtrans_decode_block(&info, info_common, cur_line); + + // copy data from line buffers and advance + for(int i=0; i < 6; i++) + memcpy(info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size); + + copy_line_to_xtrans(&info, cur_line, cur_block, cur_block_width); + + for(int i=0; i < 3; i++) + { + memset(info.linebuf[ztable[i].a], 0, ztable[i].b*line_size); + info.linebuf[ztable[i].a][0] = info.linebuf[ztable[i].a-1][1]; + info.linebuf[ztable[i].a][info_common->line_width + 1] = info.linebuf[ztable[i].a-1][info_common->line_width]; + } + } + + // release data + free(info.linealloc); + free(info.cur_buf); +} + +static unsigned sgetn(int n, uchar *s) +{ + unsigned result = 0; + while (n-- > 0) + result = (result<<8) | (*s++); + return result; +} + +void CLASS xtrans_compressed_load_raw() +{ + struct xtrans_params common_info; + int cur_block; + unsigned line_size, *block_sizes; + INT64 raw_offset, *raw_block_offsets; + //struct xtrans_block info; + + init_xtrans(&common_info); + line_size = sizeof(ushort)*(common_info.line_width+2); + + // read block sizes + block_sizes = (unsigned*) malloc(sizeof(unsigned)* fuji_total_blocks); + merror(block_sizes, "xtrans_load_raw()"); + raw_block_offsets = (INT64*) malloc(sizeof(INT64)*fuji_total_blocks); + merror(raw_block_offsets, "xtrans_load_raw()"); + + raw_offset = sizeof(unsigned)*fuji_total_blocks; + if (raw_offset & 0xC) + raw_offset += 0x10 - (raw_offset & 0xC); + + raw_offset += data_offset; + + fseek (ifp, data_offset, SEEK_SET); + fread (block_sizes, 1, sizeof(unsigned)*fuji_total_blocks, ifp); + + raw_block_offsets[0] = raw_offset; + // calculating raw block offsets + for (cur_block = 0; cur_block < fuji_total_blocks; cur_block++) + { + unsigned bsize = sgetn(4, (uchar *)(block_sizes+cur_block)); + block_sizes[cur_block] = bsize; + } + + for (cur_block = 1; cur_block < fuji_total_blocks; cur_block++) + raw_block_offsets[cur_block] = raw_block_offsets[cur_block-1] + block_sizes[cur_block-1] ; + + xtrans_decode_loop(&common_info,fuji_total_blocks,raw_block_offsets,block_sizes); + + free(block_sizes); + free(raw_block_offsets); + free(common_info.q_table); +} + +void CLASS xtrans_decode_loop(const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes) +{ + int cur_block; +#ifdef _OPENMP +#pragma omp parallel for private(cur_block) +#endif + for (cur_block = 0; cur_block < count ; cur_block++) + { + xtrans_decode_strip(common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block]); + } +} + + +void CLASS parse_xtrans_header() +{ + + uchar header[16]; + + ushort signature; + uchar version; + uchar h_raw_type; + uchar h_raw_bits; + ushort h_raw_height; + ushort h_raw_rounded_width; + ushort h_raw_width; + ushort h_block_size; + uchar h_blocks_in_row; + ushort h_total_lines; + + fseek(ifp, data_offset, SEEK_SET); + fread(header, 1, sizeof(header),ifp); + + signature = sgetn(2, header); + version = header[2]; + h_raw_type = header[3]; + h_raw_bits = header[4]; + h_raw_height = sgetn(2, header+5); + h_raw_rounded_width = sgetn(2, header+7); + h_raw_width = sgetn(2, header+9); + h_block_size = sgetn(2, header+11); + h_blocks_in_row = header[13]; + h_total_lines = sgetn(2, header+14); + + + // general validation + if (signature != 0x4953 + || version != 1 + || h_raw_height > 0x3000 + || h_raw_height < 6 + || h_raw_height % 6 + || h_raw_width > 0x3000 + || h_raw_width < 0x300 + || h_raw_width % 24 + || h_raw_rounded_width > 0x3000 + || h_raw_rounded_width < h_block_size + || h_raw_rounded_width % h_block_size + || h_raw_rounded_width - h_raw_width >= h_block_size + || h_block_size != 0x300 + || h_blocks_in_row > 0x10 + || h_blocks_in_row == 0 + || h_blocks_in_row != h_raw_rounded_width / h_block_size + || h_total_lines > 0x800 + || h_total_lines == 0 + || h_total_lines != h_raw_height / 6 + || (h_raw_bits != 12 && h_raw_bits != 14) + || h_raw_type != 16) { + xtransCompressed = false; + return; + } + // modify data + fuji_total_lines = h_total_lines; + fuji_total_blocks = h_blocks_in_row; + fuji_block_width = h_block_size; + fuji_bits = h_raw_bits; + raw_width = h_raw_width; + raw_height = h_raw_height; + data_offset += 16; + load_raw = &xtrans_compressed_load_raw; +} From f2bef65be14362367298bf096dd57c6d1fcda785 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 11 Feb 2017 18:28:52 +0100 Subject: [PATCH 33/42] small cleanup --- rtengine/dcraw.cc | 3 +-- rtengine/rawimage.cc | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index a35e3454d..3b6d98133 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -11,8 +11,7 @@ /*RT*/#define DJGPP #include "opthelper.h" -#include -#include + /* dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index c10cc5abd..bfe7092f2 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -14,8 +14,6 @@ #include #endif -#include - namespace rtengine { From d8baa48e13f2e0d4fc655e87dab858aa212bff2f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 11 Feb 2017 21:17:22 +0100 Subject: [PATCH 34/42] fixed compile issue in xtranscompressed --- rtengine/xtranscompressed.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/xtranscompressed.cc b/rtengine/xtranscompressed.cc index ed91df841..18ccbe5bf 100644 --- a/rtengine/xtranscompressed.cc +++ b/rtengine/xtranscompressed.cc @@ -771,5 +771,5 @@ void CLASS parse_xtrans_header() raw_width = h_raw_width; raw_height = h_raw_height; data_offset += 16; - load_raw = &xtrans_compressed_load_raw; + load_raw = &CLASS xtrans_compressed_load_raw; } From 45578f32e67babb709b1871d8645e1a9edf39f2f Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Sat, 11 Feb 2017 23:24:44 +0100 Subject: [PATCH 35/42] Added NIKON D80 dual-illuminant DCP, closes #3669 --- rtdata/dcpprofiles/NIKON D80.dcp | Bin 0 -> 1045582 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rtdata/dcpprofiles/NIKON D80.dcp diff --git a/rtdata/dcpprofiles/NIKON D80.dcp b/rtdata/dcpprofiles/NIKON D80.dcp new file mode 100644 index 0000000000000000000000000000000000000000..965c358aa8e014a88270ebe5a66c424dc79072e0 GIT binary patch literal 1045582 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

YN%kJjs+28Ux3#Bdpa`%bK1E91p@p4qmt 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