diff --git a/README_PACKAGERS.md b/README_PACKAGERS.md index 53f3da7d48..ef66f9d14e 100644 --- a/README_PACKAGERS.md +++ b/README_PACKAGERS.md @@ -1,76 +1,74 @@ = Notes for Packagers = == Patching Qt == Qt 5.6 is currently the recommended version to build Krita with on all platforms. However, Qt 5.6 on Linux needs to be patched for https://bugreports.qt.io/browse/QTBUG-44964 . The patch in 3rdparty/ext_qt/qt-no-motion-compression.diff == Package Contents == We recommend that all of Krita packaged in one package: there is no need to split Krita up. In particular, do not make a separate package out of the plugins directory; without the plugins Krita will not even start. Krita does not install header files, so there is no need for a corresponding -dev(el) package. == Third Party Libraries == The top-level 3rd-party directory is not relevant for packaging: it only contains CMake projects for all of Krita's dependencies which are used for building Krita on Windows and OSX. It is not called from the top-level CMakeLists.txt project. There are four forks of 3rd party libraries that are relevant and cannot be replaced by system libraries: * plugins/impex/raw/3rdparty contains a fork of kdcraw. Upstread removed most functionality from this library and is in general unable to provide a stable API. The library has been renamed to avoid conflicts with upstream kdcraw. * plugins/impex/xcf/3rdparty contains the xcftools code. This has never been released as a library * plugins/extensions/gmic/3rdparty contains G'Mic. This has never been released as a shared library. * libs/image/3rdparty contains einspline. This code is directly linke d into the kritaimage library and has never been released as a separate library. == Build flags == -Packagers must build krita with the PACKAGERS_BUILD flag enabled. This makes sure that object files for all SIMD vectorization extensions krita supports are built. The right one is then selected run-time. - Krita no longer supports a build without OpenGL. For alpha and beta packages, please build with debug output enabled, but for production packages the -DCMAKE_CXX_FLAGS="-DKDE_NO_DEBUG_OUTPUT" is recommended. A significant performance increase will be the result. If you build Krita with RelWithDebInfo to be able to create a corresponding -dbg package, please define -DQT_NO_DEBUG=1 as well to disable asserts. == Dependencies == Krita depends on: * boost and the boost-system library * eigen3 * exiv2 * fftw3 * gsl * ilmbase * jpeg: Note that libjpeg-turbo is recommended. * lcms2 * libcurl * libraw * opencolorio * openexr * png * poppler-qt5 * pthreads * qt-5: Note that Qt 5.6 is _strongly_ recommended. Qt 5.5 has bugs that interfere with proper handling of tablet events * tiff * vc: this is a build-time dependency only * zlib And the following KDE Frameworks: * Archive * Completion * Config * CoreAddons * GuiAddons * I18n * ItemModels * ItemViews * KCrash * WidgetsAddons * WindowSystem diff --git a/krita/krita.action b/krita/krita.action index 27dacce096..fe025f8224 100644 --- a/krita/krita.action +++ b/krita/krita.action @@ -1,2948 +1,2948 @@ General Open Resources Folder Opens a file browser at the location Krita saves resources such as brushes to. Opens a file browser at the location Krita saves resources such as brushes to. Open Resources Folder 0 0 false Cleanup removed files... Cleanup removed files Cleanup removed files 0 0 false C&ascade Cascade Cascade 10 0 false &Tile Tile Tile 10 0 false Create Resource Bundle... Create Resource Bundle Create Resource Bundle 0 0 false Show File Toolbar Show File Toolbar Show File Toolbar false Show color selector Show color selector Show color selector Shift+I false Show MyPaint shade selector Show MyPaint shade selector Show MyPaint shade selector Shift+M false Show minimal shade selector Show minimal shade selector Show minimal shade selector Shift+N false Show color history Show color history Show color history H false Show common colors Show common colors Show common colors U false Show Tool Options Show Tool Options Show Tool Options \ false Show Brush Editor Show Brush Editor Show Brush Editor F5 false Show Brush Presets Show Brush Presets Show Brush Presets F6 false Toggle Tablet Debugger Toggle Tablet Debugger Toggle Tablet Debugger 0 0 Ctrl+Shift+T false Rename Composition... Rename Composition Rename Composition 0 0 false Update Composition Update Composition Update Composition 0 0 false Painting Make brush color lighter Make brush color lighter Make brush color lighter 0 0 L false Make brush color darker Make brush color darker Make brush color darker 0 0 K false Make brush color more saturated Make brush color more saturated Make brush color more saturated false Make brush color more desaturated Make brush color more desaturated Make brush color more desaturated false Shift brush color hue clockwise Shift brush color hue clockwise Shift brush color hue clockwise false Shift brush color hue counter-clockwise Shift brush color hue counter-clockwise Shift brush color hue counter-clockwise false Make brush color more red Make brush color more red Make brush color more red false Make brush color more green Make brush color more green Make brush color more green false Make brush color more blue Make brush color more blue Make brush color more blue false Make brush color more yellow Make brush color more yellow Make brush color more yellow false Increase opacity Increase opacity Increase opacity 0 0 O false Decrease opacity Decrease opacity Decrease opacity 0 0 I false draw-eraser Set eraser mode Set eraser mode Set eraser mode 10000 0 E true view-refresh Reload Original Preset Reload Original Preset Reload Original Preset 10000 false transparency-unlocked Preserve Alpha Preserve Alpha Preserve Alpha 10000 true transform_icons_penPressure Use Pen Pressure Use Pen Pressure Use Pen Pressure 10000 true symmetry-horizontal Horizontal Mirror Tool Horizontal Mirror Tool Horizontal Mirror Tool 10000 true symmetry-vertical Vertical Mirror Tool Vertical Mirror Tool Vertical Mirror Tool 10000 true Paste at cursor Paste at cursor Paste at cursor 0 0 false &Invert Selection Invert current selection Invert Selection 10000000000 100 Ctrl+Shift+I false Fill with Foreground Color (Opacity) Fill with Foreground Color (Opacity) Fill with Foreground Color (Opacity) 10000 1 Ctrl+Shift+Backspace false Fill with Background Color (Opacity) Fill with Background Color (Opacity) Fill with Background Color (Opacity) 10000 1 Ctrl+Backspace false Fill with Pattern (Opacity) Fill with Pattern (Opacity) Fill with Pattern (Opacity) 10000 1 false &Toggle Selection Display Mode Toggle Selection Display Mode Toggle Selection Display Mode 0 0 false Next Favourite Preset Next Favourite Preset Next Favourite Preset , false Previous Favourite Preset Previous Favourite Preset Previous Favourite Preset . false - + preset-switcher Switch to Previous Preset Switch to Previous Preset Switch to Previous Preset / false Hide Brushes and Stuff Toolbar Hide Brushes and Stuff Toolbar Hide Brushes and Stuff Toolbar true Reset Foreground and Background Color Reset Foreground and Background Color Reset Foreground and Background Color D false Swap Foreground and Background Color Swap Foreground and Background Color Swap Foreground and Background Color X false smoothing-weighted Brush Smoothing: Weighted Brush Smoothing: Weighted Brush Smoothing: Weighted false smoothing-no Brush Smoothing: Disabled Brush Smoothing: Disabled Brush Smoothing: Disabled false smoothing-stabilizer Brush Smoothing: Stabilizer Brush Smoothing: Stabilizer Brush Smoothing: Stabilizer false Decrease Brush Size Decrease Brush Size Decrease Brush Size 0 0 [ false smoothing-basic Brush Smoothing: Basic Brush Smoothing: Basic Brush Smoothing: Basic false Increase Brush Size Increase Brush Size Increase Brush Size 0 0 ] false Toggle Assistant Toggle Assistant ToggleAssistant Ctrl+Shift+L true Undo Polygon Selection Points Undo Polygon Selection Points Undo Polygon Selection Points Shift+Z false Fill with Foreground Color (Opacity) Fill with Foreground Color (Opacity) Fill with Foreground Color (Opacity) 10000 1 Ctrl+Shift+Backspace false Fill with Background Color (Opacity) Fill with Background Color (Opacity) Fill with Background Color (Opacity) 10000 1 Ctrl+Backspace false Fill with Pattern (Opacity) Fill with Pattern (Opacity) Fill with Pattern (Opacity) 10000 1 false Convert &to Shape Convert to Shape Convert to Shape 10000000000 0 false &Select Opaque Select Opaque Select Opaque 100000 100 false &Show Global Selection Mask Shows global selection as a usual selection mask in <interface>Layers</interface> docker Show Global Selection Mask 100000 100 true Filters color-to-alpha &Color to Alpha... Color to Alpha Color to Alpha 10000 0 false &Top Edge Detection Top Edge Detection Top Edge Detection 10000 0 false &Index Colors... Index Colors Index Colors 10000 0 false Emboss Horizontal &Only Emboss Horizontal Only Emboss Horizontal Only 10000 0 false D&odge Dodge Dodge 10000 0 false &Sharpen Sharpen Sharpen 10000 0 false B&urn Burn Burn 10000 0 false &Mean Removal Mean Removal Mean Removal 10000 0 false &Gaussian Blur... Gaussian Blur Gaussian Blur 10000 0 false Emboss &in All Directions Emboss in All Directions Emboss in All Directions 10000 0 false &Small Tiles... Small Tiles Small Tiles 10000 0 false &Levels... Levels Levels 10000 0 Ctrl+L false &Sobel... Sobel Sobel 10000 0 false &Wave... Wave Wave 10000 0 false &Motion Blur... Motion Blur Motion Blur 10000 0 false &Color Adjustment curves... Color Adjustment curves Color Adjustment curves 10000 0 Ctrl+M false Pi&xelize... Pixelize Pixelize 10000 0 false Emboss (&Laplacian) Emboss (Laplacian) Emboss (Laplacian) 10000 0 false &Left Edge Detection Left Edge Detection Left Edge Detection 10000 0 false &Blur... Blur Blur 10000 0 false &Raindrops... Raindrops Raindrops 10000 0 false &Bottom Edge Detection Bottom Edge Detection Bottom Edge Detection 10000 0 false &Random Noise... Random Noise Random Noise 10000 0 false &Brightness/Contrast curve... Brightness/Contrast curve Brightness/Contrast curve 10000 0 false Colo&r Balance.. Color Balance.. Color Balance.. 10000 0 Ctrl+B false &Phong Bumpmap... Phong Bumpmap Phong Bumpmap 10000 0 false &Desaturate Desaturate Desaturate 10000 0 Ctrl+Shift+U false Color &Transfer... Color Transfer Color Transfer 10000 0 false Emboss &Vertical Only Emboss Vertical Only Emboss Vertical Only 10000 0 false &Lens Blur... Lens Blur Lens Blur 10000 0 false M&inimize Channel Minimize Channel Minimize Channel 10000 0 false M&aximize Channel Maximize Channel Maximize Channel 10000 0 false &Oilpaint... Oilpaint Oilpaint 10000 0 false &Right Edge Detection Right Edge Detection Right Edge Detection 10000 0 false &Auto Contrast Auto Contrast Auto Contrast 10000 0 false &Round Corners... Round Corners Round Corners 10000 0 false &Unsharp Mask... Unsharp Mask Unsharp Mask 10000 0 false &Emboss with Variable Depth... Emboss with Variable Depth Emboss with Variable Depth 10000 0 false Emboss &Horizontal && Vertical Emboss Horizontal & Vertical Emboss Horizontal & Vertical 10000 0 false Random &Pick... Random Pick Random Pick 10000 0 false &Gaussian Noise Reduction... Gaussian Noise Reduction Gaussian Noise Reduction 10000 0 false &Posterize... Posterize Posterize 10000 0 false &Wavelet Noise Reducer... Wavelet Noise Reducer Wavelet Noise Reducer 10000 0 false &HSV Adjustment... HSV Adjustment HSV Adjustment 10000 0 Ctrl+U false Tool Shortcuts Dynamic Brush Tool Dynamic Brush Tool Dynamic Brush Tool false Crop Tool Crop the image to an area Crop the image to an area C false Polygon Tool Polygon Tool. Shift-mouseclick ends the polygon. Polygon Tool. Shift-mouseclick ends the polygon. false References References References false Rectangle Tool Rectangle Tool Rectangle Tool false Multibrush Tool Multibrush Tool Multibrush Tool Q false Shape Manipulation Tool Shape Manipulation Tool Shape Manipulation Tool false Color Picker Select a color from the image or current layer Select a color from the image or current layer P false Text Editing Tool Text editing Text editing false Outline Selection Tool Outline Selection Tool Outline Selection Tool false Artistic Text Tool Artistic text editing Artistic text editing false Bezier Curve Selection Tool Select a Bezier Curve Selection Tool false Similar Color Selection Tool Select a Similar Color Selection Tool false Fill Tool Fill a contiguous area of color with a color, or fill a selection. Fill a contiguous area of color with a color, or fill a selection. F false Line Tool Line Tool Line Tool false Freehand Path Tool Freehand Path Tool Freehand Path Tool false Bezier Curve Tool Bezier Curve Tool. Shift-mouseclick ends the curve. Bezier Curve Tool. Shift-mouseclick ends the curve. false Ellipse Tool Ellipse Tool Ellipse Tool false Freehand Brush Tool Freehand Brush Tool Freehand Brush Tool B false Create object Create object Create object false Elliptical Selection Tool Elliptical Selection Tool Elliptical Selection Tool J false Contiguous Selection Tool Contiguous Selection Tool Contiguous Selection Tool false Pattern editing Pattern editing Pattern editing false Review Review Review false Draw a gradient. Draw a gradient. Draw a gradient. G false Polygonal Selection Tool Polygonal Selection Tool Polygonal Selection Tool false Measurement Tool Measure the distance between two points Measure the distance between two points false Rectangular Selection Tool Rectangular Selection Tool Rectangular Selection Tool Ctrl+R false Move Tool Move a layer Move a layer T false Vector Image Tool Vector Image (EMF/WMF/SVM/SVG) tool Vector Image (EMF/WMF/SVM/SVG) tool false Calligraphy Calligraphy Calligraphy false Path editing Path editing Path editing false Polyline Tool Polyline Tool. Shift-mouseclick ends the polyline. Polyline Tool. Shift-mouseclick ends the polyline. false Transform Tool Transform a layer or a selection Transform a layer or a selection Ctrl+T false Ruler assistant editor tool Ruler assistant editor tool Ruler assistant editor tool false Text tool Text tool Text tool false Gradient Editing Tool Gradient editing Gradient editing false Blending Modes Select Normal Blending Mode Select Normal Blending Mode Select Normal Blending Mode 0 0 Alt+Shift+N false Select Dissolve Blending Mode Select Dissolve Blending Mode Select Dissolve Blending Mode 0 0 Alt+Shift+I false Select Behind Blending Mode Select Behind Blending Mode Select Behind Blending Mode 0 0 Alt+Shift+Q false Select Clear Blending Mode Select Clear Blending Mode Select Clear Blending Mode 0 0 Alt+Shift+R false Select Darken Blending Mode Select Darken Blending Mode Select Darken Blending Mode 0 0 Alt+Shift+K false Select Multiply Blending Mode Select Multiply Blending Mode Select Multiply Blending Mode 0 0 Alt+Shift+M false Select Color Burn Blending Mode Select Color Burn Blending Mode Select Color Burn Blending Mode 0 0 Alt+Shift+B false Select Linear Burn Blending Mode Select Linear Burn Blending Mode Select Linear Burn Blending Mode 0 0 Alt+Shift+A false Select Lighten Blending Mode Select Lighten Blending Mode Select Lighten Blending Mode 0 0 Alt+Shift+G false Select Screen Blending Mode Select Screen Blending Mode Select Screen Blending Mode 0 0 Alt+Shift+S false Select Color Dodge Blending Mode Select Color Dodge Blending Mode Select Color Dodge Blending Mode 0 0 Alt+Shift+D false Select Linear Dodge Blending Mode Select Linear Dodge Blending Mode Select Linear Dodge Blending Mode 0 0 Alt+Shift+W false Select Overlay Blending Mode Select Overlay Blending Mode Select Overlay Blending Mode 0 0 Alt+Shift+O false Select Soft Light Blending Mode Select Soft Light Blending Mode Select Soft Light Blending Mode 0 0 Alt+Shift+F false Select Hard Light Blending Mode Select Hard Light Blending Mode Select Hard Light Blending Mode 0 0 Alt+Shift+H false Select Vivid Light Blending Mode Select Vivid Light Blending Mode Select Vivid Light Blending Mode 0 0 Alt+Shift+V false Select Linear Light Blending Mode Select Linear Light Blending Mode Select Linear Light Blending Mode 0 0 Alt+Shift+J false Select Pin Light Blending Mode Select Pin Light Blending Mode Select Pin Light Blending Mode 0 0 Alt+Shift+Z false Select Hard Mix Blending Mode Select Hard Mix Blending Mode Select Hard Mix Blending Mode 0 0 Alt+Shift+L false Select Difference Blending Mode Select Difference Blending Mode Select Difference Blending Mode 0 0 Alt+Shift+E false Select Exclusion Blending Mode Select Exclusion Blending Mode Select Exclusion Blending Mode 0 0 Alt+Shift+X false Select Hue Blending Mode Select Hue Blending Mode Select Hue Blending Mode 0 0 Alt+Shift+U false Select Saturation Blending Mode Select Saturation Blending Mode Select Saturation Blending Mode 0 0 Alt+Shift+T false Select Color Blending Mode Select Color Blending Mode Select Color Blending Mode 0 0 Alt+Shift+C false Select Luminosity Blending Mode Select Luminosity Blending Mode Select Luminosity Blending Mode 0 0 Alt+Shift+Y false Animation Previous frame Move to previous frame Move to previous frame 1 0 false Next frame Move to next frame Move to next frame 1 0 false Play / pause animation Play / pause animation Play / pause animation 1 0 false Add blank frame Add blank frame Add blank frame 100000 0 false Copy Frame Add duplicate frame Add duplicate frame 100000 0 false Toggle onion skin Toggle onion skin Toggle onion skin 100000 0 false Previous Keyframe false Next Keyframe false First Frame false Last Frame false Auto Frame Mode true true Add blank frame Add blank frame Add blank frame 100000 0 false Show in Timeline true Layers Activate next layer Activate next layer Activate next layer 1000 0 PgUp false Activate previous layer Activate previous layer Activate previous layer 1000 0 PgDown false Activate previously selected layer Activate previously selected layer Activate previously selected layer 1000 0 ; false groupLayer &Group Layer Group Layer Group Layer 1000 0 false cloneLayer &Clone Layer Clone Layer Clone Layer 1000 0 false vectorLayer &Vector Layer Vector Layer Vector Layer 1000 0 false filterLayer &Filter Layer... Filter Layer Filter Layer 1000 0 false fillLayer &Fill Layer... Fill Layer Fill Layer 1000 0 false fileLayer &File Layer... File Layer File Layer 1000 0 false transparencyMask &Transparency Mask Transparency Mask Transparency Mask 100000 0 false filterMask &Filter Mask... Filter Mask Filter Mask 100000 0 false filterMask &Colorize Mask Colorize Mask Colorize Mask 100000 0 false transformMask &Transform Mask... Transform Mask Transform Mask 100000 0 false selectionMask &Local Selection Local Selection Local Selection 100000 0 false view-filter &Isolate Layer Isolate Layer Isolate Layer 1000 0 true paintLayer &Paint Layer Paint Layer Paint Layer 1000 0 Insert false &New Layer From Visible New layer from visible New layer from visible 1000 0 false duplicatelayer &Duplicate Layer or Mask Duplicate Layer or Mask Duplicate Layer or Mask 1000 0 Ctrl+J false &Cut Selection to New Layer Cut Selection to New Layer Cut Selection to New Layer 100000000 1 Ctrl+Shift+J false Copy &Selection to New Layer Copy Selection to New Layer Copy Selection to New Layer 100000000 0 Ctrl+Alt+J false Copy Layer Copy layer to clipboard Copy layer to clipboard 10000 0 false Cut Layer Cut layer to clipboard Cut layer to clipboard 10000 0 false Paste Layer Paste layer from clipboard Paste layer from clipboard 10000 0 false Quick Group Create a group layer containing selected layers Quick Group 100000 0 Ctrl+G false Quick Ungroup Remove grouping of the layers or remove one layer out of the group Quick Ungroup 100000 0 Ctrl+Alt+G false Quick Clipping Group Group selected layers and add a layer with clipped alpha channel Quick Clipping Group 100000 0 Ctrl+Shift+G false All Layers Select all layers Select all layers 10000 0 false Visible Layers Select all visible layers Select all visible layers 10000 0 false Locked Layers Select all locked layers Select all locked layers 10000 0 false Invisible Layers Select all invisible layers Select all invisible layers 10000 0 false Unlocked Layers Select all unlocked layers Select all unlocked layers 10000 0 false document-save &Save Layer/Mask... Save Layer/Mask Save Layer/Mask 1000 0 false document-save Save &Group Layers... Save Group Layers Save Group Layers 100000 0 false Convert group to &animated layer Convert child layers into animation frames Convert child layers into animation frames 100000 0 false I&mport Layer... Import Layer Import Layer 100000 0 false paintLayer &as Paint Layer... as Paint Layer as Paint Layer 1000 0 false transparencyMask as &Transparency Mask... as Transparency Mask as Transparency Mask 1000 0 false filterMask as &Filter Mask... as Filter Mask as Filter Mask 1000 0 false selectionMask as &Selection Mask... as Selection Mask as Selection Mask 1000 0 false paintLayer to &Paint Layer to Paint Layer to Paint Layer 1000 0 false transparencyMask to &Transparency Mask to Transparency Mask to Transparency Mask 1000 0 false filterMask to &Filter Mask... to Filter Mask to Filter Mask 1000 0 false selectionMask to &Selection Mask to Selection Mask to Selection Mask 1000 0 false transparencyMask &Alpha into Mask Alpha into Mask Alpha into Mask 100000 10 false transparency-enabled &Write as Alpha Write as Alpha Write as Alpha 1000000 1 false document-save &Save Merged... Save Merged Save Merged 1000000 0 false split-layer Split Layer... Split Layer Split Layer 1000 0 false Wavelet Decompose ... Wavelet Decompose Wavelet Decompose 1000 1 false symmetry-horizontal Mirror Layer Hori&zontally Mirror Layer Horizontally Mirror Layer Horizontally 1000 1 false symmetry-vertical Mirror Layer &Vertically Mirror Layer Vertically Mirror Layer Vertically 1000 1 false &Rotate Layer... Rotate Layer Rotate Layer 100000 1 false object-rotate-right Rotate &Layer 90° to the Right Rotate Layer 90° to the Right Rotate Layer 90° to the Right 100000 1 false object-rotate-left Rotate Layer &90° to the Left Rotate Layer 90° to the Left Rotate Layer 90° to the Left 100000 1 false Rotate Layer &180° Rotate Layer 180° Rotate Layer 180° 100000 1 false Scale &Layer to new Size... Scale Layer to new Size Scale Layer to new Size 100000 1 false &Shear Layer... Shear Layer Shear Layer 100000 1 false &Offset Layer... Offset Layer Offset Layer 100000 1 false Clones &Array... Clones Array Clones Array 100000 0 false &Edit metadata... Edit metadata Edit metadata 100000 1 false &Histogram... Histogram Histogram 100000 0 false &Convert Layer Color Space... Convert Layer Color Space Convert Layer Color Space 100000 1 false merge-layer-below &Merge with Layer Below Merge with Layer Below Merge with Layer Below 100000 0 Ctrl+E false &Flatten Layer Flatten Layer Flatten Layer 100000 0 false Ras&terize Layer Rasterize Layer Rasterize Layer 10000000 1 false Flatten ima&ge Flatten image Flatten image 100000 0 Ctrl+Shift+E false La&yer Style... Layer Style Layer Style 100000 1 false Move into previous group Move into previous group Move into previous group 0 0 false Move into next group Move into next group Move into next group 0 0 false Rename current layer Rename current layer Rename current layer 100000 0 F2 false deletelayer &Remove Layer Remove Layer Remove Layer 1000 1 Shift+Delete false arrowupblr Move Layer or Mask Up Move Layer or Mask Up Ctrl+PgUp false arrowdown Move Layer or Mask Down Move Layer or Mask Down Ctrl+PgDown false properties &Properties... Properties Properties 1000 1 F3 false diff --git a/krita/pics/svg/dark_preset-switcher.svg b/krita/pics/svg/dark_preset-switcher.svg new file mode 100644 index 0000000000..5c1047ed02 --- /dev/null +++ b/krita/pics/svg/dark_preset-switcher.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/krita/pics/svg/light_preset-switcher.svg b/krita/pics/svg/light_preset-switcher.svg new file mode 100644 index 0000000000..38a28896ff --- /dev/null +++ b/krita/pics/svg/light_preset-switcher.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/krita/pics/svg/svg-icons.qrc b/krita/pics/svg/svg-icons.qrc index 93f0b518dd..312f78b568 100644 --- a/krita/pics/svg/svg-icons.qrc +++ b/krita/pics/svg/svg-icons.qrc @@ -1,148 +1,150 @@ broken-preset.svgz dark_addblankframe.svg dark_addcolor.svg dark_addduplicateframe.svg dark_deletekeyframe.svg dark_docker_lock_a.svg dark_docker_lock_b.svg dark_layer-locked.svg dark_layer-unlocked.svg dark_nextframe.svg dark_nextkeyframe.svg dark_lastframe.svg dark_prevkeyframe.svg dark_firstframe.svg dark_pallete_librarysvg.svg dark_passthrough-disabled.svg dark_passthrough-enabled.svg dark_prevframe.svg dark_selection-mode_ants.svg dark_selection-mode_invisible.svg dark_selection-mode_mask.svg dark_transparency-disabled.svg dark_transparency-enabled.svg dark_trim-to-image.svg delete.svgz layer-style-disabled.svg layer-style-enabled.svg light_addblankframe.svg light_addcolor.svg light_addduplicateframe.svg light_deletekeyframe.svg light_docker_lock_a.svg light_docker_lock_b.svg light_layer-locked.svg light_layer-unlocked.svg light_nextframe.svg light_pallete_library.svg light_passthrough-disabled.svgz light_passthrough-enabled.svgz light_prevframe.svg light_nextkeyframe.svg light_lastframe.svg light_prevkeyframe.svg light_firstframe.svg light_selection-mode_ants.svg light_selection-mode_invisible.svg light_selection-mode_mask.svg light_timeline_keyframe.svg light_transparency-disabled.svg light_transparency-enabled.svg light_trim-to-image.svg paintop_presets_disabled.svgz paintop_settings_01.svgz selection-info.svg selection-mode_invisible.svg svg-icons.qrc transparency-locked.svg transparency-unlocked.svg workspace-chooser.svg light_lazyframeOn.svg light_lazyframeOff.svg dark_lazyframeOn.svg dark_lazyframeOff.svg dark_mirror-view.svg light_mirror-view.svg dark_rotation-reset.svg light_rotation-reset.svg light_smoothing-basic.svg light_smoothing-no.svg light_smoothing-stabilizer.svg light_smoothing-weighted.svg dark_smoothing-basic.svg dark_smoothing-no.svg dark_smoothing-stabilizer.svg dark_smoothing-weighted.svg light_merge-layer-below.svg dark_merge-layer-below.svg light_rotate-canvas-left.svg light_rotate-canvas-right.svg dark_rotate-canvas-left.svg dark_rotate-canvas-right.svg light_gmic.svg dark_gmic.svg light_split-layer.svg dark_split-layer.svg light_color-to-alpha.svg dark_color-to-alpha.svg + light_preset-switcher.svg + dark_preset-switcher.svg dark_animation_play.svg dark_animation_stop.svg dark_dropframe.svg dark_droppedframes.svg light_animation_play.svg light_animation_stop.svg light_dropframe.svg light_droppedframes.svg dark_landscape.svg dark_portrait.svg light_landscape.svg light_portrait.svg dark_interpolation_constant.svg dark_interpolation_linear.svg dark_interpolation_bezier.svg dark_interpolation_sharp.svg dark_interpolation_smooth.svg light_interpolation_bezier.svg light_interpolation_constant.svg light_interpolation_linear.svg light_interpolation_sharp.svg light_interpolation_smooth.svg dark_audio-none.svg dark_audio-volume-high.svg dark_audio-volume-mute.svg dark_keyframe-add.svg dark_keyframe-remove.svg dark_zoom-fit.svg dark_zoom-horizontal.svg dark_zoom-vertical.svg light_audio-none.svg light_audio-volume-high.svg light_audio-volume-mute.svg light_keyframe-add.svg light_keyframe-remove.svg light_zoom-fit.svg light_zoom-horizontal.svg light_zoom-vertical.svg dark_showColoring.svg dark_showMarks.svg dark_showColoringOff.svg dark_showMarksOff.svg dark_updateColorize.svg light_showColoring.svg light_showMarks.svg light_showColoringOff.svg light_showMarksOff.svg light_updateColorize.svg diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt index 1888af3cab..4790fe5ba3 100644 --- a/libs/image/CMakeLists.txt +++ b/libs/image/CMakeLists.txt @@ -1,397 +1,394 @@ add_subdirectory( tests ) add_subdirectory( tiles3 ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/metadata ${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_CURRENT_SOURCE_DIR}/recorder ${CMAKE_SOURCE_DIR}/sdk/tests ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) if(FFTW3_FOUND) include_directories(${FFTW3_INCLUDE_DIR}) 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/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_marker_painter.cpp kis_progress_updater.cpp brushengine/kis_paint_information.cc brushengine/kis_random_source.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_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 commands/kis_deselect_global_selection_command.cpp commands/kis_image_change_layers_command.cpp commands/kis_image_command.cpp commands/kis_image_set_projection_color_space_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_layer_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/kis_set_global_selection_command.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 processing/kis_do_nothing_processing_visitor.cpp processing/kis_simple_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 filter/kis_filter.cc 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/kis_colorize_mask.cpp lazybrush/kis_colorize_stroke_strategy.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 kis_clone_info.cpp kis_clone_layer.cpp kis_colorspace_convert_visitor.cpp kis_config_widget.cpp kis_convolution_kernel.cc kis_convolution_painter.cc kis_gaussian_kernel.cpp kis_cubic_curve.cpp kis_default_bounds.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 kis_stroke_job_strategy.cpp kis_stroke_strategy.cpp kis_stroke.cpp kis_strokes_queue.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 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 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_signal_compressor.cpp kis_signal_compressor_with_param.cpp kis_thread_safe_signal_compressor.cpp kis_acyclic_signal_connector.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_command_utils.cpp kis_layer_utils.cpp kis_mask_projection_plane.cpp kis_projection_leaf.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 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 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_algebra_2d.cpp kis_transparency_mask.cc kis_undo_store.cpp kis_undo_stores.cpp 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 metadata/kis_meta_data_entry.cc metadata/kis_meta_data_filter.cc metadata/kis_meta_data_filter_p.cc metadata/kis_meta_data_filter_registry.cc metadata/kis_meta_data_filter_registry_model.cc metadata/kis_meta_data_io_backend.cc metadata/kis_meta_data_merge_strategy.cc metadata/kis_meta_data_merge_strategy_p.cc metadata/kis_meta_data_merge_strategy_registry.cc metadata/kis_meta_data_parser.cc metadata/kis_meta_data_schema.cc metadata/kis_meta_data_schema_registry.cc metadata/kis_meta_data_store.cc metadata/kis_meta_data_type_info.cc metadata/kis_meta_data_validator.cc metadata/kis_meta_data_value.cc recorder/kis_action_recorder.cc recorder/kis_macro.cc recorder/kis_macro_player.cc recorder/kis_node_query_path.cc recorder/kis_play_info.cc recorder/kis_recorded_action.cc recorder/kis_recorded_action_factory_registry.cc recorder/kis_recorded_action_load_context.cpp recorder/kis_recorded_action_save_context.cpp recorder/kis_recorded_filter_action.cpp recorder/kis_recorded_fill_paint_action.cpp recorder/kis_recorded_node_action.cc recorder/kis_recorded_paint_action.cpp recorder/kis_recorded_path_paint_action.cpp recorder/kis_recorded_shape_paint_action.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 KisProofingConfiguration.cpp ) 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 kritaundo2 kritawidgetutils Qt5::Concurrent ) target_link_libraries(kritaimage PUBLIC ${Boost_SYSTEM_LIBRARY}) if(OPENEXR_FOUND) target_link_libraries(kritaimage PUBLIC ${OPENEXR_LIBRARIES}) endif() if(FFTW3_FOUND) target_link_libraries(kritaimage PRIVATE ${FFTW3_LIBRARIES}) endif() if(HAVE_VC) target_link_libraries(kritaimage PUBLIC ${Vc_LIBRARIES}) - if (NOT PACKAGERS_BUILD) - set_property(TARGET kritaimage APPEND PROPERTY COMPILE_OPTIONS "${Vc_ARCHITECTURE_FLAGS}") - endif() 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}) ########### install schemas ############# install( FILES metadata/schemas/dc.schema metadata/schemas/exif.schema metadata/schemas/tiff.schema metadata/schemas/mkn.schema metadata/schemas/xmp.schema metadata/schemas/xmpmm.schema metadata/schemas/xmprights.schema DESTINATION ${DATA_INSTALL_DIR}/krita/metadata/schemas) diff --git a/libs/ui/kis_animation_exporter.cpp b/libs/ui/kis_animation_exporter.cpp index 72cdbb4cd1..3d536e0cda 100644 --- a/libs/ui/kis_animation_exporter.cpp +++ b/libs/ui/kis_animation_exporter.cpp @@ -1,378 +1,378 @@ /* * Copyright (c) 2015 Jouni Pentikäinen * * 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_animation_exporter.h" #include #include #include #include #include #include "KoFileDialog.h" #include "KisDocument.h" #include "kis_image.h" #include "KisImportExportManager.h" #include "kis_image_animation_interface.h" #include "KisPart.h" #include "KisMainWindow.h" #include "kis_paint_layer.h" #include "kis_group_layer.h" #include "kis_time_range.h" #include "kis_painter.h" #include "kis_image_lock_hijacker.h" struct KisAnimationExporterUI::Private { QWidget *parentWidget; KisAnimationExportSaver *exporter; Private(QWidget *parent) : parentWidget(parent), exporter(0) {} }; KisAnimationExporterUI::KisAnimationExporterUI(QWidget *parent) : m_d(new Private(parent)) { } KisAnimationExporterUI::~KisAnimationExporterUI() { if (m_d->exporter) { delete m_d->exporter; } } struct KisAnimationExporter::Private { Private(KisDocument *document, int fromTime, int toTime) : document(document) , image(document->image()) , firstFrame(fromTime) , lastFrame(toTime) , currentFrame(-1) , batchMode(document->fileBatchMode()) , isCancelled(false) , status(KisImportExportFilter::OK) , tmpDevice(new KisPaintDevice(image->colorSpace())) { } KisDocument *document; KisImageWSP image; int firstFrame; int lastFrame; int currentFrame; bool batchMode; bool isCancelled; KisImportExportFilter::ConversionStatus status; SaveFrameCallback saveFrameCallback; KisPaintDeviceSP tmpDevice; KisPropertiesConfigurationSP exportConfiguration; QProgressDialog progress; }; KisAnimationExporter::KisAnimationExporter(KisDocument *document, int fromTime, int toTime) : m_d(new Private(document, fromTime, toTime)) { connect(m_d->image->animationInterface(), SIGNAL(sigFrameReady(int)), this, SLOT(frameReadyToCopy(int)), Qt::DirectConnection); connect(this, SIGNAL(sigFrameReadyToSave()), this, SLOT(frameReadyToSave()), Qt::QueuedConnection); } KisAnimationExporter::~KisAnimationExporter() { } void KisAnimationExporter::setExportConfiguration(KisPropertiesConfigurationSP exportConfiguration) { m_d->exportConfiguration = exportConfiguration; } void KisAnimationExporter::setSaveFrameCallback(SaveFrameCallback func) { m_d->saveFrameCallback = func; } KisImportExportFilter::ConversionStatus KisAnimationExporter::exportAnimation() { if (!m_d->batchMode) { QString message = i18n("Preparing to export frames..."); m_d->progress.reset(); m_d->progress.setLabelText(message); m_d->progress.setWindowModality(Qt::ApplicationModal); m_d->progress.setCancelButton(0); m_d->progress.setMinimumDuration(0); m_d->progress.setValue(0); m_d->progress.setMinimum(0); m_d->progress.setMaximum(100); emit m_d->document->statusBarMessage(message); emit m_d->document->sigProgress(0); connect(m_d->document, SIGNAL(sigProgressCanceled()), this, SLOT(cancel())); } /** * HACK ALERT: Here we remove the image lock! We do it in a GUI * thread under the barrier lock held, so it is * guaranteed no other stroke will accidentally be * started by this. And showing an app-modal dialog to * the user will prevent him from doing anything * nasty. */ KisImageLockHijacker badGuy(m_d->image); Q_UNUSED(badGuy); KIS_ASSERT_RECOVER(!m_d->image->locked()) { return KisImportExportFilter::InternalError; } m_d->status = KisImportExportFilter::OK; m_d->currentFrame = m_d->firstFrame; m_d->image->animationInterface()->requestFrameRegeneration(m_d->currentFrame, m_d->image->bounds()); QEventLoop loop; loop.connect(this, SIGNAL(sigFinished()), SLOT(quit())); loop.exec(); if (!m_d->batchMode) { disconnect(m_d->document, SIGNAL(sigProgressCanceled()), this, SLOT(cancel())); emit m_d->document->sigProgress(100); emit m_d->document->clearStatusBarMessage(); m_d->progress.reset(); } return m_d->status; } void KisAnimationExporter::cancel() { m_d->isCancelled = true; } void KisAnimationExporter::frameReadyToCopy(int time) { if (time != m_d->currentFrame) return; QRect rc = m_d->image->bounds(); KisPainter::copyAreaOptimized(rc.topLeft(), m_d->image->projection(), m_d->tmpDevice, rc); emit sigFrameReadyToSave(); } void KisAnimationExporter::frameReadyToSave() { KIS_ASSERT_RECOVER(m_d->saveFrameCallback) { m_d->status = KisImportExportFilter::InternalError; emit sigFinished(); return; } if (m_d->isCancelled) { m_d->status = KisImportExportFilter::UserCancelled; emit sigFinished(); return; } KisImportExportFilter::ConversionStatus result = KisImportExportFilter::OK; int time = m_d->currentFrame; result = m_d->saveFrameCallback(time, m_d->tmpDevice, m_d->exportConfiguration); if (!m_d->batchMode) { emit m_d->document->sigProgress((time - m_d->firstFrame) * 100 / (m_d->lastFrame - m_d->firstFrame)); } qDebug() << result << time << m_d->lastFrame; QString dialogText = QString("Exporting Frame ").append(QString::number(time)).append(" of ").append(QString::number(m_d->lastFrame)); int percentageProcessed = (float(time) / float(m_d->lastFrame) * 100); m_d->progress.setLabelText(dialogText); m_d->progress.setValue(int(percentageProcessed)); if (result == KisImportExportFilter::OK && time < m_d->lastFrame) { m_d->currentFrame = time + 1; m_d->image->animationInterface()->requestFrameRegeneration(m_d->currentFrame, m_d->image->bounds()); } else { emit sigFinished(); } } struct KisAnimationExportSaver::Private { Private(KisDocument *document, int fromTime, int toTime, int _sequenceNumberingOffset) : document(document) , image(document->image()) , firstFrame(fromTime) , lastFrame(toTime) , sequenceNumberingOffset(_sequenceNumberingOffset) , tmpDoc(KisPart::instance()->createDocument()) , exporter(document, fromTime, toTime) { tmpDoc->setAutoSaveDelay(0); tmpImage = new KisImage(tmpDoc->createUndoStore(), image->bounds().width(), image->bounds().height(), image->colorSpace(), QString()); tmpImage->setResolution(image->xRes(), image->yRes()); tmpDoc->setCurrentImage(tmpImage); KisPaintLayer* paintLayer = new KisPaintLayer(tmpImage, "paint device", 255); tmpImage->addNode(paintLayer, tmpImage->rootLayer(), KisLayerSP(0)); tmpDevice = paintLayer->paintDevice(); } KisDocument *document; KisImageWSP image; int firstFrame; int lastFrame; int sequenceNumberingOffset; QScopedPointer tmpDoc; KisImageSP tmpImage; KisPaintDeviceSP tmpDevice; KisAnimationExporter exporter; QString filenamePrefix; QString filenameSuffix; }; KisAnimationExportSaver::KisAnimationExportSaver(KisDocument *document, const QString &baseFilename, int fromTime, int toTime, int sequenceNumberingOffset) : m_d(new Private(document, fromTime, toTime, sequenceNumberingOffset)) { int baseLength = baseFilename.lastIndexOf("."); if (baseLength > -1) { m_d->filenamePrefix = baseFilename.left(baseLength); m_d->filenameSuffix = baseFilename.right(baseFilename.length() - baseLength); } else { m_d->filenamePrefix = baseFilename; } QString mimefilter = KisMimeDatabase::mimeTypeForFile(baseFilename); m_d->tmpDoc->setOutputMimeType(mimefilter.toLatin1()); m_d->tmpDoc->setFileBatchMode(true); using namespace std::placeholders; // For _1 placeholder m_d->exporter.setSaveFrameCallback(std::bind(&KisAnimationExportSaver::saveFrameCallback, this, _1, _2, _3)); } KisAnimationExportSaver::~KisAnimationExportSaver() { } KisImportExportFilter::ConversionStatus KisAnimationExportSaver::exportAnimation(KisPropertiesConfigurationSP cfg) { QFileInfo info(savedFilesMask()); QDir dir(info.absolutePath()); QStringList filesList = dir.entryList({ info.fileName() }); if (!filesList.isEmpty()) { if (m_d->document->fileBatchMode()) { return KisImportExportFilter::CreationError; } QStringList truncatedList = filesList; while (truncatedList.size() > 3) { truncatedList.takeLast(); } QString exampleFiles = truncatedList.join(", "); if (truncatedList.size() != filesList.size()) { exampleFiles += QString(", ..."); } QMessageBox::StandardButton result = QMessageBox::warning(0, i18n("Delete old frames?"), i18n("Frames with the same naming " "scheme exist in the destination " "directory. They are going to be " "deleted, continue?\n\n" "Directory: %1\n" "Files: %2", info.absolutePath(), exampleFiles), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (result == QMessageBox::Yes) { Q_FOREACH (const QString &file, filesList) { if (!dir.remove(file)) { QMessageBox::critical(0, i18n("Failed to delete"), i18n("Failed to delete an old frame file:\n\n" "%1\n\n" "Rendering cancelled.", dir.absoluteFilePath(file))); return KisImportExportFilter::CreationError; } } } else { return KisImportExportFilter::UserCancelled; } } m_d->exporter.setExportConfiguration(cfg); return m_d->exporter.exportAnimation(); } KisImportExportFilter::ConversionStatus KisAnimationExportSaver::saveFrameCallback(int time, KisPaintDeviceSP frame, KisPropertiesConfigurationSP exportConfiguration) { KisImportExportFilter::ConversionStatus status = KisImportExportFilter::OK; QString frameNumber = QString("%1").arg(time - m_d->firstFrame + m_d->sequenceNumberingOffset, 4, 10, QChar('0')); QString filename = m_d->filenamePrefix + frameNumber + m_d->filenameSuffix; QRect rc = m_d->image->bounds(); KisPainter::copyAreaOptimized(rc.topLeft(), frame, m_d->tmpDevice, rc); if (!m_d->tmpDoc->exportDocument(QUrl::fromLocalFile(filename), exportConfiguration)) { status = KisImportExportFilter::InternalError; } return status; } QString KisAnimationExportSaver::savedFilesMask() const { - return m_d->filenamePrefix + "????" + m_d->filenameSuffix; + return m_d->filenamePrefix + "%04d" + m_d->filenameSuffix; } diff --git a/libs/ui/widgets/kis_paintop_presets_popup.cpp b/libs/ui/widgets/kis_paintop_presets_popup.cpp index 616f5034c0..b3137ce45b 100644 --- a/libs/ui/widgets/kis_paintop_presets_popup.cpp +++ b/libs/ui/widgets/kis_paintop_presets_popup.cpp @@ -1,577 +1,571 @@ /* This file is part of the KDE project * Copyright (C) 2008 Boudewijn Rempt * Copyright (C) 2010 Lukáš Tvrdý * Copyright (C) 2011 Silvio Heinrich * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "widgets/kis_paintop_presets_popup.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 "kis_config.h" #include "kis_resource_server_provider.h" #include "kis_lod_availability_widget.h" #include "kis_signal_auto_connection.h" // ones from brush engine selector #include #include "../kis_paint_ops_model.h" struct KisPaintOpPresetsPopup::Private { public: Ui_WdgPaintOpSettings uiWdgPaintOpPresetSettings; QGridLayout *layout; KisPaintOpConfigWidget *settingsWidget; QFont smallFont; KisCanvasResourceProvider *resourceProvider; bool detached; bool ignoreHideEvents; QSize minimumSettingsWidgetSize; QRect detachedGeometry; KisSignalAutoConnectionsStore widgetConnections; }; KisPaintOpPresetsPopup::KisPaintOpPresetsPopup(KisCanvasResourceProvider * resourceProvider, QWidget * parent) : QWidget(parent) , m_d(new Private()) { setObjectName("KisPaintOpPresetsPopup"); setFont(KoDockRegistry::dockFont()); current_paintOpId = ""; m_d->resourceProvider = resourceProvider; m_d->uiWdgPaintOpPresetSettings.setupUi(this); m_d->layout = new QGridLayout(m_d->uiWdgPaintOpPresetSettings.frmOptionWidgetContainer); m_d->layout->setSizeConstraint(QLayout::SetFixedSize); m_d->uiWdgPaintOpPresetSettings.scratchPad->setupScratchPad(resourceProvider, Qt::white); m_d->uiWdgPaintOpPresetSettings.scratchPad->setCutoutOverlayRect(QRect(25, 25, 200, 200)); m_d->uiWdgPaintOpPresetSettings.fillLayer->setIcon(KisIconUtils::loadIcon("document-new")); m_d->uiWdgPaintOpPresetSettings.fillLayer->hide(); m_d->uiWdgPaintOpPresetSettings.fillGradient->setIcon(KisIconUtils::loadIcon("krita_tool_gradient")); m_d->uiWdgPaintOpPresetSettings.fillSolid->setIcon(KisIconUtils::loadIcon("krita_tool_color_fill")); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete")); m_d->uiWdgPaintOpPresetSettings.paintPresetIcon->setIcon(KisIconUtils::loadIcon("krita_tool_freehand")); // DETAIL and THUMBNAIL view changer QMenu* menu = new QMenu(this); menu->setStyleSheet("margin: 6px"); menu->addSection(i18n("Display")); QActionGroup *actionGroup = new QActionGroup(this); KisPresetChooser::ViewMode mode = (KisPresetChooser::ViewMode)KisConfig().presetChooserViewMode(); QAction* action = menu->addAction(KisIconUtils::loadIcon("view-preview"), i18n("Thumbnails"), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotThumbnailMode())); action->setCheckable(true); action->setChecked(mode == KisPresetChooser::THUMBNAIL); action->setActionGroup(actionGroup); action = menu->addAction(KisIconUtils::loadIcon("view-list-details"), i18n("Details"), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotDetailMode())); action->setCheckable(true); action->setChecked(mode == KisPresetChooser::DETAIL); action->setActionGroup(actionGroup); // add horizontal slider for the icon size QSlider* iconSizeSlider = new QSlider(this); iconSizeSlider->setOrientation(Qt::Horizontal); iconSizeSlider->setRange(30, 80); iconSizeSlider->setValue(m_d->uiWdgPaintOpPresetSettings.presetWidget->iconSize()); iconSizeSlider->setMinimumHeight(20); iconSizeSlider->setMinimumWidth(40); iconSizeSlider->setTickInterval(10); QWidgetAction *sliderAction= new QWidgetAction(this); sliderAction->setDefaultWidget(iconSizeSlider); menu->addSection(i18n("Icon Size")); menu->addAction(sliderAction); // configure the button and assign menu m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setMenu(menu); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setPopupMode(QToolButton::InstantPopup); // show/hide buttons KisConfig cfg; m_d->uiWdgPaintOpPresetSettings.showScratchpadButton->setCheckable(true); m_d->uiWdgPaintOpPresetSettings.showScratchpadButton->setChecked(cfg.scratchpadVisible()); m_d->uiWdgPaintOpPresetSettings.showEditorButton->setCheckable(true); m_d->uiWdgPaintOpPresetSettings.showEditorButton->setChecked(true); m_d->uiWdgPaintOpPresetSettings.showPresetsButton->setText(i18n("Presets")); m_d->uiWdgPaintOpPresetSettings.showPresetsButton->setCheckable(true); m_d->uiWdgPaintOpPresetSettings.showPresetsButton->setChecked(false); // use a config to load/save this state slotSwitchShowPresets(false); // hide presets by default // Connections connect(iconSizeSlider, SIGNAL(sliderMoved(int)), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotSetIconSize(int))); connect(iconSizeSlider, SIGNAL(sliderReleased()), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotSaveIconSize())); connect(m_d->uiWdgPaintOpPresetSettings.showScratchpadButton, SIGNAL(clicked(bool)), this, SLOT(slotSwitchScratchpad(bool))); connect(m_d->uiWdgPaintOpPresetSettings.showEditorButton, SIGNAL(clicked(bool)), this, SLOT(slotSwitchShowEditor(bool))); connect(m_d->uiWdgPaintOpPresetSettings.showPresetsButton, SIGNAL(clicked(bool)), this, SLOT(slotSwitchShowPresets(bool))); connect(m_d->uiWdgPaintOpPresetSettings.eraseScratchPad, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillDefault())); connect(m_d->uiWdgPaintOpPresetSettings.fillLayer, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillLayer())); connect(m_d->uiWdgPaintOpPresetSettings.fillGradient, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillGradient())); connect(m_d->uiWdgPaintOpPresetSettings.fillSolid, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillBackground())); connect(m_d->uiWdgPaintOpPresetSettings.paintPresetIcon, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(paintPresetImage())); m_d->settingsWidget = 0; setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); connect(m_d->uiWdgPaintOpPresetSettings.bnSave, SIGNAL(clicked()), this, SIGNAL(savePresetClicked())); connect(m_d->uiWdgPaintOpPresetSettings.reload, SIGNAL(clicked()), this, SIGNAL(reloadPresetClicked())); connect(m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset, SIGNAL(clicked()), this, SIGNAL(defaultPresetClicked())); connect(m_d->uiWdgPaintOpPresetSettings.dirtyPresetCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(dirtyPresetToggled(bool))); connect(m_d->uiWdgPaintOpPresetSettings.eraserBrushSizeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(eraserBrushSizeToggled(bool))); connect(m_d->uiWdgPaintOpPresetSettings.eraserBrushOpacityCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(eraserBrushOpacityToggled(bool))); connect(m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.txtPreset, SLOT(clear())); connect(m_d->uiWdgPaintOpPresetSettings.txtPreset, SIGNAL(textChanged(QString)), SLOT(slotWatchPresetNameLineEdit())); // preset widget connections connect(m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SIGNAL(resourceSelected(KoResource*)), this, SIGNAL(signalResourceSelected(KoResource*))); - connect(m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SIGNAL(resourceClicked(KoResource*)), - this, SIGNAL(paintopActivated(currentPaintOpId()))); - connect(m_d->uiWdgPaintOpPresetSettings.bnSave, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SLOT(updateViewSettings())); connect(m_d->uiWdgPaintOpPresetSettings.reload, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SLOT(updateViewSettings())); m_d->detached = false; m_d->ignoreHideEvents = false; m_d->minimumSettingsWidgetSize = QSize(0, 0); m_d->uiWdgPaintOpPresetSettings.scratchpadControls->setVisible(cfg.scratchpadVisible()); m_d->detachedGeometry = QRect(100, 100, 0, 0); m_d->uiWdgPaintOpPresetSettings.dirtyPresetCheckBox->setChecked(cfg.useDirtyPresets()); m_d->uiWdgPaintOpPresetSettings.eraserBrushSizeCheckBox->setChecked(cfg.useEraserBrushSize()); m_d->uiWdgPaintOpPresetSettings.eraserBrushOpacityCheckBox->setChecked(cfg.useEraserBrushOpacity()); m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setCanvasResourceManager(resourceProvider->resourceManager()); - // brush engine is changed - connect(m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPaintOpChanged(int))); - connect(resourceProvider->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), SLOT(slotResourceChanged(int, QVariant))); connect(m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability, SIGNAL(sigUserChangedLodAvailability(bool)), SLOT(slotLodAvailabilityChanged(bool))); slotResourceChanged(KisCanvasResourceProvider::LodAvailability, resourceProvider->resourceManager()-> resource(KisCanvasResourceProvider::LodAvailability)); connect(m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatePaintOpFilter())); } void KisPaintOpPresetsPopup::slotResourceChanged(int key, const QVariant &value) { if (key == KisCanvasResourceProvider::LodAvailability) { m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->slotUserChangedLodAvailability(value.toBool()); } } void KisPaintOpPresetsPopup::slotLodAvailabilityChanged(bool value) { m_d->resourceProvider->resourceManager()->setResource(KisCanvasResourceProvider::LodAvailability, QVariant(value)); } KisPaintOpPresetsPopup::~KisPaintOpPresetsPopup() { if (m_d->settingsWidget) { m_d->layout->removeWidget(m_d->settingsWidget); m_d->settingsWidget->hide(); m_d->settingsWidget->setParent(0); m_d->settingsWidget = 0; } delete m_d; } void KisPaintOpPresetsPopup::setPaintOpSettingsWidget(QWidget * widget) { if (m_d->settingsWidget) { m_d->layout->removeWidget(m_d->settingsWidget); m_d->uiWdgPaintOpPresetSettings.frmOptionWidgetContainer->updateGeometry(); } m_d->layout->update(); updateGeometry(); m_d->widgetConnections.clear(); m_d->settingsWidget = 0; if (widget) { m_d->settingsWidget = dynamic_cast(widget); KIS_ASSERT_RECOVER_RETURN(m_d->settingsWidget); if (m_d->settingsWidget->supportScratchBox()) { showScratchPad(); } else { hideScratchPad(); } m_d->widgetConnections.addConnection(m_d->settingsWidget, SIGNAL(sigConfigurationItemChanged()), this, SLOT(slotUpdateLodAvailability())); widget->setFont(m_d->smallFont); QSize hint = widget->sizeHint(); m_d->minimumSettingsWidgetSize = QSize(qMax(hint.width(), m_d->minimumSettingsWidgetSize.width()), qMax(hint.height(), m_d->minimumSettingsWidgetSize.height())); widget->setMinimumSize(m_d->minimumSettingsWidgetSize); m_d->layout->addWidget(widget); m_d->layout->update(); widget->show(); } slotUpdateLodAvailability(); } void KisPaintOpPresetsPopup::slotUpdateLodAvailability() { if (!m_d->settingsWidget) return; KisPaintopLodLimitations l = m_d->settingsWidget->lodLimitations(); m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setLimitations(l); } void KisPaintOpPresetsPopup::slotWatchPresetNameLineEdit() { QString text = m_d->uiWdgPaintOpPresetSettings.txtPreset->text(); KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); bool overwrite = rServer->resourceByName(text) != 0; KisPaintOpPresetSP preset = m_d->resourceProvider->currentPreset(); bool btnSaveAvailable = preset->valid() && (preset->isPresetDirty() | !overwrite); QString btnText = overwrite ? i18n("Overwrite Preset") : i18n("Save to Presets"); m_d->uiWdgPaintOpPresetSettings.bnSave->setText(btnText); m_d->uiWdgPaintOpPresetSettings.bnSave->setEnabled(btnSaveAvailable); m_d->uiWdgPaintOpPresetSettings.reload->setVisible(true); m_d->uiWdgPaintOpPresetSettings.reload->setEnabled(btnSaveAvailable && overwrite); QFont font = m_d->uiWdgPaintOpPresetSettings.txtPreset->font(); font.setItalic(btnSaveAvailable); m_d->uiWdgPaintOpPresetSettings.txtPreset->setFont(font); } QString KisPaintOpPresetsPopup::getPresetName() const { return m_d->uiWdgPaintOpPresetSettings.txtPreset->text(); } QImage KisPaintOpPresetsPopup::cutOutOverlay() { return m_d->uiWdgPaintOpPresetSettings.scratchPad->cutoutOverlay(); } void KisPaintOpPresetsPopup::contextMenuEvent(QContextMenuEvent *e) { Q_UNUSED(e); } void KisPaintOpPresetsPopup::switchDetached(bool show) { if (parentWidget()) { m_d->detached = !m_d->detached; if (m_d->detached) { m_d->ignoreHideEvents = true; if (show) { parentWidget()->show(); } m_d->ignoreHideEvents = false; } else { KisConfig cfg; parentWidget()->hide(); } KisConfig cfg; cfg.setPaintopPopupDetached(m_d->detached); } } void KisPaintOpPresetsPopup::hideScratchPad() { m_d->uiWdgPaintOpPresetSettings.scratchPad->setEnabled(false); m_d->uiWdgPaintOpPresetSettings.fillGradient->setEnabled(false); m_d->uiWdgPaintOpPresetSettings.fillSolid->setEnabled(false); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setEnabled(false); } void KisPaintOpPresetsPopup::showScratchPad() { m_d->uiWdgPaintOpPresetSettings.scratchPad->setEnabled(true); m_d->uiWdgPaintOpPresetSettings.fillGradient->setEnabled(true); m_d->uiWdgPaintOpPresetSettings.fillSolid->setEnabled(true); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setEnabled(true); } void KisPaintOpPresetsPopup::resourceSelected(KoResource* resource) { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->setCurrentResource(resource); m_d->uiWdgPaintOpPresetSettings.txtPreset->setText(resource->name()); slotWatchPresetNameLineEdit(); m_d->uiWdgPaintOpPresetSettings.currentBrushNameLabel->setText(resource->name()); } bool variantLessThan(const KisPaintOpInfo v1, const KisPaintOpInfo v2) { return v1.priority < v2.priority; } void KisPaintOpPresetsPopup::setPaintOpList(const QList< KisPaintOpFactory* >& list) { m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->clear(); // reset combobox list just in case // create a new list so we can sort it and populate the brush engine combo box QList sortedList; for(int i=0; i < list.length(); i++) { QString fileName = KoResourcePaths::findResource("kis_images", list.at(i)->pixmap()); QPixmap pixmap(fileName); if(pixmap.isNull()){ pixmap = QPixmap(22,22); pixmap.fill(); } KisPaintOpInfo paintOpInfo; paintOpInfo.id = list.at(i)->id(); paintOpInfo.name = list.at(i)->name(); paintOpInfo.icon = pixmap; paintOpInfo.priority = list.at(i)->priority(); sortedList.append(paintOpInfo); } qStableSort(sortedList.begin(), sortedList.end(), variantLessThan ); // add an "All" option at the front to show all presets QPixmap emptyPixmap = QPixmap(22,22); emptyPixmap.fill(palette().color(QPalette::Background)); sortedList.push_front(KisPaintOpInfo(QString("all_options"), i18n("All"), QString(""), emptyPixmap, 0 )); // fill the list into the brush combo box for (int m = 0; m < sortedList.length(); m++) { m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->addItem(sortedList[m].icon, sortedList[m].name, QVariant(sortedList[m].id)); } } void KisPaintOpPresetsPopup::setCurrentPaintOpId(const QString& paintOpId) { current_paintOpId = paintOpId; } QString KisPaintOpPresetsPopup::currentPaintOpId() { return current_paintOpId; } void KisPaintOpPresetsPopup::setPresetImage(const QImage& image) { m_d->uiWdgPaintOpPresetSettings.scratchPad->setPresetImage(image); } void KisPaintOpPresetsPopup::hideEvent(QHideEvent *event) { if (m_d->ignoreHideEvents) { return; } if (m_d->detached) { m_d->detachedGeometry = window()->geometry(); } QWidget::hideEvent(event); } void KisPaintOpPresetsPopup::showEvent(QShowEvent *) { if (m_d->detached) { window()->setGeometry(m_d->detachedGeometry); } emit brushEditorShown(); } void KisPaintOpPresetsPopup::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); emit sizeChanged(); } bool KisPaintOpPresetsPopup::detached() const { return m_d->detached; } void KisPaintOpPresetsPopup::slotSwitchScratchpad(bool visible) { m_d->uiWdgPaintOpPresetSettings.scratchpadControls->setVisible(visible); KisConfig cfg; cfg.setScratchpadVisible(visible); } void KisPaintOpPresetsPopup::slotSwitchShowEditor(bool visible) { m_d->uiWdgPaintOpPresetSettings.brushEditorSettingsControls->setVisible(visible); } void KisPaintOpPresetsPopup::slotSwitchShowPresets(bool visible) { m_d->uiWdgPaintOpPresetSettings.presetsContainer->setVisible(visible); } void KisPaintOpPresetsPopup::slotUpdatePaintOpFilter() { QVariant userData = m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->currentData(); // grab paintOpID from data QString filterPaintOpId = userData.toString(); if (filterPaintOpId == "all_options") { filterPaintOpId = ""; } m_d->uiWdgPaintOpPresetSettings.presetWidget->setPresetFilter(filterPaintOpId); } void KisPaintOpPresetsPopup::updateViewSettings() { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->updateViewSettings(); } void KisPaintOpPresetsPopup::currentPresetChanged(KisPaintOpPresetSP preset) { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->setCurrentResource(preset.data()); setCurrentPaintOpId(preset->paintOp().id()); } void KisPaintOpPresetsPopup::updateThemedIcons() { m_d->uiWdgPaintOpPresetSettings.fillLayer->setIcon(KisIconUtils::loadIcon("document-new")); m_d->uiWdgPaintOpPresetSettings.fillLayer->hide(); m_d->uiWdgPaintOpPresetSettings.fillGradient->setIcon(KisIconUtils::loadIcon("krita_tool_gradient")); m_d->uiWdgPaintOpPresetSettings.fillSolid->setIcon(KisIconUtils::loadIcon("krita_tool_color_fill")); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete")); m_d->uiWdgPaintOpPresetSettings.paintPresetIcon->setIcon(KisIconUtils::loadIcon("krita_tool_freehand")); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); } diff --git a/packaging/linux/appimage/build-krita.sh b/packaging/linux/appimage/build-krita.sh index fbde58da0e..00a79f3913 100644 --- a/packaging/linux/appimage/build-krita.sh +++ b/packaging/linux/appimage/build-krita.sh @@ -1,88 +1,87 @@ #!/bin/bash # Enter a CentOS 6 chroot (you could use other methods) # git clone https://github.com/probonopd/AppImageKit.git # ./AppImageKit/build.sh # sudo ./AppImageKit/AppImageAssistant.AppDir/testappimage /isodevice/boot/iso/CentOS-6.5-x86_64-LiveCD.iso bash # Halt on errors set -e # Be verbose set -x # Now we are inside CentOS 6 grep -r "CentOS release 6" /etc/redhat-release || exit 1 # qjsonparser, used to add metadata to the plugins needs to work in a en_US.UTF-8 environment. That's # not always set correctly in CentOS 6.7 export LC_ALL=en_US.UTF-8 export LANG=en_us.UTF-8 # Determine which architecture should be built if [[ "$(arch)" = "i686" || "$(arch)" = "x86_64" ]] ; then ARCH=$(arch) else echo "Architecture could not be determined" exit 1 fi # if the library path doesn't point to our usr/lib, linking will be broken and we won't find all deps either export LD_LIBRARY_PATH=/usr/lib64/:/usr/lib:/krita.appdir/usr/lib git_pull_rebase_helper() { git reset --hard HEAD git pull } # Use the new compiler . /opt/rh/devtoolset-3/enable # Workaround for: On CentOS 6, .pc files in /usr/lib/pkgconfig are not recognized # However, this is where .pc files get installed when bulding libraries... (FIXME) # I found this by comparing the output of librevenge's "make install" command # between Ubuntu and CentOS 6 ln -sf /usr/share/pkgconfig /usr/lib/pkgconfig # A krita build layout looks like this: # krita/ -- the source directory # krita/3rdparty -- the cmake3 definitions for the dependencies # d -- downloads of the dependencies from files.kde.org # b -- build directory for the dependencies # krita_build -- build directory for krita itself # krita.appdir -- install directory for krita and the dependencies # Get Krita if [ ! -d /krita ] ; then git clone --depth 1 https://github.com/KDE/krita.git /krita fi cd /krita/ git_pull_rebase_helper cd / # If the environment variable DO_NOT_BUILD_KRITA is set to something, # then stop here. This is for docker hub which has a timeout that # prevents us from building in one go. # if [ ! -z "$DO_NOT_BUILD_KRITA" ] ; then # exit 0 # fi mkdir -p /krita_build cd /krita_build cmake3 ../krita \ -DCMAKE_INSTALL_PREFIX:PATH=/krita.appdir/usr \ -DDEFINE_NO_DEPRECATED=1 \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DPACKAGERS_BUILD=1 \ -DBUILD_TESTING=FALSE \ -DKDE4_BUILD_TESTS=FALSE \ -DHAVE_MEMORY_LEAK_TRACKER=FALSE # build make -j4 diff --git a/packaging/linux/appimage/build-release.sh b/packaging/linux/appimage/build-release.sh index c927e4411c..1bf69d31b6 100644 --- a/packaging/linux/appimage/build-release.sh +++ b/packaging/linux/appimage/build-release.sh @@ -1,259 +1,258 @@ #!/bin/bash RELEASE=krita-3.0.99.90 # Enter a CentOS 6 chroot (you could use other methods) # git clone https://github.com/probonopd/AppImageKit.git # ./AppImageKit/build.sh # sudo ./AppImageKit/AppImageAssistant.AppDir/testappimage /isodevice/boot/iso/CentOS-6.5-x86_64-LiveCD.iso bash # Halt on errors set -e # Be verbose set -x # Now we are inside CentOS 6 grep -r "CentOS release 6" /etc/redhat-release || exit 1 # If we are running inside Travis CI, then we want to build Krita # and we remove the $DO_NOT_BUILD_KRITA environment variable # that was used in the process of generating the Docker image. # Also we do not want to download and build the dependencies every # time we build Krita on travis in the docker image. In order to # use newer dependencies, we re-build the docker image instead. #unset DO_NOT_BUILD_KRITA #NO_DOWNLOAD=1 # clean up rm -rf /out/* rm -rf /krita.appdir # qjsonparser, used to add metadata to the plugins needs to work in a en_US.UTF-8 environment. That's # not always set correctly in CentOS 6.7 export LC_ALL=en_US.UTF-8 export LANG=en_us.UTF-8 # Determine which architecture should be built if [[ "$(arch)" = "i686" || "$(arch)" = "x86_64" ]] ; then ARCH=$(arch) else echo "Architecture could not be determined" exit 1 fi # if the library path doesn't point to our usr/lib, linking will be broken and we won't find all deps either export LD_LIBRARY_PATH=/usr/lib64/:/usr/lib:/krita.appdir/usr/lib cd / # Prepare the install location rm -rf /krita.appdir/ || true mkdir -p /krita.appdir/usr/bin # make sure lib and lib64 are the same thing mkdir -p /krita.appdir/usr/lib cd /krita.appdir/usr ln -s lib lib64 # Use the new compiler . /opt/rh/devtoolset-3/enable # fetch and build krita cd / wget http://files.kde.org/krita/3/source/$RELEASE.tar.xz tar -xf $RELEASE.tar.xz cd /krita_build rm -rf * cmake3 ../$RELEASE \ -DCMAKE_INSTALL_PREFIX:PATH=/krita.appdir/usr \ -DDEFINE_NO_DEPRECATED=1 \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DPACKAGERS_BUILD=1 \ -DBUILD_TESTING=FALSE \ -DKDE4_BUILD_TESTS=FALSE \ -DHAVE_MEMORY_LEAK_TRACKER=FALSE make -j4 install cd /krita.appdir # FIXME: How to find out which subset of plugins is really needed? I used strace when running the binary cp -r /usr/plugins ./usr/bin/ # copy the Qt translation cp -r /usr/translations ./usr cp $(ldconfig -p | grep libsasl2.so.2 | cut -d ">" -f 2 | xargs) ./usr/lib/ cp $(ldconfig -p | grep libGL.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # otherwise segfaults!? cp $(ldconfig -p | grep libGLU.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # otherwise segfaults!? # Fedora 23 seemed to be missing SOMETHING from the Centos 6.7. The only message was: # This application failed to start because it could not find or load the Qt platform plugin "xcb". # Setting export QT_DEBUG_PLUGINS=1 revealed the cause. # QLibraryPrivate::loadPlugin failed on "/usr/lib64/qt5/plugins/platforms/libqxcb.so" : # "Cannot load library /usr/lib64/qt5/plugins/platforms/libqxcb.so: (/lib64/libEGL.so.1: undefined symbol: drmGetNodeTypeFromFd)" # Which means that we have to copy libEGL.so.1 in too cp $(ldconfig -p | grep libEGL.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # Otherwise F23 cannot load the Qt platform plugin "xcb" # let's not copy xcb itself, that breaks on dri3 systems https://bugs.kde.org/show_bug.cgi?id=360552 #cp $(ldconfig -p | grep libxcb.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ cp $(ldconfig -p | grep libfreetype.so.6 | cut -d ">" -f 2 | xargs) ./usr/lib/ # For Fedora 20 ldd usr/bin/krita | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true #ldd usr/lib64/krita/*.so | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true #ldd usr/lib64/plugins/imageformats/*.so | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true ldd usr/bin/plugins/platforms/libqxcb.so | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true # Copy in the indirect dependencies FILES=$(find . -type f -executable) for FILE in $FILES ; do ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' usr/lib || true done #DEPS="" #for FILE in $FILES ; do # ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' echo '{}' > DEPSFILE #done #DEPS=$(cat DEPSFILE |sort | uniq) #for FILE in $DEPS ; do # if [ -f $FILE ] ; then # echo $FILE # cp --parents -rfL $FILE ./ # fi #done #rm -f DEPSFILE # The following are assumed to be part of the base system rm -f usr/lib/libcom_err.so.2 || true rm -f usr/lib/libcrypt.so.1 || true rm -f usr/lib/libdl.so.2 || true rm -f usr/lib/libexpat.so.1 || true #rm -f usr/lib/libfontconfig.so.1 || true rm -f usr/lib/libgcc_s.so.1 || true rm -f usr/lib/libglib-2.0.so.0 || true rm -f usr/lib/libgpg-error.so.0 || true rm -f usr/lib/libgssapi_krb5.so.2 || true rm -f usr/lib/libgssapi.so.3 || true rm -f usr/lib/libhcrypto.so.4 || true rm -f usr/lib/libheimbase.so.1 || true rm -f usr/lib/libheimntlm.so.0 || true rm -f usr/lib/libhx509.so.5 || true rm -f usr/lib/libICE.so.6 || true rm -f usr/lib/libidn.so.11 || true rm -f usr/lib/libk5crypto.so.3 || true rm -f usr/lib/libkeyutils.so.1 || true rm -f usr/lib/libkrb5.so.26 || true rm -f usr/lib/libkrb5.so.3 || true rm -f usr/lib/libkrb5support.so.0 || true # rm -f usr/lib/liblber-2.4.so.2 || true # needed for debian wheezy # rm -f usr/lib/libldap_r-2.4.so.2 || true # needed for debian wheezy rm -f usr/lib/libm.so.6 || true rm -f usr/lib/libp11-kit.so.0 || true rm -f usr/lib/libpcre.so.3 || true rm -f usr/lib/libpthread.so.0 || true rm -f usr/lib/libresolv.so.2 || true rm -f usr/lib/libroken.so.18 || true rm -f usr/lib/librt.so.1 || true rm -f usr/lib/libsasl2.so.2 || true rm -f usr/lib/libSM.so.6 || true rm -f usr/lib/libusb-1.0.so.0 || true rm -f usr/lib/libuuid.so.1 || true rm -f usr/lib/libwind.so.0 || true rm -f usr/lib/libfontconfig.so.* || true # Remove these libraries, we need to use the system versions; this means 11.04 is not supported (12.04 is our baseline) rm -f usr/lib/libGL.so.* || true rm -f usr/lib/libdrm.so.* || true rm -f usr/lib/libX11.so.* || true #rm -f usr/lib/libz.so.1 || true # These seem to be available on most systems but not Ubuntu 11.04 # rm -f usr/lib/libffi.so.6 usr/lib/libGL.so.1 usr/lib/libglapi.so.0 usr/lib/libxcb.so.1 usr/lib/libxcb-glx.so.0 || true # Delete potentially dangerous libraries rm -f usr/lib/libstdc* usr/lib/libgobject* usr/lib/libc.so.* || true rm -f usr/lib/libxcb.so.1 # Do NOT delete libX* because otherwise on Ubuntu 11.04: # loaded library "Xcursor" malloc.c:3096: sYSMALLOc: Assertion (...) Aborted # We don't bundle the developer stuff rm -rf usr/include || true rm -rf usr/lib/cmake3 || true rm -rf usr/lib/pkgconfig || true rm -rf usr/share/ECM/ || true rm -rf usr/share/gettext || true rm -rf usr/share/pkgconfig || true strip usr/lib/kritaplugins/* usr/bin/* usr/lib/* || true # Since we set /krita.appdir as the prefix, we need to patch it away too (FIXME) # Probably it would be better to use /app as a prefix because it has the same length for all apps cd usr/ ; find . -type f -exec sed -i -e 's|/krita.appdir/usr/|./././././././././|g' {} \; ; cd .. # On openSUSE Qt is picking up the wrong libqxcb.so # (the one from the system when in fact it should use the bundled one) - is this a Qt bug? # Also, Krita has a hardcoded /usr which we patch away cd usr/ ; find . -type f -exec sed -i -e 's|/usr|././|g' {} \; ; cd .. # We do not bundle this, so let's not search that inside the AppImage. # Fixes "Qt: Failed to create XKB context!" and lets us enter text sed -i -e 's|././/share/X11/|/usr/share/X11/|g' ./usr/bin/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.so sed -i -e 's|././/share/X11/|/usr/share/X11/|g' ./usr/lib/libQt5XcbQpa.so.5 # Workaround for: # D-Bus library appears to be incorrectly set up; # failed to read machine uuid: Failed to open # The file is more commonly in /etc/machine-id # sed -i -e 's|/var/lib/dbus/machine-id|//././././etc/machine-id|g' ./usr/lib/libdbus-1.so.3 # or rm -f ./usr/lib/libdbus-1.so.3 || true cp ../AppImageKit/AppRun . cp ./usr/share/applications/org.kde.krita.desktop krita.desktop cp /krita/krita/pics/app/64-apps-calligrakrita.png calligrakrita.png # replace krita with the lib-checking startup script. #cd /krita.appdir/usr/bin #mv krita krita.real #wget https://raw.githubusercontent.com/boudewijnrempt/AppImages/master/recipes/krita/krita #chmod a+rx krita cd / APP=krita # Source functions wget -q https://github.com/probonopd/AppImages/raw/master/functions.sh -O ./functions.sh . ./functions.sh # Install desktopintegration in usr/bin/krita.wrapper -- feel free to edit it cd /krita.appdir get_desktopintegration krita cd / VER=$(grep "#define KRITA_VERSION_STRING" krita_build/libs/version/kritaversion.h | cut -d '"' -f 2) VERSION=$VER VERSION="$(sed s/\ /-/g <<<$VERSION)" echo $VERSION if [[ "$ARCH" = "x86_64" ]] ; then APPIMAGE=$APP"-"$VERSION"-x86_64.appimage" fi if [[ "$ARCH" = "i686" ]] ; then APPIMAGE=$APP"-"$VERSION"-i386.appimage" fi echo $APPIMAGE mkdir -p /out rm -f /out/*.AppImage || true AppImageKit/AppImageAssistant.AppDir/package /krita.appdir/ /out/$APPIMAGE chmod a+rwx /out/$APPIMAGE # So that we can edit the AppImage outside of the Docker container cd /krita.appdir mv AppRun krita cd / mv krita.appdir $APP"-"$VERSION"-x86_64 tar -czf $APP"-"$VERSION"-x86_64.tgz $APP"-"$VERSION"-x86_64 diff --git a/packaging/osx/notes.txt b/packaging/osx/notes.txt index 94e812b815..a2875ce713 100644 --- a/packaging/osx/notes.txt +++ b/packaging/osx/notes.txt @@ -1,50 +1,50 @@ OSX Build Notes Setup: ~/dev/b: build location for all dependencies (run cmake ../krita/3rdparty in /dev/b) ~/dev/d: download location for all dependencies ~/dev/i: install location for all dependencies ~/dev/build: manual build location ~/dev/krita: source checkout deploy.sh: for creating the krita.app bundle cmake command to configure krita: cmake ../krita \ -DCMAKE_PREFIX_PATH=$HOME/dev/i \ -DCMAKE_LIBRARY_PATH=$HOME/dev/i/lib \ -Wno-dev \ -DCMAKE_INSTALL_PREFIX=$HOME/dev/i \ -DBUILD_TESTING=OFF \ -DDEFINE_NO_DEPRECATED=1 \ -DBUILD_doc=FALSE \ -DBUNDLE_INSTALL_DIR=$HOME/dev/i/bin cmake command to configure the ext projects cmake ../krita/3rdparty/ -DCMAKE_INSTALL_PREFIX=$HOME/dev/i/ -DEXTERNALS_DOWNLOAD_DIR=$HOME/dev/d/ -DINSTALL_ROOT=$HOME/dev/i/ cmake line for qt creator --DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DDEFINE_NO_DEPRECATED=1 -DPACKAGERS_BUILD=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$HOME/dev/i -DCMAKE_INCLUDE_PATH=$HOME/dev/i/include -DQT_QMAKE_EXECUTABLE=$HOME/dev/i/bin/qmake -DCMAKE_PREFIX_PATH=$HOME/dev/i +-DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DDEFINE_NO_DEPRECATED=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$HOME/dev/i -DCMAKE_INCLUDE_PATH=$HOME/dev/i/include -DQT_QMAKE_EXECUTABLE=$HOME/dev/i/bin/qmake -DCMAKE_PREFIX_PATH=$HOME/dev/i rm -rf ~/krita.app/ rm -rf ~/krita.dmg cp -r ~/dev/i/bin/krita.app ~ cp -r ~/dev/i/share ~/krita.app/Contents/ macdeployqt ~/krita.app \ -verbose=1 \ -extra-plugins=$HOME/dev/i/lib/kritaplugins/ \ -extra-plugins=$HOME/dev/i/lib/kf5/ \ -extra-plugins=$HOME/dev/i/lib/plugins/ \ -extra-plugins=$HOME/dev/i/plugins/ \ -dmg mkdir ~/krita.app/Contents/PlugIns/kritaplugins mv ~/krita.app/Contents/PlugIns/*so ~/krita.app/Contents/PlugIns/kritaplugins To make open_exr build, manual step after it fails because dwalookups cannot find Half: install_name_tool -add_rpath /Users/boud/dev/i/lib /Users/boud/dev/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./b44ExpLogTable install_name_tool -add_rpath /Users/boud/dev/i/lib /Users/boud/dev/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./dwaLookups diff --git a/packaging/osx/run-cmake-krita.sh b/packaging/osx/run-cmake-krita.sh index fcf22f4c0f..588d4eeeda 100755 --- a/packaging/osx/run-cmake-krita.sh +++ b/packaging/osx/run-cmake-krita.sh @@ -1,8 +1,7 @@ #export MACOSX_DEPLOYMENT_TARGET=10.7 #export SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk cmake ../krita \ -DCMAKE_INSTALL_PREFIX=/Users/boud/dev/i \ -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF \ -DKDE4_BUILD_TESTS=OFF \ - -DPACKAGERS_BUILD=ON \ -DBUNDLE_INSTALL_DIR=$HOME/dev/i/bin diff --git a/packaging/windows/build.bat b/packaging/windows/build.bat index cc2a70de8e..68fc4649e4 100644 --- a/packaging/windows/build.bat +++ b/packaging/windows/build.bat @@ -1,34 +1,34 @@ rem rem Follow the instructions in 3rdparty/README.md to setup Qt and the rem build dirs and checkout krita rem set PATH=c:\dev\i\bin\;c:\dev\i\lib;%PATH% cd c:\dev\b cmake ..\krita\3rdparty -DEXTERNALS_DOWNLOAD_DIR=/dev/d -DINSTALL_ROOT=/dev/i -G "Visual Studio 14 Win64" cmake --build . --config RelWithDebInfo --target ext_patch cmake --build . --config RelWithDebInfo --target ext_png2ico cmake --build . --config RelWithDebInfo --target ext_pthreads cmake --build . --config RelWithDebInfo --target ext_boost cmake --build . --config RelWithDebInfo --target ext_eigen3 cmake --build . --config RelWithDebInfo --target ext_fftw3 cmake --build . --config RelWithDebInfo --target ext_ilmbase cmake --build . --config RelWithDebInfo --target ext_jpeg cmake --build . --config RelWithDebInfo --target ext_lcms2 cmake --build . --config RelWithDebInfo --target ext_png cmake --build . --config RelWithDebInfo --target ext_tiff cmake --build . --config RelWithDebInfo --target ext_gsl cmake --build . --config RelWithDebInfo --target ext_vc cmake --build . --config RelWithDebInfo --target ext_libraw rem cmake --build . --config RelWithDebInfo --target ext_freetype cmake --build . --config RelWithDebInfo --target ext_ocio cmake --build . --config RelWithDebInfo --target ext_openexr cmake --build . --config RelWithDebInfo --target ext_exiv2 cmake --build . --config RelWithDebInfo --target ext_kwindowsystem REM cmake --build . --config RelWithDebInfo --target ext_poppler cd c:\dev\build -cmake ..\krita -G"Visual Studio 14 Win64" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -DPACKAGERS_BUILD=ON -Wno-dev -DDEFINE_NO_DEPRECATED=1 +cmake ..\krita -G"Visual Studio 14 Win64" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -Wno-dev -DDEFINE_NO_DEPRECATED=1 copy c:\dev\i\lib\*.dll c:\dev\i\bin copy "C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x64\*.dll" c:\dev\i\bin diff --git a/packaging/windows/build_krita.bat b/packaging/windows/build_krita.bat index c7285a5176..de52681230 100644 --- a/packaging/windows/build_krita.bat +++ b/packaging/windows/build_krita.bat @@ -1,20 +1,20 @@ set DLLTOOL_EXE=c:\TDM-GCC-64\x86_64-w64-mingw32\bin\dlltool.exe set MINGW_GCC_BIN=c:\TDM-GCC-64\bin\ set BUILDROOT=c:\dev set BUILDDIR_INSTALL=%BUILDROOT%\i set PATH=c:\dev\i\bin;c:\dev\i\lib;c:\python35;%MINGW_GCC_BIN%;%PATH% cd c:\dev\build2 set /P pkg_root=Insert krita source location: if [%pkg_root%] == [] ( echo You entered an empty name! pause exit /B ) -cmake ..\%pkg_root% -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -DPACKAGERS_BUILD=ON -Wno-dev -DDEFINE_NO_DEPRECATED=1 -DFOUNDATION_BUILD=1 +cmake ..\%pkg_root% -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -Wno-dev -DDEFINE_NO_DEPRECATED=1 -DFOUNDATION_BUILD=1 mingw32-make -j4 install cd .. diff --git a/packaging/windows/mxe.txt b/packaging/windows/mxe.txt index 352dd4fb14..ce1e19e483 100644 --- a/packaging/windows/mxe.txt +++ b/packaging/windows/mxe.txt @@ -1,49 +1,49 @@ # Where are you building? export BUILDROOT=???? cd $BUILDROOT mkdir cross mkdir cross/b mkdir cross/d mkdir cross/krita-build git clone git@github.com:boudewijnrempt/mxe.git cd mxe export PATH=$BUILDROOT/mxe/usr/bin:$BUILDROOT/mxe/usr/x86_64-w64-mingw32.shared/qt5/bin:$PATH # note: poppler-qt5 and gsl don't work yet # Use i686-w64-mingw32.shared for 32 bits builds # note: vc is 1.2, so we either need zagge's branch, or you need to build Vc 0.75 # yourself. Make sure you use -DBUILD_TESTING=OFF for Vc make MXE_TARGETS=x86_64-w64-mingw32.shared gcc boost curl eigen exiv2 expat fftw fontconfig freetype gettext ilmbase openexr jpeg lcms libpng libraw opencolorio qt5 qtscript tiff vc zlib gsl cd $BUILDROOT git clone git://anongit.kde.org/krita.git # build the deps that aren't in mxe cd b x86_64-w64-mingw32.shared-cmake ../krita/3rdparty/ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d -DINSTALL_ROOT=$BUILDROOT/mxe/usr/x86_64-w64-mingw32.shared -DMXE_TOOLCHAIN=${BUILDROOT}/mxe/usr/x86_64-w64-mingw32.shared/share/cmake/mxe-conf.cmake x86_64-w64-mingw32.shared-cmake --build . --target ext_kcrash x86_64-w64-mingw32.shared-cmake --build . --target ext_poppler # You might want to build gsl and vc 0.75 manually # build krita cd ../build -x86_64-w64-mingw32.shared-cmake ../krita -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DPACKAGERS_BUILD=ON +x86_64-w64-mingw32.shared-cmake ../krita -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF make -j4 install # to test, configure wine # WINEARCH=win64 WINEPREFIX=~/.wine64 winecfg # Go to the bin directory and test krita: # WINEPREFIX=~/.wine64 wine ./krita.exe NOTE: Windragon's patch to vc does not work when cross-building vc from ext_vc. The patch also needs to be added to mxe/vc. The reason is wrong defines for determining whether we're using mingw. diff --git a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp index 11e713d4bc..1f4c2869c7 100644 --- a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp +++ b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp @@ -1,99 +1,103 @@ /* * This file is part of the KDE project * * Copyright (c) 2016 Spencer Brown * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "krita_filter_gradient_map.h" #include #include #include #include #include #include "kis_config_widget.h" #include #include #include #include #include "gradientmap.h" #include KritaFilterGradientMap::KritaFilterGradientMap() : KisFilter(id(), categoryMap(), i18n("&Gradient Map")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); setSupportsLevelOfDetail(true); setSupportsPainting(true); - setSupportsAdjustmentLayers(true); + setSupportsAdjustmentLayers(false); setSupportsThreading(true); } void KritaFilterGradientMap::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.height() * applyRect.width()); } KoAbstractGradient *gradient = KoResourceServerProvider::instance()->gradientServer(false)->resourceByName(config->getString("gradientName")); + if (!gradient) { + qDebug() << "Could not find gradient" << config->getString("gradientName"); + return; + } KoColorSet *gradientCache = new KoColorSet(); for (int i=0; i<256; i++) { KoColor gc; gradient->colorAt(gc, ((qreal)i/255.0)); KoColorSetEntry col; col.color = gc; gradientCache->add(col); } KoColor outColor(Qt::white, device->colorSpace()); KisSequentialIterator it(device, applyRect); int p = 0; quint8 grey; const int pixelSize = device->colorSpace()->pixelSize(); do { grey = device->colorSpace()->intensity8(it.oldRawData()); outColor = gradientCache->getColor((quint32)grey).color; outColor.setOpacity(qMin(KoColor(it.oldRawData(), device->colorSpace()).opacityF(), outColor.opacityF())); outColor.convertTo(device->colorSpace()); memcpy(it.rawData(), outColor.data(), pixelSize); if (progressUpdater) progressUpdater->setValue(p++); } while (it.nextPixel()); } KisFilterConfigurationSP KritaFilterGradientMap::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("gradientmap", 1); KoAbstractGradient *gradient = KoResourceServerProvider::instance()->gradientServer(false)->resources().first(); config->setProperty("gradientName", gradient->name()); return config; } KisConfigWidget * KritaFilterGradientMap::createConfigurationWidget(QWidget * parent, const KisPaintDeviceSP dev) const { return new KritaGradientMapConfigWidget(parent, dev); } diff --git a/plugins/impex/spriter/kis_spriter_export.cpp b/plugins/impex/spriter/kis_spriter_export.cpp index 32bd73e1f5..7825478f27 100644 --- a/plugins/impex/spriter/kis_spriter_export.cpp +++ b/plugins/impex/spriter/kis_spriter_export.cpp @@ -1,616 +1,620 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_spriter_export.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 // for KisDegreesToRadians #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KisSpriterExportFactory, "krita_spriter_export.json", registerPlugin();) KisSpriterExport::KisSpriterExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisSpriterExport::~KisSpriterExport() { } bool KisSpriterExport::savePaintDevice(KisPaintDeviceSP dev, const QString &fileName) { QFileInfo fi(fileName); QDir d = fi.absoluteDir(); d.mkpath(d.path()); QRect rc = m_image->bounds().intersected(dev->exactBounds()); if (!KisPNGConverter::isColorSpaceSupported(dev->colorSpace())) { dev = new KisPaintDevice(*dev.data()); KUndo2Command *cmd = dev->convertTo(KoColorSpaceRegistry::instance()->rgb8()); delete cmd; } KisPNGOptions options; options.forceSRGB = true; vKisAnnotationSP_it beginIt = m_image->beginAnnotations(); vKisAnnotationSP_it endIt = m_image->endAnnotations(); KisPNGConverter converter(0); KisImageBuilder_Result res = converter.buildFile(fileName, rc, m_image->xRes(), m_image->yRes(), dev, beginIt, endIt, options, 0); return (res == KisImageBuilder_RESULT_OK); } -void KisSpriterExport::parseFolder(KisGroupLayerSP parentGroup, const QString &folderName, const QString &basePath) +void KisSpriterExport::parseFolder(KisGroupLayerSP parentGroup, const QString &folderName, const QString &basePath, int *folderId) { // qDebug() << "parseFolder: parent" << parentGroup->name() // << "folderName" << folderName // << "basepath" << basePath; - static int folderId = 0; + int currentFolder=0; + if(folderId == 0) + { + folderId = ¤tFolder; + } QString pathName; if (!folderName.isEmpty()) { pathName = folderName + "/"; } KisNodeSP child = parentGroup->lastChild(); while (child) { if (child->visible() && child->inherits("KisGroupLayer")) { - parseFolder(qobject_cast(child.data()), child->name().split(" ").first(), basePath + "/" + pathName); + parseFolder(qobject_cast(child.data()), child->name().split(" ").first(), basePath + "/" + pathName, folderId); } child = child->prevSibling(); } Folder folder; - folder.id = folderId; + folder.id = *folderId; folder.name = folderName; folder.groupName = parentGroup->name(); int fileId = 0; child = parentGroup->lastChild(); while (child) { if (child->visible() && !child->inherits("KisGroupLayer") && !child->inherits("KisMask")) { QRectF rc = m_image->bounds().intersected(child->exactBounds()); QString layerBaseName = child->name().split(" ").first(); SpriterFile file; file.id = fileId++; file.pathName = pathName; file.baseName = layerBaseName; file.layerName = child->name(); file.name = folderName + "/" + layerBaseName + ".png"; qreal xmin = rc.left(); qreal ymin = rc.top(); qreal xmax = rc.right(); qreal ymax = rc.bottom(); file.width = xmax - xmin; file.height = ymax - ymin; file.x = xmin; file.y = ymin; //qDebug() << "Created file" << file.id << file.name << file.pathName << file.baseName << file.width << file.height << file.layerName; savePaintDevice(child->projection(), basePath + file.name); folder.files.append(file); } child = child->prevSibling(); } if (folder.files.size() > 0) { //qDebug() << "Adding folder" << folder.id << folder.name << folder.groupName << folder.files.length(); m_folders.append(folder); - folderId++; + (*folderId)++; } } Bone *KisSpriterExport::parseBone(const Bone *parent, KisGroupLayerSP groupLayer) { static int boneId = 0; QString groupBaseName = groupLayer->name().split(" ").first(); Bone *bone = new Bone; bone->id = boneId++; bone->parentBone = parent; bone->name = groupBaseName; if (m_boneLayer) { QRectF rc = m_image->bounds().intersected(m_boneLayer->exactBounds()); qreal xmin = rc.left(); qreal ymin = rc.top(); qreal xmax = rc.right(); qreal ymax = rc.bottom(); bone->x = (xmin + xmax) / 2; bone->y = -(ymin + ymax) / 2; bone->width = xmax - xmin; bone->height = ymax - ymin; } else { bone->x = 0.0; bone->y = 0.0; bone->width = 0.0; bone->height = 0.0; } if (parent) { bone->localX = bone->x - parent->x; bone->localY = bone->y - parent->y; } else { bone->localX = bone->x; bone->localY = bone->y; } bone->localAngle = 0.0; bone->localScaleX = 1.0; bone->localScaleY = 1.0; KisNodeSP child = groupLayer->lastChild(); while (child) { if (child->visible() && child->inherits("KisGroupLayer")) { bone->bones.append(parseBone(bone, qobject_cast(child.data()))); } child = child->prevSibling(); } //qDebug() << "Created bone" << bone->id << "with" << bone->bones.size() << "bones"; return bone; } void copyBone(Bone *startBone) { startBone->fixLocalX = startBone->localX; startBone->fixLocalY = startBone->localY; startBone->fixLocalAngle = startBone->localAngle; startBone->fixLocalScaleX= startBone->localScaleX; startBone->fixLocalScaleY= startBone->localScaleY; Q_FOREACH(Bone *child, startBone->bones) { copyBone(child); } } void KisSpriterExport::fixBone(Bone *bone) { qreal boneLocalAngle = 0; qreal boneLocalScaleX = 1; if (bone->bones.length() >= 1) { // if a bone has one or more children, point at first child Bone *childBone = bone->bones[0]; qreal dx = childBone->x - bone->x; qreal dy = childBone->y - bone->y; if (qAbs(dx) > 0 || qAbs(dy) > 0) { boneLocalAngle = KisFastMath::atan2(dy, dx); boneLocalScaleX = sqrt(dx * dx + dy * dy) / 200; } } else if (bone->parentBone) { // else, if bone has parent, point away from parent qreal dx = bone->x - bone->parentBone->x; qreal dy = bone->y - bone->parentBone->y; if (qAbs(dx) > 0 || qAbs(dy) > 0) { boneLocalAngle = KisFastMath::atan2(dy, dx); boneLocalScaleX = sqrt(dx * dx + dy * dy) / 200; } } // adjust bone angle bone->fixLocalAngle += boneLocalAngle; bone->fixLocalScaleX *= boneLocalScaleX; // rotate all the child bones back to world position for (int i = 0; i < bone->bones.length(); ++i) { Bone *childBone = bone->bones[i]; qreal tx = childBone->fixLocalX; qreal ty = childBone->fixLocalY; childBone->fixLocalX = tx * cos(-boneLocalAngle) - ty * sin(-boneLocalAngle); childBone->fixLocalY = tx * sin(-boneLocalAngle) + ty * cos(-boneLocalAngle); childBone->fixLocalX /= boneLocalScaleX; childBone->fixLocalAngle -= boneLocalAngle; childBone->fixLocalScaleX /= boneLocalScaleX; } // rotate all the child objects back to world position for (int i = 0; i < m_objects.length(); ++i) { if (m_objects[i].bone == bone) { m_objects[i].fixLocalAngle -= boneLocalAngle; m_objects[i].fixLocalScaleX /= boneLocalScaleX; } } // process all child bones for (int i = 0; i < bone->bones.length(); ++i) { fixBone(bone->bones[i]); } } void KisSpriterExport::writeBoneRef(const Bone *bone, QDomElement &key, QDomDocument &scml) { if (!bone) return; QDomElement boneRef = scml.createElement("bone_ref"); key.appendChild(boneRef); boneRef.setAttribute("id", bone->id); if (bone->parentBone) { boneRef.setAttribute("parent", bone->parentBone->id); } boneRef.setAttribute("timeline", m_timelineid++); boneRef.setAttribute("key", "0"); Q_FOREACH(const Bone *childBone, bone->bones) { writeBoneRef(childBone, key, scml); } } void KisSpriterExport::writeBone(const Bone *bone, QDomElement &animation, QDomDocument &scml) { if (!bone) return; QDomElement timeline = scml.createElement("timeline"); animation.appendChild(timeline); timeline.setAttribute("id", m_timelineid); timeline.setAttribute("name", bone->name); timeline.setAttribute("object_type", "bone"); QDomElement key = scml.createElement("key"); timeline.appendChild(key); key.setAttribute("id", "0"); key.setAttribute("spin", 0); QDomElement boneEl = scml.createElement("bone"); key.appendChild(boneEl); boneEl.setAttribute("x", QString::number(bone->fixLocalX, 'f', 2)); boneEl.setAttribute("y", QString::number(bone->fixLocalY, 'f', 2)); boneEl.setAttribute("angle", QString::number(bone->fixLocalAngle, 'f', 2)); boneEl.setAttribute("scale_x", QString::number(bone->fixLocalScaleX, 'f', 2)); boneEl.setAttribute("scale_y", QString::number(bone->fixLocalScaleY, 'f', 2)); m_timelineid++; Q_FOREACH(const Bone *childBone, bone->bones) { writeBone(childBone, animation, scml); } } void KisSpriterExport::fillScml(QDomDocument &scml, const QString &entityName) { //qDebug() << "Creating scml" << entityName; QDomElement root = scml.createElement("spriter_data"); scml.appendChild(root); root.setAttribute("scml_version", 1); root.setAttribute("generator", "krita"); root.setAttribute("generator_version", qApp->applicationVersion()); Q_FOREACH(const Folder &folder, m_folders) { QDomElement fe = scml.createElement("folder"); root.appendChild(fe); fe.setAttribute("id", folder.id); fe.setAttribute("name", folder.name); Q_FOREACH(const SpriterFile &file, folder.files) { QDomElement fileElement = scml.createElement("file"); fe.appendChild(fileElement); fileElement.setAttribute("id", file.id); fileElement.setAttribute("name", file.name); fileElement.setAttribute("width", QString::number(file.width, 'f', 2)); fileElement.setAttribute("height", QString::number(file.height, 'f', 2)); - qreal pivotX=0; - qreal pivotY=1; - Q_FOREACH(const SpriterObject &object, m_objects) { - if(file.id == object.fileId) - { - pivotX = (0.0 -(object.fixLocalX / file.width)); - pivotY = (1.0 -(object.fixLocalY / file.height)); - break; - } - } - fileElement.setAttribute("pivot_x", QString::number(pivotX, 'f', 2)); - fileElement.setAttribute("pivot_y", QString::number(pivotY, 'f', 2)); + // qreal pivotX=0; + // qreal pivotY=1; + // Q_FOREACH(const SpriterObject &object, m_objects) { + // if(file.id == object.fileId) + // { + // pivotX = (0.0 -(object.fixLocalX / file.width)); + // pivotY = (1.0 -(object.fixLocalY / file.height)); + // break; + // } + // } + // fileElement.setAttribute("pivot_x", QString::number(pivotX, 'f', 2)); + // fileElement.setAttribute("pivot_y", QString::number(pivotY, 'f', 2)); } } // entity QDomElement entity = scml.createElement("entity"); root.appendChild(entity); entity.setAttribute("id", "0"); entity.setAttribute("name", entityName); // entity/animation QDomElement animation = scml.createElement("animation"); entity.appendChild(animation); animation.setAttribute("id", "0"); animation.setAttribute("name", "default"); animation.setAttribute("length", "1000"); animation.setAttribute("looping", "false"); // entity/animation/mainline QDomElement mainline = scml.createElement("mainline"); animation.appendChild(mainline); QDomElement key = scml.createElement("key"); mainline.appendChild(key); key.setAttribute("id", "0"); m_timelineid = 0; writeBoneRef(m_rootBone, key, scml); Q_FOREACH(const SpriterObject &object, m_objects) { QDomElement oe = scml.createElement("object_ref"); key.appendChild(oe); oe.setAttribute("id", object.id); if (object.bone) { oe.setAttribute("parent", object.bone->id); } oe.setAttribute("timeline", m_timelineid++); oe.setAttribute("key", "0"); oe.setAttribute("z_index", object.id); } // entity/animation/timeline m_timelineid = 0; if (m_rootBone) { writeBone(m_rootBone, animation, scml); } Q_FOREACH(const SpriterObject &object, m_objects) { Folder folder; Q_FOREACH(const Folder & f, m_folders) { if (f.id == object.folderId) { folder = f; break; } } SpriterFile file; file.id = -1; Q_FOREACH(const SpriterFile &f, folder.files) { if (f.id == object.fileId) { file = f; break; } } Q_ASSERT(file.id >= 0); QString objectName = "object-" + file.baseName; QDomElement timeline = scml.createElement("timeline"); animation.appendChild(timeline); timeline.setAttribute("id", m_timelineid++); timeline.setAttribute("name", objectName); QDomElement key = scml.createElement("key"); timeline.appendChild(key); key.setAttribute("id", "0"); key.setAttribute("spin", "0"); QDomElement objectEl = scml.createElement("object"); key.appendChild(objectEl); objectEl.setAttribute("folder", object.folderId); objectEl.setAttribute("file", object.fileId); - objectEl.setAttribute("x", "0"); - objectEl.setAttribute("y", "0"); + objectEl.setAttribute("x", object.fixLocalX); + objectEl.setAttribute("y", object.fixLocalY); objectEl.setAttribute("angle", QString::number(kisRadiansToDegrees(object.fixLocalAngle), 'f', 2)); objectEl.setAttribute("scale_x", QString::number(object.fixLocalScaleX, 'f', 2)); objectEl.setAttribute("scale_y", QString::number(object.fixLocalScaleY, 'f', 2)); } } Bone *findBoneByName(Bone *startBone, const QString &name) { if (!startBone) return 0; //qDebug() << "findBoneByName" << name << "starting with" << startBone->name; if (startBone->name == name) { return startBone; } Q_FOREACH(Bone *child, startBone->bones) { //qDebug() << "looking for" << name << "found" << child->name; if (child->name == name) { return child; } Bone *grandChild = findBoneByName(child, name); if (grandChild){ return grandChild; } } return 0; } KisImportExportFilter::ConversionStatus KisSpriterExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) { QFileInfo fi(filename()); m_image = document->savingImage(); if (m_image->rootLayer()->childCount() == 0) { return KisImportExportFilter::UsageError; } KisGroupLayerSP root = m_image->rootLayer(); m_boneLayer = qobject_cast(root->findChildByName("bone").data()); //qDebug() << "Found boneLayer" << m_boneLayer; m_rootLayer= qobject_cast(root->findChildByName("root").data()); //qDebug() << "Fond rootLayer" << m_rootLayer; parseFolder(m_image->rootLayer(), "", fi.absolutePath()); m_rootBone = 0; if (m_rootLayer) { m_rootBone = parseBone(0, m_rootLayer); } // Generate objects int objectId = 0; for (int folderIndex = 0, folderCount = m_folders.size(); folderIndex < folderCount; ++folderIndex) { Folder folder = m_folders[folderCount - 1 - folderIndex]; for (int fileIndex = 0, fileCount = folder.files.size(); fileIndex < fileCount; ++ fileIndex) { SpriterFile file = folder.files[fileCount - 1 - fileIndex]; SpriterObject spriterObject; spriterObject.id = objectId++; spriterObject.folderId = folder.id; spriterObject.fileId = file.id; spriterObject.x = file.x; spriterObject.y = -file.y; Bone *bone = 0; //qDebug() << "file layername" << file.layerName; // layer.name format: "base_name bone(bone_name) slot(slot_name)" if (file.layerName.contains("bone(")) { int start = file.layerName.indexOf("bone(") + 5; int end = file.layerName.indexOf(')', start); QString boneName = file.layerName.mid(start, end - start); bone = findBoneByName(m_rootBone, boneName); } // layer.name format: "base_name" if (!bone && m_rootBone) { bone = findBoneByName(m_rootBone, file.layerName); } // group.name format: "base_name bone(bone_name)" if (!bone && m_rootBone) { if (folder.groupName.contains("bone(")) { int start = folder.groupName.indexOf("bone(") + 5; int end = folder.groupName.indexOf(')', start); QString boneName = folder.groupName.mid(start, end - start); bone = findBoneByName(m_rootBone, boneName); } // group.name format: "base_name" if (!bone) { bone = findBoneByName(m_rootBone, folder.groupName); } } if (!bone) { bone = m_rootBone; } if (bone) { spriterObject.bone = bone; spriterObject.localX = spriterObject.x - bone->x; spriterObject.localY = spriterObject.y - bone->y; } else { spriterObject.bone = 0; spriterObject.localX = spriterObject.x; spriterObject.localY = spriterObject.y; } spriterObject.localAngle = 0; spriterObject.localScaleX = 1.0; spriterObject.localScaleY = 1.0; SpriterSlot *slot = 0; // layer.name format: "base_name bone(bone_name) slot(slot_name)" if (file.layerName.contains("slot(")) { int start = file.layerName.indexOf("slot(") + 5; int end = file.layerName.indexOf(')', start); slot->name = file.layerName.mid(start, end - start); slot->defaultAttachmentFlag = file.layerName.contains("*"); } spriterObject.slot = slot; // qDebug() << "Created object" << spriterObject.id << spriterObject.folderId // << spriterObject.fileId << spriterObject.x << spriterObject.y // << spriterObject.localX << spriterObject.localY; m_objects.append(spriterObject); } } // Copy object transforms for (int i = 0; i < m_objects.size(); ++i) { m_objects[i].fixLocalX = m_objects[i].localX; m_objects[i].fixLocalY = m_objects[i].localY; m_objects[i].fixLocalAngle = m_objects[i].localAngle; m_objects[i].fixLocalScaleX = m_objects[i].localScaleX; m_objects[i].fixLocalScaleY = m_objects[i].localScaleY; } // Calculate bone angles if (m_rootBone) { copyBone(m_rootBone); fixBone(m_rootBone); } // Generate scml QDomDocument scml; fillScml(scml, fi.baseName()); io->write("\n"); io->write(scml.toString(4).toUtf8()); delete m_rootBone; return KisImportExportFilter::OK; } void KisSpriterExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("MultiLayerCheck")->create(KisExportCheckBase::SUPPORTED)); QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID); addSupportedColorModels(supportedColorModels, "Spriter"); } #include "kis_spriter_export.moc" diff --git a/plugins/impex/spriter/kis_spriter_export.h b/plugins/impex/spriter/kis_spriter_export.h index 86daebf519..d620f17493 100644 --- a/plugins/impex/spriter/kis_spriter_export.h +++ b/plugins/impex/spriter/kis_spriter_export.h @@ -1,135 +1,135 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KIS_SPRITER_EXPORT_H_ #define _KIS_SPRITER_EXPORT_H_ #include #include #include #include #include struct SpriterFile { qreal id; QString name; QString pathName; QString baseName; QString layerName; qreal width; qreal height; qreal x; qreal y; }; struct Folder { qreal id; QString name; QString pathName; QString baseName; QString groupName; QList files; }; struct Bone { qreal id; const Bone *parentBone; QString name; qreal x; qreal y; qreal width; qreal height; qreal localX; qreal localY; qreal localAngle; qreal localScaleX; qreal localScaleY; qreal fixLocalX; qreal fixLocalY; qreal fixLocalAngle; qreal fixLocalScaleX; qreal fixLocalScaleY; QList bones; ~Bone() { qDeleteAll(bones); bones.clear();; } }; struct SpriterSlot { QString name; bool defaultAttachmentFlag; }; struct SpriterObject { qreal id; qreal folderId; qreal fileId; Bone *bone; SpriterSlot *slot; qreal x; qreal y; qreal localX; qreal localY; qreal localAngle; qreal localScaleX; qreal localScaleY; qreal fixLocalX; qreal fixLocalY; qreal fixLocalAngle; qreal fixLocalScaleX; qreal fixLocalScaleY; ~SpriterObject() { delete slot; } }; class KisSpriterExport : public KisImportExportFilter { Q_OBJECT public: KisSpriterExport(QObject *parent, const QVariantList &); virtual ~KisSpriterExport(); public: virtual KisImportExportFilter::ConversionStatus convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0); void initializeCapabilities(); private: bool savePaintDevice(KisPaintDeviceSP dev, const QString &fileName); - void parseFolder(KisGroupLayerSP parentGroup, const QString &folderName, const QString &basePath); + void parseFolder(KisGroupLayerSP parentGroup, const QString &folderName, const QString &basePath, int *folderId = 0); Bone *parseBone(const Bone *parent, KisGroupLayerSP groupLayer); void fixBone(Bone *bone); void fillScml(QDomDocument &scml, const QString &entityName); void writeBoneRef(const Bone *bone, QDomElement &mainline, QDomDocument &scml); void writeBone(const Bone *bone, QDomElement &timeline, QDomDocument &scml); KisImageSP m_image; qreal m_timelineid; QList m_folders; Bone *m_rootBone; QList m_objects; KisGroupLayerSP m_rootLayer; // Not the image's root later, but the one that is named "root" KisLayerSP m_boneLayer; }; #endif diff --git a/plugins/impex/video/video_saver.cpp b/plugins/impex/video/video_saver.cpp index 1ee24db8e6..c1d88794b5 100644 --- a/plugins/impex/video/video_saver.cpp +++ b/plugins/impex/video/video_saver.cpp @@ -1,330 +1,330 @@ /* * Copyright (c) 2016 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 "video_saver.h" #include #include #include #include #include #include #include #include #include #include #include "kis_config.h" #include "kis_animation_exporter.h" #include #include #include #include #include #include #include #include "KisPart.h" class KisFFMpegProgressWatcher : public QObject { Q_OBJECT public: KisFFMpegProgressWatcher(QFile &progressFile, int totalFrames) : m_progressFile(progressFile), m_totalFrames(totalFrames) { connect(&m_progressWatcher, SIGNAL(fileChanged(QString)), SLOT(slotFileChanged())); m_progressWatcher.addPath(m_progressFile.fileName()); } private Q_SLOTS: void slotFileChanged() { int currentFrame = -1; bool isEnded = false; while(!m_progressFile.atEnd()) { QString line = QString(m_progressFile.readLine()).remove(QChar('\n')); QStringList var = line.split("="); if (var[0] == "frame") { currentFrame = var[1].toInt(); } else if (var[0] == "progress") { isEnded = var[1] == "end"; } } if (isEnded) { emit sigProgressChanged(100); emit sigProcessingFinished(); } else { emit sigProgressChanged(100 * currentFrame / m_totalFrames); } } Q_SIGNALS: void sigProgressChanged(int percent); void sigProcessingFinished(); private: QFileSystemWatcher m_progressWatcher; QFile &m_progressFile; int m_totalFrames; }; class KisFFMpegRunner { public: KisFFMpegRunner(const QString &ffmpegPath) : m_cancelled(false), m_ffmpegPath(ffmpegPath) {} public: KisImageBuilder_Result runFFMpeg(const QStringList &specialArgs, const QString &actionName, const QString &logPath, int totalFrames) { dbgFile << "runFFMpeg: specialArgs" << specialArgs << "actionName" << actionName << "logPath" << logPath << "totalFrames" << totalFrames; QTemporaryFile progressFile(QDir::tempPath() + QDir::separator() + "KritaFFmpegProgress.XXXXXX"); progressFile.open(); m_process.setStandardOutputFile(logPath); m_process.setProcessChannelMode(QProcess::MergedChannels); QStringList args; args << "-v" << "debug" << "-nostdin" << "-progress" << progressFile.fileName() << specialArgs; qDebug() << "\t" << m_ffmpegPath << args.join(" "); m_cancelled = false; m_process.start(m_ffmpegPath, args); return waitForFFMpegProcess(actionName, progressFile, m_process, totalFrames); } void cancel() { m_cancelled = true; m_process.kill(); } private: KisImageBuilder_Result waitForFFMpegProcess(const QString &message, QFile &progressFile, QProcess &ffmpegProcess, int totalFrames) { KisFFMpegProgressWatcher watcher(progressFile, totalFrames); QProgressDialog progress(message, "", 0, 0, KisPart::instance()->currentMainwindow()); progress.setWindowModality(Qt::ApplicationModal); progress.setCancelButton(0); progress.setMinimumDuration(0); progress.setValue(0); progress.setRange(0, 100); QEventLoop loop; loop.connect(&watcher, SIGNAL(sigProcessingFinished()), SLOT(quit())); loop.connect(&ffmpegProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(quit())); loop.connect(&watcher, SIGNAL(sigProgressChanged(int)), &progress, SLOT(setValue(int))); loop.exec(); // wait for some errorneous case ffmpegProcess.waitForFinished(5000); KisImageBuilder_Result retval = KisImageBuilder_RESULT_OK; if (ffmpegProcess.state() != QProcess::NotRunning) { // sorry... ffmpegProcess.kill(); retval = KisImageBuilder_RESULT_FAILURE; } else if (m_cancelled) { retval = KisImageBuilder_RESULT_CANCEL; } else if (ffmpegProcess.exitCode()) { retval = KisImageBuilder_RESULT_FAILURE; } return retval; } private: QProcess m_process; bool m_cancelled; QString m_ffmpegPath; }; VideoSaver::VideoSaver(KisDocument *doc, const QString &ffmpegPath, bool batchMode) : m_image(doc->image()) , m_doc(doc) , m_batchMode(batchMode) , m_ffmpegPath(ffmpegPath) , m_runner(new KisFFMpegRunner(ffmpegPath)) { } VideoSaver::~VideoSaver() { } KisImageSP VideoSaver::image() { return m_image; } bool VideoSaver::hasFFMpeg() const { return !m_ffmpegPath.isEmpty(); } KisImageBuilder_Result VideoSaver::encode(const QString &filename, KisPropertiesConfigurationSP configuration) { qDebug() << "ffmpeg" << m_ffmpegPath << "filename" << filename << "configuration" << configuration->toXML(); if (m_ffmpegPath.isEmpty()) { m_ffmpegPath = configuration->getString("ffmpeg_path"); if (!QFileInfo(m_ffmpegPath).exists()) { return KisImageBuilder_RESULT_FAILURE; } } KisImageBuilder_Result result = KisImageBuilder_RESULT_OK; KisImageAnimationInterface *animation = m_image->animationInterface(); const KisTimeRange fullRange = animation->fullClipRange(); const int frameRate = animation->framerate(); KIS_SAFE_ASSERT_RECOVER_NOOP(configuration->hasProperty("first_frame")); KIS_SAFE_ASSERT_RECOVER_NOOP(configuration->hasProperty("last_frame")); KIS_SAFE_ASSERT_RECOVER_NOOP(configuration->hasProperty("include_audio")); const KisTimeRange clipRange(configuration->getInt("first_frame", fullRange.start()), configuration->getInt("last_frame", fullRange.end())); const bool includeAudio = configuration->getBool("include_audio", true); const QDir framesDir(configuration->getString("directory")); QString resultFile; if (QFileInfo(filename).isAbsolute()) { resultFile = filename; } else { resultFile = framesDir.absolutePath() + "/" + filename; } const QFileInfo info(resultFile); const QString suffix = info.suffix().toLower(); const QString palettePath = framesDir.filePath("palette.png"); const QString savedFilesMask = configuration->getString("savedFilesMask"); const QStringList additionalOptionsList = configuration->getString("customUserOptions").split(' ', QString::SkipEmptyParts); if (suffix == "gif") { { QStringList args; args << "-r" << QString::number(frameRate) - << "-pattern_type" << "glob" + << "-start_number" << QString::number(clipRange.start()) << "-i" << savedFilesMask << "-vf" << "palettegen" << "-y" << palettePath; KisImageBuilder_Result result = m_runner->runFFMpeg(args, i18n("Fetching palette..."), framesDir.filePath("log_generate_palette_gif.log"), - clipRange.duration() + clipRange.start()); + clipRange.duration()); if (result != KisImageBuilder_RESULT_OK) { return result; } } { QStringList args; args << "-r" << QString::number(frameRate) - << "-pattern_type" << "glob" + << "-start_number" << QString::number(clipRange.start()) << "-i" << savedFilesMask << "-i" << palettePath << "-lavfi" << "[0:v][1:v] paletteuse" << additionalOptionsList << "-y" << resultFile; - dbgFile << "savedFilesMask" << savedFilesMask << "start" << clipRange.start() << "duration" << clipRange.duration(); + dbgFile << "savedFilesMask" << savedFilesMask << "start" << QString::number(clipRange.start()) << "duration" << clipRange.duration(); KisImageBuilder_Result result = m_runner->runFFMpeg(args, i18n("Encoding frames..."), framesDir.filePath("log_encode_gif.log"), - clipRange.duration() + clipRange.start()); + clipRange.duration()); if (result != KisImageBuilder_RESULT_OK) { return result; } } } else { QStringList args; - args << "-r" << QString::number(frameRate); - args << "-pattern_type" << "glob"; - args << "-i" << savedFilesMask; + args << "-r" << QString::number(frameRate) + << "-start_number" << QString::number(clipRange.start()) + << "-i" << savedFilesMask; QFileInfo audioFileInfo = animation->audioChannelFileName(); if (includeAudio && audioFileInfo.exists()) { const int msecStart = clipRange.start() * 1000 / animation->framerate(); const int msecDuration = clipRange.duration() * 1000 / animation->framerate(); const QTime startTime = QTime::fromMSecsSinceStartOfDay(msecStart); const QTime durationTime = QTime::fromMSecsSinceStartOfDay(msecDuration); const QString ffmpegTimeFormat("H:m:s.zzz"); args << "-ss" << startTime.toString(ffmpegTimeFormat); args << "-t" << durationTime.toString(ffmpegTimeFormat); args << "-i" << audioFileInfo.absoluteFilePath(); } args << additionalOptionsList << "-y" << resultFile; result = m_runner->runFFMpeg(args, i18n("Encoding frames..."), framesDir.filePath("log_encode.log"), - clipRange.duration() + clipRange.start()); + clipRange.duration()); } return result; } void VideoSaver::cancel() { m_runner->cancel(); } #include "video_saver.moc"