diff --git a/krita/main.cc b/krita/main.cc index c7c03a657f..38971b80b1 100644 --- a/krita/main.cc +++ b/krita/main.cc @@ -1,467 +1,467 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2015 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050900 #include #endif #include #include #include #include #include #include "data/splash/splash_screen.xpm" #include "data/splash/splash_holidays.xpm" #include "data/splash/splash_screen_x2.xpm" #include "data/splash/splash_holidays_x2.xpm" #include "KisDocument.h" #include "kis_splash_screen.h" #include "KisPart.h" #include "KisApplicationArguments.h" #include #include "input/KisQtWidgetsTweaker.h" #if defined Q_OS_WIN #include #include #include #include #elif defined HAVE_X11 #include "config_use_qt_xcb.h" #ifndef USE_QT_XCB #include #endif #endif #if defined HAVE_KCRASH #include #elif defined USE_DRMINGW namespace { void tryInitDrMingw() { wchar_t path[MAX_PATH]; QString pathStr = QCoreApplication::applicationDirPath().replace(L'/', L'\\') + QStringLiteral("\\exchndl.dll"); if (pathStr.size() > MAX_PATH - 1) { return; } int pathLen = pathStr.toWCharArray(path); path[pathLen] = L'\0'; // toWCharArray doesn't add NULL terminator HMODULE hMod = LoadLibraryW(path); if (!hMod) { return; } // No need to call ExcHndlInit since the crash handler is installed on DllMain auto myExcHndlSetLogFileNameA = reinterpret_cast(GetProcAddress(hMod, "ExcHndlSetLogFileNameA")); if (!myExcHndlSetLogFileNameA) { return; } // Set the log file path to %LocalAppData%\kritacrash.log QString logFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation).replace(L'/', L'\\') + QStringLiteral("\\kritacrash.log"); myExcHndlSetLogFileNameA(logFile.toLocal8Bit()); } typedef enum ORIENTATION_PREFERENCE { ORIENTATION_PREFERENCE_NONE = 0x0, ORIENTATION_PREFERENCE_LANDSCAPE = 0x1, ORIENTATION_PREFERENCE_PORTRAIT = 0x2, ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED = 0x4, ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED = 0x8 } ORIENTATION_PREFERENCE; typedef BOOL WINAPI (*pSetDisplayAutoRotationPreferences_t)( ORIENTATION_PREFERENCE orientation ); void resetRotation() { QLibrary user32Lib("user32"); if (!user32Lib.load()) { qWarning() << "Failed to load user32.dll! This really should not happen."; return; } pSetDisplayAutoRotationPreferences_t pSetDisplayAutoRotationPreferences = reinterpret_cast(user32Lib.resolve("SetDisplayAutoRotationPreferences")); if (!pSetDisplayAutoRotationPreferences) { dbgKrita << "Failed to load function SetDisplayAutoRotationPreferences"; return; } bool result = pSetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE); dbgKrita << "SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE) returned" << result; } } // namespace #endif extern "C" int main(int argc, char **argv) { // The global initialization of the random generator qsrand(time(0)); bool runningInKDE = !qgetenv("KDE_FULL_SESSION").isEmpty(); #if defined HAVE_X11 qputenv("QT_QPA_PLATFORM", "xcb"); #endif // Workaround a bug in QNetworkManager qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1)); // A per-user unique string, without /, because QLocalServer cannot use names with a / in it QString key = "Krita4" + QStandardPaths::writableLocation(QStandardPaths::HomeLocation).replace("/", "_"); key = key.replace(":", "_").replace("\\","_"); QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); #if QT_VERSION >= 0x050900 QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache, true); #endif const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); bool singleApplication = true; bool enableOpenGLDebug = false; bool openGLDebugSynchronous = false; { QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); singleApplication = kritarc.value("EnableSingleApplication", true).toBool(); #if QT_VERSION >= 0x050600 if (kritarc.value("EnableHiDPI", true).toBool()) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } if (!qgetenv("KRITA_HIDPI").isEmpty()) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } #endif if (!qgetenv("KRITA_OPENGL_DEBUG").isEmpty()) { enableOpenGLDebug = true; } else { enableOpenGLDebug = kritarc.value("EnableOpenGLDebug", false).toBool(); } if (enableOpenGLDebug && (qgetenv("KRITA_OPENGL_DEBUG") == "sync" || kritarc.value("OpenGLDebugSynchronous", false).toBool())) { openGLDebugSynchronous = true; } - KisOpenGL::setDefaultFormat(enableOpenGLDebug, openGLDebugSynchronous); + KisOpenGL::setDefaultFormat(enableOpenGLDebug, openGLDebugSynchronous, &kritarc); #ifdef Q_OS_WIN QString preferredOpenGLRenderer = kritarc.value("OpenGLRenderer", "auto").toString(); // Force ANGLE to use Direct3D11. D3D9 doesn't support OpenGL ES 3 and WARP // might get weird crashes atm. qputenv("QT_ANGLE_PLATFORM", "d3d11"); // Probe QPA auto OpenGL detection char *fakeArgv[2] = { argv[0], nullptr }; // Prevents QCoreApplication from modifying the real argc/argv KisOpenGL::probeWindowsQpaOpenGL(1, fakeArgv, preferredOpenGLRenderer); // HACK: https://bugs.kde.org/show_bug.cgi?id=390651 resetRotation(); #endif } QString root; QString language; { // Create a temporary application to get the root QCoreApplication app(argc, argv); Q_UNUSED(app); root = KoResourcePaths::getApplicationRoot(); QSettings languageoverride(configPath + QStringLiteral("/klanguageoverridesrc"), QSettings::IniFormat); languageoverride.beginGroup(QStringLiteral("Language")); language = languageoverride.value(qAppName(), "").toString(); } #ifdef Q_OS_LINUX { QByteArray originalXdgDataDirs = qgetenv("XDG_DATA_DIRS"); if (originalXdgDataDirs.isEmpty()) { // We don't want to completely override the default originalXdgDataDirs = "/usr/local/share/:/usr/share/"; } qputenv("XDG_DATA_DIRS", QFile::encodeName(root + "share") + ":" + originalXdgDataDirs); } #else qputenv("XDG_DATA_DIRS", QFile::encodeName(root + "share")); #endif dbgKrita << "Setting XDG_DATA_DIRS" << qgetenv("XDG_DATA_DIRS"); // Now that the paths are set, set the language. First check the override from the language // selection dialog. dbgKrita << "Override language:" << language; bool rightToLeft = false; if (!language.isEmpty()) { KLocalizedString::setLanguages(language.split(":")); // And override Qt's locale, too qputenv("LANG", language.split(":").first().toLocal8Bit()); QLocale locale(language.split(":").first()); QLocale::setDefault(locale); const QStringList rtlLanguages = QStringList() << "ar" << "dv" << "he" << "ha" << "ku" << "fa" << "ps" << "ur" << "yi"; if (rtlLanguages.contains(language.split(':').first())) { rightToLeft = true; } } else { dbgKrita << "Qt UI languages:" << QLocale::system().uiLanguages() << qgetenv("LANG"); // And if there isn't one, check the one set by the system. QLocale locale = QLocale::system(); if (locale.name() != QStringLiteral("en")) { QStringList uiLanguages = locale.uiLanguages(); for (QString &uiLanguage : uiLanguages) { // This list of language codes that can have a specifier should // be extended whenever we have translations that need it; right // now, only en, pt, zh are in this situation. if (uiLanguage.startsWith("en") || uiLanguage.startsWith("pt")) { uiLanguage.replace(QChar('-'), QChar('_')); } else if (uiLanguage.startsWith("zh-Hant") || uiLanguage.startsWith("zh-TW")) { uiLanguage = "zh_TW"; } else if (uiLanguage.startsWith("zh-Hans") || uiLanguage.startsWith("zh-CN")) { uiLanguage = "zh_CN"; } } for (int i = 0; i < uiLanguages.size(); i++) { QString uiLanguage = uiLanguages[i]; // Strip the country code int idx = uiLanguage.indexOf(QChar('-')); if (idx != -1) { uiLanguage = uiLanguage.left(idx); uiLanguages.replace(i, uiLanguage); } } dbgKrita << "Converted ui languages:" << uiLanguages; qputenv("LANG", uiLanguages.first().toLocal8Bit()); #ifdef Q_OS_MAC // See https://bugs.kde.org/show_bug.cgi?id=396370 KLocalizedString::setLanguages(QStringList() << uiLanguages.first()); #else KLocalizedString::setLanguages(QStringList() << uiLanguages); #endif } } // first create the application so we can create a pixmap KisApplication app(key, argc, argv); if (!language.isEmpty()) { if (rightToLeft) { app.setLayoutDirection(Qt::RightToLeft); } else { app.setLayoutDirection(Qt::LeftToRight); } } KLocalizedString::setApplicationDomain("krita"); dbgKrita << "Available translations" << KLocalizedString::availableApplicationTranslations(); dbgKrita << "Available domain translations" << KLocalizedString::availableDomainTranslations("krita"); #ifdef Q_OS_WIN QDir appdir(KoResourcePaths::getApplicationRoot()); QString path = qgetenv("PATH"); qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";" + appdir.absolutePath() + "/lib" + ";" + appdir.absolutePath() + "/Frameworks" + ";" + appdir.absolutePath() + ";" + path)); dbgKrita << "PATH" << qgetenv("PATH"); #endif if (qApp->applicationDirPath().contains(KRITA_BUILD_DIR)) { qFatal("FATAL: You're trying to run krita from the build location. You can only run Krita from the installation location."); } #if defined HAVE_KCRASH KCrash::initialize(); #elif defined USE_DRMINGW tryInitDrMingw(); #endif // If we should clear the config, it has to be done as soon as possible after // KisApplication has been created. Otherwise the config file may have been read // and stored in a KConfig object we have no control over. app.askClearConfig(); KisApplicationArguments args(app); if (singleApplication && app.isRunning()) { // only pass arguments to main instance if they are not for batch processing // any batch processing would be done in this separate instance const bool batchRun = args.exportAs(); if (!batchRun) { QByteArray ba = args.serialize(); if (app.sendMessage(ba)) { return 0; } } } if (!runningInKDE) { // Icons in menus are ugly and distracting app.setAttribute(Qt::AA_DontShowIconsInMenus); } #if defined HAVE_X11 #ifndef USE_QT_XCB app.installNativeEventFilter(KisXi2EventFilter::instance()); #endif #endif app.installEventFilter(KisQtWidgetsTweaker::instance()); if (!args.noSplash()) { // then create the pixmap from an xpm: we cannot get the // location of our datadir before we've started our components, // so use an xpm. QDate currentDate = QDate::currentDate(); QWidget *splash = 0; if (currentDate > QDate(currentDate.year(), 12, 4) || currentDate < QDate(currentDate.year(), 1, 9)) { splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_holidays_xpm), QPixmap(splash_holidays_x2_xpm)); } else { splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_screen_xpm), QPixmap(splash_screen_x2_xpm)); } app.setSplashScreen(splash); } #if defined Q_OS_WIN KisConfig cfg(false); bool supportedWindowsVersion = true; #if QT_VERSION >= 0x050900 QOperatingSystemVersion osVersion = QOperatingSystemVersion::current(); if (osVersion.type() == QOperatingSystemVersion::Windows) { if (osVersion.majorVersion() >= QOperatingSystemVersion::Windows7.majorVersion()) { supportedWindowsVersion = true; } else { supportedWindowsVersion = false; if (cfg.readEntry("WarnedAboutUnsupportedWindows", false)) { QMessageBox::information(0, i18nc("@title:window", "Krita: Warning"), i18n("You are running an unsupported version of Windows: %1.\n" "This is not recommended. Do not report any bugs.\n" "Please update to a supported version of Windows: Windows 7, 8, 8.1 or 10.", osVersion.name())); cfg.writeEntry("WarnedAboutUnsupportedWindows", true); } } } #endif { if (cfg.useWin8PointerInput() && !KisTabletSupportWin8::isAvailable()) { cfg.setUseWin8PointerInput(false); } if (!cfg.useWin8PointerInput()) { bool hasWinTab = KisTabletSupportWin::init(); if (!hasWinTab && supportedWindowsVersion) { if (KisTabletSupportWin8::isPenDeviceAvailable()) { // Use WinInk automatically cfg.setUseWin8PointerInput(true); } else if (!cfg.readEntry("WarnedAboutMissingWinTab", false)) { if (KisTabletSupportWin8::isAvailable()) { QMessageBox::information(nullptr, i18n("Krita Tablet Support"), i18n("Cannot load WinTab driver and no Windows Ink pen devices are found. If you have a drawing tablet, please make sure the tablet driver is properly installed."), QMessageBox::Ok, QMessageBox::Ok); } else { QMessageBox::information(nullptr, i18n("Krita Tablet Support"), i18n("Cannot load WinTab driver. If you have a drawing tablet, please make sure the tablet driver is properly installed."), QMessageBox::Ok, QMessageBox::Ok); } cfg.writeEntry("WarnedAboutMissingWinTab", true); } } } if (cfg.useWin8PointerInput()) { KisTabletSupportWin8 *penFilter = new KisTabletSupportWin8(); if (penFilter->init()) { // penFilter.registerPointerDeviceNotifications(); app.installNativeEventFilter(penFilter); dbgKrita << "Using Win8 Pointer Input for tablet support"; } else { dbgKrita << "No Win8 Pointer Input available"; delete penFilter; } } } #endif if (!app.start(args)) { return 1; } #if QT_VERSION >= 0x050700 app.setAttribute(Qt::AA_CompressHighFrequencyEvents, false); #endif // Set up remote arguments. QObject::connect(&app, SIGNAL(messageReceived(QByteArray,QObject*)), &app, SLOT(remoteArguments(QByteArray,QObject*))); QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), &app, SLOT(fileOpenRequested(QString))); int state = app.exec(); { QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("canvasState", "OPENGL_SUCCESS"); } return state; } diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index a86eaf94e8..d6a4025471 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,594 +1,596 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) find_library(APPKIT_LIBRARY AppKit) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_config.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_infinity_manager.cpp canvas/kis_change_guides_command.cpp canvas/kis_guides_decoration.cpp canvas/kis_guides_manager.cpp canvas/kis_guides_config.cpp canvas/kis_snap_config.cpp canvas/kis_snap_line_strategy.cpp canvas/KisSnapPointStrategy.cpp dialogs/kis_about_application.cpp dialogs/kis_dlg_adj_layer_props.cc dialogs/kis_dlg_adjustment_layer.cc dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_generator_layer.cpp dialogs/kis_dlg_file_layer.cpp dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_stroke_selection_properties.cpp dialogs/kis_dlg_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc dialogs/slider_and_spin_box_sync.cpp dialogs/kis_dlg_blacklist_cleanup.cpp dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp dialogs/kis_dlg_import_image_sequence.cpp dialogs/kis_delayed_save_dialog.cpp dialogs/KisSessionManagerDialog.cpp dialogs/KisNewWindowLayoutDialog.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp flake/kis_dummies_facade.cpp flake/kis_node_shapes_graph.cpp flake/kis_node_shape.cpp flake/kis_shape_controller.cpp flake/kis_shape_layer.cc flake/kis_shape_layer_canvas.cpp flake/kis_shape_selection.cpp flake/kis_shape_selection_canvas.cpp flake/kis_shape_selection_model.cpp flake/kis_take_all_shapes_command.cpp brushhud/kis_uniform_paintop_property_widget.cpp brushhud/kis_brush_hud.cpp brushhud/kis_round_hud_button.cpp brushhud/kis_dlg_brush_hud_config.cpp brushhud/kis_brush_hud_properties_list.cpp brushhud/kis_brush_hud_properties_config.cpp kis_aspect_ratio_locker.cpp kis_autogradient.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc KisPaintopPropertiesBase.cpp kis_canvas_resource_provider.cpp kis_derived_resources.cpp kis_categories_mapper.cpp kis_categorized_list_model.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_cursor_cache.cpp kis_custom_pattern.cc kis_file_layer.cpp kis_change_file_layer_command.h kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc KisImageBarrierLockerWithFeedback.cpp kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_juggler_compressed.cpp kis_node_selection_adapter.cpp kis_node_insertion_adapter.cpp KisNodeDisplayModeAdapter.cpp kis_node_model.cpp kis_node_filter_proxy_model.cpp kis_model_index_converter_base.cpp kis_model_index_converter.cpp kis_model_index_converter_show_all.cpp kis_painting_assistant.cc kis_painting_assistants_decoration.cpp KisDecorationsManager.cpp kis_paintop_box.cc kis_paintop_option.cpp kis_paintop_options_model.cpp kis_paintop_settings_widget.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp KisResourceServerProvider.cpp KisResourceBundleServerProvider.cpp KisSelectedShapesProxy.cpp kis_selection_decoration.cc kis_selection_manager.cc KisSelectionActionsAdapter.cpp kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp KisActionPlugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kis_multinode_property.cpp kis_stopgradient_editor.cpp KisWelcomePageWidget.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp opengl/kis_opengl.cpp opengl/kis_opengl_canvas2.cpp opengl/kis_opengl_canvas_debugger.cpp opengl/kis_opengl_image_textures.cpp opengl/kis_texture_tile.cpp opengl/kis_opengl_shader_loader.cpp opengl/kis_texture_tile_info_pool.cpp opengl/KisOpenGLUpdateInfoBuilder.cpp + opengl/KisOpenGLModeProber.cpp + opengl/KisScreenInformationAdapter.cpp kis_fps_decoration.cpp tool/KisToolChangesTracker.cpp tool/KisToolChangesTrackerData.cpp tool/kis_selection_tool_helper.cpp tool/kis_selection_tool_config_widget_helper.cpp tool/kis_rectangle_constraint_widget.cpp tool/kis_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_delegated_tool_policies.cpp tool/kis_tool_freehand.cc tool/kis_speed_smoother.cpp tool/kis_painting_information_builder.cpp tool/kis_stabilized_events_sampler.cpp tool/kis_tool_freehand_helper.cpp tool/kis_tool_multihand_helper.cpp tool/kis_figure_painting_tool_helper.cpp tool/kis_tool_paint.cc tool/kis_tool_shape.cc tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_tool_utils.cpp tool/kis_resources_snapshot.cpp tool/kis_smoothing_options.cpp tool/KisStabilizerDelayedPaintHelper.cpp tool/KisStrokeSpeedMonitor.cpp tool/strokes/freehand_stroke.cpp tool/strokes/KisStrokeEfficiencyMeasurer.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.cpp tool/strokes/KisFreehandStrokeInfo.cpp tool/strokes/KisMaskedFreehandStrokePainter.cpp tool/strokes/KisMaskingBrushRenderer.cpp tool/strokes/KisMaskingBrushCompositeOpFactory.cpp tool/strokes/move_stroke_strategy.cpp tool/KisSelectionToolFactoryBase.cpp tool/KisToolPaintFactoryBase.cpp widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_advanced_color_space_selector.cc widgets/kis_cie_tongue_widget.cpp widgets/kis_tone_curve_widget.cpp widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc widgets/kis_image_from_clipboard_widget.cpp widgets/kis_double_widget.cc widgets/kis_filter_selector_widget.cc widgets/kis_gradient_chooser.cc widgets/kis_iconwidget.cc widgets/kis_mask_widgets.cpp widgets/kis_meta_data_merge_strategy_chooser_widget.cc widgets/kis_multi_bool_filter_widget.cc widgets/kis_multi_double_filter_widget.cc widgets/kis_multi_integer_filter_widget.cc widgets/kis_multipliers_double_slider_spinbox.cpp widgets/kis_paintop_presets_popup.cpp widgets/kis_tool_options_popup.cpp widgets/kis_paintop_presets_chooser_popup.cpp widgets/kis_paintop_presets_save.cpp widgets/kis_paintop_preset_icon_library.cpp widgets/kis_pattern_chooser.cc widgets/kis_preset_chooser.cpp widgets/kis_progress_widget.cpp widgets/kis_selection_options.cc widgets/kis_scratch_pad.cpp widgets/kis_scratch_pad_event_filter.cpp widgets/kis_preset_selector_strip.cpp widgets/kis_slider_spin_box.cpp widgets/KisSelectionPropertySlider.cpp widgets/kis_size_group.cpp widgets/kis_size_group_p.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/kis_categorized_list_view.cpp widgets/kis_widget_chooser.cpp widgets/kis_tool_button.cpp widgets/kis_floating_message.cpp widgets/kis_lod_availability_widget.cpp widgets/kis_color_label_selector_widget.cpp widgets/kis_color_filter_combo.cpp widgets/kis_elided_label.cpp widgets/kis_stopgradient_slider_widget.cpp widgets/kis_preset_live_preview_view.cpp widgets/KisScreenColorPicker.cpp widgets/KoDualColorButton.cpp widgets/KoStrokeConfigWidget.cpp widgets/KoFillConfigWidget.cpp KisPaletteEditor.cpp dialogs/KisDlgPaletteEditor.cpp widgets/KisNewsWidget.cpp widgets/KisGamutMaskToolbar.cpp utils/kis_document_aware_spin_box_unit_manager.cpp input/kis_input_manager.cpp input/kis_input_manager_p.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_change_frame_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_native_gesture_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp input/KisQtWidgetsTweaker.cpp input/KisInputActionGroup.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp actions/KisPasteActionFactory.cpp actions/KisTransformToolActivationCommand.cpp input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_gui_context_command.cpp kis_gui_context_command_p.cpp input/kis_tablet_debugger.cpp input/kis_input_profile_manager.cpp input/kis_input_profile.cpp input/kis_shortcut_configuration.cpp input/config/kis_input_configuration_page.cpp input/config/kis_edit_profiles_dialog.cpp input/config/kis_input_profile_model.cpp input/config/kis_input_configuration_page_item.cpp input/config/kis_action_shortcuts_model.cpp input/config/kis_input_type_delegate.cpp input/config/kis_input_mode_delegate.cpp input/config/kis_input_button.cpp input/config/kis_input_editor_delegate.cpp input/config/kis_mouse_input_editor.cpp input/config/kis_wheel_input_editor.cpp input/config/kis_key_input_editor.cpp processing/fill_processing_visitor.cpp kis_asl_layer_style_serializer.cpp kis_psd_layer_style_resource.cpp canvas/kis_mirror_axis.cpp kis_abstract_perspective_grid.cpp KisApplication.cpp KisAutoSaveRecoveryDialog.cpp KisDetailsPane.cpp KisDocument.cpp KisCloneDocumentStroke.cpp KisNodeDelegate.cpp kis_node_view_visibility_delegate.cpp KisNodeToolTip.cpp KisNodeView.cpp kis_node_view_color_scheme.cpp KisImportExportFilter.cpp KisFilterEntry.cpp KisImportExportManager.cpp KisImportExportUtils.cpp kis_async_action_feedback.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoActionsUpdateManager.cpp KisView.cpp thememanager.cpp kis_mainwindow_observer.cpp KisViewManager.cpp kis_mirror_manager.cpp qtlockedfile/qtlockedfile.cpp qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtsingleapplication.cpp KisResourceBundle.cpp KisResourceBundleManifest.cpp kis_md5_generator.cpp KisApplicationArguments.cpp KisNetworkAccessManager.cpp KisMultiFeedRSSModel.cpp KisRemoteFileFetcher.cpp KisSaveGroupVisitor.cpp KisWindowLayoutResource.cpp KisWindowLayoutManager.cpp KisSessionResource.cpp KisReferenceImagesDecoration.cpp KisReferenceImage.cpp flake/KisReferenceImagesLayer.cpp flake/KisReferenceImagesLayer.h ) if(WIN32) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp input/wintab/kis_tablet_support_win8.cpp opengl/kis_opengl_win.cpp ) endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_animation_frame_cache.cpp kis_animation_cache_populator.cpp KisAsyncAnimationRendererBase.cpp KisAsyncAnimationCacheRenderer.cpp KisAsyncAnimationFramesSavingRenderer.cpp dialogs/KisAsyncAnimationRenderDialogBase.cpp dialogs/KisAsyncAnimationCacheRenderDialog.cpp dialogs/KisAsyncAnimationFramesSaveDialog.cpp canvas/kis_animation_player.cpp kis_animation_importer.cpp KisSyncedAudioPlayback.cpp KisFrameDataSerializer.cpp KisFrameCacheStore.cpp KisFrameCacheSwapper.cpp KisAbstractFrameCacheSwapper.cpp KisInMemoryFrameCacheSwapper.cpp input/wintab/drawpile_tablettester/tablettester.cpp input/wintab/drawpile_tablettester/tablettest.cpp ) if (UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} qtlockedfile/qtlockedfile_unix.cpp ) if(NOT USE_QT_XCB) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support.cpp ) endif() if(NOT APPLE AND NOT USE_QT_XCB) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/qxcbconnection_xi2.cpp input/wintab/qxcbconnection.cpp input/wintab/kis_xi2_event_filter.cpp ) endif() endif() if(APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} osx.mm ) endif() ki18n_wrap_ui(kritaui_LIB_SRCS widgets/KoFillConfigWidget.ui widgets/KoStrokeConfigWidget.ui forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggenerators.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgcolorspaceselectoradvanced.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgsavebrushpreset.ui forms/wdgpreseticonlibrary.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/wdgstrokeselectionproperties.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui forms/wdgstopgradienteditor.ui forms/wdgsessionmanager.ui forms/wdgnewwindowlayout.ui forms/KisWelcomePage.ui forms/WdgDlgPaletteEditor.ui forms/KisNewsPage.ui forms/wdgGamutMaskToolbar.ui brushhud/kis_dlg_brush_hud_config.ui dialogs/kis_delayed_save_dialog.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui input/config/kis_mouse_input_editor.ui input/config/kis_wheel_input_editor.ui input/config/kis_key_input_editor.ui layerstyles/wdgBevelAndEmboss.ui layerstyles/wdgblendingoptions.ui layerstyles/WdgColorOverlay.ui layerstyles/wdgContour.ui layerstyles/wdgdropshadow.ui layerstyles/WdgGradientOverlay.ui layerstyles/wdgInnerGlow.ui layerstyles/wdglayerstyles.ui layerstyles/WdgPatternOverlay.ui layerstyles/WdgSatin.ui layerstyles/WdgStroke.ui layerstyles/wdgstylesselector.ui layerstyles/wdgTexture.ui wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.ui input/wintab/drawpile_tablettester/tablettest.ui ) QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h) add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} ) generate_export_header(kritaui BASE_NAME kritaui) target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ) if (HAVE_QT_MULTIMEDIA) target_link_libraries(kritaui Qt5::Multimedia) endif() if (NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${X11_X11_LIB} ${X11_Xinput_LIB} ${XCB_LIBRARIES}) endif() if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) target_link_libraries(kritaui ${APPKIT_LIBRARY}) endif () target_link_libraries(kritaui ${OPENEXR_LIBRARIES}) # Add VSync disable workaround if(NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras) endif() if(X11_FOUND) target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES}) endif() target_include_directories(kritaui PUBLIC $ $ $ $ $ $ $ ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () diff --git a/libs/ui/canvas/kis_display_color_converter.cpp b/libs/ui/canvas/kis_display_color_converter.cpp index fe93149171..ebc5ecebc8 100644 --- a/libs/ui/canvas/kis_display_color_converter.cpp +++ b/libs/ui/canvas/kis_display_color_converter.cpp @@ -1,761 +1,794 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_display_color_converter.h" #include #include #include #include #include #include #include #include #include #include "kis_config_notifier.h" #include "kis_canvas_resource_provider.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_image.h" #include "kis_node.h" #include "kundo2command.h" #include "kis_config.h" #include "kis_paint_device.h" #include "kis_iterator_ng.h" #include "kis_fixed_paint_device.h" +#include "opengl/KisOpenGLModeProber.h" Q_GLOBAL_STATIC(KisDisplayColorConverter, s_instance) struct KisDisplayColorConverter::Private { Private(KisDisplayColorConverter *_q, KoCanvasResourceProvider *_resourceManager) : q(_q), resourceManager(_resourceManager), nodeColorSpace(0), paintingColorSpace(0), monitorColorSpace(0), monitorProfile(0), renderingIntent(KoColorConversionTransformation::internalRenderingIntent()), conversionFlags(KoColorConversionTransformation::internalConversionFlags()), displayFilter(0), intermediateColorSpace(0), displayRenderer(new DisplayRenderer(_q, _resourceManager)), expectedOcioOutputColorSpace(0) { - // TODO: make switchable depending on the OpenGL surface type - expectedOcioOutputColorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id()); + QSurfaceFormat format = KisOpenGLModeProber::instance()->surfaceformatInUse(); + if (format.colorSpace() == QSurfaceFormat::scRGBColorSpace) { + expectedOcioOutputColorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id()); + } else if (format.colorSpace() == QSurfaceFormat::bt2020PQColorSpace) { + // TODO: make switchable depending on the OpenGL surface type + } + + useHDRMode = KisOpenGLModeProber::instance()->useHDRMode(); } KisDisplayColorConverter *const q; KoCanvasResourceProvider *resourceManager; const KoColorSpace *nodeColorSpace; const KoColorSpace *paintingColorSpace; const KoColorSpace *monitorColorSpace; const KoColorProfile *monitorProfile; KoColorConversionTransformation::Intent renderingIntent; KoColorConversionTransformation::ConversionFlags conversionFlags; QSharedPointer displayFilter; const KoColorSpace *intermediateColorSpace; KoColor intermediateFgColor; KisNodeSP connectedNode; const KoColorSpace *expectedOcioOutputColorSpace; + bool useHDRMode = false; + + inline KoColor approximateFromQColor(const QColor &qcolor); inline QColor approximateToQColor(const KoColor &color); void slotCanvasResourceChanged(int key, const QVariant &v); void slotUpdateCurrentNodeColorSpace(); void selectPaintingColorSpace(); void updateIntermediateFgColor(const KoColor &color); void setCurrentNode(KisNodeSP node); bool useOcio() const; template QImage convertToQImageDirect(KisPaintDeviceSP device); class DisplayRenderer : public KoColorDisplayRendererInterface { public: DisplayRenderer(KisDisplayColorConverter *displayColorConverter, KoCanvasResourceProvider *resourceManager) : m_displayColorConverter(displayColorConverter), m_resourceManager(resourceManager) { displayColorConverter->connect(displayColorConverter, SIGNAL(displayConfigurationChanged()), this, SIGNAL(displayConfigurationChanged())); } QImage convertToQImage(const KoColorSpace *srcColorSpace, const quint8 *data, qint32 width, qint32 height) const override { KisPaintDeviceSP dev = new KisPaintDevice(srcColorSpace); dev->writeBytes(data, 0, 0, width, height); return m_displayColorConverter->toQImage(dev); } QColor toQColor(const KoColor &c) const override { return m_displayColorConverter->toQColor(c); } KoColor approximateFromRenderedQColor(const QColor &c) const override { return m_displayColorConverter->approximateFromRenderedQColor(c); } KoColor fromHsv(int h, int s, int v, int a) const override { return m_displayColorConverter->fromHsv(h, s, v, a); } void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const override { m_displayColorConverter->getHsv(srcColor, h, s, v, a); } qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const override { return chaninfo->getUIMin(); } qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const override { qreal maxValue = chaninfo->getUIMax(); if (m_resourceManager) { qreal exposure = m_resourceManager->resource(KisCanvasResourceProvider::HdrExposure).value(); // not sure if *= is what we want maxValue *= std::pow(2.0, -exposure); } return maxValue; } const KoColorSpace* getPaintingColorSpace() const override { return m_displayColorConverter->paintingColorSpace(); } private: KisDisplayColorConverter *m_displayColorConverter; QPointer m_resourceManager; }; QScopedPointer displayRenderer; }; KisDisplayColorConverter::KisDisplayColorConverter(KoCanvasResourceProvider *resourceManager, QObject *parent) : QObject(parent), m_d(new Private(this, resourceManager)) { connect(m_d->resourceManager, SIGNAL(canvasResourceChanged(int,QVariant)), SLOT(slotCanvasResourceChanged(int,QVariant))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(selectPaintingColorSpace())); m_d->setCurrentNode(0); setMonitorProfile(0); setDisplayFilter(QSharedPointer(0)); } KisDisplayColorConverter::KisDisplayColorConverter() : m_d(new Private(this, 0)) { setDisplayFilter(QSharedPointer(0)); m_d->paintingColorSpace = KoColorSpaceRegistry::instance()->rgb8(); m_d->setCurrentNode(0); setMonitorProfile(0); } KisDisplayColorConverter::~KisDisplayColorConverter() { } KisDisplayColorConverter* KisDisplayColorConverter::dumbConverterInstance() { return s_instance; } KoColorDisplayRendererInterface* KisDisplayColorConverter::displayRendererInterface() const { return m_d->displayRenderer.data(); } bool KisDisplayColorConverter::Private::useOcio() const { return displayFilter && paintingColorSpace && paintingColorSpace->colorModelId() == RGBAColorModelID; } void KisDisplayColorConverter::Private::updateIntermediateFgColor(const KoColor &srcColor) { KIS_ASSERT_RECOVER_RETURN(displayFilter); KoColor color = srcColor; color.convertTo(intermediateColorSpace); displayFilter->approximateForwardTransformation(color.data(), 1); intermediateFgColor = color; } void KisDisplayColorConverter::Private::slotCanvasResourceChanged(int key, const QVariant &v) { if (key == KisCanvasResourceProvider::CurrentKritaNode) { KisNodeSP currentNode = v.value(); setCurrentNode(currentNode); } else if (useOcio() && key == KoCanvasResourceProvider::ForegroundColor) { updateIntermediateFgColor(v.value()); } } void KisDisplayColorConverter::Private::slotUpdateCurrentNodeColorSpace() { setCurrentNode(connectedNode); } inline KisPaintDeviceSP findValidDevice(KisNodeSP node) { return node->paintDevice() ? node->paintDevice() : node->original(); } void KisDisplayColorConverter::Private::setCurrentNode(KisNodeSP node) { if (connectedNode) { KisPaintDeviceSP device = findValidDevice(connectedNode); if (device) { q->disconnect(device, 0); } } nodeColorSpace = 0; if (node) { KisPaintDeviceSP device = findValidDevice(node); nodeColorSpace = device ? device->compositionSourceColorSpace() : node->colorSpace(); KIS_SAFE_ASSERT_RECOVER_NOOP(nodeColorSpace); if (device) { q->connect(device, SIGNAL(profileChanged(const KoColorProfile*)), SLOT(slotUpdateCurrentNodeColorSpace()), Qt::UniqueConnection); q->connect(device, SIGNAL(colorSpaceChanged(const KoColorSpace*)), SLOT(slotUpdateCurrentNodeColorSpace()), Qt::UniqueConnection); } } if (!nodeColorSpace) { nodeColorSpace = KoColorSpaceRegistry::instance()->rgb8(); } connectedNode = node; selectPaintingColorSpace(); } void KisDisplayColorConverter::Private::selectPaintingColorSpace() { KisConfig cfg(true); paintingColorSpace = cfg.customColorSelectorColorSpace(); if (!paintingColorSpace || displayFilter) { paintingColorSpace = nodeColorSpace; } emit q->displayConfigurationChanged(); } const KoColorSpace* KisDisplayColorConverter::paintingColorSpace() const { KIS_ASSERT_RECOVER(m_d->paintingColorSpace) { return KoColorSpaceRegistry::instance()->rgb8(); } return m_d->paintingColorSpace; } void KisDisplayColorConverter::setMonitorProfile(const KoColorProfile *monitorProfile) { + if (m_d->useHDRMode) { + // we don't use ICCcolor management in HDR mode + monitorProfile = 0; + } + + m_d->monitorColorSpace = KoColorSpaceRegistry::instance()->rgb8(monitorProfile); m_d->monitorProfile = monitorProfile; m_d->renderingIntent = renderingIntent(); m_d->conversionFlags = conversionFlags(); emit displayConfigurationChanged(); } void KisDisplayColorConverter::setDisplayFilter(QSharedPointer displayFilter) { if (m_d->displayFilter && displayFilter && displayFilter->lockCurrentColorVisualRepresentation()) { KoColor color(m_d->intermediateFgColor); displayFilter->approximateInverseTransformation(color.data(), 1); color.convertTo(m_d->paintingColorSpace); m_d->resourceManager->setForegroundColor(color); } m_d->displayFilter = displayFilter; m_d->intermediateColorSpace = 0; if (m_d->displayFilter) { // choosing default profile, which is scRGB const KoColorProfile *intermediateProfile = 0; m_d->intermediateColorSpace = KoColorSpaceRegistry::instance()-> colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), intermediateProfile); KIS_ASSERT_RECOVER(m_d->intermediateColorSpace) { m_d->intermediateColorSpace = m_d->monitorColorSpace; } m_d->updateIntermediateFgColor( m_d->resourceManager->foregroundColor()); } { // sanity check // KisConfig cfg; // KIS_ASSERT_RECOVER_NOOP(cfg.useOcio() == (bool) m_d->displayFilter); } m_d->selectPaintingColorSpace(); } KoColorConversionTransformation::Intent KisDisplayColorConverter::renderingIntent() { KisConfig cfg(true); return (KoColorConversionTransformation::Intent)cfg.monitorRenderIntent(); } KoColorConversionTransformation::ConversionFlags KisDisplayColorConverter::conversionFlags() { KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::HighQuality; KisConfig cfg(true); if (cfg.useBlackPointCompensation()) conversionFlags |= KoColorConversionTransformation::BlackpointCompensation; if (!cfg.allowLCMSOptimization()) conversionFlags |= KoColorConversionTransformation::NoOptimization; return conversionFlags; } QSharedPointer KisDisplayColorConverter::displayFilter() const { return m_d->displayFilter; } const KoColorProfile* KisDisplayColorConverter::monitorProfile() const { return m_d->monitorProfile; } bool finalIsRgba(const KoColorSpace *cs) { /** * In Krita RGB color spaces differ: 8/16bit are BGRA, 16f/32f-bit RGBA */ KoID colorDepthId = cs->colorDepthId(); return colorDepthId == Float16BitsColorDepthID || colorDepthId == Float32BitsColorDepthID; } template QColor floatArrayToQColor(const float *p) { if (flipToBgra) { return QColor(KoColorSpaceMaths::scaleToA(p[0]), KoColorSpaceMaths::scaleToA(p[1]), KoColorSpaceMaths::scaleToA(p[2]), KoColorSpaceMaths::scaleToA(p[3])); } else { return QColor(KoColorSpaceMaths::scaleToA(p[2]), KoColorSpaceMaths::scaleToA(p[1]), KoColorSpaceMaths::scaleToA(p[0]), KoColorSpaceMaths::scaleToA(p[3])); } } namespace { struct WriteToQColorPolicy { using Result = QColor; static QColor convertWhenNoOcio(const KoColor &c) { const quint8 *p = c.data(); return QColor(p[2], p[1], p[0], p[3]); } - static QColor convertWhenOcio(const QVector &values, const KoColorSpace *expectedOcioOutputColorSpace) { + static QColor convertWhenOcio(const QVector &values, const KoColorSpace *expectedOcioOutputColorSpace, const KoColorSpace *baseColorSpace) { const float *p = values.constData(); if (!expectedOcioOutputColorSpace) { - return finalIsRgba(expectedOcioOutputColorSpace) ? + return finalIsRgba(baseColorSpace) ? floatArrayToQColor(p) : floatArrayToQColor(p); } else { const KoColorSpace *sRGB = KoColorSpaceRegistry::instance()->rgb8(); QVector dstPixelData(4); expectedOcioOutputColorSpace-> convertPixelsTo((const quint8*)p, (quint8*)dstPixelData.data(), sRGB, 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); return QColor(dstPixelData[2], dstPixelData[1], dstPixelData[0], dstPixelData[3]); } } }; struct WriteToKoColorPolicy { using Result = KoColor; static KoColor convertWhenNoOcio(const KoColor &c) { return c; } - static KoColor convertWhenOcio(const QVector &values, const KoColorSpace *expectedOcioOutputColorSpace) { - KoColor c(expectedOcioOutputColorSpace); - expectedOcioOutputColorSpace->fromNormalisedChannelsValue(c.data(), values); - return c; + static KoColor convertWhenOcio(const QVector &values, const KoColorSpace *expectedOcioOutputColorSpace, const KoColorSpace *baseColorSpace) { + + if (expectedOcioOutputColorSpace) { + KoColor c(expectedOcioOutputColorSpace); + expectedOcioOutputColorSpace->fromNormalisedChannelsValue(c.data(), values); + return c; + } else { + KoColor c(baseColorSpace); + baseColorSpace->fromNormalisedChannelsValue(c.data(), values); + return c; + } } }; } template typename Policy::Result KisDisplayColorConverter::convertToDisplayImpl(const KoColor &srcColor, bool alreadyInDestinationF32) const { KoColor c(srcColor); if (!alreadyInDestinationF32) { c.convertTo(m_d->paintingColorSpace); } if (!m_d->useOcio()) { // we expect the display profile is rgb8, which is BGRA here KIS_ASSERT_RECOVER(m_d->monitorColorSpace->pixelSize() == 4) { return typename Policy::Result(); }; c.convertTo(m_d->monitorColorSpace, m_d->renderingIntent, m_d->conversionFlags); return Policy::convertWhenNoOcio(c); } else { const KoColorSpace *srcCS = c.colorSpace(); if (m_d->displayFilter->useInternalColorManagement()) { srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); c.convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); } int numChannels = srcCS->channelCount(); QVector normalizedChannels(numChannels); srcCS->normalisedChannelsValue(c.data(), normalizedChannels); m_d->displayFilter->filter((quint8*)normalizedChannels.data(), 1); - return Policy::convertWhenOcio(normalizedChannels, m_d->expectedOcioOutputColorSpace); + return Policy::convertWhenOcio(normalizedChannels, m_d->expectedOcioOutputColorSpace, srcCS); } } QColor KisDisplayColorConverter::toQColor(const KoColor &srcColor) const { return convertToDisplayImpl(srcColor); } KoColor KisDisplayColorConverter::applyDisplayFiltering(const KoColor &c, bool alreadyInF32) const { if (alreadyInF32) { KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(c.colorSpace()->colorDepthId() == Float32BitsColorDepthID, c); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(c.colorSpace()->colorModelId() == RGBAColorModelID, c); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(c.colorSpace()->profile()->uniqueId() == m_d->paintingColorSpace->profile()->uniqueId(), c); } return convertToDisplayImpl(c, alreadyInF32); } bool KisDisplayColorConverter::canSkipDisplayConversion(const KoColorSpace *cs) const { return !m_d->useOcio() && cs->colorModelId() == m_d->monitorColorSpace->colorModelId() && - cs->profile()->uniqueId() == m_d->monitorColorSpace->profile()->uniqueId(); + (!!cs->profile() == !!m_d->monitorColorSpace->profile()) && + (!cs->profile() || + cs->profile()->uniqueId() == m_d->monitorColorSpace->profile()->uniqueId()); } KoColor KisDisplayColorConverter::approximateFromRenderedQColor(const QColor &c) const { return m_d->approximateFromQColor(c); } template QImage KisDisplayColorConverter::Private::convertToQImageDirect(KisPaintDeviceSP device) { QRect bounds = device->exactBounds(); if (bounds.isEmpty()) return QImage(); QImage image(bounds.size(), QImage::Format_ARGB32); KisSequentialConstIterator it(device, bounds); quint8 *dstPtr = image.bits(); const KoColorSpace *cs = device->colorSpace(); int numChannels = cs->channelCount(); QVector normalizedChannels(numChannels); if (!expectedOcioOutputColorSpace) { while (it.nextPixel()) { cs->normalisedChannelsValue(it.rawDataConst(), normalizedChannels); displayFilter->filter((quint8*)normalizedChannels.data(), 1); const float *p = normalizedChannels.constData(); if (flipToBgra) { dstPtr[0] = KoColorSpaceMaths::scaleToA(p[2]); dstPtr[1] = KoColorSpaceMaths::scaleToA(p[1]); dstPtr[2] = KoColorSpaceMaths::scaleToA(p[0]); dstPtr[3] = KoColorSpaceMaths::scaleToA(p[3]); } else { dstPtr[0] = KoColorSpaceMaths::scaleToA(p[0]); dstPtr[1] = KoColorSpaceMaths::scaleToA(p[1]); dstPtr[2] = KoColorSpaceMaths::scaleToA(p[2]); dstPtr[3] = KoColorSpaceMaths::scaleToA(p[3]); } dstPtr += 4; } } else { const KoColorSpace *sRGB = KoColorSpaceRegistry::instance()->rgb8(); while (it.nextPixel()) { cs->normalisedChannelsValue(it.rawDataConst(), normalizedChannels); displayFilter->filter((quint8*)normalizedChannels.data(), 1); expectedOcioOutputColorSpace-> convertPixelsTo((const quint8*)normalizedChannels.data(), dstPtr, sRGB, 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); dstPtr += 4; } } return image; } QImage KisDisplayColorConverter::toQImage(KisPaintDeviceSP srcDevice) const { KisPaintDeviceSP device = srcDevice; if (*device->colorSpace() != *m_d->paintingColorSpace) { device = new KisPaintDevice(*srcDevice); KUndo2Command *cmd = device->convertTo(m_d->paintingColorSpace); delete cmd; } if (!m_d->useOcio()) { return device->convertToQImage(m_d->monitorProfile, m_d->renderingIntent, m_d->conversionFlags); } else { if (m_d->displayFilter->useInternalColorManagement()) { if (device == srcDevice) { device = new KisPaintDevice(*srcDevice); } const KoColorSpace *srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); KUndo2Command *cmd = device->convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); delete cmd; } return finalIsRgba(device->colorSpace()) ? m_d->convertToQImageDirect(device) : m_d->convertToQImageDirect(device); } return QImage(); } void KisDisplayColorConverter::applyDisplayFilteringF32(KisFixedPaintDeviceSP device) { /** * This method is optimized for the case when device is already in 32f * version of the pating color space. */ KIS_SAFE_ASSERT_RECOVER_RETURN(device->colorSpace()->colorDepthId() == Float32BitsColorDepthID); KIS_SAFE_ASSERT_RECOVER_RETURN(device->colorSpace()->colorModelId() == RGBAColorModelID); KIS_SAFE_ASSERT_RECOVER_RETURN(device->colorSpace()->profile()->uniqueId() == m_d->paintingColorSpace->profile()->uniqueId()); if (!m_d->useOcio()) { - device->convertTo(m_d->paintingColorSpace, m_d->renderingIntent, m_d->conversionFlags); + if (m_d->monitorProfile) { + const KoColorSpace *monitorColorSpaceF32 = + KoColorSpaceRegistry::instance()->colorSpace( + RGBAColorModelID.id(), + Float32BitsColorDepthID.id(), + m_d->monitorProfile); + + device->convertTo(monitorColorSpaceF32, m_d->renderingIntent, m_d->conversionFlags); + } } else { - if (m_d->displayFilter->useInternalColorManagement()) { + if (m_d->monitorProfile && m_d->displayFilter->useInternalColorManagement()) { const KoColorSpace *srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); device->convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); } m_d->displayFilter->filter(device->data(), device->bounds().width() * device->bounds().height()); } } KoColor KisDisplayColorConverter::Private::approximateFromQColor(const QColor &qcolor) { if (!useOcio()) { return KoColor(qcolor, paintingColorSpace); } else { KoColor color(qcolor, intermediateColorSpace); displayFilter->approximateInverseTransformation(color.data(), 1); color.convertTo(paintingColorSpace); return color; } qFatal("Must not be reachable"); return KoColor(); } QColor KisDisplayColorConverter::Private::approximateToQColor(const KoColor &srcColor) { KoColor color(srcColor); if (useOcio()) { color.convertTo(intermediateColorSpace); displayFilter->approximateForwardTransformation(color.data(), 1); } return color.toQColor(); } KoColor KisDisplayColorConverter::fromHsv(int h, int s, int v, int a) const { // generate HSV from sRGB! QColor qcolor(QColor::fromHsv(h, s, v, a)); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHsv(h, s, v, a); } KoColor KisDisplayColorConverter::fromHsvF(qreal h, qreal s, qreal v, qreal a) { // generate HSV from sRGB! QColor qcolor(QColor::fromHsvF(h, s, v, a)); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsvF(const KoColor &srcColor, qreal *h, qreal *s, qreal *v, qreal *a) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHsvF(h, s, v, a); } KoColor KisDisplayColorConverter::fromHslF(qreal h, qreal s, qreal l, qreal a) { // generate HSL from sRGB! QColor qcolor(QColor::fromHslF(h, s, l, a)); if (!qcolor.isValid()) { warnKrita << "Could not construct valid color from h" << h << "s" << s << "l" << l << "a" << a; qcolor = Qt::black; } return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHslF(const KoColor &srcColor, qreal *h, qreal *s, qreal *l, qreal *a) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHslF(h, s, l, a); } KoColor KisDisplayColorConverter::fromHsiF(qreal h, qreal s, qreal i) { // generate HSI from sRGB! qreal r=0.0; qreal g=0.0; qreal b=0.0; qreal a=1.0; HSIToRGB(h, s, i, &r, &g, &b); QColor qcolor; qcolor.setRgbF(qBound(0.0,r,1.0), qBound(0.0,g,1.0), qBound(0.0,b,1.0), a); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsiF(const KoColor &srcColor, qreal *h, qreal *s, qreal *i) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); qreal r=color.redF(); qreal g=color.greenF(); qreal b=color.blueF(); RGBToHSI(r, g, b, h, s, i); } KoColor KisDisplayColorConverter::fromHsyF(qreal h, qreal s, qreal y, qreal R, qreal G, qreal B, qreal gamma) { // generate HSL from sRGB! QVector channelValues(3); y = pow(y, gamma); HSYToRGB(h, s, y, &channelValues[0], &channelValues[1], &channelValues[2], R, G, B); KoColorSpaceRegistry::instance()->rgb8()->profile()->delinearizeFloatValueFast(channelValues); QColor qcolor; qcolor.setRgbF(qBound(0.0,channelValues[0],1.0), qBound(0.0,channelValues[1],1.0), qBound(0.0,channelValues[2],1.0), 1.0); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsyF(const KoColor &srcColor, qreal *h, qreal *s, qreal *y, qreal R, qreal G, qreal B, qreal gamma) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); QVector channelValues(3); channelValues[0]=color.redF(); channelValues[1]=color.greenF(); channelValues[2]=color.blueF(); //TODO: if we're going to have KoColor here, remember to check whether the TRC of the profile exists... KoColorSpaceRegistry::instance()->rgb8()->profile()->linearizeFloatValueFast(channelValues); RGBToHSY(channelValues[0], channelValues[1], channelValues[2], h, s, y, R, G, B); *y = pow(*y, 1/gamma); } #include "moc_kis_display_color_converter.cpp" diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc index d6f197a16a..1ec8887846 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.cc +++ b/libs/ui/dialogs/kis_dlg_preferences.cc @@ -1,1447 +1,1550 @@ /* * preferencesdlg.cc - part of KImageShop * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoID.h" #include #include #include #include #include #include #include "kis_action_registry.h" #include #include #include "kis_clipboard.h" #include "widgets/kis_cmb_idlist.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColorConversionTransformation.h" #include "kis_cursor.h" #include "kis_config.h" #include "kis_canvas_resource_provider.h" #include "kis_preference_set_registry.h" #include "kis_color_manager.h" #include "KisProofingConfiguration.h" #include "kis_image_config.h" #include "slider_and_spin_box_sync.h" // for the performance update #include #include #include "input/config/kis_input_configuration_page.h" #include "input/wintab/drawpile_tablettester/tablettester.h" #ifdef Q_OS_WIN # include #endif GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) { KisConfig cfg(true); // // Cursor Tab // m_cmbCursorShape->addItem(i18n("No Cursor")); m_cmbCursorShape->addItem(i18n("Tool Icon")); m_cmbCursorShape->addItem(i18n("Arrow")); m_cmbCursorShape->addItem(i18n("Small Circle")); m_cmbCursorShape->addItem(i18n("Crosshair")); m_cmbCursorShape->addItem(i18n("Triangle Righthanded")); m_cmbCursorShape->addItem(i18n("Triangle Lefthanded")); m_cmbCursorShape->addItem(i18n("Black Pixel")); m_cmbCursorShape->addItem(i18n("White Pixel")); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->addItem(i18n("No Outline")); m_cmbOutlineShape->addItem(i18n("Circle Outline")); m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting()); m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline()); KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8()); cursorColor.fromQColor(cfg.getCursorMainColor()); cursorColorBtutton->setColor(cursorColor); // // Window Tab // m_cmbMDIType->setCurrentIndex(cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView)); m_backgroundimage->setText(cfg.getMDIBackgroundImage()); connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage())); connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage())); KoColor mdiColor; mdiColor.fromQColor(cfg.getMDIBackgroundColor()); m_mdiColor->setColor(mdiColor); m_chkRubberBand->setChecked(cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages()); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); m_chkHiDPI->setChecked(kritarc.value("EnableHiDPI", true).toBool()); m_chkSingleApplication->setChecked(kritarc.value("EnableSingleApplication", true).toBool()); // // Tools tab // m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas()); chkEnableTranformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste()); m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled()); m_cmbKineticScrollingGesture->addItem(i18n("On Touch Drag")); m_cmbKineticScrollingGesture->addItem(i18n("On Click Drag")); m_cmbKineticScrollingGesture->addItem(i18n("On Middle-Click Drag")); //m_cmbKineticScrollingGesture->addItem(i18n("On Right Click Drag")); m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture()); m_kineticScrollingSensitivitySlider->setRange(0, 100); m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity()); m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars()); // // Miscellaneous // cmbStartupSession->addItem(i18n("Open default window")); cmbStartupSession->addItem(i18n("Load previous session")); cmbStartupSession->addItem(i18n("Show session manager")); cmbStartupSession->setCurrentIndex(cfg.sessionOnStartup()); chkSaveSessionOnQuit->setChecked(cfg.saveSessionOnQuit(false)); int autosaveInterval = cfg.autoSaveInterval(); //convert to minutes m_autosaveSpinBox->setValue(autosaveInterval / 60); m_autosaveCheckBox->setChecked(autosaveInterval > 0); m_chkCompressKra->setChecked(cfg.compressKra()); m_backupFileCheckBox->setChecked(cfg.backupFile()); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport()); m_undoStackSize->setValue(cfg.undoStackLimit()); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets()); chkShowRootLayer->setChecked(cfg.showRootLayer()); KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs"); bool dontUseNative = true; #ifdef Q_OS_UNIX if (qgetenv("XDG_CURRENT_DESKTOP") == "KDE") { dontUseNative = false; } #endif #ifdef Q_OS_WIN dontUseNative = false; #endif m_chkNativeFileDialog->setChecked(!group.readEntry("DontUseNativeFileDialog", dontUseNative)); intMaxBrushSize->setValue(cfg.readEntry("maximumBrushSize", 1000)); } void GeneralTab::setDefault() { KisConfig cfg(true); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true)); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true)); chkShowRootLayer->setChecked(cfg.showRootLayer(true)); m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0); //convert to minutes m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60); m_undoStackSize->setValue(cfg.undoStackLimit(true)); m_backupFileCheckBox->setChecked(cfg.backupFile(true)); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true)); m_changeBrushOutline->setChecked(!cfg.forceAlwaysFullSizedOutline(true)); m_chkNativeFileDialog->setChecked(false); intMaxBrushSize->setValue(1000); m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView); m_chkRubberBand->setChecked(cfg.useOpenGL(true)); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets(true)); KoColor mdiColor; mdiColor.fromQColor(cfg.getMDIBackgroundColor(true)); m_mdiColor->setColor(mdiColor); m_backgroundimage->setText(cfg.getMDIBackgroundImage(true)); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true)); m_chkCompressKra->setChecked(cfg.compressKra(true)); m_chkHiDPI->setChecked(false); m_chkSingleApplication->setChecked(true); m_chkHiDPI->setChecked(true); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled(true)); m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture(true)); m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity(true)); m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas(true)); chkEnableTranformToolAfterPaste->setChecked(cfg.activateTransformToolAfterPaste(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8()); cursorColor.fromQColor(cfg.getCursorMainColor(true)); cursorColorBtutton->setColor(cursorColor); } CursorStyle GeneralTab::cursorStyle() { return (CursorStyle)m_cmbCursorShape->currentIndex(); } OutlineStyle GeneralTab::outlineStyle() { return (OutlineStyle)m_cmbOutlineShape->currentIndex(); } KisConfig::SessionOnStartup GeneralTab::sessionOnStartup() const { return (KisConfig::SessionOnStartup)cmbStartupSession->currentIndex(); } bool GeneralTab::saveSessionOnQuit() const { return chkSaveSessionOnQuit->isChecked(); } bool GeneralTab::showRootLayer() { return chkShowRootLayer->isChecked(); } int GeneralTab::autoSaveInterval() { //convert to seconds return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value() * 60 : 0; } int GeneralTab::undoStackSize() { return m_undoStackSize->value(); } bool GeneralTab::showOutlineWhilePainting() { return m_showOutlinePainting->isChecked(); } int GeneralTab::mdiMode() { return m_cmbMDIType->currentIndex(); } int GeneralTab::favoritePresets() { return m_favoritePresetsSpinBox->value(); } bool GeneralTab::showCanvasMessages() { return m_chkCanvasMessages->isChecked(); } bool GeneralTab::compressKra() { return m_chkCompressKra->isChecked(); } bool GeneralTab::toolOptionsInDocker() { return m_radioToolOptionsInDocker->isChecked(); } bool GeneralTab::kineticScrollingEnabled() { return m_groupBoxKineticScrollingSettings->isChecked(); } int GeneralTab::kineticScrollingGesture() { return m_cmbKineticScrollingGesture->currentIndex(); } int GeneralTab::kineticScrollingSensitivity() { return m_kineticScrollingSensitivitySlider->value(); } bool GeneralTab::kineticScrollingHiddenScrollbars() { return m_chkKineticScrollingHideScrollbars->isChecked(); } bool GeneralTab::switchSelectionCtrlAlt() { return m_chkSwitchSelectionCtrlAlt->isChecked(); } bool GeneralTab::convertToImageColorspaceOnImport() { return m_chkConvertOnImport->isChecked(); } void GeneralTab::getBackgroundImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages"); dialog.setCaption(i18n("Select a Background Image")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); dialog.setImageFilters(); QString fn = dialog.filename(); // dialog box was canceled or somehow no file was selected if (fn.isEmpty()) { return; } QImage image(fn); if (image.isNull()) { QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn)); } else { m_backgroundimage->setText(fn); } } void GeneralTab::clearBackgroundImage() { // clearing the background image text will implicitly make the background color be used m_backgroundimage->setText(""); } #include "kactioncollection.h" #include "KisActionsSnapshot.h" ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgShortcutSettings(this); l->addWidget(m_page, 0, 0); m_snapshot.reset(new KisActionsSnapshot); KActionCollection *collection = KisPart::instance()->currentMainwindow()->actionCollection(); Q_FOREACH (QAction *action, collection->actions()) { m_snapshot->addAction(action->objectName(), action); } QMap sortedCollections = m_snapshot->actionCollections(); for (auto it = sortedCollections.constBegin(); it != sortedCollections.constEnd(); ++it) { m_page->addCollection(it.value(), it.key()); } } ShortcutSettingsTab::~ShortcutSettingsTab() { } void ShortcutSettingsTab::setDefault() { m_page->allDefault(); } void ShortcutSettingsTab::saveChanges() { m_page->save(); KisActionRegistry::instance()->settingsPageSaved(); } void ShortcutSettingsTab::cancelChanges() { m_page->undo(); } ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); // XXX: Make sure only profiles that fit the specified color model // are shown in the profile combos QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgColorSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg(true); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile()); connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool))); m_page->cmbWorkingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace()); m_page->bnAddColorProfile->setIcon(KisIconUtils::loadIcon("document-open")); m_page->bnAddColorProfile->setToolTip( i18n("Open Color Profile") ); connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile())); QFormLayout *monitorProfileGrid = new QFormLayout(m_page->monitorprofileholder); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileLabels << lbl; SqueezedComboBox *cmb = new SqueezedComboBox(); cmb->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); monitorProfileGrid->addRow(lbl, cmb); m_monitorProfileWidgets << cmb; } refillMonitorProfiles(KoID("RGBA")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization()); m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors()); KisImageConfig cfgImage(true); KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); m_page->sldAdaptationState->setMaximum(20); m_page->sldAdaptationState->setMinimum(0); m_page->sldAdaptationState->setValue((int)proofingConfig->adaptationState*20); //probably this should become the screenprofile? KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); ga.fromKoColor(proofingConfig->warningColor); m_page->gamutAlarm->setColor(ga); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel, proofingConfig->proofingDepth, proofingConfig->proofingProfile); if (proofingSpace) { m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); } m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, PASTE_ASSUME_WEB); m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, PASTE_ASSUME_MONITOR); m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, PASTE_ASK); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour()); Q_ASSERT(button); if (button) { button->setChecked(true); } m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent()); toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile()); } void ColorSettingsTab::installProfile() { KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC"); dialog.setCaption(i18n("Install Color Profiles")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile"); QStringList profileNames = dialog.filenames(); KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); Q_ASSERT(iccEngine); QString saveLocation = KoResourcePaths::saveLocation("icc_profiles"); Q_FOREACH (const QString &profileName, profileNames) { if (!QFile::copy(profileName, saveLocation + QFileInfo(profileName).fileName())) { qWarning() << "Could not install profile!" << saveLocation + QFileInfo(profileName).fileName(); continue; } iccEngine->addProfile(saveLocation + QFileInfo(profileName).fileName()); } KisConfig cfg(true); refillMonitorProfiles(KoID("RGBA")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile) { KisConfig cfg(true); if (useSystemProfile) { QStringList devices = KisColorManager::instance()->devices(); if (devices.size() == QApplication::desktop()->screenCount()) { for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); QString monitorForScreen = cfg.monitorForScreen(i, devices[i]); Q_FOREACH (const QString &device, devices) { m_monitorProfileLabels[i]->setText(i18nc("The display/screen we got from Qt", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device); if (devices[i] == monitorForScreen) { m_monitorProfileWidgets[i]->setCurrentIndex(i); } } } } } else { refillMonitorProfiles(KoID("RGBA")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } } void ColorSettingsTab::setDefault() { m_page->cmbWorkingColorSpace->setCurrent("RGBA"); refillMonitorProfiles(KoID("RGBA")); KisConfig cfg(true); KisImageConfig cfgImage(true); KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); if (proofingSpace) { m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); } m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_page->sldAdaptationState->setValue(0); //probably this should become the screenprofile? KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); ga.fromKoColor(proofingConfig->warningColor); m_page->gamutAlarm->setColor(ga); m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true)); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true)); m_page->chkForcePaletteColor->setChecked(cfg.forcePaletteColors(true)); m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true)); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true)); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true)); Q_ASSERT(button); if (button) { button->setChecked(true); } } void ColorSettingsTab::refillMonitorProfiles(const KoID & colorSpaceId) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); } QMap profileList; Q_FOREACH(const KoColorProfile *profile, KoColorSpaceRegistry::instance()->profilesFor(colorSpaceId.id())) { profileList[profile->name()] = profile; } Q_FOREACH (const KoColorProfile *profile, profileList.values()) { //qDebug() << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile(); if (profile->isSuitableForDisplay()) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->addSqueezedItem(profile->name()); } } } for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->setCurrent(KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId.id())); } } //--------------------------------------------------------------------------------------------------- void TabletSettingsTab::setDefault() { KisCubicCurve curve; curve.fromString(DEFAULT_CURVE_STRING); m_page->pressureCurve->setCurve(curve); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { KisConfig cfg(true); m_page->radioWintab->setChecked(!cfg.useWin8PointerInput(true)); m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput(true)); } else { m_page->radioWintab->setChecked(true); m_page->radioWin8PointerInput->setChecked(false); } #endif } TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgTabletSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg(true); KisCubicCurve curve; curve.fromString( cfg.pressureTabletCurve() ); m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); m_page->pressureCurve->setCurve(curve); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { m_page->radioWintab->setChecked(!cfg.useWin8PointerInput()); m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput()); } else { m_page->radioWintab->setChecked(true); m_page->radioWin8PointerInput->setChecked(false); m_page->grpTabletApi->setVisible(false); } #else m_page->grpTabletApi->setVisible(false); #endif connect(m_page->btnTabletTest, SIGNAL(clicked()), SLOT(slotTabletTest())); } void TabletSettingsTab::slotTabletTest() { TabletTestDialog tabletTestDialog(this); tabletTestDialog.exec(); } //--------------------------------------------------------------------------------------------------- #include "kis_acyclic_signal_connector.h" int getTotalRAM() { return KisImageConfig(true).totalRAM(); } int PerformanceTab::realTilesRAM() { return intMemoryLimit->value() - intPoolLimit->value(); } PerformanceTab::PerformanceTab(QWidget *parent, const char *name) : WdgPerformanceSettings(parent, name) { KisImageConfig cfg(true); const double totalRAM = cfg.totalRAM(); lblTotalMemory->setText(KFormat().formatByteSize(totalRAM * 1024 * 1024, 0, KFormat::IECBinaryDialect, KFormat::UnitMegaByte)); sliderMemoryLimit->setSuffix(i18n(" %")); sliderMemoryLimit->setRange(1, 100, 2); sliderMemoryLimit->setSingleStep(0.01); sliderPoolLimit->setSuffix(i18n(" %")); sliderPoolLimit->setRange(0, 20, 2); sliderMemoryLimit->setSingleStep(0.01); sliderUndoLimit->setSuffix(i18n(" %")); sliderUndoLimit->setRange(0, 50, 2); sliderMemoryLimit->setSingleStep(0.01); intMemoryLimit->setMinimumWidth(80); intPoolLimit->setMinimumWidth(80); intUndoLimit->setMinimumWidth(80); SliderAndSpinBoxSync *sync1 = new SliderAndSpinBoxSync(sliderMemoryLimit, intMemoryLimit, getTotalRAM); sync1->slotParentValueChanged(); m_syncs << sync1; SliderAndSpinBoxSync *sync2 = new SliderAndSpinBoxSync(sliderPoolLimit, intPoolLimit, std::bind(&KisIntParseSpinBox::value, intMemoryLimit)); connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged())); sync2->slotParentValueChanged(); m_syncs << sync2; SliderAndSpinBoxSync *sync3 = new SliderAndSpinBoxSync(sliderUndoLimit, intUndoLimit, std::bind(&PerformanceTab::realTilesRAM, this)); connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged())); sync3->slotParentValueChanged(); m_syncs << sync3; sliderSwapSize->setSuffix(i18n(" GiB")); sliderSwapSize->setRange(1, 64); intSwapSize->setRange(1, 64); KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this); swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)), intSwapSize, SLOT(setValue(int))); swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)), sliderSwapSize, SLOT(setValue(int))); lblSwapFileLocation->setText(cfg.swapDir()); connect(bnSwapFile, SIGNAL(clicked()), SLOT(selectSwapDir())); sliderThreadsLimit->setRange(1, QThread::idealThreadCount()); sliderFrameClonesLimit->setRange(1, QThread::idealThreadCount()); sliderFpsLimit->setRange(20, 100); sliderFpsLimit->setSuffix(i18n(" fps")); connect(sliderThreadsLimit, SIGNAL(valueChanged(int)), SLOT(slotThreadsLimitChanged(int))); connect(sliderFrameClonesLimit, SIGNAL(valueChanged(int)), SLOT(slotFrameClonesLimitChanged(int))); intCachedFramesSizeLimit->setRange(1, 10000); intCachedFramesSizeLimit->setSuffix(i18n(" px")); intCachedFramesSizeLimit->setSingleStep(1); intCachedFramesSizeLimit->setPageStep(1000); intRegionOfInterestMargin->setRange(1, 100); intRegionOfInterestMargin->setSuffix(i18n(" %")); intRegionOfInterestMargin->setSingleStep(1); intRegionOfInterestMargin->setPageStep(10); connect(chkCachedFramesSizeLimit, SIGNAL(toggled(bool)), intCachedFramesSizeLimit, SLOT(setEnabled(bool))); connect(chkUseRegionOfInterest, SIGNAL(toggled(bool)), intRegionOfInterestMargin, SLOT(setEnabled(bool))); load(false); } PerformanceTab::~PerformanceTab() { qDeleteAll(m_syncs); } void PerformanceTab::load(bool requestDefault) { KisImageConfig cfg(true); sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault)); sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault)); sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault)); chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault)); chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault)); sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024); lblSwapFileLocation->setText(cfg.swapDir(requestDefault)); m_lastUsedThreadsLimit = cfg.maxNumberOfThreads(requestDefault); m_lastUsedClonesLimit = cfg.frameRenderingClones(requestDefault); sliderThreadsLimit->setValue(m_lastUsedThreadsLimit); sliderFrameClonesLimit->setValue(m_lastUsedClonesLimit); sliderFpsLimit->setValue(cfg.fpsLimit(requestDefault)); { KisConfig cfg2(true); chkOpenGLFramerateLogging->setChecked(cfg2.enableOpenGLFramerateLogging(requestDefault)); chkBrushSpeedLogging->setChecked(cfg2.enableBrushSpeedLogging(requestDefault)); chkDisableVectorOptimizations->setChecked(cfg2.enableAmdVectorizationWorkaround(requestDefault)); chkBackgroundCacheGeneration->setChecked(cfg2.calculateAnimationCacheInBackground(requestDefault)); } if (cfg.useOnDiskAnimationCacheSwapping(requestDefault)) { optOnDisk->setChecked(true); } else { optInMemory->setChecked(true); } chkCachedFramesSizeLimit->setChecked(cfg.useAnimationCacheFrameSizeLimit(requestDefault)); intCachedFramesSizeLimit->setValue(cfg.animationCacheFrameSizeLimit(requestDefault)); intCachedFramesSizeLimit->setEnabled(chkCachedFramesSizeLimit->isChecked()); chkUseRegionOfInterest->setChecked(cfg.useAnimationCacheRegionOfInterest(requestDefault)); intRegionOfInterestMargin->setValue(cfg.animationCacheRegionOfInterestMargin(requestDefault) * 100.0); intRegionOfInterestMargin->setEnabled(chkUseRegionOfInterest->isChecked()); } void PerformanceTab::save() { KisImageConfig cfg(false); cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value()); cfg.setMemorySoftLimitPercent(sliderUndoLimit->value()); cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value()); cfg.setEnablePerfLog(chkPerformanceLogging->isChecked()); cfg.setEnableProgressReporting(chkProgressReporting->isChecked()); cfg.setMaxSwapSize(sliderSwapSize->value() * 1024); cfg.setSwapDir(lblSwapFileLocation->text()); cfg.setMaxNumberOfThreads(sliderThreadsLimit->value()); cfg.setFrameRenderingClones(sliderFrameClonesLimit->value()); cfg.setFpsLimit(sliderFpsLimit->value()); { KisConfig cfg2(true); cfg2.setEnableOpenGLFramerateLogging(chkOpenGLFramerateLogging->isChecked()); cfg2.setEnableBrushSpeedLogging(chkBrushSpeedLogging->isChecked()); cfg2.setEnableAmdVectorizationWorkaround(chkDisableVectorOptimizations->isChecked()); cfg2.setCalculateAnimationCacheInBackground(chkBackgroundCacheGeneration->isChecked()); } cfg.setUseOnDiskAnimationCacheSwapping(optOnDisk->isChecked()); cfg.setUseAnimationCacheFrameSizeLimit(chkCachedFramesSizeLimit->isChecked()); cfg.setAnimationCacheFrameSizeLimit(intCachedFramesSizeLimit->value()); cfg.setUseAnimationCacheRegionOfInterest(chkUseRegionOfInterest->isChecked()); cfg.setAnimationCacheRegionOfInterestMargin(intRegionOfInterestMargin->value() / 100.0); } void PerformanceTab::selectSwapDir() { KisImageConfig cfg(true); QString swapDir = cfg.swapDir(); swapDir = QFileDialog::getExistingDirectory(0, i18nc("@title:window", "Select a swap directory"), swapDir); if (swapDir.isEmpty()) { return; } lblSwapFileLocation->setText(swapDir); } void PerformanceTab::slotThreadsLimitChanged(int value) { KisSignalsBlocker b(sliderFrameClonesLimit); sliderFrameClonesLimit->setValue(qMin(m_lastUsedClonesLimit, value)); m_lastUsedThreadsLimit = value; } void PerformanceTab::slotFrameClonesLimitChanged(int value) { KisSignalsBlocker b(sliderThreadsLimit); sliderThreadsLimit->setValue(qMax(m_lastUsedThreadsLimit, value)); m_lastUsedClonesLimit = value; } //--------------------------------------------------------------------------------------------------- #include "KoColor.h" +#include "opengl/KisOpenGLModeProber.h" +#include "opengl/KisScreenInformationAdapter.h" +#include +#include + +QString colorSpaceString(QSurfaceFormat::ColorSpace cs, int depth) +{ + const QString csString = + cs == QSurfaceFormat::bt2020PQColorSpace ? "Rec. 2020 PQ" : + cs == QSurfaceFormat::scRGBColorSpace ? "Rec. 709 Linear" : + cs == QSurfaceFormat::sRGBColorSpace ? "sRGB" : + cs == QSurfaceFormat::DefaultColorSpace ? "sRGB" : + "Unknown Color Space"; + + return QString("%1 (%2 bit)").arg(csString).arg(depth); +} + +int formatToIndex(KisConfig::RootSurfaceFormat fmt) +{ + return fmt == KisConfig::BT2020_PQ ? 1 : + fmt == KisConfig::BT709_G10 ? 2 : + 0; +} + +KisConfig::RootSurfaceFormat indexToFormat(int value) +{ + return value == 1 ? KisConfig::BT2020_PQ : + value == 2 ? KisConfig::BT709_G10 : + KisConfig::BT709_G22; +} DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name) : WdgDisplaySettings(parent, name) { KisConfig cfg(true); const QString rendererOpenGLText = i18nc("canvas renderer", "OpenGL"); #ifdef Q_OS_WIN const QString rendererAngleText = i18nc("canvas renderer", "Direct3D 11 via ANGLE"); cmbRenderer->clear(); QString qtPreferredRendererText; if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererAngle) { qtPreferredRendererText = rendererAngleText; } else { qtPreferredRendererText = rendererOpenGLText; } cmbRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto); cmbRenderer->setCurrentIndex(0); if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererDesktopGL) { cmbRenderer->addItem(rendererOpenGLText, KisOpenGL::RendererDesktopGL); if (KisOpenGL::getNextUserOpenGLRendererConfig() == KisOpenGL::RendererDesktopGL) { cmbRenderer->setCurrentIndex(cmbRenderer->count() - 1); } } if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererAngle) { cmbRenderer->addItem(rendererAngleText, KisOpenGL::RendererAngle); if (KisOpenGL::getNextUserOpenGLRendererConfig() == KisOpenGL::RendererAngle) { cmbRenderer->setCurrentIndex(cmbRenderer->count() - 1); } } #else lblRenderer->setEnabled(false); cmbRenderer->setEnabled(false); cmbRenderer->clear(); cmbRenderer->addItem(rendererOpenGLText); cmbRenderer->setCurrentIndex(0); #endif #ifdef Q_OS_WIN if (!(KisOpenGL::getSupportedOpenGLRenderers() & (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererAngle))) { #else if (!KisOpenGL::hasOpenGL()) { #endif grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL()); chkUseTextureBuffer->setEnabled(cfg.useOpenGL()); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer()); chkDisableVsync->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableVsync->setEnabled(cfg.useOpenGL()); chkDisableVsync->setChecked(cfg.disableVSync()); cmbFilterMode->setEnabled(cfg.useOpenGL()); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode()); // Don't show the high quality filtering mode if it's not available if (!KisOpenGL::supportsLoD()) { cmbFilterMode->removeItem(3); } } + lblCurrentDisplayFormat->setText(""); + lblCurrentRootSurfaceFormat->setText(""); + lblHDRWarning->setText(""); + cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(QSurfaceFormat::sRGBColorSpace, 8)); + cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(QSurfaceFormat::bt2020PQColorSpace, 10)); + cmbPreferedRootSurfaceFormat->addItem(colorSpaceString(QSurfaceFormat::scRGBColorSpace, 16)); + cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22)); + slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); + + QOpenGLContext *context = QOpenGLContext::currentContext(); + if (context) { + QScreen *screen = QGuiApplication::screenAt(rect().center()); + KisScreenInformationAdapter adapter(context); + if (screen && adapter.isValid()) { + KisScreenInformationAdapter::ScreenInfo info = adapter.infoForScreen(screen); + if (info.isValid()) { + QStringList toolTip; + + toolTip << i18n("Display Id: %1", info.screen->name()); + toolTip << i18n("Display Name: %1 %2", info.screen->manufacturer(), info.screen->model()); + toolTip << i18n("Min Luminance: %1", info.minLuminance); + toolTip << i18n("Max Luminance: %1", info.maxLuminance); + toolTip << i18n("Max Full Frame Luminance: %1", info.maxFullFrameLuminance); + toolTip << i18n("Red Primary: %1, %2", info.redPrimary[0], info.redPrimary[1]); + toolTip << i18n("Green Primary: %1, %2", info.greenPrimary[0], info.greenPrimary[1]); + toolTip << i18n("Blue Primary: %1, %2", info.bluePrimary[0], info.bluePrimary[1]); + toolTip << i18n("White Point: %1, %2", info.whitePoint[0], info.whitePoint[1]); + + lblCurrentDisplayFormat->setToolTip(toolTip.join('\n')); + lblCurrentDisplayFormat->setText(colorSpaceString(info.colorSpace, info.bitsPerColor)); + } else { + lblCurrentDisplayFormat->setToolTip(""); + lblCurrentDisplayFormat->setText(i18n("Unknown")); + } + grpHDRSettings->setEnabled(info.isValid()); + + const QSurfaceFormat currentFormat = KisOpenGLModeProber::instance()->surfaceformatInUse(); + lblCurrentRootSurfaceFormat->setText(colorSpaceString(currentFormat.colorSpace(), currentFormat.redBufferSize())); + cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(cfg.rootSurfaceFormat())); + + connect(cmbPreferedRootSurfaceFormat, SIGNAL(currentIndexChanged(int)), SLOT(slotPreferredSurfaceFormatChanged(int))); + slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); + } else { + grpHDRSettings->setEnabled(false); + } + } + const QStringList openglWarnings = KisOpenGL::getOpenGLWarnings(); if (openglWarnings.isEmpty()) { lblOpenGLWarnings->setVisible(false); } else { QString text(" "); text.append(i18n("Warning(s):")); text.append("
    "); Q_FOREACH (const QString &warning, openglWarnings) { text.append("
  • "); text.append(warning.toHtmlEscaped()); text.append("
  • "); } text.append("
