diff --git a/cmake/modules/FindLibMyPaint.cmake b/cmake/modules/FindLibMyPaint.cmake index e5f2a3a77f..cd2736dc4c 100644 --- a/cmake/modules/FindLibMyPaint.cmake +++ b/cmake/modules/FindLibMyPaint.cmake @@ -1,19 +1,27 @@ #For finding LibMyPaint library in the system include(LibFindMacros) libfind_pkg_check_modules(MYPAINT_PKGCONF libmypaint) find_path(LIBMYPAINT_INCLUDE_DIR - NAMES libmypaint/mypaint-brush.h - HINTS ${MYPAINT_PKGCONF_INCLUDE_DIRS} ${MYPAINT_PKGCONF_INCLUDEDIR} + NAMES mypaint-config.h + /usr/include + /usr/local/include + /sw/include + /opt/local/include + ${MYPAINT_PKGCONF_INCLUDE_DIRS} + ${MYPAINT_PKGCONF_INCLUDEDIR} PATH_SUFFIXES libmypaint ) find_library(LIBMYPAINT_LIBRARY NAMES libmypaint mypaint HINTS ${MYPAINT_PKGCONF_LIBRARY_DIRS} ${MYPAINT_PKGCONF_LIBDIR} DOC "Libraries to link against for mypaint brush engine Support" ) +string(REGEX MATCH "(.*)/libmypaint.so" LIBMYPAINT_LIBRARIES ${LIBMYPAINT_LIBRARY}) + +set(LIBMYPAINT_LIBRARIES ${CMAKE_MATCH_1}) set(LIBMYPAINT_FOUND ${MYPAINT_PKGCONF_FOUND}) set(LIBMYPAINT_VERSION ${MYPAINT_PKGCONF_VERSION}) diff --git a/krita/pics/paintops/mypaintbrush.png b/krita/pics/paintops/mypaintbrush.png new file mode 100644 index 0000000000..af5f166d19 Binary files /dev/null and b/krita/pics/paintops/mypaintbrush.png differ diff --git a/krita/pics/paintops/paintops-icons.qrc b/krita/pics/paintops/paintops-icons.qrc index 535ed480f5..968c88f82b 100644 --- a/krita/pics/paintops/paintops-icons.qrc +++ b/krita/pics/paintops/paintops-icons.qrc @@ -1,37 +1,38 @@ dark_bristlebrush.svg dark_clonebrush.svg dark_colorsmudge.svg dark_curvebrush.svg dark_deformbrush.svg dark_dynabrush.svg dark_filterbrush.svg dark_gridbrush.svg dark_hatchingbrush.svg dark_particlebrush.svg dark_pixelbrush.svg dark_quickbrush.svg dark_shapebrush.svg dark_sketchbrush.svg dark_spraybrush.svg dark_tangentnormal.svg light_bristlebrush.svg light_clonebrush.svg light_colorsmudge.svg light_curvebrush.svg light_deformbrush.svg light_dynabrush.svg light_filterbrush.svg light_gridbrush.svg light_hatchingbrush.svg light_particlebrush.svg light_pixelbrush.svg light_quickbrush.svg light_shapebrush.svg light_sketchbrush.svg light_spraybrush.svg light_tangentnormal.svg + mypaintbrush.png diff --git a/libs/global/KisUsageLogger.cpp b/libs/global/KisUsageLogger.cpp index 46ef05ce0d..d62ad5d71f 100644 --- a/libs/global/KisUsageLogger.cpp +++ b/libs/global/KisUsageLogger.cpp @@ -1,253 +1,253 @@ /* * Copyright (c) 2019 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 "KisUsageLogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Q_GLOBAL_STATIC(KisUsageLogger, s_instance) const QString KisUsageLogger::s_sectionHeader("================================================================================\n"); struct KisUsageLogger::Private { bool active {false}; QFile logFile; QFile sysInfoFile; }; KisUsageLogger::KisUsageLogger() : d(new Private) { d->logFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/krita.log"); d->sysInfoFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/krita-sysinfo.log"); rotateLog(); d->logFile.open(QFile::Append | QFile::Text); d->sysInfoFile.open(QFile::WriteOnly | QFile::Text); } KisUsageLogger::~KisUsageLogger() { if (d->active) { close(); } } void KisUsageLogger::initialize() { s_instance->d->active = true; QString systemInfo = basicSystemInfo(); s_instance->d->sysInfoFile.write(systemInfo.toUtf8()); } QString KisUsageLogger::basicSystemInfo() { QString systemInfo; // NOTE: This is intentionally not translated! // Krita version info systemInfo.append("Krita\n"); systemInfo.append("\n Version: ").append(KritaVersionWrapper::versionString(true)); systemInfo.append("\n Languages: ").append(KLocalizedString::languages().join(", ")); systemInfo.append("\n Hidpi: ").append(QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling) ? "true" : "false"); systemInfo.append("\n\n"); systemInfo.append("Qt\n"); systemInfo.append("\n Version (compiled): ").append(QT_VERSION_STR); systemInfo.append("\n Version (loaded): ").append(qVersion()); systemInfo.append("\n\n"); // OS information systemInfo.append("OS Information\n"); systemInfo.append("\n Build ABI: ").append(QSysInfo::buildAbi()); systemInfo.append("\n Build CPU: ").append(QSysInfo::buildCpuArchitecture()); systemInfo.append("\n CPU: ").append(QSysInfo::currentCpuArchitecture()); systemInfo.append("\n Kernel Type: ").append(QSysInfo::kernelType()); systemInfo.append("\n Kernel Version: ").append(QSysInfo::kernelVersion()); systemInfo.append("\n Pretty Productname: ").append(QSysInfo::prettyProductName()); systemInfo.append("\n Product Type: ").append(QSysInfo::productType()); systemInfo.append("\n Product Version: ").append(QSysInfo::productVersion()); #ifdef Q_OS_LINUX systemInfo.append("\n Desktop: ").append(qgetenv("XDG_CURRENT_DESKTOP")); #endif systemInfo.append("\n\n"); return systemInfo; } void KisUsageLogger::close() { log("CLOSING SESSION"); s_instance->d->active = false; s_instance->d->logFile.flush(); s_instance->d->logFile.close(); s_instance->d->sysInfoFile.flush(); s_instance->d->sysInfoFile.close(); } void KisUsageLogger::log(const QString &message) { if (!s_instance->d->active) return; if (!s_instance->d->logFile.isOpen()) return; s_instance->d->logFile.write(QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8()); s_instance->d->logFile.write(": "); write(message); } void KisUsageLogger::write(const QString &message) { if (!s_instance->d->active) return; if (!s_instance->d->logFile.isOpen()) return; s_instance->d->logFile.write(message.toUtf8()); s_instance->d->logFile.write("\n"); s_instance->d->logFile.flush(); } void KisUsageLogger::writeSysInfo(const QString &message) { if (!s_instance->d->active) return; if (!s_instance->d->sysInfoFile.isOpen()) return; s_instance->d->sysInfoFile.write(message.toUtf8()); s_instance->d->sysInfoFile.write("\n"); s_instance->d->sysInfoFile.flush(); } void KisUsageLogger::writeHeader() { - Q_ASSERT(s_instance->d->sysInfoFile.isOpen()); +// Q_ASSERT(s_instance->d->sysInfoFile.isOpen()); s_instance->d->logFile.write(s_sectionHeader.toUtf8()); QString sessionHeader = QString("SESSION: %1. Executing %2\n\n") .arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date)) .arg(qApp->arguments().join(' ')); s_instance->d->logFile.write(sessionHeader.toUtf8()); QString KritaAndQtVersion; KritaAndQtVersion.append("Krita Version: ").append(KritaVersionWrapper::versionString(true)) .append(", Qt version compiled: ").append(QT_VERSION_STR) .append(", loaded: ").append(qVersion()) .append(". Process ID: ") .append(QString::number(qApp->applicationPid())).append("\n"); KritaAndQtVersion.append("-- -- -- -- -- -- -- --\n"); s_instance->d->logFile.write(KritaAndQtVersion.toUtf8()); s_instance->d->logFile.flush(); } QString KisUsageLogger::screenInformation() { QList screens = qApp->screens(); QString info; info.append("Display Information"); info.append("\nNumber of screens: ").append(QString::number(screens.size())); for (int i = 0; i < screens.size(); ++i ) { QScreen *screen = screens[i]; info.append("\n\tScreen: ").append(QString::number(i)); info.append("\n\t\tName: ").append(screen->name()); info.append("\n\t\tDepth: ").append(QString::number(screen->depth())); info.append("\n\t\tScale: ").append(QString::number(screen->devicePixelRatio())); info.append("\n\t\tResolution in pixels: ").append(QString::number(screen->geometry().width())) .append("x") .append(QString::number(screen->geometry().height())); info.append("\n\t\tManufacturer: ").append(screen->manufacturer()); info.append("\n\t\tModel: ").append(screen->model()); info.append("\n\t\tRefresh Rate: ").append(QString::number(screen->refreshRate())); } info.append("\n"); return info; } void KisUsageLogger::rotateLog() { if (d->logFile.exists()) { { // Check for CLOSING SESSION d->logFile.open(QFile::ReadOnly); QString log = QString::fromUtf8(d->logFile.readAll()); if (!log.split(s_sectionHeader).last().contains("CLOSING SESSION")) { log.append("\nKRITA DID NOT CLOSE CORRECTLY\n"); QString crashLog = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/kritacrash.log"); if (QFileInfo(crashLog).exists()) { QFile f(crashLog); f.open(QFile::ReadOnly); QString crashes = QString::fromUtf8(f.readAll()); f.close(); QStringList crashlist = crashes.split("-------------------"); log.append(QString("\nThere were %1 crashes in total in the crash log.\n").arg(crashlist.size())); if (crashes.size() > 0) { log.append(crashlist.last()); } } d->logFile.close(); d->logFile.open(QFile::WriteOnly); d->logFile.write(log.toUtf8()); } d->logFile.flush(); d->logFile.close(); } { // Rotate d->logFile.open(QFile::ReadOnly); QString log = QString::fromUtf8(d->logFile.readAll()); int sectionCount = log.count(s_sectionHeader); int nextSectionIndex = log.indexOf(s_sectionHeader, s_sectionHeader.length()); while(sectionCount >= s_maxLogs) { log = log.remove(0, log.indexOf(s_sectionHeader, nextSectionIndex)); nextSectionIndex = log.indexOf(s_sectionHeader, s_sectionHeader.length()); sectionCount = log.count(s_sectionHeader); } d->logFile.close(); d->logFile.open(QFile::WriteOnly); d->logFile.write(log.toUtf8()); d->logFile.flush(); d->logFile.close(); } } } diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt index 810dee2f16..510e1844a4 100644 --- a/libs/image/CMakeLists.txt +++ b/libs/image/CMakeLists.txt @@ -1,387 +1,396 @@ add_subdirectory( tests ) add_subdirectory( tiles3 ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty ${CMAKE_CURRENT_SOURCE_DIR}/brushengine ${CMAKE_CURRENT_SOURCE_DIR}/commands ${CMAKE_CURRENT_SOURCE_DIR}/commands_new ${CMAKE_CURRENT_SOURCE_DIR}/filter ${CMAKE_CURRENT_SOURCE_DIR}/floodfill ${CMAKE_CURRENT_SOURCE_DIR}/generator ${CMAKE_CURRENT_SOURCE_DIR}/layerstyles ${CMAKE_CURRENT_SOURCE_DIR}/processing ${CMAKE_SOURCE_DIR}/sdk/tests ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ) if(FFTW3_FOUND) include_directories(${FFTW3_INCLUDE_DIR}) endif() +if(LIBMYPAINT_FOUND) + include_directories(${LIBMYPAINT_INCLUDE_DIR}) + link_directories(${LIBMYPAINT_LIBRARIES}) +endif() + if(HAVE_VC) include_directories(SYSTEM ${Vc_INCLUDE_DIR} ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS}) ko_compile_for_all_implementations(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp) else() set(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp) endif() set(kritaimage_LIB_SRCS tiles3/kis_tile.cc tiles3/kis_tile_data.cc tiles3/kis_tile_data_store.cc tiles3/kis_tile_data_pooler.cc tiles3/kis_tiled_data_manager.cc tiles3/KisTiledExtentManager.cpp tiles3/kis_memento_manager.cc tiles3/kis_hline_iterator.cpp tiles3/kis_vline_iterator.cpp tiles3/kis_random_accessor.cc tiles3/swap/kis_abstract_compression.cpp tiles3/swap/kis_lzf_compression.cpp tiles3/swap/kis_abstract_tile_compressor.cpp tiles3/swap/kis_legacy_tile_compressor.cpp tiles3/swap/kis_tile_compressor_2.cpp tiles3/swap/kis_chunk_allocator.cpp tiles3/swap/kis_memory_window.cpp tiles3/swap/kis_swapped_data_store.cpp tiles3/swap/kis_tile_data_swapper.cpp kis_distance_information.cpp kis_painter.cc kis_painter_blt_multi_fixed.cpp kis_marker_painter.cpp KisPrecisePaintDeviceWrapper.cpp kis_progress_updater.cpp brushengine/kis_paint_information.cc brushengine/kis_random_source.cpp brushengine/KisPerStrokeRandomSource.cpp brushengine/kis_stroke_random_source.cpp brushengine/kis_paintop.cc brushengine/kis_paintop_factory.cpp brushengine/kis_paintop_preset.cpp brushengine/kis_paintop_registry.cc brushengine/kis_paintop_settings.cpp brushengine/kis_paintop_settings_update_proxy.cpp brushengine/kis_paintop_utils.cpp brushengine/kis_no_size_paintop_settings.cpp brushengine/kis_locked_properties.cc brushengine/kis_locked_properties_proxy.cpp brushengine/kis_locked_properties_server.cpp brushengine/kis_paintop_config_widget.cpp brushengine/kis_uniform_paintop_property.cpp brushengine/kis_combo_based_paintop_property.cpp brushengine/kis_slider_based_paintop_property.cpp brushengine/kis_standard_uniform_properties_factory.cpp brushengine/KisStrokeSpeedMeasurer.cpp brushengine/KisPaintopSettingsIds.cpp commands/kis_deselect_global_selection_command.cpp commands/KisDeselectActiveSelectionCommand.cpp commands/kis_image_change_layers_command.cpp commands/kis_image_change_visibility_command.cpp commands/kis_image_command.cpp commands/kis_image_layer_add_command.cpp commands/kis_image_layer_move_command.cpp commands/kis_image_layer_remove_command.cpp commands/kis_image_layer_remove_command_impl.cpp commands/kis_image_lock_command.cpp commands/kis_node_command.cpp commands/kis_node_compositeop_command.cpp commands/kis_node_opacity_command.cpp commands/kis_node_property_list_command.cpp commands/kis_reselect_global_selection_command.cpp commands/KisReselectActiveSelectionCommand.cpp commands/kis_set_global_selection_command.cpp commands/KisNodeRenameCommand.cpp commands_new/kis_saved_commands.cpp commands_new/kis_processing_command.cpp commands_new/kis_image_resize_command.cpp commands_new/kis_image_set_resolution_command.cpp commands_new/kis_node_move_command2.cpp commands_new/kis_set_layer_style_command.cpp commands_new/kis_selection_move_command2.cpp commands_new/kis_update_command.cpp commands_new/kis_switch_current_time_command.cpp commands_new/kis_change_projection_color_command.cpp commands_new/kis_activate_selection_mask_command.cpp commands_new/kis_transaction_based_command.cpp commands_new/KisHoldUIUpdatesCommand.cpp commands_new/KisChangeChannelFlagsCommand.cpp commands_new/KisChangeChannelLockFlagsCommand.cpp commands_new/KisMergeLabeledLayersCommand.cpp processing/kis_do_nothing_processing_visitor.cpp processing/kis_simple_processing_visitor.cpp processing/kis_convert_color_space_processing_visitor.cpp processing/kis_assign_profile_processing_visitor.cpp processing/kis_crop_processing_visitor.cpp processing/kis_crop_selections_processing_visitor.cpp processing/kis_transform_processing_visitor.cpp processing/kis_mirror_processing_visitor.cpp processing/KisSelectionBasedProcessingHelper.cpp filter/kis_filter.cc filter/kis_filter_category_ids.cpp filter/kis_filter_configuration.cc filter/kis_color_transformation_configuration.cc filter/kis_filter_registry.cc filter/kis_color_transformation_filter.cc generator/kis_generator.cpp generator/kis_generator_layer.cpp generator/kis_generator_registry.cpp floodfill/kis_fill_interval_map.cpp floodfill/kis_scanline_fill.cpp lazybrush/kis_min_cut_worker.cpp lazybrush/kis_lazy_fill_tools.cpp lazybrush/kis_multiway_cut.cpp lazybrush/KisWatershedWorker.cpp lazybrush/kis_colorize_mask.cpp lazybrush/kis_colorize_stroke_strategy.cpp KisDelayedUpdateNodeInterface.cpp KisCroppedOriginalLayerInterface.cpp KisDecoratedNodeInterface.cpp kis_adjustment_layer.cc kis_selection_based_layer.cpp kis_node_filter_interface.cpp kis_base_accessor.cpp kis_base_node.cpp kis_base_processor.cpp kis_bookmarked_configuration_manager.cc KisBusyWaitBroker.cpp KisSafeBlockingQueueConnectionProxy.cpp kis_node_uuid_info.cpp kis_clone_layer.cpp kis_config_widget.cpp kis_convolution_kernel.cc kis_convolution_painter.cc kis_gaussian_kernel.cpp kis_edge_detection_kernel.cpp kis_cubic_curve.cpp kis_default_bounds.cpp kis_default_bounds_node_wrapper.cpp kis_default_bounds_base.cpp kis_effect_mask.cc kis_fast_math.cpp kis_fill_painter.cc kis_filter_mask.cpp kis_filter_strategy.cc kis_transform_mask.cpp kis_transform_mask_params_interface.cpp kis_recalculate_transform_mask_job.cpp kis_recalculate_generator_layer_job.cpp kis_transform_mask_params_factory_registry.cpp kis_safe_transform.cpp kis_gradient_painter.cc kis_gradient_shape_strategy.cpp kis_cached_gradient_shape_strategy.cpp kis_polygonal_gradient_shape_strategy.cpp kis_iterator_ng.cpp kis_async_merger.cpp kis_merge_walker.cc kis_updater_context.cpp kis_update_job_item.cpp kis_stroke_strategy_undo_command_based.cpp kis_simple_stroke_strategy.cpp KisRunnableBasedStrokeStrategy.cpp KisRunnableStrokeJobDataBase.cpp KisRunnableStrokeJobData.cpp KisRunnableStrokeJobsInterface.cpp KisFakeRunnableStrokeJobsExecutor.cpp kis_stroke_job_strategy.cpp kis_stroke_strategy.cpp kis_stroke.cpp kis_strokes_queue.cpp KisStrokesQueueMutatedJobInterface.cpp kis_simple_update_queue.cpp kis_update_scheduler.cpp kis_queues_progress_updater.cpp kis_composite_progress_proxy.cpp kis_sync_lod_cache_stroke_strategy.cpp kis_lod_capable_layer_offset.cpp kis_update_time_monitor.cpp KisImageConfigNotifier.cpp kis_group_layer.cc kis_count_visitor.cpp kis_histogram.cc kis_image_interfaces.cpp kis_image_animation_interface.cpp kis_time_range.cpp kis_node_graph_listener.cpp kis_image.cc kis_image_signal_router.cpp KisImageSignals.cpp kis_image_config.cpp kis_projection_updates_filter.cpp kis_suspend_projection_updates_stroke_strategy.cpp kis_regenerate_frame_stroke_strategy.cpp kis_switch_time_stroke_strategy.cpp kis_crop_saved_extra_data.cpp kis_timed_signal_threshold.cpp kis_layer.cc kis_indirect_painting_support.cpp kis_abstract_projection_plane.cpp kis_layer_projection_plane.cpp kis_layer_utils.cpp kis_mask_projection_plane.cpp kis_projection_leaf.cpp KisSafeNodeProjectionStore.cpp kis_mask.cc kis_base_mask_generator.cpp kis_rect_mask_generator.cpp kis_circle_mask_generator.cpp kis_gauss_circle_mask_generator.cpp kis_gauss_rect_mask_generator.cpp ${__per_arch_circle_mask_generator_objs} kis_curve_circle_mask_generator.cpp kis_curve_rect_mask_generator.cpp kis_math_toolbox.cpp kis_memory_statistics_server.cpp kis_name_server.cpp kis_node.cpp kis_node_facade.cpp kis_node_progress_proxy.cpp kis_busy_progress_indicator.cpp kis_node_visitor.cpp kis_paint_device.cc kis_paint_device_debug_utils.cpp kis_fixed_paint_device.cpp KisOptimizedByteArray.cpp kis_paint_layer.cc kis_perspective_math.cpp kis_pixel_selection.cpp kis_processing_information.cpp kis_properties_configuration.cc kis_random_accessor_ng.cpp kis_random_generator.cc kis_random_sub_accessor.cpp kis_wrapped_random_accessor.cpp kis_selection.cc KisSelectionUpdateCompressor.cpp kis_selection_mask.cpp kis_update_outline_job.cpp kis_update_selection_job.cpp kis_serializable_configuration.cc kis_transaction_data.cpp kis_transform_worker.cc kis_perspectivetransform_worker.cpp bsplines/kis_bspline_1d.cpp bsplines/kis_bspline_2d.cpp bsplines/kis_nu_bspline_2d.cpp kis_warptransform_worker.cc kis_cage_transform_worker.cpp kis_liquify_transform_worker.cpp kis_green_coordinates_math.cpp kis_transparency_mask.cc kis_undo_adapter.cpp kis_macro_based_undo_store.cpp kis_surrogate_undo_adapter.cpp kis_legacy_undo_adapter.cpp kis_post_execution_undo_adapter.cpp kis_processing_visitor.cpp kis_processing_applicator.cpp krita_utils.cpp kis_outline_generator.cpp kis_layer_composition.cpp kis_selection_filters.cpp KisProofingConfiguration.h KisRecycleProjectionsJob.cpp kis_keyframe.cpp kis_keyframe_channel.cpp kis_keyframe_commands.cpp kis_scalar_keyframe_channel.cpp kis_raster_keyframe_channel.cpp kis_onion_skin_compositor.cpp kis_onion_skin_cache.cpp kis_idle_watcher.cpp kis_psd_layer_style.cpp kis_layer_properties_icons.cpp layerstyles/kis_multiple_projection.cpp layerstyles/kis_layer_style_filter.cpp layerstyles/kis_layer_style_filter_environment.cpp layerstyles/kis_layer_style_filter_projection_plane.cpp layerstyles/kis_layer_style_projection_plane.cpp layerstyles/kis_ls_drop_shadow_filter.cpp layerstyles/kis_ls_satin_filter.cpp layerstyles/kis_ls_stroke_filter.cpp layerstyles/kis_ls_bevel_emboss_filter.cpp layerstyles/kis_ls_overlay_filter.cpp layerstyles/kis_ls_utils.cpp layerstyles/gimp_bump_map.cpp layerstyles/KisLayerStyleKnockoutBlower.cpp KisProofingConfiguration.cpp kis_node_query_path.cc ) set(einspline_SRCS 3rdparty/einspline/bspline_create.cpp 3rdparty/einspline/bspline_data.cpp 3rdparty/einspline/multi_bspline_create.cpp 3rdparty/einspline/nubasis.cpp 3rdparty/einspline/nubspline_create.cpp 3rdparty/einspline/nugrid.cpp ) add_library(kritaimage SHARED ${kritaimage_LIB_SRCS} ${einspline_SRCS}) generate_export_header(kritaimage BASE_NAME kritaimage) target_link_libraries(kritaimage PUBLIC kritaversion kritawidgets kritaglobal kritapsd kritaodf kritapigment kritacommand kritawidgetutils kritametadata Qt5::Concurrent ) target_link_libraries(kritaimage PUBLIC ${Boost_SYSTEM_LIBRARY}) if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) target_link_libraries(kritaimage PUBLIC atomic) endif() endif() if(OPENEXR_FOUND) target_link_libraries(kritaimage PUBLIC ${OPENEXR_LIBRARIES}) endif() if(FFTW3_FOUND) target_link_libraries(kritaimage PRIVATE ${FFTW3_LIBRARIES}) endif() +if(LIBMYPAINT_FOUND) + target_link_libraries(kritaimage PUBLIC mypaint) +endif() + if(HAVE_VC) target_link_libraries(kritaimage PUBLIC ${Vc_LIBRARIES}) endif() if (NOT GSL_FOUND) message (WARNING "KRITA WARNING! No GNU Scientific Library was found! Krita's Shaped Gradients might be non-normalized! Please install GSL library.") else () target_link_libraries(kritaimage PRIVATE ${GSL_LIBRARIES} ${GSL_CBLAS_LIBRARIES}) endif () target_include_directories(kritaimage PUBLIC $ $ $ $ $ ) set_target_properties(kritaimage PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaimage ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/image/brushengine/kis_paintop_preset.cpp b/libs/image/brushengine/kis_paintop_preset.cpp index 59d3f0aa2c..c78e645cc5 100644 --- a/libs/image/brushengine/kis_paintop_preset.cpp +++ b/libs/image/brushengine/kis_paintop_preset.cpp @@ -1,425 +1,452 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * Copyright (C) Sven Langkamp , (C) 2009 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include "kis_paintop_registry.h" #include "kis_painter.h" #include #include "kis_paint_device.h" #include "kis_image.h" #include "kis_paintop_settings_update_proxy.h" #include #include +#include struct Q_DECL_HIDDEN KisPaintOpPreset::Private { Private() : settings(0), dirtyPreset(false) { } KisPaintOpSettingsSP settings; bool dirtyPreset; QScopedPointer updateProxy; }; KisPaintOpPreset::KisPaintOpPreset() : KoResource(QString()) , m_d(new Private) { } KisPaintOpPreset::KisPaintOpPreset(const QString & fileName) : KoResource(fileName) , m_d(new Private) { } KisPaintOpPreset::~KisPaintOpPreset() { delete m_d; } KisPaintOpPresetSP KisPaintOpPreset::clone() const { KisPaintOpPresetSP preset(new KisPaintOpPreset()); if (settings()) { preset->setSettings(settings()); // the settings are cloned inside! } preset->setDirty(isDirty()); // only valid if we could clone the settings preset->setValid(settings()); preset->setPaintOp(paintOp()); preset->setName(name()); preset->setImage(image()); preset->settings()->setPreset(KisPaintOpPresetWSP(preset)); Q_ASSERT(preset->valid()); return preset; } void KisPaintOpPreset::setDirty(bool value) { m_d->dirtyPreset = value; } bool KisPaintOpPreset::isDirty() const { return m_d->dirtyPreset; } void KisPaintOpPreset::setPaintOp(const KoID & paintOp) { Q_ASSERT(m_d->settings); m_d->settings->setProperty("paintop", paintOp.id()); } KoID KisPaintOpPreset::paintOp() const { Q_ASSERT(m_d->settings); return KoID(m_d->settings->getString("paintop")); } void KisPaintOpPreset::setOptionsWidget(KisPaintOpConfigWidget* widget) { if (m_d->settings) { m_d->settings->setOptionsWidget(widget); if (widget) { widget->setConfigurationSafe(m_d->settings); } } } void KisPaintOpPreset::setSettings(KisPaintOpSettingsSP settings) { Q_ASSERT(settings); Q_ASSERT(!settings->getString("paintop", QString()).isEmpty()); DirtyStateSaver dirtyStateSaver(this); KisPaintOpConfigWidget *oldOptionsWidget = 0; if (m_d->settings) { oldOptionsWidget = m_d->settings->optionsWidget(); m_d->settings->setOptionsWidget(0); m_d->settings->setPreset(0); m_d->settings = 0; } if (settings) { m_d->settings = settings->clone(); m_d->settings->setPreset(KisPaintOpPresetWSP(this)); if (oldOptionsWidget) { oldOptionsWidget->setConfigurationSafe(m_d->settings); m_d->settings->setOptionsWidget(oldOptionsWidget); } } setValid(m_d->settings); if (m_d->updateProxy) { m_d->updateProxy->notifyUniformPropertiesChanged(); m_d->updateProxy->notifySettingsChanged(); } } KisPaintOpSettingsSP KisPaintOpPreset::settings() const { Q_ASSERT(m_d->settings); Q_ASSERT(!m_d->settings->getString("paintop", QString()).isEmpty()); return m_d->settings; } bool KisPaintOpPreset::load() { dbgImage << "Load preset " << filename(); setValid(false); if (filename().isEmpty()) { return false; } QIODevice *dev = 0; QByteArray ba; if (filename().startsWith("bundle://")) { QString bn = filename().mid(9); int pos = bn.lastIndexOf(":"); QString fn = bn.right(bn.size() - pos - 1); bn = bn.left(pos); QScopedPointer resourceStore(KoStore::createStore(bn, KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { warnKrita << "Could not open store on bundle" << bn; return false; } if (resourceStore->isOpen()) resourceStore->close(); if (!resourceStore->open(fn)) { warnKrita << "Could not open preset" << fn << "in bundle" << bn; return false; } ba = resourceStore->device()->readAll(); dev = new QBuffer(&ba); resourceStore->close(); } else { dev = new QFile(filename()); if (dev->size() == 0) { delete dev; return false; } if (!dev->open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); delete dev; return false; } } - bool res = loadFromDevice(dev); + bool res = false; + if(filename().endsWith(".myb")) { + // res = loadMYB(dev); + } + else { + res = loadFromDevice(dev); + } delete dev; setValid(res); setDirty(false); return res; } bool KisPaintOpPreset::loadFromDevice(QIODevice *dev) { QImageReader reader(dev, "PNG"); QString version = reader.text("version"); QString preset = reader.text("preset"); dbgImage << version; if (version != "2.2") { return false; } QImage img; if (!reader.read(&img)) { dbgImage << "Fail to decode PNG"; return false; } //Workaround for broken presets //Presets was saved with nested cdata section preset.replace(""); preset.replace("]]>", ""); QDomDocument doc; if (!doc.setContent(preset)) { return false; } fromXML(doc.documentElement()); if (!m_d->settings) { return false; } setValid(true); setImage(img); return true; } +bool KisPaintOpPreset::loadMYB(QIODevice *dev) { + + QString pngFilePath = filename(); + pngFilePath = pngFilePath.remove(filename().size()-4, 4); + pngFilePath = pngFilePath + "_prev.png"; + QIODevice *imgDev = new QFile(pngFilePath); + + QImageReader reader(imgDev, "PNG"); + + QImage img; + if (!reader.read(&img)) { + dbgImage << "Fail to decode PNG"; + return false; + } + + setValid(true); + setImage(img); + return true; +} + bool KisPaintOpPreset::save() { if (filename().isEmpty()) return false; QString paintopid = m_d->settings->getString("paintop", QString()); if (paintopid.isEmpty()) return false; QFile f(filename()); f.open(QFile::WriteOnly); return saveToDevice(&f); } void KisPaintOpPreset::toXML(QDomDocument& doc, QDomElement& elt) const { QString paintopid = m_d->settings->getString("paintop", QString()); elt.setAttribute("paintopid", paintopid); elt.setAttribute("name", name()); // sanitize the settings bool hasTexture = m_d->settings->getBool("Texture/Pattern/Enabled"); if (!hasTexture) { Q_FOREACH (const QString & key, m_d->settings->getProperties().keys()) { if (key.startsWith("Texture") && key != "Texture/Pattern/Enabled") { m_d->settings->removeProperty(key); } } } m_d->settings->toXML(doc, elt); } void KisPaintOpPreset::fromXML(const QDomElement& presetElt) { setName(presetElt.attribute("name")); QString paintopid = presetElt.attribute("paintopid"); if (paintopid.isEmpty()) { dbgImage << "No paintopid attribute"; setValid(false); return; } if (KisPaintOpRegistry::instance()->get(paintopid) == 0) { dbgImage << "No paintop " << paintopid; setValid(false); return; } KoID id(paintopid, QString()); KisPaintOpSettingsSP settings = KisPaintOpRegistry::instance()->settings(id); if (!settings) { setValid(false); warnKrita << "Could not load settings for preset" << paintopid; return; } settings->fromXML(presetElt); // sanitize the settings bool hasTexture = settings->getBool("Texture/Pattern/Enabled"); if (!hasTexture) { Q_FOREACH (const QString & key, settings->getProperties().keys()) { if (key.startsWith("Texture") && key != "Texture/Pattern/Enabled") { settings->removeProperty(key); } } } setSettings(settings); } bool KisPaintOpPreset::saveToDevice(QIODevice *dev) const { QImageWriter writer(dev, "PNG"); QDomDocument doc; QDomElement root = doc.createElement("Preset"); toXML(doc, root); doc.appendChild(root); writer.setText("version", "2.2"); writer.setText("preset", doc.toString()); QImage img; if (image().isNull()) { img = QImage(1, 1, QImage::Format_RGB32); } else { img = image(); } m_d->dirtyPreset = false; KoResource::saveToDevice(dev); return writer.write(img); } KisPaintopSettingsUpdateProxy* KisPaintOpPreset::updateProxy() const { if (!m_d->updateProxy) { m_d->updateProxy.reset(new KisPaintopSettingsUpdateProxy()); } return m_d->updateProxy.data(); } KisPaintopSettingsUpdateProxy* KisPaintOpPreset::updateProxyNoCreate() const { return m_d->updateProxy.data(); } QList KisPaintOpPreset::uniformProperties() { return m_d->settings->uniformProperties(m_d->settings); } bool KisPaintOpPreset::hasMaskingPreset() const { return m_d->settings && m_d->settings->hasMaskingSettings(); } KisPaintOpPresetSP KisPaintOpPreset::createMaskingPreset() const { KisPaintOpPresetSP result; if (m_d->settings && m_d->settings->hasMaskingSettings()) { result = new KisPaintOpPreset(); result->setSettings(m_d->settings->createMaskingSettings()); if (!result->valid()) { result.clear(); } } return result; } KisPaintOpPreset::UpdatedPostponer::UpdatedPostponer(KisPaintOpPreset *preset) : m_updateProxy(preset->updateProxyNoCreate()) { if (m_updateProxy) { m_updateProxy->postponeSettingsChanges(); } } KisPaintOpPreset::UpdatedPostponer::~UpdatedPostponer() { if (m_updateProxy) { m_updateProxy->unpostponeSettingsChanges(); } } diff --git a/libs/image/brushengine/kis_paintop_preset.h b/libs/image/brushengine/kis_paintop_preset.h index 3cfbd9c40a..b87abc7d1d 100644 --- a/libs/image/brushengine/kis_paintop_preset.h +++ b/libs/image/brushengine/kis_paintop_preset.h @@ -1,154 +1,156 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_PAINTOP_PRESET_H #define KIS_PAINTOP_PRESET_H #include #include "KoID.h" #include "kis_types.h" #include "kis_shared.h" #include "kritaimage_export.h" #include class KisPaintopSettingsUpdateProxy; class KisPaintOpConfigWidget; /** * A KisPaintOpPreset contains a particular set of settings * associated with a paintop, like brush, paintopsettings. * A new property in this class is to make it dirty. That means the * user can now temporarily save any tweaks in the Preset throughout * the session. The Dirty Preset setting/unsetting is handled by KisPaintOpPresetSettings */ class KRITAIMAGE_EXPORT KisPaintOpPreset : public KoResource, public KisShared { public: KisPaintOpPreset(); KisPaintOpPreset(const QString& filename); ~KisPaintOpPreset() override; KisPaintOpPresetSP clone() const; /// set the id of the paintop plugin void setPaintOp(const KoID & paintOp); /// return the id of the paintop plugin KoID paintOp() const; /// replace the current settings object with the specified settings void setSettings(KisPaintOpSettingsSP settings); void setOriginalSettings(KisPaintOpSettingsSP originalSettings); /// return the settings that define this paintop preset KisPaintOpSettingsSP settings() const; KisPaintOpSettingsSP originalSettings() const; bool load() override; bool loadFromDevice(QIODevice *dev) override; bool save() override; bool saveToDevice(QIODevice* dev) const override; void toXML(QDomDocument& doc, QDomElement& elt) const; void fromXML(const QDomElement& elt); + bool loadMYB(QIODevice* dev); + bool removable() const { return true; } QString defaultFileExtension() const override { return ".kpp"; } /// Mark the preset as modified but not saved void setDirty(bool value); /// @return true if the preset has been modified, but not saved bool isDirty() const; /** * Never use manual save/restore calls to * isPresetDirty()/setPresetDirty()! They will lead to * hard-to-tack-down bugs when the dirty state will not be * restored on jumps like 'return', 'break' or exception. */ class KRITAIMAGE_EXPORT DirtyStateSaver { public: DirtyStateSaver(KisPaintOpPreset *preset) : m_preset(preset), m_isDirty(preset->isDirty()) { } ~DirtyStateSaver() { m_preset->setDirty(m_isDirty); } private: KisPaintOpPreset *m_preset; bool m_isDirty; }; /** * @brief The UpdatedPostponer class * @see KisPaintopSettingsUpdateProxy::postponeSettingsChanges() */ class KRITAIMAGE_EXPORT UpdatedPostponer{ public: UpdatedPostponer(KisPaintOpPreset *preset); ~UpdatedPostponer(); private: KisPaintopSettingsUpdateProxy *m_updateProxy; }; void setOptionsWidget(KisPaintOpConfigWidget *widget); KisPaintopSettingsUpdateProxy* updateProxy() const; KisPaintopSettingsUpdateProxy* updateProxyNoCreate() const; QList uniformProperties(); /** * @return true if this preset demands a secondary masked brush running * alongside it */ bool hasMaskingPreset() const; /** * @return a newly created preset of the masked brush that should be run * alongside the current brush */ KisPaintOpPresetSP createMaskingPreset() const; private: struct Private; Private * const m_d; }; Q_DECLARE_METATYPE(KisPaintOpPresetSP) #endif diff --git a/libs/ui/KisResourceServerProvider.cpp b/libs/ui/KisResourceServerProvider.cpp index 5360352ce8..602fe77054 100644 --- a/libs/ui/KisResourceServerProvider.cpp +++ b/libs/ui/KisResourceServerProvider.cpp @@ -1,120 +1,120 @@ /* * kis_resourceserver.cc - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2005 Sven Langkamp * * 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 "KisResourceServerProvider.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Q_GLOBAL_STATIC(KisResourceServerProvider, s_instance) typedef KoResourceServerSimpleConstruction > KisPaintOpPresetResourceServer; typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter; KisResourceServerProvider::KisResourceServerProvider() { KisBrushServer *brushServer = KisBrushServer::instance(); - m_paintOpPresetServer = new KisPaintOpPresetResourceServer("kis_paintoppresets", "*.kpp"); + m_paintOpPresetServer = new KisPaintOpPresetResourceServer("kis_paintoppresets", "*.kpp:*.myb"); m_paintOpPresetServer->loadResources(KoResourceServerProvider::blacklistFileNames(m_paintOpPresetServer->fileNames(), m_paintOpPresetServer->blackListedFiles())); m_workspaceServer = new KoResourceServerSimpleConstruction("kis_workspaces", "*.kws"); m_workspaceServer->loadResources(KoResourceServerProvider::blacklistFileNames(m_workspaceServer->fileNames(), m_workspaceServer->blackListedFiles())); m_windowLayoutServer = new KoResourceServerSimpleConstruction("kis_windowlayouts", "*.kwl"); m_windowLayoutServer->loadResources(KoResourceServerProvider::blacklistFileNames(m_windowLayoutServer->fileNames(), m_windowLayoutServer->blackListedFiles())); m_sessionServer = new KoResourceServerSimpleConstruction("kis_sessions", "*.ksn"); m_sessionServer->loadResources(KoResourceServerProvider::blacklistFileNames(m_sessionServer->fileNames(), m_sessionServer->blackListedFiles())); m_layerStyleCollectionServer = new KoResourceServerSimpleConstruction("psd_layer_style_collections", "*.asl"); m_layerStyleCollectionServer->loadResources(KoResourceServerProvider::blacklistFileNames(m_layerStyleCollectionServer->fileNames(), m_layerStyleCollectionServer->blackListedFiles())); connect(this, SIGNAL(notifyBrushBlacklistCleanup()), brushServer, SLOT(slotRemoveBlacklistedResources())); } KisResourceServerProvider::~KisResourceServerProvider() { delete m_paintOpPresetServer; delete m_workspaceServer; delete m_sessionServer; delete m_windowLayoutServer; delete m_layerStyleCollectionServer; } KisResourceServerProvider* KisResourceServerProvider::instance() { return s_instance; } KisPaintOpPresetResourceServer* KisResourceServerProvider::paintOpPresetServer() { return m_paintOpPresetServer; } KoResourceServer< KisWorkspaceResource >* KisResourceServerProvider::workspaceServer() { return m_workspaceServer; } KoResourceServer< KisWindowLayoutResource >* KisResourceServerProvider::windowLayoutServer() { return m_windowLayoutServer; } KoResourceServer< KisSessionResource >* KisResourceServerProvider::sessionServer() { return m_sessionServer; } KoResourceServer *KisResourceServerProvider::layerStyleCollectionServer() { return m_layerStyleCollectionServer; } void KisResourceServerProvider::brushBlacklistCleanup() { emit notifyBrushBlacklistCleanup(); } diff --git a/libs/widgetutils/KoResourcePaths.cpp b/libs/widgetutils/KoResourcePaths.cpp index 7cc3b4a3c5..ae27975a1b 100644 --- a/libs/widgetutils/KoResourcePaths.cpp +++ b/libs/widgetutils/KoResourcePaths.cpp @@ -1,602 +1,606 @@ /* * Copyright (c) 2015 Boudewijn Rempt * * 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; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoResourcePaths.h" #include #include #include #include #include #include #include #include #include #include #include "kis_debug.h" Q_GLOBAL_STATIC(KoResourcePaths, s_instance) static QString cleanup(const QString &path) { return QDir::cleanPath(path); } static QStringList cleanup(const QStringList &pathList) { QStringList cleanedPathList; Q_FOREACH(const QString &path, pathList) { cleanedPathList << cleanup(path); } return cleanedPathList; } static QString cleanupDirs(const QString &path) { return QDir::cleanPath(path) + QDir::separator(); } static QStringList cleanupDirs(const QStringList &pathList) { QStringList cleanedPathList; Q_FOREACH(const QString &path, pathList) { cleanedPathList << cleanupDirs(path); } return cleanedPathList; } void appendResources(QStringList *dst, const QStringList &src, bool eliminateDuplicates) { Q_FOREACH (const QString &resource, src) { QString realPath = QDir::cleanPath(resource); if (!eliminateDuplicates || !dst->contains(realPath)) { *dst << realPath; } } } #ifdef Q_OS_WIN static const Qt::CaseSensitivity cs = Qt::CaseInsensitive; #else static const Qt::CaseSensitivity cs = Qt::CaseSensitive; #endif #ifdef Q_OS_MACOS #include #include #include #endif QString getInstallationPrefix() { #ifdef Q_OS_MACOS QString appPath = qApp->applicationDirPath(); dbgResources << "1" << appPath; appPath.chop(QString("MacOS/").length()); dbgResources << "2" << appPath; bool makeInstall = QDir(appPath + "/../../../share/kritaplugins").exists(); bool inBundle = QDir(appPath + "/Resources/kritaplugins").exists(); dbgResources << "3. After make install" << makeInstall; dbgResources << "4. In Bundle" << inBundle; QString bundlePath; if (inBundle) { bundlePath = appPath + "/"; } else if (makeInstall) { appPath.chop(QString("Contents/").length()); bundlePath = appPath + "/../../"; } else { qFatal("Cannot calculate the bundle path from the app path"); } dbgResources << ">>>>>>>>>>>" << bundlePath; return bundlePath; #else #ifdef Q_OS_QWIN QDir appdir(qApp->applicationDirPath()); // Corrects for mismatched case errors in path (qtdeclarative fails to load) wchar_t buffer[1024]; QString absolute = appdir.absolutePath(); DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024); rv = ::GetLongPathName(buffer, buffer, 1024); QString correctedPath((QChar *)buffer); appdir.setPath(correctedPath); appdir.cdUp(); return appdir.canonicalPath(); #else #ifdef Q_OS_ANDROID // qApp->applicationDirPath() isn't writable and android system won't allow // any files other than libraries return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/"; #else return qApp->applicationDirPath() + "/../"; #endif #endif #endif } class Q_DECL_HIDDEN KoResourcePaths::Private { public: QMap absolutes; // For each resource type, the list of absolute paths, from most local (most priority) to most global QMap relatives; // Same with relative paths QMutex relativesMutex; QMutex absolutesMutex; QStringList aliases(const QString &type) { QStringList r; QStringList a; relativesMutex.lock(); if (relatives.contains(type)) { r += relatives[type]; } relativesMutex.unlock(); dbgResources << "\trelatives" << r; absolutesMutex.lock(); if (absolutes.contains(type)) { a += absolutes[type]; } dbgResources << "\tabsolutes" << a; absolutesMutex.unlock(); return r + a; } QStandardPaths::StandardLocation mapTypeToQStandardPaths(const QString &type) { if (type == "tmp") { return QStandardPaths::TempLocation; } else if (type == "appdata") { return QStandardPaths::AppDataLocation; } else if (type == "data") { return QStandardPaths::AppDataLocation; } else if (type == "cache") { return QStandardPaths::CacheLocation; } else if (type == "locale") { return QStandardPaths::AppDataLocation; } else { return QStandardPaths::AppDataLocation; } } }; KoResourcePaths::KoResourcePaths() : d(new Private) { } KoResourcePaths::~KoResourcePaths() { } QString KoResourcePaths::getApplicationRoot() { return getInstallationPrefix(); } void KoResourcePaths::addResourceType(const char *type, const char *basetype, const QString &relativeName, bool priority) { s_instance->addResourceTypeInternal(QString::fromLatin1(type), QString::fromLatin1(basetype), relativeName, priority); } void KoResourcePaths::addResourceDir(const char *type, const QString &dir, bool priority) { s_instance->addResourceDirInternal(QString::fromLatin1(type), dir, priority); } QString KoResourcePaths::findResource(const char *type, const QString &fileName) { return cleanup(s_instance->findResourceInternal(QString::fromLatin1(type), fileName)); } QStringList KoResourcePaths::findDirs(const char *type) { return cleanupDirs(s_instance->findDirsInternal(QString::fromLatin1(type))); } QStringList KoResourcePaths::findAllResources(const char *type, const QString &filter, SearchOptions options) { return cleanup(s_instance->findAllResourcesInternal(QString::fromLatin1(type), filter, options)); } QStringList KoResourcePaths::resourceDirs(const char *type) { return cleanupDirs(s_instance->resourceDirsInternal(QString::fromLatin1(type))); } QString KoResourcePaths::saveLocation(const char *type, const QString &suffix, bool create) { return cleanupDirs(s_instance->saveLocationInternal(QString::fromLatin1(type), suffix, create)); } QString KoResourcePaths::locate(const char *type, const QString &filename) { return cleanup(s_instance->locateInternal(QString::fromLatin1(type), filename)); } QString KoResourcePaths::locateLocal(const char *type, const QString &filename, bool createDir) { return cleanup(s_instance->locateLocalInternal(QString::fromLatin1(type), filename, createDir)); } void KoResourcePaths::addResourceTypeInternal(const QString &type, const QString &basetype, const QString &relativename, bool priority) { Q_UNUSED(basetype); if (relativename.isEmpty()) return; QString copy = relativename; Q_ASSERT(basetype == "data"); if (!copy.endsWith(QLatin1Char('/'))) { copy += QLatin1Char('/'); } d->relativesMutex.lock(); QStringList &rels = d->relatives[type]; // find or insert if (!rels.contains(copy, cs)) { if (priority) { rels.prepend(copy); } else { rels.append(copy); } } d->relativesMutex.unlock(); dbgResources << "addResourceType: type" << type << "basetype" << basetype << "relativename" << relativename << "priority" << priority << d->relatives[type]; } void KoResourcePaths::addResourceDirInternal(const QString &type, const QString &absdir, bool priority) { if (absdir.isEmpty() || type.isEmpty()) return; // find or insert entry in the map QString copy = absdir; if (copy.at(copy.length() - 1) != QLatin1Char('/')) { copy += QLatin1Char('/'); } d->absolutesMutex.lock(); QStringList &paths = d->absolutes[type]; if (!paths.contains(copy, cs)) { if (priority) { paths.prepend(copy); } else { paths.append(copy); } } d->absolutesMutex.unlock(); dbgResources << "addResourceDir: type" << type << "absdir" << absdir << "priority" << priority << d->absolutes[type]; } QString KoResourcePaths::findResourceInternal(const QString &type, const QString &fileName) { QStringList aliases = d->aliases(type); dbgResources<< "aliases" << aliases << getApplicationRoot(); QString resource = QStandardPaths::locate(QStandardPaths::AppDataLocation, fileName, QStandardPaths::LocateFile); if (resource.isEmpty()) { Q_FOREACH (const QString &alias, aliases) { resource = QStandardPaths::locate(d->mapTypeToQStandardPaths(type), alias + '/' + fileName, QStandardPaths::LocateFile); dbgResources << "\t1" << resource; if (QFile::exists(resource)) { continue; } } } if (resource.isEmpty() || !QFile::exists(resource)) { QString approot = getApplicationRoot(); Q_FOREACH (const QString &alias, aliases) { resource = approot + "/share/" + alias + '/' + fileName; dbgResources << "\t2" << resource; if (QFile::exists(resource)) { continue; } } } if (resource.isEmpty() || !QFile::exists(resource)) { QString approot = getApplicationRoot(); Q_FOREACH (const QString &alias, aliases) { resource = approot + "/share/krita/" + alias + '/' + fileName; dbgResources << "\t3" << resource; if (QFile::exists(resource)) { continue; } } } if (resource.isEmpty() || !QFile::exists(resource)) { QString extraResourceDirs = qgetenv("EXTRA_RESOURCE_DIRS"); if (!extraResourceDirs.isEmpty()) { Q_FOREACH(const QString &extraResourceDir, extraResourceDirs.split(':', QString::SkipEmptyParts)) { if (aliases.isEmpty()) { resource = extraResourceDir + '/' + fileName; dbgResources<< "\t4" << resource; if (QFile::exists(resource)) { continue; } } else { Q_FOREACH (const QString &alias, aliases) { resource = extraResourceDir + '/' + alias + '/' + fileName; dbgResources<< "\t4" << resource; if (QFile::exists(resource)) { continue; } } } } } } dbgResources<< "findResource: type" << type << "filename" << fileName << "resource" << resource; Q_ASSERT(!resource.isEmpty()); return resource; } QStringList filesInDir(const QString &startdir, const QString & filter, bool recursive) { dbgResources << "filesInDir: startdir" << startdir << "filter" << filter << "recursive" << recursive; QStringList result; // First the entries in this path QStringList nameFilters; nameFilters << filter; const QStringList fileNames = QDir(startdir).entryList(nameFilters, QDir::Files | QDir::CaseSensitive, QDir::Name); dbgResources << "\tFound:" << fileNames.size() << ":" << fileNames; Q_FOREACH (const QString &fileName, fileNames) { QString file = startdir + '/' + fileName; result << file; } // And then everything underneath, if recursive is specified if (recursive) { const QStringList entries = QDir(startdir).entryList(QDir::Dirs | QDir::NoDotAndDotDot); Q_FOREACH (const QString &subdir, entries) { dbgResources << "\tGoing to look in subdir" << subdir << "of" << startdir; result << filesInDir(startdir + '/' + subdir, filter, recursive); } } return result; } QStringList KoResourcePaths::findDirsInternal(const QString &type) { QStringList aliases = d->aliases(type); dbgResources << type << aliases << d->mapTypeToQStandardPaths(type); QStringList dirs; QStringList standardDirs = QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), "", QStandardPaths::LocateDirectory); appendResources(&dirs, standardDirs, true); Q_FOREACH (const QString &alias, aliases) { QStringList aliasDirs = QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), alias + '/', QStandardPaths::LocateDirectory); appendResources(&dirs, aliasDirs, true); #ifdef Q_OS_MACOS dbgResources << "MAC:" << getApplicationRoot(); QStringList bundlePaths; bundlePaths << getApplicationRoot() + "/share/krita/" + alias; bundlePaths << getApplicationRoot() + "/../share/krita/" + alias; dbgResources << "bundlePaths" << bundlePaths; appendResources(&dirs, bundlePaths, true); Q_ASSERT(!dirs.isEmpty()); #endif QStringList fallbackPaths; fallbackPaths << getApplicationRoot() + "/share/" + alias; fallbackPaths << getApplicationRoot() + "/share/krita/" + alias; appendResources(&dirs, fallbackPaths, true); } dbgResources << "findDirs: type" << type << "resource" << dirs; return dirs; } QStringList KoResourcePaths::findAllResourcesInternal(const QString &type, const QString &_filter, SearchOptions options) const { dbgResources << "====================================================="; dbgResources << type << _filter << QStandardPaths::standardLocations(d->mapTypeToQStandardPaths(type)); bool recursive = options & KoResourcePaths::Recursive; dbgResources << "findAllResources: type" << type << "filter" << _filter << "recursive" << recursive; QStringList aliases = d->aliases(type); QString filter = _filter; // In cases where the filter is like "color-schemes/*.colors" instead of "*.kpp", used with unregistered resource types if (filter.indexOf('*') > 0) { aliases << filter.split('*').first(); filter = '*' + filter.split('*')[1]; dbgResources << "Split up alias" << aliases << "filter" << filter; } QStringList resources; if (aliases.isEmpty()) { QStringList standardResources = QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), filter, QStandardPaths::LocateFile); dbgResources << "standardResources" << standardResources; appendResources(&resources, standardResources, true); dbgResources << "1" << resources; } QString extraResourceDirs = qgetenv("EXTRA_RESOURCE_DIRS"); dbgResources << "extraResourceDirs" << extraResourceDirs; if (!extraResourceDirs.isEmpty()) { Q_FOREACH(const QString &extraResourceDir, extraResourceDirs.split(':', QString::SkipEmptyParts)) { if (aliases.isEmpty()) { appendResources(&resources, filesInDir(extraResourceDir + '/' + type, filter, recursive), true); } else { Q_FOREACH (const QString &alias, aliases) { appendResources(&resources, filesInDir(extraResourceDir + '/' + alias + '/', filter, recursive), true); } } } } dbgResources << "\tresources from qstandardpaths:" << resources.size(); Q_FOREACH (const QString &alias, aliases) { dbgResources << "\t\talias:" << alias; QStringList dirs; QFileInfo dirInfo(alias); if (dirInfo.exists() && dirInfo.isDir() && dirInfo.isAbsolute()) { dirs << alias; } else { dirs << QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), alias, QStandardPaths::LocateDirectory) << getInstallationPrefix() + "share/" + alias + "/" << getInstallationPrefix() + "share/krita/" + alias + "/"; } + if(_filter.endsWith("*.myb")) { + dirs << "/usr/share" << "/home"; + } + Q_FOREACH (const QString &dir, dirs) { appendResources(&resources, filesInDir(dir, filter, recursive), true); } } dbgResources << "\tresources also from aliases:" << resources.size(); // if the original filter is "input/*", we only want share/input/* and share/krita/input/* here, but not // share/*. therefore, use _filter here instead of filter which was split into alias and "*". QFileInfo fi(_filter); QStringList prefixResources; prefixResources << filesInDir(getInstallationPrefix() + "share/" + fi.path(), fi.fileName(), false); prefixResources << filesInDir(getInstallationPrefix() + "share/krita/" + fi.path(), fi.fileName(), false); appendResources(&resources, prefixResources, true); dbgResources << "\tresources from installation:" << resources.size(); dbgResources << "====================================================="; return resources; } QStringList KoResourcePaths::resourceDirsInternal(const QString &type) { QStringList resourceDirs; QStringList aliases = d->aliases(type); Q_FOREACH (const QString &alias, aliases) { QStringList aliasDirs; aliasDirs << QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), alias, QStandardPaths::LocateDirectory); aliasDirs << getInstallationPrefix() + "share/" + alias + "/" << QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), alias, QStandardPaths::LocateDirectory); aliasDirs << getInstallationPrefix() + "share/krita/" + alias + "/" << QStandardPaths::locateAll(d->mapTypeToQStandardPaths(type), alias, QStandardPaths::LocateDirectory); appendResources(&resourceDirs, aliasDirs, true); } dbgResources << "resourceDirs: type" << type << resourceDirs; return resourceDirs; } QString KoResourcePaths::saveLocationInternal(const QString &type, const QString &suffix, bool create) { QStringList aliases = d->aliases(type); QString path; if (aliases.size() > 0) { path = QStandardPaths::writableLocation(d->mapTypeToQStandardPaths(type)) + '/' + aliases.first(); } else { path = QStandardPaths::writableLocation(d->mapTypeToQStandardPaths(type)); if (!path.endsWith("krita")) { path += "/krita"; } if (!suffix.isEmpty()) { path += "/" + suffix; } } QDir d(path); if (!d.exists() && create) { d.mkpath(path); } dbgResources << "saveLocation: type" << type << "suffix" << suffix << "create" << create << "path" << path; return path; } QString KoResourcePaths::locateInternal(const QString &type, const QString &filename) { QStringList aliases = d->aliases(type); QStringList locations; if (aliases.isEmpty()) { locations << QStandardPaths::locate(d->mapTypeToQStandardPaths(type), filename, QStandardPaths::LocateFile); } Q_FOREACH (const QString &alias, aliases) { locations << QStandardPaths::locate(d->mapTypeToQStandardPaths(type), (alias.endsWith('/') ? alias : alias + '/') + filename, QStandardPaths::LocateFile); } dbgResources << "locate: type" << type << "filename" << filename << "locations" << locations; if (locations.size() > 0) { return locations.first(); } else { return ""; } } QString KoResourcePaths::locateLocalInternal(const QString &type, const QString &filename, bool createDir) { QString path = saveLocationInternal(type, "", createDir); dbgResources << "locateLocal: type" << type << "filename" << filename << "CreateDir" << createDir << "path" << path; return path + '/' + filename; } diff --git a/plugins/paintops/CMakeLists.txt b/plugins/paintops/CMakeLists.txt index cf3377e38b..174718a820 100644 --- a/plugins/paintops/CMakeLists.txt +++ b/plugins/paintops/CMakeLists.txt @@ -1,18 +1,19 @@ include_directories(libpaintop) add_subdirectory( libpaintop ) add_subdirectory( defaultpresets ) add_subdirectory( defaultpaintops ) add_subdirectory( hairy ) add_subdirectory( deform ) add_subdirectory( curvebrush ) add_subdirectory( spray ) add_subdirectory( filterop ) add_subdirectory( experiment ) add_subdirectory( particle ) add_subdirectory( gridbrush ) add_subdirectory( hatching) add_subdirectory( sketch ) add_subdirectory( colorsmudge ) add_subdirectory( roundmarker ) add_subdirectory( tangentnormal ) +add_subdirectory( mypaint ) diff --git a/plugins/paintops/mypaint/CMakeLists.txt b/plugins/paintops/mypaint/CMakeLists.txt new file mode 100644 index 0000000000..1eb44dd485 --- /dev/null +++ b/plugins/paintops/mypaint/CMakeLists.txt @@ -0,0 +1,27 @@ +if(LIBMYPAINT_FOUND) + include_directories(${LIBMYPAINT_INCLUDE_DIR}) + link_directories(${LIBMYPAINT_LIBRARIES}) +endif() + +set(kritamypaintop_SOURCES + my_paintop_plugin.cpp + kis_my_paintop.cpp + #kis_myop_option.cpp + kis_my_paintop_settings.cpp + kis_my_paintop_settings_widget.cpp +) + +#ki18n_wrap_ui(kritasketchpaintop_SOURCES wdgsketchoptions.ui ) + +add_library(kritamypaintop MODULE ${kritamypaintop_SOURCES}) + +target_link_libraries(kritamypaintop kritalibpaintop mypaint) + +install(TARGETS kritamypaintop DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) + + +########### install files ############### + +install( FILES krita-mypaint.png DESTINATION ${DATA_INSTALL_DIR}/krita/images) + + diff --git a/plugins/paintops/mypaint/kis_my_paintop.cpp b/plugins/paintops/mypaint/kis_my_paintop.cpp new file mode 100644 index 0000000000..af39938737 --- /dev/null +++ b/plugins/paintops/mypaint/kis_my_paintop.cpp @@ -0,0 +1,32 @@ +#include "kis_my_paintop.h" + +#include "kis_paintop.h" +#include "kis_spacing_information.h" +#include "kis_my_paintop_settings.h" +#include +#include + +#include + + +KisMyPaintOp::KisMyPaintOp(const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image) + : KisPaintOp (painter) { + + MyPaintBrush *brush = mypaint_brush_new(); +} + +KisMyPaintOp::~KisMyPaintOp() { + +} + +KisSpacingInformation KisMyPaintOp::paintAt(const KisPaintInformation& info) { + + KisSpacingInformation spacingInfo; + return spacingInfo; +} + +KisSpacingInformation KisMyPaintOp::updateSpacingImpl(const KisPaintInformation &info) const +{ + KisSpacingInformation spacingInfo; + return spacingInfo; +} diff --git a/plugins/paintops/mypaint/kis_my_paintop.h b/plugins/paintops/mypaint/kis_my_paintop.h new file mode 100644 index 0000000000..c76d72fec5 --- /dev/null +++ b/plugins/paintops/mypaint/kis_my_paintop.h @@ -0,0 +1,40 @@ +#ifndef KIS_MY_PAINTOP_H_ +#define KIS_MY_PAINTOP_H_ + +#include +#include + +//#include "kis_spray_paintop_settings.h" +//#include "kis_brush_option.h" +// #include +// #include +// #include +// #include +// #include + +class KisPainter; + + +class KisMyPaintOp : public KisPaintOp +{ + +public: + + KisMyPaintOp(const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image); + ~KisMyPaintOp() override; + +protected: + + KisSpacingInformation paintAt(const KisPaintInformation& info) override; + + KisSpacingInformation updateSpacingImpl(const KisPaintInformation &info) const override; + + //KisTimingInformation updateTimingImpl(const KisPaintInformation &info) const override; + +private: + //KisSpacingInformation computeSpacing(const KisPaintInformation &info, qreal lodScale) const; + +private: +}; + +#endif // KIS_MY_PAINTOP_H_ diff --git a/plugins/paintops/mypaint/kis_my_paintop_settings.cpp b/plugins/paintops/mypaint/kis_my_paintop_settings.cpp new file mode 100644 index 0000000000..cedcbbfeff --- /dev/null +++ b/plugins/paintops/mypaint/kis_my_paintop_settings.cpp @@ -0,0 +1,200 @@ +#include + +#include +#include + +#include "kis_my_paintop_settings.h" +///#include "kis_sprayop_option.h" + +struct KisMyPaintOpSettings::Private +{ + QList uniformProperties; +}; + + +KisMyPaintOpSettings::KisMyPaintOpSettings() + : KisOutlineGenerationPolicy(KisCurrentOutlineFetcher::SIZE_OPTION | + KisCurrentOutlineFetcher::ROTATION_OPTION), + m_d(new Private) +{ +} + +KisMyPaintOpSettings::~KisMyPaintOpSettings() +{ +} + +void KisMyPaintOpSettings::setPaintOpSize(qreal value) +{ +// KisMyOptionProperties option; +// option.readOptionSetting(this); +// option.diameter = value; +// option.writeOptionSetting(this); +} + +qreal KisMyPaintOpSettings::paintOpSize() const +{ + +// KisSprayOptionProperties option; +// option.readOptionSetting(this); +// +// return option.diameter; + return 2; +} + +bool KisMyPaintOpSettings::paintIncremental() +{ + return (enumPaintActionType)getInt("PaintOpAction", WASH) == BUILDUP; +} + + +QPainterPath KisMyPaintOpSettings::brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom) +{ + QPainterPath path; +// if (mode.isVisible) { +// qreal width = getInt(SPRAY_DIAMETER); +// qreal height = getInt(SPRAY_DIAMETER) * getDouble(SPRAY_ASPECT); +// path = ellipseOutline(width, height, getDouble(SPRAY_SCALE), getDouble(SPRAY_ROTATION)); + +// path = outlineFetcher()->fetchOutline(info, this, path, mode, alignForZoom); + +// if (mode.forceFullSize) { +// QPainterPath tiltLine = +// makeTiltIndicator(info, QPointF(0.0, 0.0), width * 0.5, 3.0); +// path.addPath(outlineFetcher()->fetchOutline(info, this, tiltLine, mode, alignForZoom, 1.0, 0.0, true, 0, 0)); +// } +// } + return path; +} + +#include +#include "kis_paintop_preset.h" +#include "kis_paintop_settings_update_proxy.h" +#include "kis_standard_uniform_properties_factory.h" + + +QList KisMyPaintOpSettings::uniformProperties(KisPaintOpSettingsSP settings) +{ + QList props = + listWeakToStrong(m_d->uniformProperties); + +// if (props.isEmpty()) { +// { +// KisDoubleSliderBasedPaintOpPropertyCallback *prop = +// new KisDoubleSliderBasedPaintOpPropertyCallback( +// KisDoubleSliderBasedPaintOpPropertyCallback::Double, +// "spacing", +// i18n("Spacing"), +// settings, 0); + +// prop->setRange(0.01, 10); +// prop->setSingleStep(0.01); +// prop->setExponentRatio(3.0); + +// prop->setReadCallback( +// [](KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); + +// prop->setValue(option.spacing); +// }); +// prop->setWriteCallback( +// [](KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); +// option.spacing = prop->value().toReal(); +// option.writeOptionSetting(prop->settings().data()); +// }); + +// QObject::connect(preset()->updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue())); +// prop->requestReadValue(); +// props << toQShared(prop); +// } +// { +// KisIntSliderBasedPaintOpPropertyCallback *prop = +// new KisIntSliderBasedPaintOpPropertyCallback( +// KisIntSliderBasedPaintOpPropertyCallback::Int, +// "spray_particlecount", +// i18n("Particle Count"), +// settings, 0); + +// prop->setRange(0, 1000); +// prop->setExponentRatio(3); + +// prop->setReadCallback( +// [](KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); + +// prop->setValue(int(option.particleCount)); +// }); +// prop->setWriteCallback( +// [](KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); +// option.particleCount = prop->value().toInt(); +// option.writeOptionSetting(prop->settings().data()); +// }); +// prop->setIsVisibleCallback( +// [](const KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); +// return !option.useDensity; +// }); + +// QObject::connect(preset()->updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue())); +// prop->requestReadValue(); +// props << toQShared(prop); +// } +// { +// KisDoubleSliderBasedPaintOpPropertyCallback *prop = +// new KisDoubleSliderBasedPaintOpPropertyCallback( +// KisDoubleSliderBasedPaintOpPropertyCallback::Double, +// "spray_density", +// i18n("Density"), +// settings, 0); + +// prop->setRange(0.1, 100); +// prop->setSingleStep(0.01); +// prop->setDecimals(2); +// prop->setExponentRatio(3); +// prop->setSuffix(i18n("%")); + +// prop->setReadCallback( +// [](KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); +// prop->setValue(option.coverage); +// }); +// prop->setWriteCallback( +// [](KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); +// option.coverage = prop->value().toReal(); +// option.writeOptionSetting(prop->settings().data()); +// }); +// prop->setIsVisibleCallback( +// [](const KisUniformPaintOpProperty *prop) { +// KisSprayOptionProperties option; +// option.readOptionSetting(prop->settings().data()); +// return option.useDensity; +// }); + +// QObject::connect(preset()->updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue())); +// prop->requestReadValue(); +// props << toQShared(prop); +// } +// } +// { +// using namespace KisStandardUniformPropertiesFactory; + +// Q_FOREACH (KisUniformPaintOpPropertySP prop, KisPaintOpSettings::uniformProperties(settings)) { +// if (prop->id() == opacity.id() || +// prop->id() == size.id()) { + +// props.prepend(prop); +// } +// } +// } + + return props; +} diff --git a/plugins/paintops/mypaint/kis_my_paintop_settings.h b/plugins/paintops/mypaint/kis_my_paintop_settings.h new file mode 100644 index 0000000000..b7ab6cff07 --- /dev/null +++ b/plugins/paintops/mypaint/kis_my_paintop_settings.h @@ -0,0 +1,44 @@ +#ifndef KIS_MY_PAINTOP_SETTINGS_H_ +#define KIS_MY_PAINTOP_SETTINGS_H_ + +#include + +#include +#include + +#include +#include "kis_my_paintop_settings_widget.h" + + +class KisMyPaintOpSettings : public KisOutlineGenerationPolicy +{ +public: + KisMyPaintOpSettings(); + ~KisMyPaintOpSettings() override; + + void setPaintOpSize(qreal value) override; + qreal paintOpSize() const override; + + QPainterPath brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom) override; + + QString modelName() const override { + return "airbrush"; + } + + bool paintIncremental() override; + +protected: + + QList uniformProperties(KisPaintOpSettingsSP settings) override; + +private: + Q_DISABLE_COPY(KisMyPaintOpSettings) + + struct Private; + const QScopedPointer m_d; + +}; + +typedef KisSharedPtr KisMyPaintOpSettingsSP; + +#endif diff --git a/plugins/paintops/mypaint/kis_my_paintop_settings_widget.cpp b/plugins/paintops/mypaint/kis_my_paintop_settings_widget.cpp new file mode 100644 index 0000000000..eff36b52d1 --- /dev/null +++ b/plugins/paintops/mypaint/kis_my_paintop_settings_widget.cpp @@ -0,0 +1,33 @@ +#include "kis_my_paintop_settings_widget.h" + +#include "kis_my_paintop_settings.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +KisMyPaintOpSettingsWidget:: KisMyPaintOpSettingsWidget(QWidget* parent) + : KisPaintOpSettingsWidget(parent) +{ +} + +KisMyPaintOpSettingsWidget::~ KisMyPaintOpSettingsWidget() +{ +} + +KisPropertiesConfigurationSP KisMyPaintOpSettingsWidget::configuration() const +{ + KisMyPaintOpSettings* config = new KisMyPaintOpSettings(); + config->setOptionsWidget(const_cast(this)); + config->setProperty("paintop", "mypaintbrush"); // XXX: make this a const id string + writeConfiguration(config); + return config; +} diff --git a/plugins/paintops/mypaint/kis_my_paintop_settings_widget.h b/plugins/paintops/mypaint/kis_my_paintop_settings_widget.h new file mode 100644 index 0000000000..96bccbcb1d --- /dev/null +++ b/plugins/paintops/mypaint/kis_my_paintop_settings_widget.h @@ -0,0 +1,18 @@ +#ifndef KIS_MYPAINTOP_SETTINGS_WIDGET_H_ +#define KIS_MYPAINTOP_SETTINGS_WIDGET_H_ + +#include + +class KisMyPaintOpSettingsWidget : public KisPaintOpSettingsWidget +{ + Q_OBJECT + +public: + KisMyPaintOpSettingsWidget(QWidget* parent = 0); + ~KisMyPaintOpSettingsWidget() override; + + KisPropertiesConfigurationSP configuration() const override; + +}; + +#endif diff --git a/plugins/paintops/mypaint/krita-mypaint.png b/plugins/paintops/mypaint/krita-mypaint.png new file mode 100644 index 0000000000..8e0a1b77c7 Binary files /dev/null and b/plugins/paintops/mypaint/krita-mypaint.png differ diff --git a/plugins/paintops/mypaint/kritamypaintop.json b/plugins/paintops/mypaint/kritamypaintop.json new file mode 100644 index 0000000000..e5355b9358 --- /dev/null +++ b/plugins/paintops/mypaint/kritamypaintop.json @@ -0,0 +1,9 @@ +{ + "Id": "MyPaint Brush", + "Type": "Service", + "X-KDE-Library": "kritamypaintop", + "X-KDE-ServiceTypes": [ + "Krita/Paintop" + ], + "X-Krita-Version": "28" +} diff --git a/plugins/paintops/mypaint/my_paintop_plugin.cpp b/plugins/paintops/mypaint/my_paintop_plugin.cpp new file mode 100644 index 0000000000..1ab93c33dc --- /dev/null +++ b/plugins/paintops/mypaint/my_paintop_plugin.cpp @@ -0,0 +1,32 @@ +#include "my_paintop_plugin.h" + +#include + +#include +#include + +#include +#include +#include "kis_my_paintop.h" +#include "kis_my_paintop_settings.h" +#include "kis_my_paintop_settings_widget.h" +#include "kis_simple_paintop_factory.h" + +#include "kis_global.h" + +K_PLUGIN_FACTORY_WITH_JSON(MyPaintOpPluginFactory, "kritamypaintop.json", registerPlugin();) + + +MyPaintOpPlugin::MyPaintOpPlugin(QObject *parent, const QVariantList &) + : QObject(parent) +{ + KisPaintOpRegistry *r = KisPaintOpRegistry::instance(); + r->add(new KisSimplePaintOpFactory("mypaintbrush", i18n("MyPaint"), KisPaintOpFactory::categoryStable() , "krita-mypaint.png", QString(), QStringList(), 6)); + +} + +MyPaintOpPlugin::~MyPaintOpPlugin() +{ +} + +#include "my_paintop_plugin.moc" diff --git a/plugins/paintops/mypaint/my_paintop_plugin.h b/plugins/paintops/mypaint/my_paintop_plugin.h new file mode 100644 index 0000000000..2cef13a477 --- /dev/null +++ b/plugins/paintops/mypaint/my_paintop_plugin.h @@ -0,0 +1,18 @@ +#ifndef MY_PAINTOP_PLUGIN_H_ +#define MY_PAINTOP_PLUGIN_H_ + +#include +#include + +/** + * A plugin wrapper that adds the paintop factories to the paintop registry. + */ +class MyPaintOpPlugin : public QObject +{ + Q_OBJECT +public: + MyPaintOpPlugin(QObject *parent, const QVariantList &); + ~MyPaintOpPlugin() override; +}; + +#endif // MY_PAINTOP_PLUGIN_H_