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 @@
+
+
+
+
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 @@
+
+
+
+
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"