"); lblOpenGLWarnings->setText(text); lblOpenGLWarnings->setVisible(true); } if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { grpOpenGL->setVisible(false); grpOpenGL->setMaximumHeight(0); } KisImageConfig imageCfg(false); KoColor c; c.fromQColor(imageCfg.selectionOverlayMaskColor()); c.setOpacity(1.0); btnSelectionOverlayColor->setColor(c); sldSelectionOverlayOpacity->setRange(0.0, 1.0, 2); sldSelectionOverlayOpacity->setSingleStep(0.05); sldSelectionOverlayOpacity->setValue(imageCfg.selectionOverlayMaskColor().alphaF()); intCheckSize->setValue(cfg.checkSize()); chkMoving->setChecked(cfg.scrollCheckers()); KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); ck1.fromQColor(cfg.checkersColor1()); colorChecks1->setColor(ck1); KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); ck2.fromQColor(cfg.checkersColor2()); colorChecks2->setColor(ck2); KoColor cb(KoColorSpaceRegistry::instance()->rgb8()); cb.fromQColor(cfg.canvasBorderColor()); canvasBorder->setColor(cb); hideScrollbars->setChecked(cfg.hideScrollbars()); chkCurveAntialiasing->setChecked(cfg.antialiasCurves()); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline()); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor()); chkHidePopups->setChecked(cfg.hidePopups()); connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8()); gridColor.fromQColor(cfg.getPixelGridColor()); pixelGridColorButton->setColor(gridColor); pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold() * 100); } void DisplaySettingsTab::setDefault() { KisConfig cfg(true); cmbRenderer->setCurrentIndex(0); #ifdef Q_OS_WIN if (!(KisOpenGL::getSupportedOpenGLRenderers() & (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererAngle))) { #else if (!KisOpenGL::hasOpenGL()) { #endif grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL(true)); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true)); chkUseTextureBuffer->setEnabled(true); chkDisableVsync->setEnabled(true); chkDisableVsync->setChecked(cfg.disableVSync(true)); cmbFilterMode->setEnabled(true); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true)); } chkMoving->setChecked(cfg.scrollCheckers(true)); intCheckSize->setValue(cfg.checkSize(true)); KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); ck1.fromQColor(cfg.checkersColor1(true)); colorChecks1->setColor(ck1); KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); ck2.fromQColor(cfg.checkersColor2(true)); colorChecks2->setColor(ck2); KoColor cvb(KoColorSpaceRegistry::instance()->rgb8()); cvb.fromQColor(cfg.canvasBorderColor(true)); canvasBorder->setColor(cvb); hideScrollbars->setChecked(cfg.hideScrollbars(true)); chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true)); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true)); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true)); chkHidePopups->setChecked(cfg.hidePopups(true)); KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8()); gridColor.fromQColor(cfg.getPixelGridColor(true)); pixelGridColorButton->setColor(gridColor); pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold(true) * 100); + + cmbPreferedRootSurfaceFormat->setCurrentIndex(formatToIndex(KisConfig::BT709_G22)); + slotPreferredSurfaceFormatChanged(cmbPreferedRootSurfaceFormat->currentIndex()); } void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked) { chkUseTextureBuffer->setEnabled(isChecked); chkDisableVsync->setEnabled(isChecked); cmbFilterMode->setEnabled(isChecked); } +void DisplaySettingsTab::slotPreferredSurfaceFormatChanged(int index) +{ + Q_UNUSED(index); + + QOpenGLContext *context = QOpenGLContext::currentContext(); + if (context) { + QScreen *screen = QGuiApplication::screenAt(rect().center()); + KisScreenInformationAdapter adapter(context); + if (adapter.isValid()) { + KisScreenInformationAdapter::ScreenInfo info = adapter.infoForScreen(screen); + if (info.isValid()) { + if (cmbPreferedRootSurfaceFormat->currentIndex() != formatToIndex(KisConfig::BT709_G22) && + info.colorSpace == QSurfaceFormat::sRGBColorSpace) { + lblHDRWarning->setText(i18n("WARNING: current display doesn't support HDR rendering")); + } else { + lblHDRWarning->setText(""); + } + } + } + } +} + //--------------------------------------------------------------------------------------------------- FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent) { KisConfig cfg(true); chkDockers->setChecked(cfg.hideDockersFullscreen()); chkMenu->setChecked(cfg.hideMenuFullscreen()); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen()); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen()); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen()); chkToolbar->setChecked(cfg.hideToolbarFullscreen()); } void FullscreenSettingsTab::setDefault() { KisConfig cfg(true); chkDockers->setChecked(cfg.hideDockersFullscreen(true)); chkMenu->setChecked(cfg.hideMenuFullscreen(true)); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true)); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true)); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true)); chkToolbar->setChecked(cfg.hideToolbarFullscreen(true)); } //--------------------------------------------------------------------------------------------------- KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) : KPageDialog(parent) { Q_UNUSED(name); setWindowTitle(i18n("Configure Krita")); setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); setFaceType(KPageDialog::Tree); // General KoVBox *vbox = new KoVBox(); KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General")); page->setObjectName("general"); page->setHeader(i18n("General")); page->setIcon(KisIconUtils::loadIcon("go-home")); m_pages << page; addPage(page); m_general = new GeneralTab(vbox); // Shortcuts vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts")); page->setObjectName("shortcuts"); page->setHeader(i18n("Shortcuts")); page->setIcon(KisIconUtils::loadIcon("document-export")); m_pages << page; addPage(page); m_shortcutSettings = new ShortcutSettingsTab(vbox); connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_shortcutSettings, SLOT(cancelChanges())); // Canvas input settings m_inputConfiguration = new KisInputConfigurationPage(); page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); page->setHeader(i18n("Canvas Input")); page->setObjectName("canvasinput"); page->setIcon(KisIconUtils::loadIcon("configure")); m_pages << page; // Display vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Display")); page->setObjectName("display"); page->setHeader(i18n("Display")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-display")); m_pages << page; addPage(page); m_displaySettings = new DisplaySettingsTab(vbox); // Color vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Color Management")); page->setObjectName("colormanagement"); page->setHeader(i18n("Color")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-color")); m_pages << page; addPage(page); m_colorSettings = new ColorSettingsTab(vbox); // Performance vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Performance")); page->setObjectName("performance"); page->setHeader(i18n("Performance")); page->setIcon(KisIconUtils::loadIcon("applications-system")); m_pages << page; addPage(page); m_performanceSettings = new PerformanceTab(vbox); // Tablet vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Tablet settings")); page->setObjectName("tablet"); page->setHeader(i18n("Tablet")); page->setIcon(KisIconUtils::loadIcon("document-edit")); m_pages << page; addPage(page); m_tabletSettings = new TabletSettingsTab(vbox); // full-screen mode vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Canvas-only settings")); page->setObjectName("canvasonly"); page->setHeader(i18n("Canvas-only")); page->setIcon(KisIconUtils::loadIcon("folder-pictures")); m_pages << page; addPage(page); m_fullscreenSettings = new FullscreenSettingsTab(vbox); // Author profiles m_authorPage = new KoConfigAuthorPage(); page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" )); page->setObjectName("author"); page->setHeader(i18n("Author")); page->setIcon(KisIconUtils::loadIcon("im-user")); m_pages << page; QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults); restoreDefaultsButton->setText(i18nc("@action:button", "Restore Defaults")); connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); Q_FOREACH (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet(); vbox = new KoVBox(); page = new KPageWidgetItem(vbox, preferenceSet->name()); page->setHeader(preferenceSet->header()); page->setIcon(preferenceSet->icon()); addPage(page); preferenceSet->setParent(vbox); preferenceSet->loadPreferences(); connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection); connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection); } connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault())); KisConfig cfg(true); QString currentPageName = cfg.readEntry("KisDlgPreferences/CurrentPage"); Q_FOREACH(KPageWidgetItem *page, m_pages) { if (page->objectName() == currentPageName) { setCurrentPage(page); break; } } } KisDlgPreferences::~KisDlgPreferences() { KisConfig cfg(true); cfg.writeEntry("KisDlgPreferences/CurrentPage", currentPage()->objectName()); } void KisDlgPreferences::showEvent(QShowEvent *event){ KPageDialog::showEvent(event); button(QDialogButtonBox::Cancel)->setAutoDefault(false); button(QDialogButtonBox::Ok)->setAutoDefault(false); button(QDialogButtonBox::RestoreDefaults)->setAutoDefault(false); button(QDialogButtonBox::Cancel)->setDefault(false); button(QDialogButtonBox::Ok)->setDefault(false); button(QDialogButtonBox::RestoreDefaults)->setDefault(false); } void KisDlgPreferences::slotDefault() { if (currentPage()->objectName() == "general") { m_general->setDefault(); } else if (currentPage()->objectName() == "shortcuts") { m_shortcutSettings->setDefault(); } else if (currentPage()->objectName() == "display") { m_displaySettings->setDefault(); } else if (currentPage()->objectName() == "colormanagement") { m_colorSettings->setDefault(); } else if (currentPage()->objectName() == "performance") { m_performanceSettings->load(true); } else if (currentPage()->objectName() == "tablet") { m_tabletSettings->setDefault(); } else if (currentPage()->objectName() == "canvasonly") { m_fullscreenSettings->setDefault(); } else if (currentPage()->objectName() == "canvasinput") { m_inputConfiguration->setDefaults(); } } bool KisDlgPreferences::editPreferences() { KisDlgPreferences* dialog; dialog = new KisDlgPreferences(); bool baccept = (dialog->exec() == Accepted); if (baccept) { // General settings KisConfig cfg(false); cfg.setNewCursorStyle(dialog->m_general->cursorStyle()); cfg.setNewOutlineStyle(dialog->m_general->outlineStyle()); cfg.setShowRootLayer(dialog->m_general->showRootLayer()); cfg.setShowOutlineWhilePainting(dialog->m_general->showOutlineWhilePainting()); cfg.setForceAlwaysFullSizedOutline(!dialog->m_general->m_changeBrushOutline->isChecked()); cfg.setSessionOnStartup(dialog->m_general->sessionOnStartup()); cfg.setSaveSessionOnQuit(dialog->m_general->saveSessionOnQuit()); KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs"); group.writeEntry("DontUseNativeFileDialog", !dialog->m_general->m_chkNativeFileDialog->isChecked()); cfg.writeEntry("maximumBrushSize", dialog->m_general->intMaxBrushSize->value()); cfg.writeEntry("mdi_viewmode", dialog->m_general->mdiMode()); cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color().toQColor()); cfg.setMDIBackgroundImage(dialog->m_general->m_backgroundimage->text()); cfg.setAutoSaveInterval(dialog->m_general->autoSaveInterval()); cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages()); cfg.setCompressKra(dialog->m_general->compressKra()); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("EnableHiDPI", dialog->m_general->m_chkHiDPI->isChecked()); kritarc.setValue("EnableSingleApplication", dialog->m_general->m_chkSingleApplication->isChecked()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); cfg.setKineticScrollingEnabled(dialog->m_general->kineticScrollingEnabled()); cfg.setKineticScrollingGesture(dialog->m_general->kineticScrollingGesture()); cfg.setKineticScrollingSensitivity(dialog->m_general->kineticScrollingSensitivity()); cfg.setKineticScrollingHideScrollbars(dialog->m_general->kineticScrollingHiddenScrollbars()); cfg.setSwitchSelectionCtrlAlt(dialog->m_general->switchSelectionCtrlAlt()); cfg.setDisableTouchOnCanvas(!dialog->m_general->chkEnableTouch->isChecked()); cfg.setActivateTransformToolAfterPaste(dialog->m_general->chkEnableTranformToolAfterPaste->isChecked()); cfg.setConvertToImageColorspaceOnImport(dialog->m_general->convertToImageColorspaceOnImport()); cfg.setUndoStackLimit(dialog->m_general->undoStackSize()); cfg.setFavoritePresets(dialog->m_general->favoritePresets()); // Color settings cfg.setUseSystemMonitorProfile(dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) { int currentIndex = dialog->m_colorSettings->m_monitorProfileWidgets[i]->currentIndex(); QString monitorid = dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString(); cfg.setMonitorForScreen(i, monitorid); } else { cfg.setMonitorProfile(i, dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemHighlighted(), dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); } } cfg.setWorkingColorSpace(dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentItem().id()); KisImageConfig cfgImage(false); cfgImage.setDefaultProofingConfig(dialog->m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(), dialog->m_colorSettings->m_page->cmbProofingIntent->currentIndex(), dialog->m_colorSettings->m_page->ckbProofBlackPoint->isChecked(), dialog->m_colorSettings->m_page->gamutAlarm->color(), (double)dialog->m_colorSettings->m_page->sldAdaptationState->value()/20); cfg.setUseBlackPointCompensation(dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); cfg.setAllowLCMSOptimization(dialog->m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked()); cfg.setForcePaletteColors(dialog->m_colorSettings->m_page->chkForcePaletteColor->isChecked()); cfg.setPasteBehaviour(dialog->m_colorSettings->m_pasteBehaviourGroup.checkedId()); cfg.setRenderIntent(dialog->m_colorSettings->m_page->cmbMonitorIntent->currentIndex()); // Tablet settings cfg.setPressureTabletCurve( dialog->m_tabletSettings->m_page->pressureCurve->curve().toString() ); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { cfg.setUseWin8PointerInput(dialog->m_tabletSettings->m_page->radioWin8PointerInput->isChecked()); } #endif dialog->m_performanceSettings->save(); #ifdef Q_OS_WIN { KisOpenGL::OpenGLRenderer renderer = static_cast( dialog->m_displaySettings->cmbRenderer->itemData( dialog->m_displaySettings->cmbRenderer->currentIndex()).toInt()); KisOpenGL::setNextUserOpenGLRendererConfig(renderer); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("OpenGLRenderer", KisOpenGL::convertOpenGLRendererToConfig(renderer)); } #endif if (!cfg.useOpenGL() && dialog->m_displaySettings->grpOpenGL->isChecked()) cfg.setCanvasState("TRY_OPENGL"); cfg.setUseOpenGL(dialog->m_displaySettings->grpOpenGL->isChecked()); cfg.setUseOpenGLTextureBuffer(dialog->m_displaySettings->chkUseTextureBuffer->isChecked()); cfg.setOpenGLFilteringMode(dialog->m_displaySettings->cmbFilterMode->currentIndex()); cfg.setDisableVSync(dialog->m_displaySettings->chkDisableVsync->isChecked()); + cfg.setRootSurfaceFormat(&kritarc, indexToFormat(dialog->m_displaySettings->cmbPreferedRootSurfaceFormat->currentIndex())); cfg.setCheckSize(dialog->m_displaySettings->intCheckSize->value()); cfg.setScrollingCheckers(dialog->m_displaySettings->chkMoving->isChecked()); cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color().toQColor()); cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color().toQColor()); cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color().toQColor()); cfg.setHideScrollbars(dialog->m_displaySettings->hideScrollbars->isChecked()); KoColor c = dialog->m_displaySettings->btnSelectionOverlayColor->color(); c.setOpacity(dialog->m_displaySettings->sldSelectionOverlayOpacity->value()); cfgImage.setSelectionOverlayMaskColor(c.toQColor()); cfg.setAntialiasCurves(dialog->m_displaySettings->chkCurveAntialiasing->isChecked()); cfg.setAntialiasSelectionOutline(dialog->m_displaySettings->chkSelectionOutlineAntialiasing->isChecked()); cfg.setShowSingleChannelAsColor(dialog->m_displaySettings->chkChannelsAsColor->isChecked()); cfg.setHidePopups(dialog->m_displaySettings->chkHidePopups->isChecked()); cfg.setHideDockersFullscreen(dialog->m_fullscreenSettings->chkDockers->checkState()); cfg.setHideMenuFullscreen(dialog->m_fullscreenSettings->chkMenu->checkState()); cfg.setHideScrollbarsFullscreen(dialog->m_fullscreenSettings->chkScrollbars->checkState()); cfg.setHideStatusbarFullscreen(dialog->m_fullscreenSettings->chkStatusbar->checkState()); cfg.setHideTitlebarFullscreen(dialog->m_fullscreenSettings->chkTitlebar->checkState()); cfg.setHideToolbarFullscreen(dialog->m_fullscreenSettings->chkToolbar->checkState()); cfg.setCursorMainColor(dialog->m_general->cursorColorBtutton->color().toQColor()); cfg.setPixelGridColor(dialog->m_displaySettings->pixelGridColorButton->color().toQColor()); cfg.setPixelGridDrawingThreshold(dialog->m_displaySettings->pixelGridDrawingThresholdBox->value() / 100); dialog->m_authorPage->apply(); } delete dialog; return baccept; } diff --git a/libs/ui/dialogs/kis_dlg_preferences.h b/libs/ui/dialogs/kis_dlg_preferences.h index 626c42a097..5fe0308a83 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.h +++ b/libs/ui/dialogs/kis_dlg_preferences.h @@ -1,353 +1,354 @@ /* * preferencesdlg.h - part of KImageShop^WKrita * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_DLG_PREFERENCES_H_ #define _KIS_DLG_PREFERENCES_H_ #include #include #include #include #include #include #include "kis_global.h" #include #include "ui_wdggeneralsettings.h" #include "ui_wdgdisplaysettings.h" #include "ui_wdgcolorsettings.h" #include "ui_wdgtabletsettings.h" #include "ui_wdgperformancesettings.h" #include "ui_wdgfullscreensettings.h" #include "KisShortcutsDialog.h" class KoID; class KisInputConfigurationPage; class KoConfigAuthorPage; /** * "General"-tab for preferences dialog */ class WdgGeneralSettings : public QWidget, public Ui::WdgGeneralSettings { Q_OBJECT public: WdgGeneralSettings(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); chkShowRootLayer->setVisible(false); } }; class GeneralTab : public WdgGeneralSettings { Q_OBJECT public: GeneralTab(QWidget *parent = 0, const char *name = 0); CursorStyle cursorStyle(); OutlineStyle outlineStyle(); KisConfig::SessionOnStartup sessionOnStartup() const; bool saveSessionOnQuit() const; bool showRootLayer(); int autoSaveInterval(); void setDefault(); int undoStackSize(); bool showOutlineWhilePainting(); int mdiMode(); int favoritePresets(); bool showCanvasMessages(); bool compressKra(); bool toolOptionsInDocker(); bool kineticScrollingEnabled(); int kineticScrollingGesture(); int kineticScrollingSensitivity(); bool kineticScrollingHiddenScrollbars(); bool switchSelectionCtrlAlt(); bool convertToImageColorspaceOnImport(); private Q_SLOTS: void getBackgroundImage(); void clearBackgroundImage(); }; /** * "Shortcuts" tab for preferences dialog */ class WdgShortcutSettings : public KisShortcutsDialog { Q_OBJECT public: WdgShortcutSettings(QWidget *parent) : KisShortcutsDialog(KisShortcutsEditor::AllActions, KisShortcutsEditor::LetterShortcutsAllowed, parent) { } }; class KisActionsSnapshot; class ShortcutSettingsTab : public QWidget { Q_OBJECT public: ShortcutSettingsTab(QWidget *parent = 0, const char *name = 0); ~ShortcutSettingsTab() override; public: void setDefault(); WdgShortcutSettings *m_page; QScopedPointer m_snapshot; public Q_SLOTS: void saveChanges(); void cancelChanges(); }; /** * "Color" tab for preferences dialog */ class WdgColorSettings : public QWidget, public Ui::WdgColorSettings { Q_OBJECT public: WdgColorSettings(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class ColorSettingsTab : public QWidget { Q_OBJECT public: ColorSettingsTab(QWidget *parent = 0, const char *name = 0); private Q_SLOTS: void refillMonitorProfiles(const KoID & s); void installProfile(); void toggleAllowMonitorProfileSelection(bool useSystemProfile); public: void setDefault(); WdgColorSettings *m_page; QButtonGroup m_pasteBehaviourGroup; QList m_monitorProfileLabels; QList m_monitorProfileWidgets; }; //======================= class WdgTabletSettings : public QWidget, public Ui::WdgTabletSettings { Q_OBJECT public: WdgTabletSettings(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class TabletSettingsTab : public QWidget { Q_OBJECT public: TabletSettingsTab(QWidget *parent = 0, const char *name = 0); private Q_SLOTS: void slotTabletTest(); public: void setDefault(); WdgTabletSettings *m_page; }; //======================= /** * "Performance"-tab for preferences dialog */ class SliderAndSpinBoxSync; class WdgPerformanceSettings : public QWidget, public Ui::WdgPerformanceSettings { Q_OBJECT public: WdgPerformanceSettings(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); } }; class PerformanceTab : public WdgPerformanceSettings { Q_OBJECT public: PerformanceTab(QWidget *parent = 0, const char *name = 0); ~PerformanceTab() override; void load(bool requestDefault); void save(); private Q_SLOTS: void selectSwapDir(); void slotThreadsLimitChanged(int value); void slotFrameClonesLimitChanged(int value); private: int realTilesRAM(); private: QVector m_syncs; int m_lastUsedThreadsLimit; int m_lastUsedClonesLimit; }; //======================= class WdgDisplaySettings : public QWidget, public Ui::WdgDisplaySettings { Q_OBJECT public: WdgDisplaySettings(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); } }; /** * Display settings tab for preferences dialog */ class DisplaySettingsTab : public WdgDisplaySettings { Q_OBJECT public: DisplaySettingsTab(QWidget *parent = 0, const char *name = 0); public: void setDefault(); protected Q_SLOTS: void slotUseOpenGLToggled(bool isChecked); + void slotPreferredSurfaceFormatChanged(int index); public: }; //======================= /** * Full screen settings tab for preferences dialog */ class WdgFullscreenSettingsBase : public QWidget, public Ui::WdgFullscreenSettings { Q_OBJECT public: WdgFullscreenSettingsBase(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class FullscreenSettingsTab : public WdgFullscreenSettingsBase { Q_OBJECT public: FullscreenSettingsTab(QWidget *parent); public: void setDefault(); }; //======================= /** * Preferences dialog of KImageShop^WKrayon^WKrita */ class KisDlgPreferences : public KPageDialog { Q_OBJECT public: static bool editPreferences(); protected: KisDlgPreferences(QWidget *parent = 0, const char *name = 0); ~KisDlgPreferences() override; void showEvent(QShowEvent *event) override; protected: GeneralTab *m_general; ShortcutSettingsTab *m_shortcutSettings; ColorSettingsTab *m_colorSettings; PerformanceTab *m_performanceSettings; DisplaySettingsTab *m_displaySettings; TabletSettingsTab *m_tabletSettings; FullscreenSettingsTab *m_fullscreenSettings; KisInputConfigurationPage *m_inputConfiguration; KoConfigAuthorPage *m_authorPage; QList m_pages; protected Q_SLOTS: void slotDefault(); }; #endif diff --git a/libs/ui/forms/wdgdisplaysettings.ui b/libs/ui/forms/wdgdisplaysettings.ui index d1f6c65afc..642c087abd 100644 --- a/libs/ui/forms/wdgdisplaysettings.ui +++ b/libs/ui/forms/wdgdisplaysettings.ui @@ -1,481 +1,538 @@ WdgDisplaySettings 0 0 598 546 0 0 Display 15 0 0 Canvas &Graphics Acceleration true 0 0 0 Nearest Neighbour Bilinear Filtering Trilinear Filtering High Quality Filtering 0 0 <html><head/><body><p>Try to disable vsync for Krita. This makes painting more responsive. Uncheck only when experiencing crashes with some GPU/driver combinations.</p></body></html> Disable vsync (needs restart) true 0 0 <html><head/><body><p>Use Texture Buffering. This can be faster on some GPU/Driver combinations (like Intel) or broken on some others (like AMD/Radeon).</p></body></html> Use texture buffer 0 0 Scaling Mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Renderer (needs restart): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 OpenGL Warnings Qt::RichText true + + + + HDR + + + false + + + + + + Display Format: + + + + + + + Current Display Format + + + + + + + Current Output Format: + + + + + + + Current Surface Value + + + + + + + Preferred Output Format: + + + + + + + + + + HDR Warning.................................. + + + + + + 15 7 Si&ze: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intCheckSize px 256 32 Qt::Horizontal 40 20 Start showing at: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 % 9999.000000000000000 Qt::Horizontal 40 20 Opacity: 0 0 50 20 Pixel Grid: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Selection Overlay: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Transparency Checkerboard: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Canvas Border Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 20 0 10 Hide Window Scrollbars false Hide layer thumbnail popup Enable curve anti-aliasing Color channels in color false Enable selection outline anti-aliasing If checked, the checkers will move when scrolling the canvas. Determines whether the checks will stay put or whether they will scroll together with the canvas &Move checkers when scrolling true Qt::Vertical 20 40 - - KisColorButton - QPushButton -
kis_color_button.h
-
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
+ + KisColorButton + QPushButton +
kis_color_button.h
+
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc index 0eba622a79..bd28b509b2 100644 --- a/libs/ui/kis_config.cc +++ b/libs/ui/kis_config.cc @@ -1,2035 +1,2074 @@ /* * Copyright (c) 2002 Patrick Julien * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas_resource_provider.h" #include "kis_config_notifier.h" #include "kis_snap_config.h" #include #include KisConfig::KisConfig(bool readOnly) : m_cfg( KSharedConfig::openConfig()->group("")) , m_readOnly(readOnly) { if (!readOnly) { KIS_SAFE_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread()); } } KisConfig::~KisConfig() { if (m_readOnly) return; if (qApp->thread() != QThread::currentThread()) { dbgKrita << "WARNING: KisConfig: requested config synchronization from nonGUI thread! Called from:" << kisBacktrace(); return; } m_cfg.sync(); } bool KisConfig::disableTouchOnCanvas(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("disableTouchOnCanvas", false)); } void KisConfig::setDisableTouchOnCanvas(bool value) const { m_cfg.writeEntry("disableTouchOnCanvas", value); } bool KisConfig::useProjections(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useProjections", true)); } void KisConfig::setUseProjections(bool useProj) const { m_cfg.writeEntry("useProjections", useProj); } bool KisConfig::undoEnabled(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("undoEnabled", true)); } void KisConfig::setUndoEnabled(bool undo) const { m_cfg.writeEntry("undoEnabled", undo); } int KisConfig::undoStackLimit(bool defaultValue) const { return (defaultValue ? 30 : m_cfg.readEntry("undoStackLimit", 30)); } void KisConfig::setUndoStackLimit(int limit) const { m_cfg.writeEntry("undoStackLimit", limit); } bool KisConfig::useCumulativeUndoRedo(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useCumulativeUndoRedo",false)); } void KisConfig::setCumulativeUndoRedo(bool value) { m_cfg.writeEntry("useCumulativeUndoRedo", value); } qreal KisConfig::stackT1(bool defaultValue) const { return (defaultValue ? 5 : m_cfg.readEntry("stackT1",5)); } void KisConfig::setStackT1(int T1) { m_cfg.writeEntry("stackT1", T1); } qreal KisConfig::stackT2(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("stackT2",1)); } void KisConfig::setStackT2(int T2) { m_cfg.writeEntry("stackT2", T2); } int KisConfig::stackN(bool defaultValue) const { return (defaultValue ? 5 : m_cfg.readEntry("stackN",5)); } void KisConfig::setStackN(int N) { m_cfg.writeEntry("stackN", N); } qint32 KisConfig::defImageWidth(bool defaultValue) const { return (defaultValue ? 1600 : m_cfg.readEntry("imageWidthDef", 1600)); } qint32 KisConfig::defImageHeight(bool defaultValue) const { return (defaultValue ? 1200 : m_cfg.readEntry("imageHeightDef", 1200)); } qreal KisConfig::defImageResolution(bool defaultValue) const { return (defaultValue ? 100.0 : m_cfg.readEntry("imageResolutionDef", 100.0)) / 72.0; } QString KisConfig::defColorModel(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id() : m_cfg.readEntry("colorModelDef", KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id())); } void KisConfig::defColorModel(const QString & model) const { m_cfg.writeEntry("colorModelDef", model); } QString KisConfig::defaultColorDepth(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id() : m_cfg.readEntry("colorDepthDef", KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id())); } void KisConfig::setDefaultColorDepth(const QString & depth) const { m_cfg.writeEntry("colorDepthDef", depth); } QString KisConfig::defColorProfile(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->profile()->name() : m_cfg.readEntry("colorProfileDef", KoColorSpaceRegistry::instance()->rgb8()->profile()->name())); } void KisConfig::defColorProfile(const QString & profile) const { m_cfg.writeEntry("colorProfileDef", profile); } void KisConfig::defImageWidth(qint32 width) const { m_cfg.writeEntry("imageWidthDef", width); } void KisConfig::defImageHeight(qint32 height) const { m_cfg.writeEntry("imageHeightDef", height); } void KisConfig::defImageResolution(qreal res) const { m_cfg.writeEntry("imageResolutionDef", res*72.0); } int KisConfig::preferredVectorImportResolutionPPI(bool defaultValue) const { return defaultValue ? 100.0 : m_cfg.readEntry("preferredVectorImportResolution", 100.0); } void KisConfig::setPreferredVectorImportResolutionPPI(int value) const { m_cfg.writeEntry("preferredVectorImportResolution", value); } void cleanOldCursorStyleKeys(KConfigGroup &cfg) { if (cfg.hasKey("newCursorStyle") && cfg.hasKey("newOutlineStyle")) { cfg.deleteEntry("cursorStyleDef"); } } CursorStyle KisConfig::newCursorStyle(bool defaultValue) const { if (defaultValue) { return CURSOR_STYLE_NO_CURSOR; } int style = m_cfg.readEntry("newCursorStyle", int(-1)); if (style < 0) { // old style format style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE)); switch (style) { case OLD_CURSOR_STYLE_TOOLICON: style = CURSOR_STYLE_TOOLICON; break; case OLD_CURSOR_STYLE_CROSSHAIR: case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS: style = CURSOR_STYLE_CROSSHAIR; break; case OLD_CURSOR_STYLE_POINTER: style = CURSOR_STYLE_POINTER; break; case OLD_CURSOR_STYLE_OUTLINE: case OLD_CURSOR_STYLE_NO_CURSOR: style = CURSOR_STYLE_NO_CURSOR; break; case OLD_CURSOR_STYLE_SMALL_ROUND: case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT: style = CURSOR_STYLE_SMALL_ROUND; break; case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED: style = CURSOR_STYLE_TRIANGLE_RIGHTHANDED; break; case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED: style = CURSOR_STYLE_TRIANGLE_LEFTHANDED; break; default: style = -1; } } cleanOldCursorStyleKeys(m_cfg); // compatibility with future versions if (style < 0 || style >= N_CURSOR_STYLE_SIZE) { style = CURSOR_STYLE_NO_CURSOR; } return (CursorStyle) style; } void KisConfig::setNewCursorStyle(CursorStyle style) { m_cfg.writeEntry("newCursorStyle", (int)style); } QColor KisConfig::getCursorMainColor(bool defaultValue) const { QColor col; col.setRgbF(0.501961, 1.0, 0.501961); return (defaultValue ? col : m_cfg.readEntry("cursorMaincColor", col)); } void KisConfig::setCursorMainColor(const QColor &v) const { m_cfg.writeEntry("cursorMaincColor", v); } OutlineStyle KisConfig::newOutlineStyle(bool defaultValue) const { if (defaultValue) { return OUTLINE_FULL; } int style = m_cfg.readEntry("newOutlineStyle", int(-1)); if (style < 0) { // old style format style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE)); switch (style) { case OLD_CURSOR_STYLE_TOOLICON: case OLD_CURSOR_STYLE_CROSSHAIR: case OLD_CURSOR_STYLE_POINTER: case OLD_CURSOR_STYLE_NO_CURSOR: case OLD_CURSOR_STYLE_SMALL_ROUND: case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED: style = OUTLINE_NONE; break; case OLD_CURSOR_STYLE_OUTLINE: case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT: case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED: style = OUTLINE_FULL; break; default: style = -1; } } cleanOldCursorStyleKeys(m_cfg); // compatibility with future versions if (style < 0 || style >= N_OUTLINE_STYLE_SIZE) { style = OUTLINE_FULL; } return (OutlineStyle) style; } void KisConfig::setNewOutlineStyle(OutlineStyle style) { m_cfg.writeEntry("newOutlineStyle", (int)style); } QRect KisConfig::colorPreviewRect() const { return m_cfg.readEntry("colorPreviewRect", QVariant(QRect(32, 32, 48, 48))).toRect(); } void KisConfig::setColorPreviewRect(const QRect &rect) { m_cfg.writeEntry("colorPreviewRect", QVariant(rect)); } bool KisConfig::useDirtyPresets(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useDirtyPresets",false)); } void KisConfig::setUseDirtyPresets(bool value) { m_cfg.writeEntry("useDirtyPresets",value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::useEraserBrushSize(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useEraserBrushSize",false)); } void KisConfig::setUseEraserBrushSize(bool value) { m_cfg.writeEntry("useEraserBrushSize",value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::useEraserBrushOpacity(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useEraserBrushOpacity",false)); } void KisConfig::setUseEraserBrushOpacity(bool value) { m_cfg.writeEntry("useEraserBrushOpacity",value); KisConfigNotifier::instance()->notifyConfigChanged(); } QColor KisConfig::getMDIBackgroundColor(bool defaultValue) const { QColor col(77, 77, 77); return (defaultValue ? col : m_cfg.readEntry("mdiBackgroundColor", col)); } void KisConfig::setMDIBackgroundColor(const QColor &v) const { m_cfg.writeEntry("mdiBackgroundColor", v); } QString KisConfig::getMDIBackgroundImage(bool defaultValue) const { return (defaultValue ? "" : m_cfg.readEntry("mdiBackgroundImage", "")); } void KisConfig::setMDIBackgroundImage(const QString &filename) const { m_cfg.writeEntry("mdiBackgroundImage", filename); } QString KisConfig::monitorProfile(int screen) const { // Note: keep this in sync with the default profile for the RGB colorspaces! QString profile = m_cfg.readEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), "sRGB-elle-V2-srgbtrc.icc"); //dbgKrita << "KisConfig::monitorProfile()" << profile; return profile; } QString KisConfig::monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue) const { return (defaultValue ? defaultMonitor : m_cfg.readEntry(QString("monitor_for_screen_%1").arg(screen), defaultMonitor)); } void KisConfig::setMonitorForScreen(int screen, const QString& monitor) { m_cfg.writeEntry(QString("monitor_for_screen_%1").arg(screen), monitor); } void KisConfig::setMonitorProfile(int screen, const QString & monitorProfile, bool override) const { m_cfg.writeEntry("monitorProfile/OverrideX11", override); m_cfg.writeEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), monitorProfile); } const KoColorProfile *KisConfig::getScreenProfile(int screen) { if (screen < 0) return 0; KisConfig cfg(true); QString monitorId; if (KisColorManager::instance()->devices().size() > screen) { monitorId = cfg.monitorForScreen(screen, KisColorManager::instance()->devices()[screen]); } //dbgKrita << "getScreenProfile(). Screen" << screen << "monitor id" << monitorId; if (monitorId.isEmpty()) { return 0; } QByteArray bytes = KisColorManager::instance()->displayProfile(monitorId); //dbgKrita << "\tgetScreenProfile()" << bytes.size(); if (bytes.length() > 0) { const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Integer8BitsColorDepthID.id(), bytes); //dbgKrita << "\tKisConfig::getScreenProfile for screen" << screen << profile->name(); return profile; } else { //dbgKrita << "\tCould not get a system monitor profile"; return 0; } } const KoColorProfile *KisConfig::displayProfile(int screen) const { if (screen < 0) return 0; // if the user plays with the settings, they can override the display profile, in which case // we don't want the system setting. bool override = useSystemMonitorProfile(); //dbgKrita << "KisConfig::displayProfile(). Override X11:" << override; const KoColorProfile *profile = 0; if (override) { //dbgKrita << "\tGoing to get the screen profile"; profile = KisConfig::getScreenProfile(screen); } // if it fails. check the configuration if (!profile || !profile->isSuitableForDisplay()) { //dbgKrita << "\tGoing to get the monitor profile"; QString monitorProfileName = monitorProfile(screen); //dbgKrita << "\t\tmonitorProfileName:" << monitorProfileName; if (!monitorProfileName.isEmpty()) { profile = KoColorSpaceRegistry::instance()->profileByName(monitorProfileName); } if (profile) { //dbgKrita << "\t\tsuitable for display" << profile->isSuitableForDisplay(); } else { //dbgKrita << "\t\tstill no profile"; } } // if we still don't have a profile, or the profile isn't suitable for display, // we need to get a last-resort profile. the built-in sRGB is a good choice then. if (!profile || !profile->isSuitableForDisplay()) { //dbgKrita << "\tnothing worked, going to get sRGB built-in"; profile = KoColorSpaceRegistry::instance()->profileByName("sRGB Built-in"); } if (profile) { //dbgKrita << "\tKisConfig::displayProfile for screen" << screen << "is" << profile->name(); } else { //dbgKrita << "\tCouldn't get a display profile at all"; } return profile; } QString KisConfig::workingColorSpace(bool defaultValue) const { return (defaultValue ? "RGBA" : m_cfg.readEntry("workingColorSpace", "RGBA")); } void KisConfig::setWorkingColorSpace(const QString & workingColorSpace) const { m_cfg.writeEntry("workingColorSpace", workingColorSpace); } QString KisConfig::printerColorSpace(bool /*defaultValue*/) const { //TODO currently only rgb8 is supported //return (defaultValue ? "RGBA" : m_cfg.readEntry("printerColorSpace", "RGBA")); return QString("RGBA"); } void KisConfig::setPrinterColorSpace(const QString & printerColorSpace) const { m_cfg.writeEntry("printerColorSpace", printerColorSpace); } QString KisConfig::printerProfile(bool defaultValue) const { return (defaultValue ? "" : m_cfg.readEntry("printerProfile", "")); } void KisConfig::setPrinterProfile(const QString & printerProfile) const { m_cfg.writeEntry("printerProfile", printerProfile); } bool KisConfig::useBlackPointCompensation(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useBlackPointCompensation", true)); } void KisConfig::setUseBlackPointCompensation(bool useBlackPointCompensation) const { m_cfg.writeEntry("useBlackPointCompensation", useBlackPointCompensation); } bool KisConfig::allowLCMSOptimization(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("allowLCMSOptimization", true)); } void KisConfig::setAllowLCMSOptimization(bool allowLCMSOptimization) { m_cfg.writeEntry("allowLCMSOptimization", allowLCMSOptimization); } bool KisConfig::forcePaletteColors(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("colorsettings/forcepalettecolors", false)); } void KisConfig::setForcePaletteColors(bool forcePaletteColors) { m_cfg.writeEntry("colorsettings/forcepalettecolors", forcePaletteColors); } bool KisConfig::showRulers(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showrulers", false)); } void KisConfig::setShowRulers(bool rulers) const { m_cfg.writeEntry("showrulers", rulers); } bool KisConfig::forceShowSaveMessages(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("forceShowSaveMessages", false)); } void KisConfig::setForceShowSaveMessages(bool value) const { m_cfg.writeEntry("forceShowSaveMessages", value); } bool KisConfig::forceShowAutosaveMessages(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("forceShowAutosaveMessages", false)); } void KisConfig::setForceShowAutosaveMessages(bool value) const { m_cfg.writeEntry("forceShowAutosaveMessages", value); } bool KisConfig::rulersTrackMouse(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("rulersTrackMouse", true)); } void KisConfig::setRulersTrackMouse(bool value) const { m_cfg.writeEntry("rulersTrackMouse", value); } qint32 KisConfig::pasteBehaviour(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("pasteBehaviour", 2)); } void KisConfig::setPasteBehaviour(qint32 renderIntent) const { m_cfg.writeEntry("pasteBehaviour", renderIntent); } qint32 KisConfig::monitorRenderIntent(bool defaultValue) const { qint32 intent = m_cfg.readEntry("renderIntent", INTENT_PERCEPTUAL); if (intent > 3) intent = 3; if (intent < 0) intent = 0; return (defaultValue ? INTENT_PERCEPTUAL : intent); } void KisConfig::setRenderIntent(qint32 renderIntent) const { if (renderIntent > 3) renderIntent = 3; if (renderIntent < 0) renderIntent = 0; m_cfg.writeEntry("renderIntent", renderIntent); } bool KisConfig::useOpenGL(bool defaultValue) const { if (defaultValue) { return true; } //dbgKrita << "use opengl" << m_cfg.readEntry("useOpenGL", true) << "success" << m_cfg.readEntry("canvasState", "OPENGL_SUCCESS"); QString cs = canvasState(); #ifdef Q_OS_WIN return (m_cfg.readEntry("useOpenGLWindows", true) && (cs == "OPENGL_SUCCESS" || cs == "TRY_OPENGL")); #else return (m_cfg.readEntry("useOpenGL", true) && (cs == "OPENGL_SUCCESS" || cs == "TRY_OPENGL")); #endif } void KisConfig::setUseOpenGL(bool useOpenGL) const { #ifdef Q_OS_WIN m_cfg.writeEntry("useOpenGLWindows", useOpenGL); #else m_cfg.writeEntry("useOpenGL", useOpenGL); #endif } int KisConfig::openGLFilteringMode(bool defaultValue) const { return (defaultValue ? 3 : m_cfg.readEntry("OpenGLFilterMode", 3)); } void KisConfig::setOpenGLFilteringMode(int filteringMode) { m_cfg.writeEntry("OpenGLFilterMode", filteringMode); } bool KisConfig::useOpenGLTextureBuffer(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useOpenGLTextureBuffer", true)); } void KisConfig::setUseOpenGLTextureBuffer(bool useBuffer) { m_cfg.writeEntry("useOpenGLTextureBuffer", useBuffer); } int KisConfig::openGLTextureSize(bool defaultValue) const { return (defaultValue ? 256 : m_cfg.readEntry("textureSize", 256)); } bool KisConfig::disableVSync(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("disableVSync", true)); } void KisConfig::setDisableVSync(bool disableVSync) { m_cfg.writeEntry("disableVSync", disableVSync); } bool KisConfig::showAdvancedOpenGLSettings(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showAdvancedOpenGLSettings", false)); } bool KisConfig::forceOpenGLFenceWorkaround(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("forceOpenGLFenceWorkaround", false)); } int KisConfig::numMipmapLevels(bool defaultValue) const { return (defaultValue ? 4 : m_cfg.readEntry("numMipmapLevels", 4)); } int KisConfig::textureOverlapBorder() const { return 1 << qMax(0, numMipmapLevels()); } quint32 KisConfig::getGridMainStyle(bool defaultValue) const { int v = m_cfg.readEntry("gridmainstyle", 0); v = qBound(0, v, 2); return (defaultValue ? 0 : v); } void KisConfig::setGridMainStyle(quint32 v) const { m_cfg.writeEntry("gridmainstyle", v); } quint32 KisConfig::getGridSubdivisionStyle(bool defaultValue) const { quint32 v = m_cfg.readEntry("gridsubdivisionstyle", 1); if (v > 2) v = 2; return (defaultValue ? 1 : v); } void KisConfig::setGridSubdivisionStyle(quint32 v) const { m_cfg.writeEntry("gridsubdivisionstyle", v); } QColor KisConfig::getGridMainColor(bool defaultValue) const { QColor col(99, 99, 99); return (defaultValue ? col : m_cfg.readEntry("gridmaincolor", col)); } void KisConfig::setGridMainColor(const QColor & v) const { m_cfg.writeEntry("gridmaincolor", v); } QColor KisConfig::getGridSubdivisionColor(bool defaultValue) const { QColor col(150, 150, 150); return (defaultValue ? col : m_cfg.readEntry("gridsubdivisioncolor", col)); } void KisConfig::setGridSubdivisionColor(const QColor & v) const { m_cfg.writeEntry("gridsubdivisioncolor", v); } QColor KisConfig::getPixelGridColor(bool defaultValue) const { QColor col(255, 255, 255); return (defaultValue ? col : m_cfg.readEntry("pixelGridColor", col)); } void KisConfig::setPixelGridColor(const QColor & v) const { m_cfg.writeEntry("pixelGridColor", v); } qreal KisConfig::getPixelGridDrawingThreshold(bool defaultValue) const { qreal border = 24.0f; return (defaultValue ? border : m_cfg.readEntry("pixelGridDrawingThreshold", border)); } void KisConfig::setPixelGridDrawingThreshold(qreal v) const { m_cfg.writeEntry("pixelGridDrawingThreshold", v); } bool KisConfig::pixelGridEnabled(bool defaultValue) const { bool enabled = true; return (defaultValue ? enabled : m_cfg.readEntry("pixelGridEnabled", enabled)); } void KisConfig::enablePixelGrid(bool v) const { m_cfg.writeEntry("pixelGridEnabled", v); } quint32 KisConfig::guidesLineStyle(bool defaultValue) const { int v = m_cfg.readEntry("guidesLineStyle", 0); v = qBound(0, v, 2); return (defaultValue ? 0 : v); } void KisConfig::setGuidesLineStyle(quint32 v) const { m_cfg.writeEntry("guidesLineStyle", v); } QColor KisConfig::guidesColor(bool defaultValue) const { QColor col(99, 99, 99); return (defaultValue ? col : m_cfg.readEntry("guidesColor", col)); } void KisConfig::setGuidesColor(const QColor & v) const { m_cfg.writeEntry("guidesColor", v); } void KisConfig::loadSnapConfig(KisSnapConfig *config, bool defaultValue) const { KisSnapConfig defaultConfig(false); if (defaultValue) { *config = defaultConfig; return; } config->setOrthogonal(m_cfg.readEntry("globalSnapOrthogonal", defaultConfig.orthogonal())); config->setNode(m_cfg.readEntry("globalSnapNode", defaultConfig.node())); config->setExtension(m_cfg.readEntry("globalSnapExtension", defaultConfig.extension())); config->setIntersection(m_cfg.readEntry("globalSnapIntersection", defaultConfig.intersection())); config->setBoundingBox(m_cfg.readEntry("globalSnapBoundingBox", defaultConfig.boundingBox())); config->setImageBounds(m_cfg.readEntry("globalSnapImageBounds", defaultConfig.imageBounds())); config->setImageCenter(m_cfg.readEntry("globalSnapImageCenter", defaultConfig.imageCenter())); } void KisConfig::saveSnapConfig(const KisSnapConfig &config) { m_cfg.writeEntry("globalSnapOrthogonal", config.orthogonal()); m_cfg.writeEntry("globalSnapNode", config.node()); m_cfg.writeEntry("globalSnapExtension", config.extension()); m_cfg.writeEntry("globalSnapIntersection", config.intersection()); m_cfg.writeEntry("globalSnapBoundingBox", config.boundingBox()); m_cfg.writeEntry("globalSnapImageBounds", config.imageBounds()); m_cfg.writeEntry("globalSnapImageCenter", config.imageCenter()); } qint32 KisConfig::checkSize(bool defaultValue) const { return (defaultValue ? 32 : m_cfg.readEntry("checksize", 32)); } void KisConfig::setCheckSize(qint32 checksize) const { m_cfg.writeEntry("checksize", checksize); } bool KisConfig::scrollCheckers(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("scrollingcheckers", false)); } void KisConfig::setScrollingCheckers(bool sc) const { m_cfg.writeEntry("scrollingcheckers", sc); } QColor KisConfig::canvasBorderColor(bool defaultValue) const { QColor color(QColor(128,128,128)); return (defaultValue ? color : m_cfg.readEntry("canvasBorderColor", color)); } void KisConfig::setCanvasBorderColor(const QColor& color) const { m_cfg.writeEntry("canvasBorderColor", color); } bool KisConfig::hideScrollbars(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("hideScrollbars", false)); } void KisConfig::setHideScrollbars(bool value) const { m_cfg.writeEntry("hideScrollbars", value); } QColor KisConfig::checkersColor1(bool defaultValue) const { QColor col(220, 220, 220); return (defaultValue ? col : m_cfg.readEntry("checkerscolor", col)); } void KisConfig::setCheckersColor1(const QColor & v) const { m_cfg.writeEntry("checkerscolor", v); } QColor KisConfig::checkersColor2(bool defaultValue) const { return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("checkerscolor2", QColor(Qt::white))); } void KisConfig::setCheckersColor2(const QColor & v) const { m_cfg.writeEntry("checkerscolor2", v); } bool KisConfig::antialiasCurves(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("antialiascurves", true)); } void KisConfig::setAntialiasCurves(bool v) const { m_cfg.writeEntry("antialiascurves", v); } bool KisConfig::antialiasSelectionOutline(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("AntialiasSelectionOutline", false)); } void KisConfig::setAntialiasSelectionOutline(bool v) const { m_cfg.writeEntry("AntialiasSelectionOutline", v); } bool KisConfig::showRootLayer(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ShowRootLayer", false)); } void KisConfig::setShowRootLayer(bool showRootLayer) const { m_cfg.writeEntry("ShowRootLayer", showRootLayer); } bool KisConfig::showGlobalSelection(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ShowGlobalSelection", false)); } void KisConfig::setShowGlobalSelection(bool showGlobalSelection) const { m_cfg.writeEntry("ShowGlobalSelection", showGlobalSelection); } bool KisConfig::showOutlineWhilePainting(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("ShowOutlineWhilePainting", true)); } void KisConfig::setShowOutlineWhilePainting(bool showOutlineWhilePainting) const { m_cfg.writeEntry("ShowOutlineWhilePainting", showOutlineWhilePainting); } bool KisConfig::forceAlwaysFullSizedOutline(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("forceAlwaysFullSizedOutline", false)); } void KisConfig::setForceAlwaysFullSizedOutline(bool value) const { m_cfg.writeEntry("forceAlwaysFullSizedOutline", value); } KisConfig::SessionOnStartup KisConfig::sessionOnStartup(bool defaultValue) const { int value = defaultValue ? SOS_BlankSession : m_cfg.readEntry("sessionOnStartup", (int)SOS_BlankSession); return (KisConfig::SessionOnStartup)value; } void KisConfig::setSessionOnStartup(SessionOnStartup value) { m_cfg.writeEntry("sessionOnStartup", (int)value); } bool KisConfig::saveSessionOnQuit(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("saveSessionOnQuit", false); } void KisConfig::setSaveSessionOnQuit(bool value) { m_cfg.writeEntry("saveSessionOnQuit", value); } qreal KisConfig::outlineSizeMinimum(bool defaultValue) const { return (defaultValue ? 1.0 : m_cfg.readEntry("OutlineSizeMinimum", 1.0)); } void KisConfig::setOutlineSizeMinimum(qreal outlineSizeMinimum) const { m_cfg.writeEntry("OutlineSizeMinimum", outlineSizeMinimum); } qreal KisConfig::selectionViewSizeMinimum(bool defaultValue) const { return (defaultValue ? 5.0 : m_cfg.readEntry("SelectionViewSizeMinimum", 5.0)); } void KisConfig::setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const { m_cfg.writeEntry("SelectionViewSizeMinimum", outlineSizeMinimum); } int KisConfig::autoSaveInterval(bool defaultValue) const { return (defaultValue ? 15 * 60 : m_cfg.readEntry("AutoSaveInterval", 15 * 60)); } void KisConfig::setAutoSaveInterval(int seconds) const { return m_cfg.writeEntry("AutoSaveInterval", seconds); } bool KisConfig::backupFile(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("CreateBackupFile", true)); } void KisConfig::setBackupFile(bool backupFile) const { m_cfg.writeEntry("CreateBackupFile", backupFile); } bool KisConfig::showFilterGallery(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showFilterGallery", false)); } void KisConfig::setShowFilterGallery(bool showFilterGallery) const { m_cfg.writeEntry("showFilterGallery", showFilterGallery); } bool KisConfig::showFilterGalleryLayerMaskDialog(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showFilterGalleryLayerMaskDialog", true)); } void KisConfig::setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const { m_cfg.writeEntry("setShowFilterGalleryLayerMaskDialog", showFilterGallery); } QString KisConfig::canvasState(bool defaultValue) const { const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); return (defaultValue ? "OPENGL_NOT_TRIED" : kritarc.value("canvasState", "OPENGL_NOT_TRIED").toString()); } void KisConfig::setCanvasState(const QString& state) const { static QStringList acceptableStates; if (acceptableStates.isEmpty()) { acceptableStates << "OPENGL_SUCCESS" << "TRY_OPENGL" << "OPENGL_NOT_TRIED" << "OPENGL_FAILED"; } if (acceptableStates.contains(state)) { const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("canvasState", state); } } bool KisConfig::toolOptionsPopupDetached(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ToolOptionsPopupDetached", false)); } void KisConfig::setToolOptionsPopupDetached(bool detached) const { m_cfg.writeEntry("ToolOptionsPopupDetached", detached); } bool KisConfig::paintopPopupDetached(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("PaintopPopupDetached", false)); } void KisConfig::setPaintopPopupDetached(bool detached) const { m_cfg.writeEntry("PaintopPopupDetached", detached); } QString KisConfig::pressureTabletCurve(bool defaultValue) const { return (defaultValue ? "0,0;1,1" : m_cfg.readEntry("tabletPressureCurve","0,0;1,1;")); } void KisConfig::setPressureTabletCurve(const QString& curveString) const { m_cfg.writeEntry("tabletPressureCurve", curveString); } bool KisConfig::useWin8PointerInput(bool defaultValue) const { #ifdef Q_OS_WIN return (defaultValue ? false : m_cfg.readEntry("useWin8PointerInput", false)); #else Q_UNUSED(defaultValue); return false; #endif } void KisConfig::setUseWin8PointerInput(bool value) const { #ifdef Q_OS_WIN // Special handling: Only set value if changed // I don't want it to be set if the user hasn't touched it if (useWin8PointerInput() != value) { m_cfg.writeEntry("useWin8PointerInput", value); } #else Q_UNUSED(value) #endif } qreal KisConfig::vastScrolling(bool defaultValue) const { return (defaultValue ? 0.9 : m_cfg.readEntry("vastScrolling", 0.9)); } void KisConfig::setVastScrolling(const qreal factor) const { m_cfg.writeEntry("vastScrolling", factor); } int KisConfig::presetChooserViewMode(bool defaultValue) const { return (defaultValue ? 0 : m_cfg.readEntry("presetChooserViewMode", 0)); } void KisConfig::setPresetChooserViewMode(const int mode) const { m_cfg.writeEntry("presetChooserViewMode", mode); } int KisConfig::presetIconSize(bool defaultValue) const { return (defaultValue ? 60 : m_cfg.readEntry("presetIconSize", 60)); } void KisConfig::setPresetIconSize(const int value) const { m_cfg.writeEntry("presetIconSize", value); } bool KisConfig::firstRun(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("firstRun", true)); } void KisConfig::setFirstRun(const bool first) const { m_cfg.writeEntry("firstRun", first); } int KisConfig::horizontalSplitLines(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("horizontalSplitLines", 1)); } void KisConfig::setHorizontalSplitLines(const int numberLines) const { m_cfg.writeEntry("horizontalSplitLines", numberLines); } int KisConfig::verticalSplitLines(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("verticalSplitLines", 1)); } void KisConfig::setVerticalSplitLines(const int numberLines) const { m_cfg.writeEntry("verticalSplitLines", numberLines); } bool KisConfig::clicklessSpacePan(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("clicklessSpacePan", true)); } void KisConfig::setClicklessSpacePan(const bool toggle) const { m_cfg.writeEntry("clicklessSpacePan", toggle); } bool KisConfig::hideDockersFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideDockersFullScreen", true)); } void KisConfig::setHideDockersFullscreen(const bool value) const { m_cfg.writeEntry("hideDockersFullScreen", value); } bool KisConfig::showDockers(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showDockers", true)); } void KisConfig::setShowDockers(const bool value) const { m_cfg.writeEntry("showDockers", value); } bool KisConfig::showStatusBar(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showStatusBar", true)); } void KisConfig::setShowStatusBar(const bool value) const { m_cfg.writeEntry("showStatusBar", value); } bool KisConfig::hideMenuFullscreen(bool defaultValue) const { return (defaultValue ? true: m_cfg.readEntry("hideMenuFullScreen", true)); } void KisConfig::setHideMenuFullscreen(const bool value) const { m_cfg.writeEntry("hideMenuFullScreen", value); } bool KisConfig::hideScrollbarsFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideScrollbarsFullScreen", true)); } void KisConfig::setHideScrollbarsFullscreen(const bool value) const { m_cfg.writeEntry("hideScrollbarsFullScreen", value); } bool KisConfig::hideStatusbarFullscreen(bool defaultValue) const { return (defaultValue ? true: m_cfg.readEntry("hideStatusbarFullScreen", true)); } void KisConfig::setHideStatusbarFullscreen(const bool value) const { m_cfg.writeEntry("hideStatusbarFullScreen", value); } bool KisConfig::hideTitlebarFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideTitleBarFullscreen", true)); } void KisConfig::setHideTitlebarFullscreen(const bool value) const { m_cfg.writeEntry("hideTitleBarFullscreen", value); } bool KisConfig::hideToolbarFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideToolbarFullscreen", true)); } void KisConfig::setHideToolbarFullscreen(const bool value) const { m_cfg.writeEntry("hideToolbarFullscreen", value); } bool KisConfig::fullscreenMode(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("fullscreenMode", true)); } void KisConfig::setFullscreenMode(const bool value) const { m_cfg.writeEntry("fullscreenMode", value); } QStringList KisConfig::favoriteCompositeOps(bool defaultValue) const { return (defaultValue ? QStringList() : m_cfg.readEntry("favoriteCompositeOps", QStringList())); } void KisConfig::setFavoriteCompositeOps(const QStringList& compositeOps) const { m_cfg.writeEntry("favoriteCompositeOps", compositeOps); } QString KisConfig::exportConfiguration(const QString &filterId, bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("ExportConfiguration-" + filterId, QString())); } void KisConfig::setExportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const { QString exportConfig = properties->toXML(); m_cfg.writeEntry("ExportConfiguration-" + filterId, exportConfig); } QString KisConfig::importConfiguration(const QString &filterId, bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("ImportConfiguration-" + filterId, QString())); } void KisConfig::setImportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const { QString importConfig = properties->toXML(); m_cfg.writeEntry("ImportConfiguration-" + filterId, importConfig); } bool KisConfig::useOcio(bool defaultValue) const { #ifdef HAVE_OCIO return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/UseOcio", false)); #else Q_UNUSED(defaultValue); return false; #endif } void KisConfig::setUseOcio(bool useOCIO) const { m_cfg.writeEntry("Krita/Ocio/UseOcio", useOCIO); } int KisConfig::favoritePresets(bool defaultValue) const { return (defaultValue ? 10 : m_cfg.readEntry("numFavoritePresets", 10)); } void KisConfig::setFavoritePresets(const int value) { m_cfg.writeEntry("numFavoritePresets", value); } bool KisConfig::levelOfDetailEnabled(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("levelOfDetailEnabled", false)); } void KisConfig::setLevelOfDetailEnabled(bool value) { m_cfg.writeEntry("levelOfDetailEnabled", value); } KisConfig::OcioColorManagementMode KisConfig::ocioColorManagementMode(bool defaultValue) const { return (OcioColorManagementMode)(defaultValue ? INTERNAL : m_cfg.readEntry("Krita/Ocio/OcioColorManagementMode", (int) INTERNAL)); } void KisConfig::setOcioColorManagementMode(OcioColorManagementMode mode) const { m_cfg.writeEntry("Krita/Ocio/OcioColorManagementMode", (int) mode); } QString KisConfig::ocioConfigurationPath(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioConfigPath", QString())); } void KisConfig::setOcioConfigurationPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioConfigPath", path); } QString KisConfig::ocioLutPath(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioLutPath", QString())); } void KisConfig::setOcioLutPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioLutPath", path); } int KisConfig::ocioLutEdgeSize(bool defaultValue) const { return (defaultValue ? 64 : m_cfg.readEntry("Krita/Ocio/LutEdgeSize", 64)); } void KisConfig::setOcioLutEdgeSize(int value) { m_cfg.writeEntry("Krita/Ocio/LutEdgeSize", value); } bool KisConfig::ocioLockColorVisualRepresentation(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/OcioLockColorVisualRepresentation", false)); } void KisConfig::setOcioLockColorVisualRepresentation(bool value) { m_cfg.writeEntry("Krita/Ocio/OcioLockColorVisualRepresentation", value); } QString KisConfig::defaultPalette(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("defaultPalette", "Default")); } void KisConfig::setDefaultPalette(const QString& name) const { m_cfg.writeEntry("defaultPalette", name); } QString KisConfig::toolbarSlider(int sliderNumber, bool defaultValue) const { QString def = "flow"; if (sliderNumber == 1) { def = "opacity"; } if (sliderNumber == 2) { def = "size"; } return (defaultValue ? def : m_cfg.readEntry(QString("toolbarslider_%1").arg(sliderNumber), def)); } void KisConfig::setToolbarSlider(int sliderNumber, const QString &slider) { m_cfg.writeEntry(QString("toolbarslider_%1").arg(sliderNumber), slider); } int KisConfig::layerThumbnailSize(bool defaultValue) const { return (defaultValue ? 20 : m_cfg.readEntry("layerThumbnailSize", 20)); } void KisConfig::setLayerThumbnailSize(int size) { m_cfg.writeEntry("layerThumbnailSize", size); } bool KisConfig::sliderLabels(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("sliderLabels", true)); } void KisConfig::setSliderLabels(bool enabled) { m_cfg.writeEntry("sliderLabels", enabled); } QString KisConfig::currentInputProfile(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("currentInputProfile", QString())); } void KisConfig::setCurrentInputProfile(const QString& name) { m_cfg.writeEntry("currentInputProfile", name); } bool KisConfig::useSystemMonitorProfile(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ColorManagement/UseSystemMonitorProfile", false)); } void KisConfig::setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const { m_cfg.writeEntry("ColorManagement/UseSystemMonitorProfile", _useSystemMonitorProfile); } bool KisConfig::presetStripVisible(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("presetStripVisible", true)); } void KisConfig::setPresetStripVisible(bool visible) { m_cfg.writeEntry("presetStripVisible", visible); } bool KisConfig::scratchpadVisible(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("scratchpadVisible", true)); } void KisConfig::setScratchpadVisible(bool visible) { m_cfg.writeEntry("scratchpadVisible", visible); } bool KisConfig::showSingleChannelAsColor(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showSingleChannelAsColor", false)); } void KisConfig::setShowSingleChannelAsColor(bool asColor) { m_cfg.writeEntry("showSingleChannelAsColor", asColor); } bool KisConfig::hidePopups(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("hidePopups", false)); } void KisConfig::setHidePopups(bool hidepopups) { m_cfg.writeEntry("hidePopups", hidepopups); } int KisConfig::numDefaultLayers(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("NumberOfLayersForNewImage", 2)); } void KisConfig::setNumDefaultLayers(int num) { m_cfg.writeEntry("NumberOfLayersForNewImage", num); } quint8 KisConfig::defaultBackgroundOpacity(bool defaultValue) const { return (defaultValue ? (int)OPACITY_OPAQUE_U8 : m_cfg.readEntry("BackgroundOpacityForNewImage", (int)OPACITY_OPAQUE_U8)); } void KisConfig::setDefaultBackgroundOpacity(quint8 value) { m_cfg.writeEntry("BackgroundOpacityForNewImage", (int)value); } QColor KisConfig::defaultBackgroundColor(bool defaultValue) const { return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("BackgroundColorForNewImage", QColor(Qt::white))); } void KisConfig::setDefaultBackgroundColor(QColor value) { m_cfg.writeEntry("BackgroundColorForNewImage", value); } KisConfig::BackgroundStyle KisConfig::defaultBackgroundStyle(bool defaultValue) const { return (KisConfig::BackgroundStyle)(defaultValue ? LAYER : m_cfg.readEntry("BackgroundStyleForNewImage", (int)LAYER)); } void KisConfig::setDefaultBackgroundStyle(KisConfig::BackgroundStyle value) { m_cfg.writeEntry("BackgroundStyleForNewImage", (int)value); } int KisConfig::lineSmoothingType(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("LineSmoothingType", 1)); } void KisConfig::setLineSmoothingType(int value) { m_cfg.writeEntry("LineSmoothingType", value); } qreal KisConfig::lineSmoothingDistance(bool defaultValue) const { return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDistance", 50.0)); } void KisConfig::setLineSmoothingDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDistance", value); } qreal KisConfig::lineSmoothingTailAggressiveness(bool defaultValue) const { return (defaultValue ? 0.15 : m_cfg.readEntry("LineSmoothingTailAggressiveness", 0.15)); } void KisConfig::setLineSmoothingTailAggressiveness(qreal value) { m_cfg.writeEntry("LineSmoothingTailAggressiveness", value); } bool KisConfig::lineSmoothingSmoothPressure(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("LineSmoothingSmoothPressure", false)); } void KisConfig::setLineSmoothingSmoothPressure(bool value) { m_cfg.writeEntry("LineSmoothingSmoothPressure", value); } bool KisConfig::lineSmoothingScalableDistance(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingScalableDistance", true)); } void KisConfig::setLineSmoothingScalableDistance(bool value) { m_cfg.writeEntry("LineSmoothingScalableDistance", value); } qreal KisConfig::lineSmoothingDelayDistance(bool defaultValue) const { return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDelayDistance", 50.0)); } void KisConfig::setLineSmoothingDelayDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDelayDistance", value); } bool KisConfig::lineSmoothingUseDelayDistance(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingUseDelayDistance", true)); } void KisConfig::setLineSmoothingUseDelayDistance(bool value) { m_cfg.writeEntry("LineSmoothingUseDelayDistance", value); } bool KisConfig::lineSmoothingFinishStabilizedCurve(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingFinishStabilizedCurve", true)); } void KisConfig::setLineSmoothingFinishStabilizedCurve(bool value) { m_cfg.writeEntry("LineSmoothingFinishStabilizedCurve", value); } bool KisConfig::lineSmoothingStabilizeSensors(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingStabilizeSensors", true)); } void KisConfig::setLineSmoothingStabilizeSensors(bool value) { m_cfg.writeEntry("LineSmoothingStabilizeSensors", value); } int KisConfig::tabletEventsDelay(bool defaultValue) const { return (defaultValue ? 10 : m_cfg.readEntry("tabletEventsDelay", 10)); } void KisConfig::setTabletEventsDelay(int value) { m_cfg.writeEntry("tabletEventsDelay", value); } bool KisConfig::trackTabletEventLatency(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("trackTabletEventLatency", false)); } void KisConfig::setTrackTabletEventLatency(bool value) { m_cfg.writeEntry("trackTabletEventLatency", value); } bool KisConfig::testingAcceptCompressedTabletEvents(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("testingAcceptCompressedTabletEvents", false)); } void KisConfig::setTestingAcceptCompressedTabletEvents(bool value) { m_cfg.writeEntry("testingAcceptCompressedTabletEvents", value); } bool KisConfig::shouldEatDriverShortcuts(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("shouldEatDriverShortcuts", false)); } bool KisConfig::testingCompressBrushEvents(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("testingCompressBrushEvents", false)); } void KisConfig::setTestingCompressBrushEvents(bool value) { m_cfg.writeEntry("testingCompressBrushEvents", value); } int KisConfig::workaroundX11SmoothPressureSteps(bool defaultValue) const { return (defaultValue ? 0 : m_cfg.readEntry("workaroundX11SmoothPressureSteps", 0)); } bool KisConfig::showCanvasMessages(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showOnCanvasMessages", true)); } void KisConfig::setShowCanvasMessages(bool show) { m_cfg.writeEntry("showOnCanvasMessages", show); } bool KisConfig::compressKra(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("compressLayersInKra", false)); } void KisConfig::setCompressKra(bool compress) { m_cfg.writeEntry("compressLayersInKra", compress); } bool KisConfig::toolOptionsInDocker(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("ToolOptionsInDocker", true)); } void KisConfig::setToolOptionsInDocker(bool inDocker) { m_cfg.writeEntry("ToolOptionsInDocker", inDocker); } bool KisConfig::kineticScrollingEnabled(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("KineticScrollingEnabled", true)); } void KisConfig::setKineticScrollingEnabled(bool value) { m_cfg.writeEntry("KineticScrollingEnabled", value); } int KisConfig::kineticScrollingGesture(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("KineticScrollingGesture", 2)); } void KisConfig::setKineticScrollingGesture(int gesture) { m_cfg.writeEntry("KineticScrollingGesture", gesture); } int KisConfig::kineticScrollingSensitivity(bool defaultValue) const { return (defaultValue ? 75 : m_cfg.readEntry("KineticScrollingSensitivity", 75)); } void KisConfig::setKineticScrollingSensitivity(int sensitivity) { m_cfg.writeEntry("KineticScrollingSensitivity", sensitivity); } bool KisConfig::kineticScrollingHiddenScrollbars(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("KineticScrollingHideScrollbar", false)); } void KisConfig::setKineticScrollingHideScrollbars(bool scrollbar) { m_cfg.writeEntry("KineticScrollingHideScrollbar", scrollbar); } const KoColorSpace* KisConfig::customColorSelectorColorSpace(bool defaultValue) const { const KoColorSpace *cs = 0; KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); if (defaultValue || cfg.readEntry("useCustomColorSpace", true)) { KoColorSpaceRegistry* csr = KoColorSpaceRegistry::instance(); QString modelID = cfg.readEntry("customColorSpaceModel", "RGBA"); QString depthID = cfg.readEntry("customColorSpaceDepthID", "U8"); QString profile = cfg.readEntry("customColorSpaceProfile", "sRGB built-in - (lcms internal)"); if (profile == "default") { // qDebug() << "Falling back to default color profile."; profile = "sRGB built-in - (lcms internal)"; } cs = csr->colorSpace(modelID, depthID, profile); } return cs; } void KisConfig::setCustomColorSelectorColorSpace(const KoColorSpace *cs) { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); cfg.writeEntry("useCustomColorSpace", bool(cs)); if(cs) { cfg.writeEntry("customColorSpaceModel", cs->colorModelId().id()); cfg.writeEntry("customColorSpaceDepthID", cs->colorDepthId().id()); cfg.writeEntry("customColorSpaceProfile", cs->profile()->name()); } KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::enableOpenGLFramerateLogging(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("enableOpenGLFramerateLogging", false)); } void KisConfig::setEnableOpenGLFramerateLogging(bool value) const { m_cfg.writeEntry("enableOpenGLFramerateLogging", value); } bool KisConfig::enableBrushSpeedLogging(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("enableBrushSpeedLogging", false)); } void KisConfig::setEnableBrushSpeedLogging(bool value) const { m_cfg.writeEntry("enableBrushSpeedLogging", value); } void KisConfig::setEnableAmdVectorizationWorkaround(bool value) { m_cfg.writeEntry("amdDisableVectorWorkaround", value); } bool KisConfig::enableAmdVectorizationWorkaround(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("amdDisableVectorWorkaround", false)); } void KisConfig::setAnimationDropFrames(bool value) { bool oldValue = animationDropFrames(); if (value == oldValue) return; m_cfg.writeEntry("animationDropFrames", value); KisConfigNotifier::instance()->notifyDropFramesModeChanged(); } bool KisConfig::animationDropFrames(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("animationDropFrames", true)); } int KisConfig::scrubbingUpdatesDelay(bool defaultValue) const { return (defaultValue ? 30 : m_cfg.readEntry("scrubbingUpdatesDelay", 30)); } void KisConfig::setScrubbingUpdatesDelay(int value) { m_cfg.writeEntry("scrubbingUpdatesDelay", value); } int KisConfig::scrubbingAudioUpdatesDelay(bool defaultValue) const { return (defaultValue ? -1 : m_cfg.readEntry("scrubbingAudioUpdatesDelay", -1)); } void KisConfig::setScrubbingAudioUpdatesDelay(int value) { m_cfg.writeEntry("scrubbingAudioUpdatesDelay", value); } int KisConfig::audioOffsetTolerance(bool defaultValue) const { return (defaultValue ? -1 : m_cfg.readEntry("audioOffsetTolerance", -1)); } void KisConfig::setAudioOffsetTolerance(int value) { m_cfg.writeEntry("audioOffsetTolerance", value); } bool KisConfig::switchSelectionCtrlAlt(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("switchSelectionCtrlAlt", false); } void KisConfig::setSwitchSelectionCtrlAlt(bool value) { m_cfg.writeEntry("switchSelectionCtrlAlt", value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::convertToImageColorspaceOnImport(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("ConvertToImageColorSpaceOnImport", false); } void KisConfig::setConvertToImageColorspaceOnImport(bool value) { m_cfg.writeEntry("ConvertToImageColorSpaceOnImport", value); } int KisConfig::stabilizerSampleSize(bool defaultValue) const { #ifdef Q_OS_WIN const int defaultSampleSize = 50; #else const int defaultSampleSize = 15; #endif return defaultValue ? defaultSampleSize : m_cfg.readEntry("stabilizerSampleSize", defaultSampleSize); } void KisConfig::setStabilizerSampleSize(int value) { m_cfg.writeEntry("stabilizerSampleSize", value); } bool KisConfig::stabilizerDelayedPaint(bool defaultValue) const { const bool defaultEnabled = true; return defaultValue ? defaultEnabled : m_cfg.readEntry("stabilizerDelayedPaint", defaultEnabled); } void KisConfig::setStabilizerDelayedPaint(bool value) { m_cfg.writeEntry("stabilizerDelayedPaint", value); } QString KisConfig::customFFMpegPath(bool defaultValue) const { return defaultValue ? QString() : m_cfg.readEntry("ffmpegExecutablePath", QString()); } void KisConfig::setCustomFFMpegPath(const QString &value) const { m_cfg.writeEntry("ffmpegExecutablePath", value); } bool KisConfig::showBrushHud(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("showBrushHud", false); } void KisConfig::setShowBrushHud(bool value) { m_cfg.writeEntry("showBrushHud", value); } QString KisConfig::brushHudSetting(bool defaultValue) const { QString defaultDoc = "\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n"; return defaultValue ? defaultDoc : m_cfg.readEntry("brushHudSettings", defaultDoc); } void KisConfig::setBrushHudSetting(const QString &value) const { m_cfg.writeEntry("brushHudSettings", value); } bool KisConfig::calculateAnimationCacheInBackground(bool defaultValue) const { return defaultValue ? true : m_cfg.readEntry("calculateAnimationCacheInBackground", true); } void KisConfig::setCalculateAnimationCacheInBackground(bool value) { m_cfg.writeEntry("calculateAnimationCacheInBackground", value); } QColor KisConfig::defaultAssistantsColor(bool defaultValue) const { static const QColor defaultColor = QColor(176, 176, 176, 255); return defaultValue ? defaultColor : m_cfg.readEntry("defaultAssistantsColor", defaultColor); } void KisConfig::setDefaultAssistantsColor(const QColor &color) const { m_cfg.writeEntry("defaultAssistantsColor", color); } bool KisConfig::autoSmoothBezierCurves(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("autoSmoothBezierCurves", false); } void KisConfig::setAutoSmoothBezierCurves(bool value) { m_cfg.writeEntry("autoSmoothBezierCurves", value); } bool KisConfig::activateTransformToolAfterPaste(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("activateTransformToolAfterPaste", false); } void KisConfig::setActivateTransformToolAfterPaste(bool value) { m_cfg.writeEntry("activateTransformToolAfterPaste", value); } +KisConfig::RootSurfaceFormat KisConfig::rootSurfaceFormat(bool defaultValue) const +{ + const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); + QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); + + return rootSurfaceFormat(&kritarc, defaultValue); +} + +void KisConfig::setRootSurfaceFormat(KisConfig::RootSurfaceFormat value) +{ + const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); + QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); + + setRootSurfaceFormat(&kritarc, value); +} + +KisConfig::RootSurfaceFormat KisConfig::rootSurfaceFormat(QSettings *displayrc, bool defaultValue) +{ + QString textValue = "bt709-g22"; + + if (!defaultValue) { + textValue = displayrc->value("rootSurfaceFormat", textValue).toString(); + } + + return textValue == "bt709-g10" ? BT709_G10 : + textValue == "bt2020-pq" ? BT2020_PQ : + BT709_G22; +} + +void KisConfig::setRootSurfaceFormat(QSettings *displayrc, KisConfig::RootSurfaceFormat value) +{ + const QString textValue = + value == BT709_G10 ? "bt709-g10" : + value == BT2020_PQ ? "bt2020-pq" : + "bt709-g22"; + + displayrc->setValue("rootSurfaceFormat", textValue); +} + #include #include void KisConfig::writeKoColor(const QString& name, const KoColor& color) const { QDomDocument doc = QDomDocument(name); QDomElement el = doc.createElement(name); doc.appendChild(el); color.toXML(doc, el); m_cfg.writeEntry(name, doc.toString()); } //ported from kispropertiesconfig. KoColor KisConfig::readKoColor(const QString& name, const KoColor& color) const { QDomDocument doc; if (!m_cfg.readEntry(name).isNull()) { doc.setContent(m_cfg.readEntry(name)); QDomElement e = doc.documentElement().firstChild().toElement(); return KoColor::fromXML(e, Integer16BitsColorDepthID.id()); } else { QString blackColor = "\n\n \n\n"; doc.setContent(blackColor); QDomElement e = doc.documentElement().firstChild().toElement(); return KoColor::fromXML(e, Integer16BitsColorDepthID.id()); } return color; } diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h index eb7aa92606..77146b6438 100644 --- a/libs/ui/kis_config.h +++ b/libs/ui/kis_config.h @@ -1,616 +1,627 @@ /* * Copyright (c) 2002 Patrick Julien * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CONFIG_H_ #define KIS_CONFIG_H_ #include #include #include #include #include #include #include #include #include "kritaui_export.h" class KoColorProfile; class KoColorSpace; class KisSnapConfig; +class QSettings; class KRITAUI_EXPORT KisConfig { public: /** * @brief KisConfig create a kisconfig object * @param readOnly if true, there will be no call to sync when the object is deleted. * Any KisConfig object created in a thread must be read-only. */ KisConfig(bool readOnly); ~KisConfig(); bool disableTouchOnCanvas(bool defaultValue = false) const; void setDisableTouchOnCanvas(bool value) const; bool useProjections(bool defaultValue = false) const; void setUseProjections(bool useProj) const; bool undoEnabled(bool defaultValue = false) const; void setUndoEnabled(bool undo) const; int undoStackLimit(bool defaultValue = false) const; void setUndoStackLimit(int limit) const; bool useCumulativeUndoRedo(bool defaultValue = false) const; void setCumulativeUndoRedo(bool value); double stackT1(bool defaultValue = false) const; void setStackT1(int T1); double stackT2(bool defaultValue = false) const; void setStackT2(int T2); int stackN(bool defaultValue = false) const; void setStackN(int N); qint32 defImageWidth(bool defaultValue = false) const; void defImageWidth(qint32 width) const; qint32 defImageHeight(bool defaultValue = false) const; void defImageHeight(qint32 height) const; qreal defImageResolution(bool defaultValue = false) const; void defImageResolution(qreal res) const; int preferredVectorImportResolutionPPI(bool defaultValue = false) const; void setPreferredVectorImportResolutionPPI(int value) const; /** * @return the id of the default color model used for creating new images. */ QString defColorModel(bool defaultValue = false) const; /** * set the id of the default color model used for creating new images. */ void defColorModel(const QString & model) const; /** * @return the id of the default color depth used for creating new images. */ QString defaultColorDepth(bool defaultValue = false) const; /** * set the id of the default color depth used for creating new images. */ void setDefaultColorDepth(const QString & depth) const; /** * @return the id of the default color profile used for creating new images. */ QString defColorProfile(bool defaultValue = false) const; /** * set the id of the default color profile used for creating new images. */ void defColorProfile(const QString & depth) const; CursorStyle newCursorStyle(bool defaultValue = false) const; void setNewCursorStyle(CursorStyle style); QColor getCursorMainColor(bool defaultValue = false) const; void setCursorMainColor(const QColor& v) const; OutlineStyle newOutlineStyle(bool defaultValue = false) const; void setNewOutlineStyle(OutlineStyle style); QRect colorPreviewRect() const; void setColorPreviewRect(const QRect &rect); /// get the profile the user has selected for the given screen QString monitorProfile(int screen) const; void setMonitorProfile(int screen, const QString & monitorProfile, bool override) const; QString monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue = true) const; void setMonitorForScreen(int screen, const QString& monitor); /// Get the actual profile to be used for the given screen, which is /// either the screen profile set by the color management system or /// the custom monitor profile set by the user, depending on the configuration const KoColorProfile *displayProfile(int screen) const; QString workingColorSpace(bool defaultValue = false) const; void setWorkingColorSpace(const QString & workingColorSpace) const; QString importProfile(bool defaultValue = false) const; void setImportProfile(const QString & importProfile) const; QString printerColorSpace(bool defaultValue = false) const; void setPrinterColorSpace(const QString & printerColorSpace) const; QString printerProfile(bool defaultValue = false) const; void setPrinterProfile(const QString & printerProfile) const; bool useBlackPointCompensation(bool defaultValue = false) const; void setUseBlackPointCompensation(bool useBlackPointCompensation) const; bool allowLCMSOptimization(bool defaultValue = false) const; void setAllowLCMSOptimization(bool allowLCMSOptimization); bool forcePaletteColors(bool defaultValue = false) const; void setForcePaletteColors(bool forcePaletteColors); void writeKoColor(const QString& name, const KoColor& color) const; KoColor readKoColor(const QString& name, const KoColor& color = KoColor()) const; bool showRulers(bool defaultValue = false) const; void setShowRulers(bool rulers) const; bool forceShowSaveMessages(bool defaultValue = true) const; void setForceShowSaveMessages(bool value) const; bool forceShowAutosaveMessages(bool defaultValue = true) const; void setForceShowAutosaveMessages(bool ShowAutosaveMessages) const; bool rulersTrackMouse(bool defaultValue = false) const; void setRulersTrackMouse(bool value) const; qint32 pasteBehaviour(bool defaultValue = false) const; void setPasteBehaviour(qint32 behaviour) const; qint32 monitorRenderIntent(bool defaultValue = false) const; void setRenderIntent(qint32 monitorRenderIntent) const; bool useOpenGL(bool defaultValue = false) const; void setUseOpenGL(bool useOpenGL) const; int openGLFilteringMode(bool defaultValue = false) const; void setOpenGLFilteringMode(int filteringMode); bool useOpenGLTextureBuffer(bool defaultValue = false) const; void setUseOpenGLTextureBuffer(bool useBuffer); bool disableVSync(bool defaultValue = false) const; void setDisableVSync(bool disableVSync); bool showAdvancedOpenGLSettings(bool defaultValue = false) const; bool forceOpenGLFenceWorkaround(bool defaultValue = false) const; int numMipmapLevels(bool defaultValue = false) const; int openGLTextureSize(bool defaultValue = false) const; int textureOverlapBorder() const; quint32 getGridMainStyle(bool defaultValue = false) const; void setGridMainStyle(quint32 v) const; quint32 getGridSubdivisionStyle(bool defaultValue = false) const; void setGridSubdivisionStyle(quint32 v) const; QColor getGridMainColor(bool defaultValue = false) const; void setGridMainColor(const QColor & v) const; QColor getGridSubdivisionColor(bool defaultValue = false) const; void setGridSubdivisionColor(const QColor & v) const; QColor getPixelGridColor(bool defaultValue = false) const; void setPixelGridColor(const QColor & v) const; qreal getPixelGridDrawingThreshold(bool defaultValue = false) const; void setPixelGridDrawingThreshold(qreal v) const; bool pixelGridEnabled(bool defaultValue = false) const; void enablePixelGrid(bool v) const; quint32 guidesLineStyle(bool defaultValue = false) const; void setGuidesLineStyle(quint32 v) const; QColor guidesColor(bool defaultValue = false) const; void setGuidesColor(const QColor & v) const; void loadSnapConfig(KisSnapConfig *config, bool defaultValue = false) const; void saveSnapConfig(const KisSnapConfig &config); qint32 checkSize(bool defaultValue = false) const; void setCheckSize(qint32 checkSize) const; bool scrollCheckers(bool defaultValue = false) const; void setScrollingCheckers(bool scollCheckers) const; QColor checkersColor1(bool defaultValue = false) const; void setCheckersColor1(const QColor & v) const; QColor checkersColor2(bool defaultValue = false) const; void setCheckersColor2(const QColor & v) const; QColor canvasBorderColor(bool defaultValue = false) const; void setCanvasBorderColor(const QColor &color) const; bool hideScrollbars(bool defaultValue = false) const; void setHideScrollbars(bool value) const; bool antialiasCurves(bool defaultValue = false) const; void setAntialiasCurves(bool v) const; bool antialiasSelectionOutline(bool defaultValue = false) const; void setAntialiasSelectionOutline(bool v) const; bool showRootLayer(bool defaultValue = false) const; void setShowRootLayer(bool showRootLayer) const; bool showGlobalSelection(bool defaultValue = false) const; void setShowGlobalSelection(bool showGlobalSelection) const; bool showOutlineWhilePainting(bool defaultValue = false) const; void setShowOutlineWhilePainting(bool showOutlineWhilePainting) const; bool forceAlwaysFullSizedOutline(bool defaultValue = false) const; void setForceAlwaysFullSizedOutline(bool value) const; enum SessionOnStartup { SOS_BlankSession, SOS_PreviousSession, SOS_ShowSessionManager }; SessionOnStartup sessionOnStartup(bool defaultValue = false) const; void setSessionOnStartup(SessionOnStartup value); bool saveSessionOnQuit(bool defaultValue) const; void setSaveSessionOnQuit(bool value); qreal outlineSizeMinimum(bool defaultValue = false) const; void setOutlineSizeMinimum(qreal outlineSizeMinimum) const; qreal selectionViewSizeMinimum(bool defaultValue = false) const; void setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const; int autoSaveInterval(bool defaultValue = false) const; void setAutoSaveInterval(int seconds) const; bool backupFile(bool defaultValue = false) const; void setBackupFile(bool backupFile) const; bool showFilterGallery(bool defaultValue = false) const; void setShowFilterGallery(bool showFilterGallery) const; bool showFilterGalleryLayerMaskDialog(bool defaultValue = false) const; void setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const; // OPENGL_SUCCESS, TRY_OPENGL, OPENGL_NOT_TRIED, OPENGL_FAILED QString canvasState(bool defaultValue = false) const; void setCanvasState(const QString& state) const; bool toolOptionsPopupDetached(bool defaultValue = false) const; void setToolOptionsPopupDetached(bool detached) const; bool paintopPopupDetached(bool defaultValue = false) const; void setPaintopPopupDetached(bool detached) const; QString pressureTabletCurve(bool defaultValue = false) const; void setPressureTabletCurve(const QString& curveString) const; bool useWin8PointerInput(bool defaultValue = false) const; void setUseWin8PointerInput(bool value) const; qreal vastScrolling(bool defaultValue = false) const; void setVastScrolling(const qreal factor) const; int presetChooserViewMode(bool defaultValue = false) const; void setPresetChooserViewMode(const int mode) const; int presetIconSize(bool defaultValue = false) const; void setPresetIconSize(const int value) const; bool firstRun(bool defaultValue = false) const; void setFirstRun(const bool firstRun) const; bool clicklessSpacePan(bool defaultValue = false) const; void setClicklessSpacePan(const bool toggle) const; int horizontalSplitLines(bool defaultValue = false) const; void setHorizontalSplitLines(const int numberLines) const; int verticalSplitLines(bool defaultValue = false) const; void setVerticalSplitLines(const int numberLines) const; bool hideDockersFullscreen(bool defaultValue = false) const; void setHideDockersFullscreen(const bool value) const; bool showDockers(bool defaultValue = false) const; void setShowDockers(const bool value) const; bool showStatusBar(bool defaultValue = false) const; void setShowStatusBar(const bool value) const; bool hideMenuFullscreen(bool defaultValue = false) const; void setHideMenuFullscreen(const bool value) const; bool hideScrollbarsFullscreen(bool defaultValue = false) const; void setHideScrollbarsFullscreen(const bool value) const; bool hideStatusbarFullscreen(bool defaultValue = false) const; void setHideStatusbarFullscreen(const bool value) const; bool hideTitlebarFullscreen(bool defaultValue = false) const; void setHideTitlebarFullscreen(const bool value) const; bool hideToolbarFullscreen(bool defaultValue = false) const; void setHideToolbarFullscreen(const bool value) const; bool fullscreenMode(bool defaultValue = false) const; void setFullscreenMode(const bool value) const; QStringList favoriteCompositeOps(bool defaultValue = false) const; void setFavoriteCompositeOps(const QStringList& compositeOps) const; QString exportConfiguration(const QString &filterId, bool defaultValue = false) const; void setExportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const; QString importConfiguration(const QString &filterId, bool defaultValue = false) const; void setImportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const; bool useOcio(bool defaultValue = false) const; void setUseOcio(bool useOCIO) const; int favoritePresets(bool defaultValue = false) const; void setFavoritePresets(const int value); bool levelOfDetailEnabled(bool defaultValue = false) const; void setLevelOfDetailEnabled(bool value); enum OcioColorManagementMode { INTERNAL = 0, OCIO_CONFIG, OCIO_ENVIRONMENT }; OcioColorManagementMode ocioColorManagementMode(bool defaultValue = false) const; void setOcioColorManagementMode(OcioColorManagementMode mode) const; QString ocioConfigurationPath(bool defaultValue = false) const; void setOcioConfigurationPath(const QString &path) const; QString ocioLutPath(bool defaultValue = false) const; void setOcioLutPath(const QString &path) const; int ocioLutEdgeSize(bool defaultValue = false) const; void setOcioLutEdgeSize(int value); bool ocioLockColorVisualRepresentation(bool defaultValue = false) const; void setOcioLockColorVisualRepresentation(bool value); bool useSystemMonitorProfile(bool defaultValue = false) const; void setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const; QString defaultPalette(bool defaultValue = false) const; void setDefaultPalette(const QString& name) const; QString toolbarSlider(int sliderNumber, bool defaultValue = false) const; void setToolbarSlider(int sliderNumber, const QString &slider); int layerThumbnailSize(bool defaultValue = false) const; void setLayerThumbnailSize(int size); bool sliderLabels(bool defaultValue = false) const; void setSliderLabels(bool enabled); QString currentInputProfile(bool defaultValue = false) const; void setCurrentInputProfile(const QString& name); bool presetStripVisible(bool defaultValue = false) const; void setPresetStripVisible(bool visible); bool scratchpadVisible(bool defaultValue = false) const; void setScratchpadVisible(bool visible); bool showSingleChannelAsColor(bool defaultValue = false) const; void setShowSingleChannelAsColor(bool asColor); bool hidePopups(bool defaultValue = false) const; void setHidePopups(bool hidepopups); int numDefaultLayers(bool defaultValue = false) const; void setNumDefaultLayers(int num); quint8 defaultBackgroundOpacity(bool defaultValue = false) const; void setDefaultBackgroundOpacity(quint8 value); QColor defaultBackgroundColor(bool defaultValue = false) const; void setDefaultBackgroundColor(QColor value); enum BackgroundStyle { LAYER = 0, PROJECTION = 1 }; BackgroundStyle defaultBackgroundStyle(bool defaultValue = false) const; void setDefaultBackgroundStyle(BackgroundStyle value); int lineSmoothingType(bool defaultValue = false) const; void setLineSmoothingType(int value); qreal lineSmoothingDistance(bool defaultValue = false) const; void setLineSmoothingDistance(qreal value); qreal lineSmoothingTailAggressiveness(bool defaultValue = false) const; void setLineSmoothingTailAggressiveness(qreal value); bool lineSmoothingSmoothPressure(bool defaultValue = false) const; void setLineSmoothingSmoothPressure(bool value); bool lineSmoothingScalableDistance(bool defaultValue = false) const; void setLineSmoothingScalableDistance(bool value); qreal lineSmoothingDelayDistance(bool defaultValue = false) const; void setLineSmoothingDelayDistance(qreal value); bool lineSmoothingUseDelayDistance(bool defaultValue = false) const; void setLineSmoothingUseDelayDistance(bool value); bool lineSmoothingFinishStabilizedCurve(bool defaultValue = false) const; void setLineSmoothingFinishStabilizedCurve(bool value); bool lineSmoothingStabilizeSensors(bool defaultValue = false) const; void setLineSmoothingStabilizeSensors(bool value); int tabletEventsDelay(bool defaultValue = false) const; void setTabletEventsDelay(int value); bool trackTabletEventLatency(bool defaultValue = false) const; void setTrackTabletEventLatency(bool value); bool testingAcceptCompressedTabletEvents(bool defaultValue = false) const; void setTestingAcceptCompressedTabletEvents(bool value); bool shouldEatDriverShortcuts(bool defaultValue = false) const; bool testingCompressBrushEvents(bool defaultValue = false) const; void setTestingCompressBrushEvents(bool value); const KoColorSpace* customColorSelectorColorSpace(bool defaultValue = false) const; void setCustomColorSelectorColorSpace(const KoColorSpace *cs); bool useDirtyPresets(bool defaultValue = false) const; void setUseDirtyPresets(bool value); bool useEraserBrushSize(bool defaultValue = false) const; void setUseEraserBrushSize(bool value); bool useEraserBrushOpacity(bool defaultValue = false) const; void setUseEraserBrushOpacity(bool value); QColor getMDIBackgroundColor(bool defaultValue = false) const; void setMDIBackgroundColor(const QColor & v) const; QString getMDIBackgroundImage(bool defaultValue = false) const; void setMDIBackgroundImage(const QString & fileName) const; int workaroundX11SmoothPressureSteps(bool defaultValue = false) const; bool showCanvasMessages(bool defaultValue = false) const; void setShowCanvasMessages(bool show); bool compressKra(bool defaultValue = false) const; void setCompressKra(bool compress); bool toolOptionsInDocker(bool defaultValue = false) const; void setToolOptionsInDocker(bool inDocker); bool kineticScrollingEnabled(bool defaultValue = false) const; void setKineticScrollingEnabled(bool enabled); int kineticScrollingGesture(bool defaultValue = false) const; void setKineticScrollingGesture(int kineticScroll); int kineticScrollingSensitivity(bool defaultValue = false) const; void setKineticScrollingSensitivity(int sensitivity); bool kineticScrollingHiddenScrollbars(bool defaultValue = false) const; void setKineticScrollingHideScrollbars(bool scrollbar); void setEnableOpenGLFramerateLogging(bool value) const; bool enableOpenGLFramerateLogging(bool defaultValue = false) const; void setEnableBrushSpeedLogging(bool value) const; bool enableBrushSpeedLogging(bool defaultValue = false) const; void setEnableAmdVectorizationWorkaround(bool value); bool enableAmdVectorizationWorkaround(bool defaultValue = false) const; bool animationDropFrames(bool defaultValue = false) const; void setAnimationDropFrames(bool value); int scrubbingUpdatesDelay(bool defaultValue = false) const; void setScrubbingUpdatesDelay(int value); int scrubbingAudioUpdatesDelay(bool defaultValue = false) const; void setScrubbingAudioUpdatesDelay(int value); int audioOffsetTolerance(bool defaultValue = false) const; void setAudioOffsetTolerance(int value); bool switchSelectionCtrlAlt(bool defaultValue = false) const; void setSwitchSelectionCtrlAlt(bool value); bool convertToImageColorspaceOnImport(bool defaultValue = false) const; void setConvertToImageColorspaceOnImport(bool value); int stabilizerSampleSize(bool defaultValue = false) const; void setStabilizerSampleSize(int value); bool stabilizerDelayedPaint(bool defaultValue = false) const; void setStabilizerDelayedPaint(bool value); QString customFFMpegPath(bool defaultValue = false) const; void setCustomFFMpegPath(const QString &value) const; bool showBrushHud(bool defaultValue = false) const; void setShowBrushHud(bool value); QString brushHudSetting(bool defaultValue = false) const; void setBrushHudSetting(const QString &value) const; bool calculateAnimationCacheInBackground(bool defaultValue = false) const; void setCalculateAnimationCacheInBackground(bool value); QColor defaultAssistantsColor(bool defaultValue = false) const; void setDefaultAssistantsColor(const QColor &color) const; bool autoSmoothBezierCurves(bool defaultValue = false) const; void setAutoSmoothBezierCurves(bool value); bool activateTransformToolAfterPaste(bool defaultValue = false) const; void setActivateTransformToolAfterPaste(bool value); + enum RootSurfaceFormat { + BT709_G22 = 0, + BT709_G10, + BT2020_PQ + }; + RootSurfaceFormat rootSurfaceFormat(bool defaultValue = false) const; + void setRootSurfaceFormat(RootSurfaceFormat value); + + static RootSurfaceFormat rootSurfaceFormat(QSettings *displayrc, bool defaultValue = false); + static void setRootSurfaceFormat(QSettings *displayrc, RootSurfaceFormat value); template void writeEntry(const QString& name, const T& value) { m_cfg.writeEntry(name, value); } template void writeList(const QString& name, const QList& value) { m_cfg.writeEntry(name, value); } template T readEntry(const QString& name, const T& defaultValue=T()) { return m_cfg.readEntry(name, defaultValue); } template QList readList(const QString& name, const QList& defaultValue=QList()) { return m_cfg.readEntry(name, defaultValue); } /// get the profile the color management system has stored for the given screen static const KoColorProfile* getScreenProfile(int screen); private: KisConfig(const KisConfig&); KisConfig& operator=(const KisConfig&) const; private: mutable KConfigGroup m_cfg; bool m_readOnly; }; #endif // KIS_CONFIG_H_ diff --git a/libs/ui/opengl/KisOpenGLModeProber.cpp b/libs/ui/opengl/KisOpenGLModeProber.cpp new file mode 100644 index 0000000000..92cd3bbba8 --- /dev/null +++ b/libs/ui/opengl/KisOpenGLModeProber.cpp @@ -0,0 +1,74 @@ +#include "KisOpenGLModeProber.h" + +#include +Q_GLOBAL_STATIC(KisOpenGLModeProber, s_instance) + + +KisOpenGLModeProber::KisOpenGLModeProber() +{ +} + +KisOpenGLModeProber::~KisOpenGLModeProber() +{ + +} + +KisOpenGLModeProber *KisOpenGLModeProber::instance() +{ + return s_instance; +} + +bool KisOpenGLModeProber::useHDRMode() const +{ + return isFormatHDR(QSurfaceFormat::defaultFormat()); +} + +QSurfaceFormat KisOpenGLModeProber::surfaceformatInUse() const +{ + return QSurfaceFormat::defaultFormat(); +} + +void KisOpenGLModeProber::initSurfaceFormatFromConfig(KisConfig::RootSurfaceFormat config, + QSurfaceFormat *format) +{ + if (config == KisConfig::BT2020_PQ) { + format->setRedBufferSize(10); + format->setGreenBufferSize(10); + format->setBlueBufferSize(10); + format->setAlphaBufferSize(2); + format->setColorSpace(QSurfaceFormat::bt2020PQColorSpace); + } else if (config == KisConfig::BT709_G10) { + format->setRedBufferSize(16); + format->setGreenBufferSize(16); + format->setBlueBufferSize(16); + format->setAlphaBufferSize(16); + format->setColorSpace(QSurfaceFormat::scRGBColorSpace); + } else { + format->setRedBufferSize(8); + format->setGreenBufferSize(8); + format->setBlueBufferSize(8); + format->setAlphaBufferSize(8); + // TODO: check if we can use real sRGB space here + format->setColorSpace(QSurfaceFormat::DefaultColorSpace); + } +} + +bool KisOpenGLModeProber::isFormatHDR(const QSurfaceFormat &format) +{ + bool isBt2020PQ = + format.colorSpace() == QSurfaceFormat::bt2020PQColorSpace && + format.redBufferSize() == 10 && + format.greenBufferSize() == 10 && + format.blueBufferSize() == 10 && + format.alphaBufferSize() == 10; + + bool isBt709G10 = + format.colorSpace() == QSurfaceFormat::scRGBColorSpace && + format.redBufferSize() == 16 && + format.greenBufferSize() == 16 && + format.blueBufferSize() == 16 && + format.alphaBufferSize() == 16; + + + return isBt2020PQ || isBt709G10; +} diff --git a/libs/ui/opengl/KisOpenGLModeProber.h b/libs/ui/opengl/KisOpenGLModeProber.h new file mode 100644 index 0000000000..4efcf4ca34 --- /dev/null +++ b/libs/ui/opengl/KisOpenGLModeProber.h @@ -0,0 +1,25 @@ +#ifndef KISOPENGLMODEPROBER_H +#define KISOPENGLMODEPROBER_H + +#include "kritaui_export.h" +#include "kis_config.h" +#include + +class KRITAUI_EXPORT KisOpenGLModeProber +{ +public: + KisOpenGLModeProber(); + ~KisOpenGLModeProber(); + + static KisOpenGLModeProber* instance(); + + bool useHDRMode() const; + QSurfaceFormat surfaceformatInUse() const; + +public: + static void initSurfaceFormatFromConfig(KisConfig::RootSurfaceFormat config, + QSurfaceFormat *format); + static bool isFormatHDR(const QSurfaceFormat &format); +}; + +#endif // KISOPENGLMODEPROBER_H diff --git a/libs/ui/opengl/KisScreenInformationAdapter.cpp b/libs/ui/opengl/KisScreenInformationAdapter.cpp new file mode 100644 index 0000000000..b5b6fbf9f0 --- /dev/null +++ b/libs/ui/opengl/KisScreenInformationAdapter.cpp @@ -0,0 +1,245 @@ +#include "KisScreenInformationAdapter.h" + +#include "kis_debug.h" +#include + +//#include +#include +#include +#include +#include +#include +#include +#include "EGL/egl.h" +#include "EGL/eglext.h" + + +namespace { +struct EGLException { + EGLException() {} + EGLException(const QString &what) : m_what(what) {} + + QString what() const { + return m_what; + } + +private: + QString m_what; +}; + +template +void getProcAddressSafe(QOpenGLContext *context, const char *funcName, FuncType &func) +{ + func = reinterpret_cast(context->getProcAddress(funcName)); + if (!func) { + throw EGLException(QString("failed to fetch function %1").arg(funcName)); + } +} + +typedef const char *(EGLAPIENTRYP PFNEGLQUERYSTRINGPROC) (EGLDisplay dpy, EGLint name); +} + + +struct KisScreenInformationAdapter::Private +{ + void initialize(QOpenGLContext *context); + + QOpenGLContext *context; + QString errorString; + + Microsoft::WRL::ComPtr dxgiAdapter; +}; + +KisScreenInformationAdapter::KisScreenInformationAdapter(QOpenGLContext *context) + : m_d(new Private) +{ + m_d->initialize(context); +} + +KisScreenInformationAdapter::~KisScreenInformationAdapter() +{ +} + +void KisScreenInformationAdapter::Private::initialize(QOpenGLContext *newContext) +{ + context = newContext; + errorString.clear(); + + try { + + if (!context->isOpenGLES()) { + throw EGLException("the context is not OpenGL ES"); + } + + PFNEGLQUERYSTRINGPROC queryString = nullptr; + getProcAddressSafe(context, "eglQueryString", queryString); + + const char* client_extensions = queryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + const QList extensions = QByteArray(client_extensions).split(' '); + + if (!extensions.contains("EGL_ANGLE_platform_angle_d3d") || + !extensions.contains("EGL_ANGLE_device_creation_d3d11")) { + + throw EGLException("the context is not Angle + D3D11"); + } + + PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT = nullptr; + PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT = nullptr; + + getProcAddressSafe(context, "eglQueryDisplayAttribEXT", queryDisplayAttribEXT); + getProcAddressSafe(context, "eglQueryDeviceAttribEXT", queryDeviceAttribEXT); + + QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface(); + EGLDisplay display = reinterpret_cast(nativeInterface->nativeResourceForContext("egldisplay", context)); + + if (!display) { + throw EGLException( + QString("couldn't request EGLDisplay handle, display = 0x%1").arg(uintptr_t(display), 0, 16)); + } + + EGLAttrib value = 0; + EGLBoolean result = false; + + result = queryDisplayAttribEXT(display, EGL_DEVICE_EXT, &value); + + if (!result || value == EGL_NONE) { + throw EGLException( + QString("couldn't request EGLDeviceEXT handle, result = 0x%1, value = 0x%2") + .arg(result, 0, 16).arg(value, 0, 16)); + } + + EGLDeviceEXT device = reinterpret_cast(value); + + result = queryDeviceAttribEXT(device, EGL_D3D11_DEVICE_ANGLE, &value); + + if (!result || value == EGL_NONE) { + throw EGLException( + QString("couldn't request ID3D11Device pointer, result = 0x%1, value = 0x%2") + .arg(result, 0, 16).arg(value, 0, 16)); + } + ID3D11Device *deviceD3D = reinterpret_cast(value); + + { + HRESULT result = 0; + + Microsoft::WRL::ComPtr dxgiDevice; + result = deviceD3D->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + + if (FAILED(result)) { + throw EGLException( + QString("couldn't request IDXGIDevice pointer, result = 0x%1").arg(result, 0, 16)); + } + + Microsoft::WRL::ComPtr dxgiAdapter; + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter1), (void**)&dxgiAdapter); + + if (FAILED(result)) { + throw EGLException( + QString("couldn't request IDXGIAdapter1 pointer, result = 0x%1").arg(result, 0, 16)); + } + + this->dxgiAdapter = dxgiAdapter; + } + } catch (EGLException &e) { + this->context = 0; + this->errorString = e.what(); + this->dxgiAdapter.Reset(); + } +} + +bool KisScreenInformationAdapter::isValid() const +{ + return m_d->context && m_d->dxgiAdapter; +} + +QString KisScreenInformationAdapter::errorString() const +{ + return m_d->errorString; +} + +KisScreenInformationAdapter::ScreenInfo KisScreenInformationAdapter::infoForScreen(QScreen *screen) const +{ + ScreenInfo info; + + QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface(); + HMONITOR monitor = reinterpret_cast(nativeInterface->nativeResourceForScreen("handle", screen)); + + if (!monitor) { + qWarning("%s: failed to get HMONITOR handle for screen: screen = 0x%X, monitor = 0x%X", + __PRETTY_FUNCTION__, screen, monitor); + } + + UINT i = 0; + Microsoft::WRL::ComPtr currentOutput; + + while (m_d->dxgiAdapter->EnumOutputs(i, ¤tOutput) != DXGI_ERROR_NOT_FOUND) + { + + HRESULT result = 0; + Microsoft::WRL::ComPtr output6; + result = currentOutput.As(&output6); + + if (output6) { + DXGI_OUTPUT_DESC1 desc; + result = output6->GetDesc1(&desc); + + if (desc.Monitor == monitor) { + info.screen = screen; + info.bitsPerColor = desc.BitsPerColor; + info.redPrimary[0] = desc.RedPrimary[0]; + info.redPrimary[1] = desc.RedPrimary[1]; + info.greenPrimary[0] = desc.GreenPrimary[0]; + info.greenPrimary[1] = desc.GreenPrimary[1]; + info.bluePrimary[0] = desc.BluePrimary[0]; + info.bluePrimary[1] = desc.BluePrimary[1]; + info.whitePoint[0] = desc.WhitePoint[0]; + info.whitePoint[1] = desc.WhitePoint[1]; + info.minLuminance = desc.MinLuminance; + info.maxLuminance = desc.MaxLuminance; + info.maxFullFrameLuminance = desc.MaxFullFrameLuminance; + + info.colorSpace = QSurfaceFormat::DefaultColorSpace; + + if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) { + info.colorSpace = QSurfaceFormat::sRGBColorSpace; + } else if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) { + info.colorSpace = QSurfaceFormat::scRGBColorSpace; + } else if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) { + info.colorSpace = QSurfaceFormat::bt2020PQColorSpace; + } else { + qWarning("WARNING: unknown display color space! 0x%X", desc.ColorSpace); + } + + break; + } + } + + i++; + } + + return info; +} + +QDebug operator<<(QDebug dbg, const KisScreenInformationAdapter::ScreenInfo &info) +{ + QDebugStateSaver saver(dbg); + + if (info.isValid()) { + dbg.nospace() << "ScreenInfo(" + << "screen " << info.screen + << ", bitsPerColor " << info.bitsPerColor + << ", colorSpace " << info.colorSpace + << ", redPrimary " << "(" << info.redPrimary[0] << ", " << info.redPrimary[1] << ")" + << ", greenPrimary " << "(" << info.greenPrimary[0] << ", " << info.greenPrimary[1] << ")" + << ", bluePrimary " << "(" << info.bluePrimary[0] << ", " << info.bluePrimary[1] << ")" + << ", whitePoint " << "(" << info.whitePoint[0] << ", " << info.whitePoint[1] << ")" + << ", minLuminance " << info.minLuminance + << ", maxLuminance " << info.maxLuminance + << ", maxFullFrameLuminance " << info.maxFullFrameLuminance + << ')'; + } else { + dbg.nospace() << "ScreenInfo()"; + } + + return dbg; +} diff --git a/libs/ui/opengl/KisScreenInformationAdapter.h b/libs/ui/opengl/KisScreenInformationAdapter.h new file mode 100644 index 0000000000..fd6334d81b --- /dev/null +++ b/libs/ui/opengl/KisScreenInformationAdapter.h @@ -0,0 +1,48 @@ +#ifndef KISSCREENINFORMATIONADAPTER_H +#define KISSCREENINFORMATIONADAPTER_H + +#include "kritaui_export.h" +#include +#include + +class QScreen; +class QOpenGLContext; + +class KRITAUI_EXPORT KisScreenInformationAdapter +{ +public: + struct ScreenInfo { + QScreen *screen = 0; + int bitsPerColor = 0; + QSurfaceFormat::ColorSpace colorSpace = QSurfaceFormat::DefaultColorSpace; + qreal redPrimary[2] = {0, 0}; + qreal greenPrimary[2] = {0, 0}; + qreal bluePrimary[2] = {0, 0}; + qreal whitePoint[2] = {0, 0}; + qreal minLuminance = 0; + qreal maxLuminance = 0; + qreal maxFullFrameLuminance = 0; + + bool isValid() const { + return screen; + } + }; + +public: + KisScreenInformationAdapter(QOpenGLContext *context); + ~KisScreenInformationAdapter(); + + bool isValid() const; + QString errorString() const; + + ScreenInfo infoForScreen(QScreen *screen) const; + + +private: + struct Private; + const QScopedPointer m_d; +}; + +QDebug operator<<(QDebug, const KisScreenInformationAdapter::ScreenInfo &); + +#endif // KISSCREENINFORMATIONADAPTER_H diff --git a/libs/ui/opengl/kis_opengl.cpp b/libs/ui/opengl/kis_opengl.cpp index 7137aee4c8..984c635dfd 100644 --- a/libs/ui/opengl/kis_opengl.cpp +++ b/libs/ui/opengl/kis_opengl.cpp @@ -1,309 +1,312 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "opengl/kis_opengl.h" #include "opengl/kis_opengl_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include "KisOpenGLModeProber.h" #include #ifndef GL_RENDERER # define GL_RENDERER 0x1F01 #endif using namespace KisOpenGLPrivate; namespace { bool defaultFormatIsSet = false; bool isDebugEnabled = false; bool isDebugSynchronous = false; boost::optional openGLCheckResult; bool NeedsFenceWorkaround = false; bool NeedsPixmapCacheWorkaround = false; QString debugText("OpenGL Info\n **OpenGL not initialized**"); QVector openglWarningStrings; void openglOnMessageLogged(const QOpenGLDebugMessage& debugMessage) { qDebug() << "OpenGL:" << debugMessage; } } KisOpenGLPrivate::OpenGLCheckResult::OpenGLCheckResult(QOpenGLContext &context) { if (!context.isValid()) { return; } QOpenGLFunctions *funcs = context.functions(); // funcs is ready to be used m_rendererString = QString(reinterpret_cast(funcs->glGetString(GL_RENDERER))); m_driverVersionString = QString(reinterpret_cast(funcs->glGetString(GL_VERSION))); m_glMajorVersion = context.format().majorVersion(); m_glMinorVersion = context.format().minorVersion(); m_supportsDeprecatedFunctions = (context.format().options() & QSurfaceFormat::DeprecatedFunctions); m_isOpenGLES = context.isOpenGLES(); } void KisOpenGLPrivate::appendOpenGLWarningString(KLocalizedString warning) { openglWarningStrings << warning; } bool KisOpenGLPrivate::isDefaultFormatSet() { return defaultFormatIsSet; } void KisOpenGL::initialize() { if (openGLCheckResult) return; KIS_SAFE_ASSERT_RECOVER(defaultFormatIsSet) { qWarning() << "Default OpenGL format was not set before calling KisOpenGL::initialize. This might be a BUG!"; setDefaultFormat(); } // we need a QSurface active to get our GL functions from the context QWindow surface; surface.setSurfaceType( QSurface::OpenGLSurface ); surface.create(); QOpenGLContext context; if (!context.create()) { qDebug() << "OpenGL context cannot be created"; return; } if (!context.isValid()) { qDebug() << "OpenGL context is not valid"; return; } if (!context.makeCurrent(&surface)) { qDebug() << "OpenGL context cannot be made current"; return; } QOpenGLFunctions *funcs = context.functions(); openGLCheckResult = OpenGLCheckResult(context); debugText.clear(); QDebug debugOut(&debugText); debugOut << "OpenGL Info"; debugOut << "\n Vendor: " << reinterpret_cast(funcs->glGetString(GL_VENDOR)); debugOut << "\n Renderer: " << openGLCheckResult->rendererString(); debugOut << "\n Version: " << openGLCheckResult->driverVersionString(); debugOut << "\n Shading language: " << reinterpret_cast(funcs->glGetString(GL_SHADING_LANGUAGE_VERSION)); debugOut << "\n Requested format: " << QSurfaceFormat::defaultFormat(); debugOut << "\n Current format: " << context.format(); debugOut.nospace(); debugOut << "\n Version: " << openGLCheckResult->glMajorVersion() << "." << openGLCheckResult->glMinorVersion(); debugOut.resetFormat(); debugOut << "\n Supports deprecated functions" << openGLCheckResult->supportsDeprecatedFunctions(); debugOut << "\n is OpenGL ES:" << openGLCheckResult->isOpenGLES(); appendPlatformOpenGLDebugText(debugOut); dbgOpenGL.noquote() << debugText; } void KisOpenGL::initializeContext(QOpenGLContext *ctx) { KisConfig cfg(true); initialize(); dbgUI << "OpenGL: Opening new context"; if (isDebugEnabled) { // Passing ctx for ownership management only, not specifying context. // QOpenGLDebugLogger only function on the current active context. // FIXME: Do we need to make sure ctx is the active context? QOpenGLDebugLogger* openglLogger = new QOpenGLDebugLogger(ctx); if (openglLogger->initialize()) { qDebug() << "QOpenGLDebugLogger is initialized. Check whether you get a message below."; QObject::connect(openglLogger, &QOpenGLDebugLogger::messageLogged, &openglOnMessageLogged); openglLogger->startLogging(isDebugSynchronous ? QOpenGLDebugLogger::SynchronousLogging : QOpenGLDebugLogger::AsynchronousLogging); openglLogger->logMessage(QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("QOpenGLDebugLogger is logging."))); } else { qDebug() << "QOpenGLDebugLogger cannot be initialized."; delete openglLogger; } } // Double check we were given the version we requested QSurfaceFormat format = ctx->format(); QOpenGLFunctions *f = ctx->functions(); f->initializeOpenGLFunctions(); QFile log(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/krita-opengl.txt"); log.open(QFile::WriteOnly); QString vendor((const char*)f->glGetString(GL_VENDOR)); log.write(vendor.toLatin1()); log.write(", "); log.write(openGLCheckResult->rendererString().toLatin1()); log.write(", "); QString version((const char*)f->glGetString(GL_VERSION)); log.write(version.toLatin1()); log.close(); // Check if we have a bugged driver that needs fence workaround bool isOnX11 = false; #ifdef HAVE_X11 isOnX11 = true; #endif if ((isOnX11 && openGLCheckResult->rendererString().startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) { NeedsFenceWorkaround = true; } /** * NVidia + Qt's openGL don't play well together and one cannot * draw a pixmap on a widget more than once in one rendering cycle. * * It can be workarounded by drawing strictly via QPixmapCache and * only when the pixmap size in bigger than doubled size of the * display framebuffer. That is for 8-bit HD display, you should have * a cache bigger than 16 MiB. Don't ask me why. (DK) * * See bug: https://bugs.kde.org/show_bug.cgi?id=361709 * * TODO: check if this workaround is still needed after merging * Qt5+openGL3 branch. */ if (vendor.toUpper().contains("NVIDIA")) { NeedsPixmapCacheWorkaround = true; const QRect screenSize = QApplication::desktop()->screenGeometry(); const int minCacheSize = 20 * 1024; const int cacheSize = 2048 + 2 * 4 * screenSize.width() * screenSize.height() / 1024; //KiB QPixmapCache::setCacheLimit(qMax(minCacheSize, cacheSize)); } } const QString &KisOpenGL::getDebugText() { initialize(); return debugText; } QStringList KisOpenGL::getOpenGLWarnings() { QStringList strings; Q_FOREACH (const KLocalizedString &item, openglWarningStrings) { strings << item.toString(); } return strings; } // XXX Temporary function to allow LoD on OpenGL3 without triggering // all of the other 3.2 functionality, can be removed once we move to Qt5.7 bool KisOpenGL::supportsLoD() { initialize(); return openGLCheckResult->supportsLoD(); } bool KisOpenGL::hasOpenGL3() { initialize(); return openGLCheckResult->hasOpenGL3(); } bool KisOpenGL::hasOpenGLES() { initialize(); return openGLCheckResult->isOpenGLES(); } bool KisOpenGL::supportsFenceSync() { initialize(); return openGLCheckResult->supportsFenceSync(); } bool KisOpenGL::needsFenceWorkaround() { initialize(); return NeedsFenceWorkaround; } bool KisOpenGL::needsPixmapCacheWorkaround() { initialize(); return NeedsPixmapCacheWorkaround; } -void KisOpenGL::setDefaultFormat(bool enableDebug, bool debugSynchronous) +void KisOpenGL::setDefaultFormat(bool enableDebug, bool debugSynchronous, QSettings *kritadisplayrc) { if (defaultFormatIsSet) { return; } defaultFormatIsSet = true; QSurfaceFormat format; #ifdef Q_OS_OSX format.setVersion(3, 2); format.setProfile(QSurfaceFormat::CoreProfile); #else // XXX This can be removed once we move to Qt5.7 format.setVersion(3, 0); format.setProfile(QSurfaceFormat::CompatibilityProfile); format.setOptions(QSurfaceFormat::DeprecatedFunctions); #endif format.setDepthBufferSize(24); format.setStencilBufferSize(8); - format.setRedBufferSize(16); - format.setGreenBufferSize(16); - format.setBlueBufferSize(16); - format.setColorSpace(QSurfaceFormat::scRGBColorSpace); + + if (kritadisplayrc) { + KisConfig::RootSurfaceFormat rootSurfaceFormat = KisConfig::rootSurfaceFormat(kritadisplayrc); + KisOpenGLModeProber::initSurfaceFormatFromConfig(rootSurfaceFormat, &format); + } + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); format.setSwapInterval(0); // Disable vertical refresh syncing isDebugEnabled = enableDebug; if (enableDebug) { format.setOption(QSurfaceFormat::DebugContext, true); isDebugSynchronous = debugSynchronous; qDebug() << "QOpenGLDebugLogger will be enabled, synchronous:" << debugSynchronous; } QSurfaceFormat::setDefaultFormat(format); } bool KisOpenGL::hasOpenGL() { return openGLCheckResult->isSupportedVersion(); } diff --git a/libs/ui/opengl/kis_opengl.h b/libs/ui/opengl/kis_opengl.h index 0bf157b2d1..136d953e63 100644 --- a/libs/ui/opengl/kis_opengl.h +++ b/libs/ui/opengl/kis_opengl.h @@ -1,117 +1,118 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_H_ #define KIS_OPENGL_H_ /** @file */ #include #include #include "kritaui_export.h" class QOpenGLContext; class QString; class QStringList; +class QSettings; /** * This class manages a shared OpenGL context and provides utility * functions for checking capabilities and error reporting. */ class KRITAUI_EXPORT KisOpenGL { public: enum FilterMode { NearestFilterMode, // nearest BilinearFilterMode, // linear, no mipmap TrilinearFilterMode, // LINEAR_MIPMAP_LINEAR HighQualityFiltering // Mipmaps + custom shader }; public: #ifdef Q_OS_WIN enum OpenGLRenderer { RendererNone = 0x00, RendererAuto = 0x01, RendererDesktopGL = 0x02, RendererAngle = 0x04, }; Q_DECLARE_FLAGS(OpenGLRenderers, OpenGLRenderer); // Probe the Windows platform abstraction layer for OpenGL detection static void probeWindowsQpaOpenGL(int argc, char **argv, QString userRendererConfigString); static OpenGLRenderer getCurrentOpenGLRenderer(); static OpenGLRenderer getQtPreferredOpenGLRenderer(); static OpenGLRenderers getSupportedOpenGLRenderers(); static OpenGLRenderer getUserOpenGLRendererConfig(); static OpenGLRenderer getNextUserOpenGLRendererConfig(); static void setNextUserOpenGLRendererConfig(OpenGLRenderer renderer); static QString convertOpenGLRendererToConfig(OpenGLRenderer renderer); static OpenGLRenderer convertConfigToOpenGLRenderer(QString renderer); #endif /// Request OpenGL version 3.2 static void initialize(); /// Initialize shared OpenGL context static void initializeContext(QOpenGLContext *ctx); static const QString &getDebugText(); static QStringList getOpenGLWarnings(); static bool supportsLoD(); static bool hasOpenGL3(); static bool hasOpenGLES(); /// Check for OpenGL static bool hasOpenGL(); /** * @brief supportsFilter * @return True if OpenGL provides fence sync methods. */ static bool supportsFenceSync(); /** * Returns true if we have a driver that has bugged support to sync objects (a fence) * and false otherwise. */ static bool needsFenceWorkaround(); /** * @see a comment in initializeContext() */ static bool needsPixmapCacheWorkaround(); - static void setDefaultFormat(bool enableDebug = false, bool debugSynchronous = false); + static void setDefaultFormat(bool enableDebug = false, bool debugSynchronous = false, QSettings *kritadisplayrc = 0); private: KisOpenGL(); }; #ifdef Q_OS_WIN Q_DECLARE_OPERATORS_FOR_FLAGS(KisOpenGL::OpenGLRenderers); #endif #endif // KIS_OPENGL_H_ diff --git a/libs/ui/opengl/kis_opengl_canvas2.cpp b/libs/ui/opengl/kis_opengl_canvas2.cpp index 5fe376b799..2b6dc61fe4 100644 --- a/libs/ui/opengl/kis_opengl_canvas2.cpp +++ b/libs/ui/opengl/kis_opengl_canvas2.cpp @@ -1,961 +1,965 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2006-2013 * Copyright (C) 2015 Michael Abrahams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define GL_GLEXT_PROTOTYPES #include "opengl/kis_opengl_canvas2.h" #include "opengl/kis_opengl_canvas2_p.h" #include "opengl/kis_opengl_shader_loader.h" #include "opengl/kis_opengl_canvas_debugger.h" #include "canvas/kis_canvas2.h" #include "canvas/kis_coordinates_converter.h" #include "canvas/kis_display_filter.h" #include "canvas/kis_display_color_converter.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include #include #include #include +#include "KisOpenGLModeProber.h" #ifndef Q_OS_OSX #include #endif #define NEAR_VAL -1000.0 #define FAR_VAL 1000.0 #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 static bool OPENGL_SUCCESS = false; struct KisOpenGLCanvas2::Private { public: ~Private() { delete displayShader; delete checkerShader; delete solidColorShader; Sync::deleteSync(glSyncObject); } bool canvasInitialized{false}; KisOpenGLImageTexturesSP openGLImageTextures; KisOpenGLShaderLoader shaderLoader; KisShaderProgram *displayShader{0}; KisShaderProgram *checkerShader{0}; KisShaderProgram *solidColorShader{0}; bool displayShaderCompiledWithDisplayFilterSupport{false}; GLfloat checkSizeScale; bool scrollCheckers; QSharedPointer displayFilter; KisOpenGL::FilterMode filterMode; bool proofingConfigIsUpdated=false; GLsync glSyncObject{0}; bool wrapAroundMode{false}; // Stores a quad for drawing the canvas QOpenGLVertexArrayObject quadVAO; QOpenGLBuffer quadBuffers[2]; // Stores data for drawing tool outlines QOpenGLVertexArrayObject outlineVAO; QOpenGLBuffer lineBuffer; QVector3D vertices[6]; QVector2D texCoords[6]; #ifndef Q_OS_OSX QOpenGLFunctions_2_1 *glFn201; #endif qreal pixelGridDrawingThreshold; bool pixelGridEnabled; QColor gridColor; QColor cursorColor; bool lodSwitchInProgress = false; int xToColWithWrapCompensation(int x, const QRect &imageRect) { int firstImageColumn = openGLImageTextures->xToCol(imageRect.left()); int lastImageColumn = openGLImageTextures->xToCol(imageRect.right()); int colsPerImage = lastImageColumn - firstImageColumn + 1; int numWraps = floor(qreal(x) / imageRect.width()); int remainder = x - imageRect.width() * numWraps; return colsPerImage * numWraps + openGLImageTextures->xToCol(remainder); } int yToRowWithWrapCompensation(int y, const QRect &imageRect) { int firstImageRow = openGLImageTextures->yToRow(imageRect.top()); int lastImageRow = openGLImageTextures->yToRow(imageRect.bottom()); int rowsPerImage = lastImageRow - firstImageRow + 1; int numWraps = floor(qreal(y) / imageRect.height()); int remainder = y - imageRect.height() * numWraps; return rowsPerImage * numWraps + openGLImageTextures->yToRow(remainder); } }; KisOpenGLCanvas2::KisOpenGLCanvas2(KisCanvas2 *canvas, KisCoordinatesConverter *coordinatesConverter, QWidget *parent, KisImageWSP image, KisDisplayColorConverter *colorConverter) : QOpenGLWidget(parent) , KisCanvasWidgetBase(canvas, coordinatesConverter) , d(new Private()) { KisConfig cfg(false); cfg.setCanvasState("OPENGL_STARTED"); d->openGLImageTextures = KisOpenGLImageTextures::getImageTextures(image, colorConverter->monitorProfile(), colorConverter->renderingIntent(), colorConverter->conversionFlags()); setAcceptDrops(true); setAutoFillBackground(false); setFocusPolicy(Qt::StrongFocus); setAttribute(Qt::WA_NoSystemBackground, true); #ifdef Q_OS_OSX setAttribute(Qt::WA_AcceptTouchEvents, false); #else setAttribute(Qt::WA_AcceptTouchEvents, true); #endif setAttribute(Qt::WA_InputMethodEnabled, false); setAttribute(Qt::WA_DontCreateNativeAncestors, true); - setTextureFormat(GL_RGBA16F); + + if (KisOpenGLModeProber::instance()->useHDRMode()) { + setTextureFormat(GL_RGBA16F); + } setDisplayFilterImpl(colorConverter->displayFilter(), true); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); connect(KisConfigNotifier::instance(), SIGNAL(pixelGridModeChanged()), SLOT(slotPixelGridModeChanged())); slotConfigChanged(); slotPixelGridModeChanged(); cfg.writeEntry("canvasState", "OPENGL_SUCCESS"); } KisOpenGLCanvas2::~KisOpenGLCanvas2() { delete d; } void KisOpenGLCanvas2::setDisplayFilter(QSharedPointer displayFilter) { setDisplayFilterImpl(displayFilter, false); } void KisOpenGLCanvas2::setDisplayFilterImpl(QSharedPointer displayFilter, bool initializing) { bool needsInternalColorManagement = !displayFilter || displayFilter->useInternalColorManagement(); bool needsFullRefresh = d->openGLImageTextures->setInternalColorManagementActive(needsInternalColorManagement); d->displayFilter = displayFilter; if (!initializing && needsFullRefresh) { canvas()->startUpdateInPatches(canvas()->image()->bounds()); } else if (!initializing) { canvas()->updateCanvas(); } } void KisOpenGLCanvas2::setWrapAroundViewingMode(bool value) { d->wrapAroundMode = value; update(); } inline void rectToVertices(QVector3D* vertices, const QRectF &rc) { vertices[0] = QVector3D(rc.left(), rc.bottom(), 0.f); vertices[1] = QVector3D(rc.left(), rc.top(), 0.f); vertices[2] = QVector3D(rc.right(), rc.bottom(), 0.f); vertices[3] = QVector3D(rc.left(), rc.top(), 0.f); vertices[4] = QVector3D(rc.right(), rc.top(), 0.f); vertices[5] = QVector3D(rc.right(), rc.bottom(), 0.f); } inline void rectToTexCoords(QVector2D* texCoords, const QRectF &rc) { texCoords[0] = QVector2D(rc.left(), rc.bottom()); texCoords[1] = QVector2D(rc.left(), rc.top()); texCoords[2] = QVector2D(rc.right(), rc.bottom()); texCoords[3] = QVector2D(rc.left(), rc.top()); texCoords[4] = QVector2D(rc.right(), rc.top()); texCoords[5] = QVector2D(rc.right(), rc.bottom()); } void KisOpenGLCanvas2::initializeGL() { KisOpenGL::initializeContext(context()); initializeOpenGLFunctions(); #ifndef Q_OS_OSX if (!KisOpenGL::hasOpenGLES()) { d->glFn201 = context()->versionFunctions(); if (!d->glFn201) { warnUI << "Cannot obtain QOpenGLFunctions_2_1, glLogicOp cannot be used"; } } else { d->glFn201 = nullptr; } #endif KisConfig cfg(true); d->openGLImageTextures->setProofingConfig(canvas()->proofingConfiguration()); d->openGLImageTextures->initGL(context()->functions()); d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); initializeShaders(); // If we support OpenGL 3.2, then prepare our VAOs and VBOs for drawing if (KisOpenGL::hasOpenGL3()) { d->quadVAO.create(); d->quadVAO.bind(); glEnableVertexAttribArray(PROGRAM_VERTEX_ATTRIBUTE); glEnableVertexAttribArray(PROGRAM_TEXCOORD_ATTRIBUTE); // Create the vertex buffer object, it has 6 vertices with 3 components d->quadBuffers[0].create(); d->quadBuffers[0].setUsagePattern(QOpenGLBuffer::StaticDraw); d->quadBuffers[0].bind(); d->quadBuffers[0].allocate(d->vertices, 6 * 3 * sizeof(float)); glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, 0); // Create the texture buffer object, it has 6 texture coordinates with 2 components d->quadBuffers[1].create(); d->quadBuffers[1].setUsagePattern(QOpenGLBuffer::StaticDraw); d->quadBuffers[1].bind(); d->quadBuffers[1].allocate(d->texCoords, 6 * 2 * sizeof(float)); glVertexAttribPointer(PROGRAM_TEXCOORD_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0); // Create the outline buffer, this buffer will store the outlines of // tools and will frequently change data d->outlineVAO.create(); d->outlineVAO.bind(); glEnableVertexAttribArray(PROGRAM_VERTEX_ATTRIBUTE); // The outline buffer has a StreamDraw usage pattern, because it changes constantly d->lineBuffer.create(); d->lineBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); d->lineBuffer.bind(); glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, 0); } Sync::init(context()); d->canvasInitialized = true; } /** * Loads all shaders and reports compilation problems */ void KisOpenGLCanvas2::initializeShaders() { KIS_SAFE_ASSERT_RECOVER_RETURN(!d->canvasInitialized); delete d->checkerShader; delete d->solidColorShader; d->checkerShader = 0; d->solidColorShader = 0; try { d->checkerShader = d->shaderLoader.loadCheckerShader(); d->solidColorShader = d->shaderLoader.loadSolidColorShader(); } catch (const ShaderLoaderException &e) { reportFailedShaderCompilation(e.what()); } initializeDisplayShader(); } void KisOpenGLCanvas2::initializeDisplayShader() { KIS_SAFE_ASSERT_RECOVER_RETURN(!d->canvasInitialized); bool useHiQualityFiltering = d->filterMode == KisOpenGL::HighQualityFiltering; delete d->displayShader; d->displayShader = 0; try { d->displayShader = d->shaderLoader.loadDisplayShader(d->displayFilter, useHiQualityFiltering); d->displayShaderCompiledWithDisplayFilterSupport = d->displayFilter; } catch (const ShaderLoaderException &e) { reportFailedShaderCompilation(e.what()); } } /** * Displays a message box telling the user that * shader compilation failed and turns off OpenGL. */ void KisOpenGLCanvas2::reportFailedShaderCompilation(const QString &context) { KisConfig cfg(false); qDebug() << "Shader Compilation Failure: " << context; QMessageBox::critical(this, i18nc("@title:window", "Krita"), i18n("Krita could not initialize the OpenGL canvas:\n\n%1\n\n Krita will disable OpenGL and close now.", context), QMessageBox::Close); cfg.setUseOpenGL(false); cfg.setCanvasState("OPENGL_FAILED"); } void KisOpenGLCanvas2::resizeGL(int width, int height) { coordinatesConverter()->setCanvasWidgetSize(QSize(width, height)); paintGL(); } void KisOpenGLCanvas2::paintGL() { if (!OPENGL_SUCCESS) { KisConfig cfg(false); cfg.writeEntry("canvasState", "OPENGL_PAINT_STARTED"); } KisOpenglCanvasDebugger::instance()->nofityPaintRequested(); renderCanvasGL(); if (d->glSyncObject) { Sync::deleteSync(d->glSyncObject); } d->glSyncObject = Sync::getSync(); QPainter gc(this); renderDecorations(&gc); gc.end(); if (!OPENGL_SUCCESS) { KisConfig cfg(false); cfg.writeEntry("canvasState", "OPENGL_SUCCESS"); OPENGL_SUCCESS = true; } } void KisOpenGLCanvas2::paintToolOutline(const QPainterPath &path) { if (!d->solidColorShader->bind()) { return; } // setup the mvp transformation QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(coordinatesConverter()->flakeToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->solidColorShader->setUniformValue(d->solidColorShader->location(Uniform::ModelViewProjection), modelMatrix); if (!KisOpenGL::hasOpenGLES()) { glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_COLOR_LOGIC_OP); #ifndef Q_OS_OSX if (d->glFn201) { d->glFn201->glLogicOp(GL_XOR); } #else glLogicOp(GL_XOR); #endif } else { glEnable(GL_BLEND); glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ZERO, GL_ONE, GL_ONE); } d->solidColorShader->setUniformValue( d->solidColorShader->location(Uniform::FragmentColor), QVector4D(d->cursorColor.redF(), d->cursorColor.greenF(), d->cursorColor.blueF(), 1.0f)); // Paint the tool outline if (KisOpenGL::hasOpenGL3()) { d->outlineVAO.bind(); d->lineBuffer.bind(); } // Convert every disjointed subpath to a polygon and draw that polygon QList subPathPolygons = path.toSubpathPolygons(); for (int i = 0; i < subPathPolygons.size(); i++) { const QPolygonF& polygon = subPathPolygons.at(i); QVector vertices; vertices.resize(polygon.count()); for (int j = 0; j < polygon.count(); j++) { QPointF p = polygon.at(j); vertices[j].setX(p.x()); vertices[j].setY(p.y()); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.allocate(vertices.constData(), 3 * vertices.size() * sizeof(float)); } else { d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, vertices.constData()); } glDrawArrays(GL_LINE_STRIP, 0, vertices.size()); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.release(); d->outlineVAO.release(); } if (!KisOpenGL::hasOpenGLES()) { glDisable(GL_COLOR_LOGIC_OP); } else { glDisable(GL_BLEND); } d->solidColorShader->release(); } bool KisOpenGLCanvas2::isBusy() const { const bool isBusyStatus = Sync::syncStatus(d->glSyncObject) == Sync::Unsignaled; KisOpenglCanvasDebugger::instance()->nofitySyncStatus(isBusyStatus); return isBusyStatus; } void KisOpenGLCanvas2::setLodResetInProgress(bool value) { d->lodSwitchInProgress = value; } void KisOpenGLCanvas2::drawCheckers() { if (!d->checkerShader) { return; } KisCoordinatesConverter *converter = coordinatesConverter(); QTransform textureTransform; QTransform modelTransform; QRectF textureRect; QRectF modelRect; QRectF viewportRect = !d->wrapAroundMode ? converter->imageRectInViewportPixels() : converter->widgetToViewport(this->rect()); if (!canvas()->renderingLimit().isEmpty()) { const QRect vrect = converter->imageToViewport(canvas()->renderingLimit()).toAlignedRect(); viewportRect &= vrect; } converter->getOpenGLCheckersInfo(viewportRect, &textureTransform, &modelTransform, &textureRect, &modelRect, d->scrollCheckers); textureTransform *= QTransform::fromScale(d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE, d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE); if (!d->checkerShader->bind()) { qWarning() << "Could not bind checker shader"; return; } QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(modelTransform); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::ModelViewProjection), modelMatrix); QMatrix4x4 textureMatrix(textureTransform); d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::TextureMatrix), textureMatrix); //Setup the geometry for rendering if (KisOpenGL::hasOpenGL3()) { rectToVertices(d->vertices, modelRect); d->quadBuffers[0].bind(); d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float)); rectToTexCoords(d->texCoords, textureRect); d->quadBuffers[1].bind(); d->quadBuffers[1].write(0, d->texCoords, 2 * 6 * sizeof(float)); } else { rectToVertices(d->vertices, modelRect); d->checkerShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->checkerShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices); rectToTexCoords(d->texCoords, textureRect); d->checkerShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); d->checkerShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords); } // render checkers glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, d->openGLImageTextures->checkerTexture()); glDrawArrays(GL_TRIANGLES, 0, 6); glBindTexture(GL_TEXTURE_2D, 0); d->checkerShader->release(); glBindBuffer(GL_ARRAY_BUFFER, 0); } void KisOpenGLCanvas2::drawGrid() { if (!d->solidColorShader->bind()) { return; } QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->solidColorShader->setUniformValue(d->solidColorShader->location(Uniform::ModelViewProjection), modelMatrix); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); d->solidColorShader->setUniformValue( d->solidColorShader->location(Uniform::FragmentColor), QVector4D(d->gridColor.redF(), d->gridColor.greenF(), d->gridColor.blueF(), 0.5f)); if (KisOpenGL::hasOpenGL3()) { d->outlineVAO.bind(); d->lineBuffer.bind(); } QRectF widgetRect(0,0, width(), height()); QRectF widgetRectInImagePixels = coordinatesConverter()->documentToImage(coordinatesConverter()->widgetToDocument(widgetRect)); QRect wr = widgetRectInImagePixels.toAlignedRect(); if (!d->wrapAroundMode) { wr &= d->openGLImageTextures->storedImageBounds(); } QPoint topLeftCorner = wr.topLeft(); QPoint bottomRightCorner = wr.bottomRight() + QPoint(1, 1); QVector grid; for (int i = topLeftCorner.x(); i <= bottomRightCorner.x(); ++i) { grid.append(QVector3D(i, topLeftCorner.y(), 0)); grid.append(QVector3D(i, bottomRightCorner.y(), 0)); } for (int i = topLeftCorner.y(); i <= bottomRightCorner.y(); ++i) { grid.append(QVector3D(topLeftCorner.x(), i, 0)); grid.append(QVector3D(bottomRightCorner.x(), i, 0)); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.allocate(grid.constData(), 3 * grid.size() * sizeof(float)); } else { d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, grid.constData()); } glDrawArrays(GL_LINES, 0, grid.size()); if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.release(); d->outlineVAO.release(); } d->solidColorShader->release(); glDisable(GL_BLEND); } void KisOpenGLCanvas2::drawImage() { if (!d->displayShader) { return; } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); KisCoordinatesConverter *converter = coordinatesConverter(); d->displayShader->bind(); QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(converter->imageToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->displayShader->setUniformValue(d->displayShader->location(Uniform::ModelViewProjection), modelMatrix); QMatrix4x4 textureMatrix; textureMatrix.setToIdentity(); d->displayShader->setUniformValue(d->displayShader->location(Uniform::TextureMatrix), textureMatrix); QRectF widgetRect(0,0, width(), height()); QRectF widgetRectInImagePixels = converter->documentToImage(converter->widgetToDocument(widgetRect)); const QRect renderingLimit = canvas()->renderingLimit(); if (!renderingLimit.isEmpty()) { widgetRectInImagePixels &= renderingLimit; } qreal scaleX, scaleY; converter->imagePhysicalScale(&scaleX, &scaleY); d->displayShader->setUniformValue(d->displayShader->location(Uniform::ViewportScale), (GLfloat) scaleX); d->displayShader->setUniformValue(d->displayShader->location(Uniform::TexelSize), (GLfloat) d->openGLImageTextures->texelSize()); QRect ir = d->openGLImageTextures->storedImageBounds(); QRect wr = widgetRectInImagePixels.toAlignedRect(); if (!d->wrapAroundMode) { // if we don't want to paint wrapping images, just limit the // processing area, and the code will handle all the rest wr &= ir; } int firstColumn = d->xToColWithWrapCompensation(wr.left(), ir); int lastColumn = d->xToColWithWrapCompensation(wr.right(), ir); int firstRow = d->yToRowWithWrapCompensation(wr.top(), ir); int lastRow = d->yToRowWithWrapCompensation(wr.bottom(), ir); int minColumn = d->openGLImageTextures->xToCol(ir.left()); int maxColumn = d->openGLImageTextures->xToCol(ir.right()); int minRow = d->openGLImageTextures->yToRow(ir.top()); int maxRow = d->openGLImageTextures->yToRow(ir.bottom()); int imageColumns = maxColumn - minColumn + 1; int imageRows = maxRow - minRow + 1; for (int col = firstColumn; col <= lastColumn; col++) { for (int row = firstRow; row <= lastRow; row++) { int effectiveCol = col; int effectiveRow = row; QPointF tileWrappingTranslation; if (effectiveCol > maxColumn || effectiveCol < minColumn) { int translationStep = floor(qreal(col) / imageColumns); int originCol = translationStep * imageColumns; effectiveCol = col - originCol; tileWrappingTranslation.rx() = translationStep * ir.width(); } if (effectiveRow > maxRow || effectiveRow < minRow) { int translationStep = floor(qreal(row) / imageRows); int originRow = translationStep * imageRows; effectiveRow = row - originRow; tileWrappingTranslation.ry() = translationStep * ir.height(); } KisTextureTile *tile = d->openGLImageTextures->getTextureTileCR(effectiveCol, effectiveRow); if (!tile) { warnUI << "OpenGL: Trying to paint texture tile but it has not been created yet."; continue; } /* * We create a float rect here to workaround Qt's * "history reasons" in calculation of right() * and bottom() coordinates of integer rects. */ QRectF textureRect; QRectF modelRect; if (renderingLimit.isEmpty()) { textureRect = tile->tileRectInTexturePixels(); modelRect = tile->tileRectInImagePixels().translated(tileWrappingTranslation.x(), tileWrappingTranslation.y()); } else { const QRect limitedTileRect = tile->tileRectInImagePixels() & renderingLimit; textureRect = tile->imageRectInTexturePixels(limitedTileRect); modelRect = limitedTileRect.translated(tileWrappingTranslation.x(), tileWrappingTranslation.y()); } //Setup the geometry for rendering if (KisOpenGL::hasOpenGL3()) { rectToVertices(d->vertices, modelRect); d->quadBuffers[0].bind(); d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float)); rectToTexCoords(d->texCoords, textureRect); d->quadBuffers[1].bind(); d->quadBuffers[1].write(0, d->texCoords, 2 * 6 * sizeof(float)); } else { rectToVertices(d->vertices, modelRect); d->displayShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->displayShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices); rectToTexCoords(d->texCoords, textureRect); d->displayShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); d->displayShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords); } if (d->displayFilter) { glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_3D, d->displayFilter->lutTexture()); d->displayShader->setUniformValue(d->displayShader->location(Uniform::Texture1), 1); } glActiveTexture(GL_TEXTURE0); const int currentLodPlane = tile->bindToActiveTexture(d->lodSwitchInProgress); if (d->displayShader->location(Uniform::FixedLodLevel) >= 0) { d->displayShader->setUniformValue(d->displayShader->location(Uniform::FixedLodLevel), (GLfloat) currentLodPlane); } if (currentLodPlane > 0) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else if (SCALE_MORE_OR_EQUAL_TO(scaleX, scaleY, 2.0)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); switch(d->filterMode) { case KisOpenGL::NearestFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); break; case KisOpenGL::BilinearFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); break; case KisOpenGL::TrilinearFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); break; case KisOpenGL::HighQualityFiltering: if (SCALE_LESS_THAN(scaleX, scaleY, 0.5)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } break; } } glDrawArrays(GL_TRIANGLES, 0, 6); } } glBindTexture(GL_TEXTURE_2D, 0); d->displayShader->release(); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_BLEND); } void KisOpenGLCanvas2::slotConfigChanged() { KisConfig cfg(true); d->checkSizeScale = KisOpenGLImageTextures::BACKGROUND_TEXTURE_CHECK_SIZE / static_cast(cfg.checkSize()); d->scrollCheckers = cfg.scrollCheckers(); d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); d->openGLImageTextures->updateConfig(cfg.useOpenGLTextureBuffer(), cfg.numMipmapLevels()); d->filterMode = (KisOpenGL::FilterMode) cfg.openGLFilteringMode(); d->cursorColor = cfg.getCursorMainColor(); notifyConfigChanged(); } void KisOpenGLCanvas2::slotPixelGridModeChanged() { KisConfig cfg(true); d->pixelGridDrawingThreshold = cfg.getPixelGridDrawingThreshold(); d->pixelGridEnabled = cfg.pixelGridEnabled(); d->gridColor = cfg.getPixelGridColor(); update(); } QVariant KisOpenGLCanvas2::inputMethodQuery(Qt::InputMethodQuery query) const { return processInputMethodQuery(query); } void KisOpenGLCanvas2::inputMethodEvent(QInputMethodEvent *event) { processInputMethodEvent(event); } void KisOpenGLCanvas2::renderCanvasGL() { // Draw the border (that is, clear the whole widget to the border color) QColor widgetBackgroundColor = borderColor(); glClearColor(widgetBackgroundColor.redF(), widgetBackgroundColor.greenF(), widgetBackgroundColor.blueF(), 1.0); glClear(GL_COLOR_BUFFER_BIT); if ((d->displayFilter && d->displayFilter->updateShader()) || (bool(d->displayFilter) != d->displayShaderCompiledWithDisplayFilterSupport)) { KIS_SAFE_ASSERT_RECOVER_NOOP(d->canvasInitialized); d->canvasInitialized = false; // TODO: check if actually needed? initializeDisplayShader(); d->canvasInitialized = true; } if (KisOpenGL::hasOpenGL3()) { d->quadVAO.bind(); } drawCheckers(); drawImage(); if ((coordinatesConverter()->effectiveZoom() > d->pixelGridDrawingThreshold - 0.00001) && d->pixelGridEnabled) { drawGrid(); } if (KisOpenGL::hasOpenGL3()) { d->quadVAO.release(); } } void KisOpenGLCanvas2::renderDecorations(QPainter *painter) { QRect boundingRect = coordinatesConverter()->imageRectInWidgetPixels().toAlignedRect(); drawDecorations(*painter, boundingRect); } void KisOpenGLCanvas2::setDisplayProfile(KisDisplayColorConverter *colorConverter) { d->openGLImageTextures->setMonitorProfile(colorConverter->monitorProfile(), colorConverter->renderingIntent(), colorConverter->conversionFlags()); } void KisOpenGLCanvas2::channelSelectionChanged(const QBitArray &channelFlags) { d->openGLImageTextures->setChannelFlags(channelFlags); } void KisOpenGLCanvas2::finishResizingImage(qint32 w, qint32 h) { if (d->canvasInitialized) { d->openGLImageTextures->slotImageSizeChanged(w, h); } } KisUpdateInfoSP KisOpenGLCanvas2::startUpdateCanvasProjection(const QRect & rc, const QBitArray &channelFlags) { d->openGLImageTextures->setChannelFlags(channelFlags); if (canvas()->proofingConfigUpdated()) { d->openGLImageTextures->setProofingConfig(canvas()->proofingConfiguration()); canvas()->setProofingConfigUpdated(false); } return d->openGLImageTextures->updateCache(rc, d->openGLImageTextures->image()); } QRect KisOpenGLCanvas2::updateCanvasProjection(KisUpdateInfoSP info) { // See KisQPainterCanvas::updateCanvasProjection for more info bool isOpenGLUpdateInfo = dynamic_cast(info.data()); if (isOpenGLUpdateInfo) { d->openGLImageTextures->recalculateCache(info, d->lodSwitchInProgress); } return QRect(); // FIXME: Implement dirty rect for OpenGL } QVector KisOpenGLCanvas2::updateCanvasProjection(const QVector &infoObjects) { #ifdef Q_OS_OSX /** * On OSX openGL defferent (shared) contexts have different execution queues. * It means that the textures uploading and their painting can be easily reordered. * To overcome the issue, we should ensure that the textures are uploaded in the * same openGL context as the painting is done. */ QOpenGLContext *oldContext = QOpenGLContext::currentContext(); QSurface *oldSurface = oldContext ? oldContext->surface() : 0; this->makeCurrent(); #endif QVector result = KisCanvasWidgetBase::updateCanvasProjection(infoObjects); #ifdef Q_OS_OSX if (oldContext) { oldContext->makeCurrent(oldSurface); } else { this->doneCurrent(); } #endif return result; } bool KisOpenGLCanvas2::callFocusNextPrevChild(bool next) { return focusNextPrevChild(next); } KisOpenGLImageTexturesSP KisOpenGLCanvas2::openGLImageTextures() const { return d->openGLImageTextures; } diff --git a/plugins/dockers/smallcolorselector/kis_small_color_widget.cc b/plugins/dockers/smallcolorselector/kis_small_color_widget.cc index ef85e15ebf..c4f52e8ded 100644 --- a/plugins/dockers/smallcolorselector/kis_small_color_widget.cc +++ b/plugins/dockers/smallcolorselector/kis_small_color_widget.cc @@ -1,458 +1,490 @@ /* * Copyright (c) 2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_small_color_widget.h" #include #include "kis_slider_spin_box.h" #include #include "kis_signal_compressor.h" #include #include #include "kis_debug.h" #include "kis_assert.h" #include #include "KisGLImageF16.h" #include "KisGLImageWidget.h" #include "KisClickableGLImageWidget.h" #include "kis_display_color_converter.h" #include "kis_signal_auto_connection.h" #include #include #include "kis_fixed_paint_device.h" +#include struct KisSmallColorWidget::Private { qreal hue; // 0 ... 1.0 qreal value; // 0 ... 1.0 qreal saturation; // 0 ... 1.0 bool updateAllowed; QTimer updateTimer; KisClickableGLImageWidget *hueWidget; KisClickableGLImageWidget *valueWidget; KisSignalCompressor *resizeUpdateCompressor; KisSignalCompressor *valueSliderUpdateCompressor; int huePreferredHeight = 32; KisSliderSpinBox *dynamicRange = 0; qreal currentRelativeDynamicRange = 1.0; KisDisplayColorConverter *displayColorConverter = 0; KisSignalAutoConnectionsStore colorConverterConnections; bool hasHDR = false; + bool hasHardwareHDR = false; qreal effectiveRelativeDynamicRange() const { return hasHDR ? currentRelativeDynamicRange : 1.0; } }; KisSmallColorWidget::KisSmallColorWidget(QWidget* parent) : QWidget(parent), d(new Private) { d->hue = 0.0; d->value = 0; d->saturation = 0; d->updateAllowed = true; d->updateTimer.setInterval(1); d->updateTimer.setSingleShot(true); connect(&(d->updateTimer), SIGNAL(timeout()), this, SLOT(update())); d->resizeUpdateCompressor = new KisSignalCompressor(200, KisSignalCompressor::FIRST_ACTIVE, this); connect(d->resizeUpdateCompressor, SIGNAL(timeout()), SLOT(slotUpdatePalettes())); d->valueSliderUpdateCompressor = new KisSignalCompressor(100, KisSignalCompressor::FIRST_ACTIVE, this); connect(d->valueSliderUpdateCompressor, SIGNAL(timeout()), SLOT(updateSVPalette())); - const QSurfaceFormat::ColorSpace colorSpace = QSurfaceFormat::scRGBColorSpace; + const QSurfaceFormat::ColorSpace colorSpace = QSurfaceFormat::DefaultColorSpace; d->hueWidget = new KisClickableGLImageWidget(colorSpace, this); d->hueWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); d->hueWidget->setHandlePaintingStrategy(new KisClickableGLImageWidget::VerticalLineHandleStrategy); connect(d->hueWidget, SIGNAL(selected(const QPointF&)), SLOT(slotHueSliderChanged(const QPointF&))); d->valueWidget = new KisClickableGLImageWidget(colorSpace, this); d->valueWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); d->valueWidget->setHandlePaintingStrategy(new KisClickableGLImageWidget::CircularHandleStrategy); connect(d->valueWidget, SIGNAL(selected(const QPointF&)), SLOT(slotValueSliderChanged(const QPointF&))); - d->dynamicRange = new KisSliderSpinBox(this); - d->dynamicRange->setRange(80, 10000); - d->dynamicRange->setExponentRatio(3.0); - d->dynamicRange->setSingleStep(1); - d->dynamicRange->setPageStep(100); - d->dynamicRange->setSuffix("cd/m²"); - d->dynamicRange->setValue(80.0 * d->currentRelativeDynamicRange); - connect(d->dynamicRange, SIGNAL(valueChanged(int)), SLOT(slotUpdateDynamicRange(int))); + d->hasHardwareHDR = KisOpenGLModeProber::instance()->useHDRMode(); + + if (d->hasHardwareHDR) { + d->dynamicRange = new KisSliderSpinBox(this); + d->dynamicRange->setRange(80, 10000); + d->dynamicRange->setExponentRatio(3.0); + d->dynamicRange->setSingleStep(1); + d->dynamicRange->setPageStep(100); + d->dynamicRange->setSuffix("cd/m²"); + d->dynamicRange->setValue(80.0 * d->currentRelativeDynamicRange); + connect(d->dynamicRange, SIGNAL(valueChanged(int)), SLOT(slotUpdateDynamicRange(int))); + } QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(d->hueWidget, 0); layout->addWidget(d->valueWidget, 1); - layout->addSpacing(16); - layout->addWidget(d->dynamicRange, 0); + + if (d->dynamicRange) { + layout->addSpacing(16); + layout->addWidget(d->dynamicRange, 0); + } setLayout(layout); slotUpdatePalettes(); } KisSmallColorWidget::~KisSmallColorWidget() { delete d; } void KisSmallColorWidget::setHue(qreal h) { h = qBound(0.0, h, 1.0); d->hue = h; tellColorChanged(); d->valueSliderUpdateCompressor->start(); d->updateTimer.start(); } void KisSmallColorWidget::setHSV(qreal h, qreal s, qreal v, bool notifyChanged) { h = qBound(0.0, h, 1.0); s = qBound(0.0, s, 1.0); v = qBound(0.0, v, 1.0); bool newH = !qFuzzyCompare(d->hue, h); d->hue = h; d->value = v; d->saturation = s; // TODO: remove and make acyclic! if (notifyChanged) { tellColorChanged(); } if(newH) { d->valueSliderUpdateCompressor->start(); } d->updateTimer.start(); } void KisSmallColorWidget::setColor(const KoColor &color) { if (!d->updateAllowed) return; - KIS_SAFE_ASSERT_RECOVER(d->hasHDR == d->dynamicRange->isEnabled()) { + KIS_SAFE_ASSERT_RECOVER(!d->dynamicRange || d->hasHDR == d->dynamicRange->isEnabled()) { slotDisplayConfigurationChanged(); } + KIS_SAFE_ASSERT_RECOVER_RETURN(!d->hasHDR || d->hasHardwareHDR); + const KoColorSpace *cs = d->displayColorConverter->paintingColorSpace(); if (cs->colorModelId() != RGBAColorModelID) { cs = KoColorSpaceRegistry::instance()->rgb8(); } KoColor newColor(color); newColor.convertTo(cs); QVector channels(4); cs->normalisedChannelsValue(newColor.data(), channels); float r, g, b; if (cs->colorDepthId() == Integer8BitsColorDepthID) { r = channels[2]; g = channels[1]; b = channels[0]; } else { r = channels[0]; g = channels[1]; b = channels[2]; } if (d->hasHDR) { qreal rangeCoeff = d->effectiveRelativeDynamicRange(); if (rangeCoeff < r || rangeCoeff < g || rangeCoeff < b) { rangeCoeff = std::max({r, g, b}) * 1.10f; const int newMaxLuminance = qRound(80.0 * rangeCoeff); slotUpdateDynamicRange(newMaxLuminance); d->dynamicRange->setValue(newMaxLuminance); } r /= rangeCoeff; g /= rangeCoeff; b /= rangeCoeff; } else { r = qBound(0.0f, r, 1.0f); g = qBound(0.0f, g, 1.0f); b = qBound(0.0f, b, 1.0f); } float denormHue, saturation, value; RGBToHSV(r, g, b, &denormHue, &saturation, &value); d->hueWidget->setNormalizedPos(QPointF(denormHue / 360.0, 0.0)); d->valueWidget->setNormalizedPos(QPointF(saturation, 1.0 - value)); setHSV(denormHue / 360.0, saturation, value, false); } void KisSmallColorWidget::slotUpdatePalettes() { updateHuePalette(); updateSVPalette(); } namespace { struct FillHPolicy { static inline void getRGB(qreal hue, float xPortionCoeff, float yPortionCoeff, int x, int y, float *r, float *g, float *b) { HSVToRGB(xPortionCoeff * x * 360.0f, 1.0, 1.0, r, g, b); } }; struct FillSVPolicy { static inline void getRGB(qreal hue, float xPortionCoeff, float yPortionCoeff, int x, int y, float *r, float *g, float *b) { HSVToRGB(hue * 360.0, xPortionCoeff * x, 1.0 - yPortionCoeff * y, r, g, b); } }; } template void KisSmallColorWidget::uploadPaletteData(KisGLImageWidget *widget, const QSize &size) { KisGLImageF16 image(size); const float xPortionCoeff = 1.0 / image.width(); const float yPortionCoeff = 1.0 / image.height(); const float rangeCoeff = d->effectiveRelativeDynamicRange(); - const KoColorSpace *cs = d->displayColorConverter ? d->displayColorConverter->paintingColorSpace() : 0; - - if (!cs || cs->colorModelId() != RGBAColorModelID) { - cs = KoColorSpaceRegistry::instance()-> - colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id()); - } else if (cs->colorDepthId() != Float32BitsColorDepthID) { - cs = KoColorSpaceRegistry::instance()-> - colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), cs->profile()); + const KoColorSpace *generationColorSpace = d->displayColorConverter ? d->displayColorConverter->paintingColorSpace() : 0; + const KoColorSpace *outputColorSpace = KoColorSpaceRegistry::instance()-> + colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), + KoColorSpaceRegistry::instance()->rgb8()->profile()); + + QSurfaceFormat::ColorSpace surfaceColorSpace = KisOpenGLModeProber::instance()->surfaceformatInUse().colorSpace(); + + if (surfaceColorSpace == QSurfaceFormat::sRGBColorSpace) { + // use the default one! + } else if (surfaceColorSpace == QSurfaceFormat::scRGBColorSpace) { + // p709-g10 + outputColorSpace = KoColorSpaceRegistry::instance()-> + colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id()); + } else if (surfaceColorSpace == QSurfaceFormat::bt2020PQColorSpace) { + qWarning() << "Small Color Selector: output for p2020-pq is not fully supported"; } + if (!generationColorSpace || generationColorSpace->colorModelId() != RGBAColorModelID) { + generationColorSpace = outputColorSpace; + } else if (generationColorSpace->colorDepthId() != Float32BitsColorDepthID) { + generationColorSpace = KoColorSpaceRegistry::instance()-> + colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), generationColorSpace->profile()); + } - if (!d->displayColorConverter || d->displayColorConverter->canSkipDisplayConversion(cs)) { + if (!d->displayColorConverter || d->displayColorConverter->canSkipDisplayConversion(generationColorSpace)) { half *pixelPtr = image.data(); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { Imf::Rgba &pxl = reinterpret_cast(*pixelPtr); float r, g, b; FillPolicy::getRGB(d->hue, xPortionCoeff, yPortionCoeff, x, y, &r, &g, &b); pxl.r = r * rangeCoeff; pxl.g = g * rangeCoeff; pxl.b = b * rangeCoeff; pxl.a = 1.0; pixelPtr += 4; } } } else { KIS_SAFE_ASSERT_RECOVER_RETURN(d->displayColorConverter); - KisFixedPaintDeviceSP device = new KisFixedPaintDevice(cs); + KisFixedPaintDeviceSP device = new KisFixedPaintDevice(generationColorSpace); device->setRect(QRect(QPoint(), image.size())); device->reallocateBufferWithoutInitialization(); float *devicePtr = reinterpret_cast(device->data()); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { FillPolicy::getRGB(d->hue, xPortionCoeff, yPortionCoeff, x, y, devicePtr, devicePtr + 1, devicePtr + 2); devicePtr[0] *= rangeCoeff; devicePtr[1] *= rangeCoeff; devicePtr[2] *= rangeCoeff; devicePtr[3] = 1.0; devicePtr += 4; } } d->displayColorConverter->applyDisplayFilteringF32(device); + /** + * TODO: theoretically, we could skip this step, because the surface format + * should coincide with the one of the image + */ + device->convertTo(outputColorSpace); + half *imagePtr = image.data(); devicePtr = reinterpret_cast(device->data()); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { imagePtr[0] = devicePtr[0]; imagePtr[1] = devicePtr[1]; imagePtr[2] = devicePtr[2]; imagePtr[3] = devicePtr[3]; devicePtr += 4; imagePtr += 4; } } } widget->loadImage(image); } void KisSmallColorWidget::updateHuePalette() { uploadPaletteData(d->hueWidget, QSize(width(), d->huePreferredHeight)); } void KisSmallColorWidget::updateSVPalette() { // TODO: make preferred size be different from image size, // so that we could create the image of the exact size we need //KisGLImageF16 image(d->valueWidget->size()); uploadPaletteData(d->valueWidget, size()); } void KisSmallColorWidget::slotHueSliderChanged(const QPointF &pos) { const qreal newHue = pos.x(); if (!qFuzzyCompare(newHue, d->hue)) { setHue(newHue); } } void KisSmallColorWidget::slotValueSliderChanged(const QPointF &pos) { const qreal newSaturation = pos.x(); const qreal newValue = 1.0 - pos.y(); if (!qFuzzyCompare(newSaturation, d->saturation) || !qFuzzyCompare(newValue, d->value)) { setHSV(d->hue, newSaturation, newValue); } } void KisSmallColorWidget::slotUpdateDynamicRange(int maxLuminance) { const qreal oldRange = d->currentRelativeDynamicRange; const qreal newRange = qreal(maxLuminance) / 80.0; if (qFuzzyCompare(oldRange, newRange)) return; float r, g, b; float denormHue = d->hue * 360.0; float saturation = d->saturation; float value = d->value; HSVToRGB(denormHue, saturation, value, &r, &g, &b); const qreal transformCoeff = newRange / oldRange; r = qBound(0.0, r * transformCoeff, 1.0); g = qBound(0.0, g * transformCoeff, 1.0); b = qBound(0.0, b * transformCoeff, 1.0); RGBToHSV(r, g, b, &denormHue, &saturation, &value); d->currentRelativeDynamicRange = newRange; slotUpdatePalettes(); setHSV(denormHue / 360.0, saturation, value, false); d->hueWidget->setNormalizedPos(QPointF(denormHue / 360.0, 0)); d->valueWidget->setNormalizedPos(QPointF(saturation, 1.0 - value)); } void KisSmallColorWidget::setDisplayColorConverter(KisDisplayColorConverter *converter) { d->colorConverterConnections.clear(); d->displayColorConverter = converter; if (d->displayColorConverter) { d->colorConverterConnections.addConnection( d->displayColorConverter, SIGNAL(displayConfigurationChanged()), this, SLOT(slotDisplayConfigurationChanged())); } slotDisplayConfigurationChanged(); } void KisSmallColorWidget::slotDisplayConfigurationChanged() { d->hasHDR = false; - if (d->displayColorConverter) { + if (d->hasHardwareHDR && d->displayColorConverter) { const KoColorSpace *cs = d->displayColorConverter->paintingColorSpace(); d->hasHDR = cs->colorModelId() == RGBAColorModelID && (cs->colorDepthId() == Float16BitsColorDepthID || cs->colorDepthId() == Float32BitsColorDepthID || cs->colorDepthId() == Float64BitsColorDepthID); } - d->dynamicRange->setEnabled(d->hasHDR); + if (d->dynamicRange) { + d->dynamicRange->setEnabled(d->hasHDR); + } d->hueWidget->setUseHandleOpacity(!d->hasHDR); d->valueWidget->setUseHandleOpacity(!d->hasHDR); slotUpdatePalettes(); // TODO: also set the currently selected color again } void KisSmallColorWidget::tellColorChanged() { d->updateAllowed = false; float r, g, b; HSVToRGB(d->hue * 360.0, d->saturation, d->value, &r, &g, &b); if (d->hasHDR) { const float rangeCoeff = d->effectiveRelativeDynamicRange(); r *= rangeCoeff; g *= rangeCoeff; b *= rangeCoeff; } const KoColorSpace *cs = d->displayColorConverter->paintingColorSpace(); if (cs->colorModelId() != RGBAColorModelID) { cs = KoColorSpaceRegistry::instance()->rgb8(); } QVector values(4); if (cs->colorDepthId() == Integer8BitsColorDepthID) { values[0] = b; values[1] = g; values[2] = r; values[3] = 1.0f; } else { values[0] = r; values[1] = g; values[2] = b; values[3] = 1.0f; } KoColor c(cs); cs->fromNormalisedChannelsValue(c.data(), values); emit colorChanged(c); d->updateAllowed = true; } void KisSmallColorWidget::resizeEvent(QResizeEvent * event) { QWidget::resizeEvent(event); update(); d->resizeUpdateCompressor->start(); } diff --git a/plugins/tools/basictools/kis_tool_colorpicker.cc b/plugins/tools/basictools/kis_tool_colorpicker.cc index c40bb633d4..9e8e780546 100644 --- a/plugins/tools/basictools/kis_tool_colorpicker.cc +++ b/plugins/tools/basictools/kis_tool_colorpicker.cc @@ -1,358 +1,373 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2018 Emmet & Eoin O'Neill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_colorpicker.h" #include #include #include "kis_cursor.h" #include "KisDocument.h" #include "kis_canvas2.h" #include "KisReferenceImagesLayer.h" #include "KoCanvasBase.h" #include "kis_random_accessor_ng.h" #include "KoResourceServerProvider.h" #include #include "kis_wrapped_rect.h" #include "kis_tool_utils.h" namespace { // GUI ComboBox index constants const int SAMPLE_MERGED = 0; } KisToolColorPicker::KisToolColorPicker(KoCanvasBase *canvas) : KisTool(canvas, KisCursor::pickerCursor()), m_config(new KisToolUtils::ColorPickerConfig) { setObjectName("tool_colorpicker"); m_isActivated = false; m_optionsWidget = 0; m_pickedColor = KoColor(); } KisToolColorPicker::~KisToolColorPicker() { if (m_isActivated) { m_config->save(m_toolActivationSource == KisTool::DefaultActivation); } } void KisToolColorPicker::paint(QPainter &gc, const KoViewConverter &converter) { Q_UNUSED(gc); Q_UNUSED(converter); } void KisToolColorPicker::activate(ToolActivation activation, const QSet &shapes) { m_isActivated = true; m_toolActivationSource = activation; m_config->load(m_toolActivationSource == KisTool::DefaultActivation); updateOptionWidget(); KisTool::activate(activation, shapes); } void KisToolColorPicker::deactivate() { m_config->save(m_toolActivationSource == KisTool::DefaultActivation); m_isActivated = false; KisTool::deactivate(); } bool KisToolColorPicker::pickColor(const QPointF &pos) { // Timer check. if (m_colorPickerDelayTimer.isActive()) { return false; } else { m_colorPickerDelayTimer.setSingleShot(true); m_colorPickerDelayTimer.start(100); } QScopedPointer> imageLocker; m_pickedColor.setOpacity(0.0); // Pick from reference images. if (m_optionsWidget->cmbSources->currentIndex() == SAMPLE_MERGED) { auto *kisCanvas = dynamic_cast(canvas()); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(kisCanvas, false); KisSharedPtr referenceImageLayer = kisCanvas->imageView()->document()->referenceImagesLayer(); if (referenceImageLayer && kisCanvas->referenceImagesDecoration()->visible()) { QColor color = referenceImageLayer->getPixel(pos); if (color.isValid()) { m_pickedColor.fromQColor(color); } } } if (m_pickedColor.opacityU8() == OPACITY_TRANSPARENT_U8) { if (!currentImage()->bounds().contains(pos.toPoint()) && !currentImage()->wrapAroundModePermitted()) { return false; } KisPaintDeviceSP dev; if (m_optionsWidget->cmbSources->currentIndex() != SAMPLE_MERGED && currentNode() && currentNode()->colorPickSourceDevice()) { dev = currentNode()->colorPickSourceDevice(); } else { imageLocker.reset(new boost::lock_guard(*currentImage())); dev = currentImage()->projection(); } KoColor previousColor = canvas()->resourceManager()->foregroundColor(); KisToolUtils::pickColor(m_pickedColor, dev, pos.toPoint(), &previousColor, m_config->radius, m_config->blend); } if (m_config->updateColor && m_pickedColor.opacityU8() != OPACITY_TRANSPARENT_U8) { KoColor publicColor = m_pickedColor; publicColor.setOpacity(OPACITY_OPAQUE_U8); // Alpha is unwanted for FG and BG colors. if (m_config->toForegroundColor) { canvas()->resourceManager()->setResource(KoCanvasResourceProvider::ForegroundColor, publicColor); } else { canvas()->resourceManager()->setResource(KoCanvasResourceProvider::BackgroundColor, publicColor); } } return true; } void KisToolColorPicker::beginPrimaryAction(KoPointerEvent *event) { bool sampleMerged = m_optionsWidget->cmbSources->currentIndex() == SAMPLE_MERGED; if (!sampleMerged) { if (!currentNode()) { QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot pick a color as no layer is active.")); event->ignore(); return; } if (!currentNode()->visible()) { QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot pick a color as the active layer is not visible.")); event->ignore(); return; } } QPoint pos = convertToImagePixelCoordFloored(event); setMode(KisTool::PAINT_MODE); bool picked = pickColor(pos); if (!picked) { // Color picking has to start in the visible part of the layer event->ignore(); return; } displayPickedColor(); } void KisToolColorPicker::continuePrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); QPoint pos = convertToImagePixelCoordFloored(event); pickColor(pos); displayPickedColor(); } +#include "kis_canvas2.h" +#include "kis_display_color_converter.h" + void KisToolColorPicker::endPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); if (m_config->addPalette) { KisSwatch ent; ent.setColor(m_pickedColor); // We don't ask for a name, too intrusive here KoColorSet *palette = m_palettes.at(m_optionsWidget->cmbPalette->currentIndex()); palette->add(ent); if (!palette->save()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Cannot write to palette file %1. Maybe it is read-only.", palette->filename())); } } + } struct PickedChannel { QString name; QString valueText; }; void KisToolColorPicker::displayPickedColor() { if (m_pickedColor.data() && m_optionsWidget) { QList channels = m_pickedColor.colorSpace()->channels(); m_optionsWidget->listViewChannels->clear(); QVector pickedChannels; for (int i = 0; i < channels.count(); ++i) { pickedChannels.append(PickedChannel()); } for (int i = 0; i < channels.count(); ++i) { PickedChannel pc; pc.name = channels[i]->name(); if (m_config->normaliseValues) { pc.valueText = m_pickedColor.colorSpace()->normalisedChannelValueText(m_pickedColor.data(), i); } else { pc.valueText = m_pickedColor.colorSpace()->channelValueText(m_pickedColor.data(), i); } pickedChannels[channels[i]->displayPosition()] = pc; } Q_FOREACH (const PickedChannel &pc, pickedChannels) { QTreeWidgetItem *item = new QTreeWidgetItem(m_optionsWidget->listViewChannels); item->setText(0, pc.name); item->setText(1, pc.valueText); } + + KisCanvas2 *kritaCanvas = dynamic_cast(canvas()); + KoColor newColor = kritaCanvas->displayColorConverter()->applyDisplayFiltering(m_pickedColor, false); + QVector values(4); + newColor.colorSpace()->normalisedChannelsValue(newColor.data(), values); + + for (int i = 0; i < values.size(); i++) { + QTreeWidgetItem *item = new QTreeWidgetItem(m_optionsWidget->listViewChannels); + item->setText(0, QString("DisplayCh%1").arg(i)); + item->setText(1, QString::number(values[i])); + } } } QWidget* KisToolColorPicker::createOptionWidget() { m_optionsWidget = new ColorPickerOptionsWidget(0); m_optionsWidget->setObjectName(toolId() + " option widget"); m_optionsWidget->listViewChannels->setSortingEnabled(false); // See https://bugs.kde.org/show_bug.cgi?id=316896 QWidget *specialSpacer = new QWidget(m_optionsWidget); specialSpacer->setObjectName("SpecialSpacer"); specialSpacer->setFixedSize(0, 0); m_optionsWidget->layout()->addWidget(specialSpacer); // Initialize blend KisSliderSpinBox m_optionsWidget->blend->setRange(0,100); m_optionsWidget->blend->setSuffix("%"); updateOptionWidget(); connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool))); connect(m_optionsWidget->cbNormaliseValues, SIGNAL(toggled(bool)), SLOT(slotSetNormaliseValues(bool))); connect(m_optionsWidget->cbPalette, SIGNAL(toggled(bool)), SLOT(slotSetAddPalette(bool))); connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)), SLOT(slotChangeRadius(int))); connect(m_optionsWidget->blend, SIGNAL(valueChanged(int)), SLOT(slotChangeBlend(int))); connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)), SLOT(slotSetColorSource(int))); KoResourceServer *srv = KoResourceServerProvider::instance()->paletteServer(); if (!srv) { return m_optionsWidget; } QList palettes = srv->resources(); Q_FOREACH (KoColorSet *palette, palettes) { if (palette) { m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); m_palettes.append(palette); } } return m_optionsWidget; } void KisToolColorPicker::updateOptionWidget() { if (!m_optionsWidget) return; m_optionsWidget->cbNormaliseValues->setChecked(m_config->normaliseValues); m_optionsWidget->cbUpdateCurrentColor->setChecked(m_config->updateColor); m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged); m_optionsWidget->cbPalette->setChecked(m_config->addPalette); m_optionsWidget->radius->setValue(m_config->radius); m_optionsWidget->blend->setValue(m_config->blend); } void KisToolColorPicker::setToForeground(bool newValue) { m_config->toForegroundColor = newValue; emit toForegroundChanged(); } bool KisToolColorPicker::toForeground() const { return m_config->toForegroundColor; } void KisToolColorPicker::slotSetUpdateColor(bool state) { m_config->updateColor = state; } void KisToolColorPicker::slotSetNormaliseValues(bool state) { m_config->normaliseValues = state; displayPickedColor(); } void KisToolColorPicker::slotSetAddPalette(bool state) { m_config->addPalette = state; } void KisToolColorPicker::slotChangeRadius(int value) { m_config->radius = value; } void KisToolColorPicker::slotChangeBlend(int value) { m_config->blend = value; } void KisToolColorPicker::slotSetColorSource(int value) { m_config->sampleMerged = value == SAMPLE_MERGED; } void KisToolColorPicker::slotAddPalette(KoResource *resource) { KoColorSet *palette = dynamic_cast(resource); if (palette) { m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); m_palettes.append(palette); } } diff --git a/plugins/tools/basictools/wdgcolorpicker.ui b/plugins/tools/basictools/wdgcolorpicker.ui index 5b8e0de566..c4356d6c7f 100644 --- a/plugins/tools/basictools/wdgcolorpicker.ui +++ b/plugins/tools/basictools/wdgcolorpicker.ui @@ -1,268 +1,274 @@ ColorPickerOptionsWidget 0 0 263 323 Color Picker 1 Blend: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 0 0 <nobr>Blending controls the percentage of color that is picked</nobr> and mixed with your current brush color. A full blending value picks colors completely, ignoring brush color. 0 0 200 0 200 32767 <nobr>Determines whether the color picker will sample</nobr> colors from all visible layers or only the currently selected layer. 0 Sample All Visible Layers Sample Current Layer Displays per-channel color information below as percentages instead of bytes. Show colors as percentages + + + 0 + 1 + + 0 100 2 Channel Value QFrame::Plain 1 Qt::Horizontal 1 0 0 0 0 Radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 0 0 <nobr>Radius controls the color picker's sampling area.</nobr> Pixel colors within this radius are mixed together. px 1 900 1 0 0 0 0 <nobr>Checking this box will add a new color swatch</nobr> to a palette each time you pick a color. Add to palette: <nobr>Controls whether the color picker updates the</nobr> current foreground or not. Update color QFrame::Plain 1 Qt::Horizontal KisSliderSpinBox QWidget
kis_slider_spin_box.h
SqueezedComboBox QComboBox
squeezedcombobox.h
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h