diff --git a/krita/data/CMakeLists.txt b/krita/data/CMakeLists.txt
index 50e35120da..1013dfb365 100644
--- a/krita/data/CMakeLists.txt
+++ b/krita/data/CMakeLists.txt
@@ -1,25 +1,26 @@
add_subdirectory( actions )
add_subdirectory( brushes )
add_subdirectory( bundles )
add_subdirectory( patterns )
add_subdirectory( gradients )
add_subdirectory( profiles )
add_subdirectory( templates )
add_subdirectory( workspaces )
add_subdirectory( themes )
add_subdirectory( predefined_image_sizes )
add_subdirectory( input )
add_subdirectory( shortcuts )
add_subdirectory( paintoppresets )
add_subdirectory( palettes )
add_subdirectory( symbols )
add_subdirectory( preset_icons )
add_subdirectory( metadata/schemas )
+add_subdirectory( gamutmasks )
########### install files ###############
install( FILES
kritarc
DESTINATION ${CONFIG_INSTALL_DIR}
)
diff --git a/krita/data/gamutmasks/Atmosphere_With_Accent.kgm b/krita/data/gamutmasks/Atmosphere_With_Accent.kgm
new file mode 100644
index 0000000000..8bea9a5673
Binary files /dev/null and b/krita/data/gamutmasks/Atmosphere_With_Accent.kgm differ
diff --git a/krita/data/gamutmasks/Atmospheric_Triad.kgm b/krita/data/gamutmasks/Atmospheric_Triad.kgm
new file mode 100644
index 0000000000..638fc6a49d
Binary files /dev/null and b/krita/data/gamutmasks/Atmospheric_Triad.kgm differ
diff --git a/krita/data/gamutmasks/CMakeLists.txt b/krita/data/gamutmasks/CMakeLists.txt
new file mode 100644
index 0000000000..39a055e18d
--- /dev/null
+++ b/krita/data/gamutmasks/CMakeLists.txt
@@ -0,0 +1,14 @@
+########### install files ###############
+
+install( FILES
+ GamutMaskTemplate.kra
+ empty_mask_preview.png
+ Atmosphere_With_Accent.kgm
+ Atmospheric_Triad.kgm
+ Complementary.kgm
+ Dominant_Hue_With_Accent.kgm
+ Shifted_Triad.kgm
+ Split_Complementary.kgm
+
+DESTINATION ${DATA_INSTALL_DIR}/krita/gamutmasks)
+
diff --git a/krita/data/gamutmasks/Complementary.kgm b/krita/data/gamutmasks/Complementary.kgm
new file mode 100644
index 0000000000..801df35332
Binary files /dev/null and b/krita/data/gamutmasks/Complementary.kgm differ
diff --git a/krita/data/gamutmasks/Dominant_Hue_With_Accent.kgm b/krita/data/gamutmasks/Dominant_Hue_With_Accent.kgm
new file mode 100644
index 0000000000..1bfecf468e
Binary files /dev/null and b/krita/data/gamutmasks/Dominant_Hue_With_Accent.kgm differ
diff --git a/krita/data/gamutmasks/GamutMaskTemplate.kra b/krita/data/gamutmasks/GamutMaskTemplate.kra
new file mode 100644
index 0000000000..b2994bd54e
Binary files /dev/null and b/krita/data/gamutmasks/GamutMaskTemplate.kra differ
diff --git a/krita/data/gamutmasks/Shifted_Triad.kgm b/krita/data/gamutmasks/Shifted_Triad.kgm
new file mode 100644
index 0000000000..4939b02bff
Binary files /dev/null and b/krita/data/gamutmasks/Shifted_Triad.kgm differ
diff --git a/krita/data/gamutmasks/Split_Complementary.kgm b/krita/data/gamutmasks/Split_Complementary.kgm
new file mode 100644
index 0000000000..5744fa6cdb
Binary files /dev/null and b/krita/data/gamutmasks/Split_Complementary.kgm differ
diff --git a/krita/data/gamutmasks/empty_mask_preview.png b/krita/data/gamutmasks/empty_mask_preview.png
new file mode 100644
index 0000000000..03e96215a7
Binary files /dev/null and b/krita/data/gamutmasks/empty_mask_preview.png differ
diff --git a/krita/data/kritarc b/krita/data/kritarc
index 80f1c19618..16ce4b018a 100644
--- a/krita/data/kritarc
+++ b/krita/data/kritarc
@@ -1,479 +1,478 @@
favoriteCompositeOps=normal,erase,multiply,burn,darken,add,dodge,screen,overlay,soft_light_svg,luminize,lighten,saturation,color
ArtColorSel.ColorSpace=0
ArtColorSel.InversedSaturation=false
ArtColorSel.Light=0.5
-ArtColorSel.LightPieces=19
-ArtColorSel.NumRings=11
-ArtColorSel.RelativeLight=false
+ArtColorSel.LightPieces=11
+ArtColorSel.NumRings=7
ArtColorSel.RingAngles=0,0,0,0,0,0,0,0,0,0,0
ArtColorSel.RingPieces=12
ArtColorSel.SelColorA=1
ArtColorSel.SelColorH=0
ArtColorSel.SelColorS=0
ArtColorSel.SelColorX=0.5
BackgroundColorForNewImage=255,255,255
BackgroundOpacityForNewImage=255
BackgroundStyleForNewImage=0
Krita/Ocio/OcioColorManagementMode=0
Krita/Ocio/OcioLockColorVisualRepresentation=false
Krita/Ocio/UseOcio=false
LastBackGroundColor=\n\n \n\n
LastForeGroundColor=\n\n \n\n
LastPreset=Basic_circle
LastPreset_-1=Basic_circle
LineSmoothingDelayDistance=50
LineSmoothingDistance=50
LineSmoothingFinishStabilizedCurve=true
LineSmoothingStabilizeSensors=true
LineSmoothingTailAggressiveness=0.14999999999999999
LineSmoothingType=1
LineSmoothingUseDelayDistance=true
NumberOfLayersForNewImage=2
PaintopPopupDetached=false
SpecificColorSelector/ShowColorSpaceSelector=false
baseLength=50
colorDepthDef=U8
colorModelDef=RGBA
colorProfileDef=sRGB-elle-V2-srgbtrc.icc
favoritePresetsTag=★ My Favorites
internal_selector_active_color_set=Default
globalSnapBoundingBox=false
globalSnapExtension=false
globalSnapImageBounds=true
globalSnapImageCenter=true
globalSnapIntersection=false
globalSnapNode=false
globalSnapOrthogonal=false
gridmaincolor=99,99,99
gridmainstyle=0
gridsubdivisioncolor=150,150,150
gridsubdivisionstyle=1
guidesColor=99,99,99
guidesLineStyle=0
imageHeightDef=1200
imageResolutionDef=300
imageWidthDef=1600
levelOfDetailEnabled=true
numberOfOnionSkins=10
oninSkinTintColorForward=0,255,0
onionSkinOpacity_-1=173
onionSkinOpacity_-10=22
onionSkinOpacity_-2=163
onionSkinOpacity_-3=147
onionSkinOpacity_-4=127
onionSkinOpacity_-5=107
onionSkinOpacity_-6=84
onionSkinOpacity_-7=63
onionSkinOpacity_-8=48
onionSkinOpacity_-9=33
onionSkinOpacity_0=175
onionSkinOpacity_1=173
onionSkinOpacity_10=22
onionSkinOpacity_2=163
onionSkinOpacity_3=147
onionSkinOpacity_4=127
onionSkinOpacity_5=107
onionSkinOpacity_6=84
onionSkinOpacity_7=63
onionSkinOpacity_8=48
onionSkinOpacity_9=33
onionSkinState_-1=true
onionSkinState_-10=false
onionSkinState_-2=true
onionSkinState_-3=false
onionSkinState_-4=false
onionSkinState_-5=false
onionSkinState_-6=false
onionSkinState_-7=false
onionSkinState_-8=false
onionSkinState_-9=false
onionSkinState_0=true
onionSkinState_1=true
onionSkinState_10=false
onionSkinState_2=true
onionSkinState_3=false
onionSkinState_4=false
onionSkinState_5=false
onionSkinState_6=false
onionSkinState_7=false
onionSkinState_8=false
onionSkinState_9=false
onionSkinTintColorBackward=255,0,0
onionSkinTintFactor=191
presethistory=Basic_tip_default
showAdditionalOnionSkinsSettings=true
toolbarslider_1=opacity
toolbarslider_2=size
toolbarslider_3=flow
[advancedColorSelector]
allowHorizontalLayout=true
colorSelectorConfiguration=3|0|5|0
commonColorsAlignment=false
commonColorsAutoUpdate=false
commonColorsCount=12
commonColorsHeight=16
commonColorsNumCols=1
commonColorsNumRows=1
commonColorsScrolling=false
commonColorsShow=true
commonColorsWidth=16
customColorSpaceDepthID=U8
customColorSpaceModel=RGBA
customColorSpaceProfile=sRGB built-in
lastUsedColorsAlignment=true
lastUsedColorsCount=20
lastUsedColorsHeight=16
lastUsedColorsNumCols=1
lastUsedColorsNumRows=1
lastUsedColorsScrolling=true
lastUsedColorsShow=true
lastUsedColorsWidth=16
minimalShadeSelectorAsGradient=true
minimalShadeSelectorLineConfig=0|0.2|0|0|0|0|0;1|0|1|1|0|0|0;2|0|-1|1|0|0|0;
minimalShadeSelectorLineHeight=10
minimalShadeSelectorPatchCount=10
popupOnMouseClick=true
popupOnMouseOver=false
shadeSelectorHideable=false
shadeSelectorType=Minimal
shadeSelectorUpdateOnBackground=true
shadeSelectorUpdateOnForeground=true
shadeSelectorUpdateOnLeftClick=false
shadeSelectorUpdateOnRightClick=false
useCustomColorSpace=false
zoomSize=280
[DockWidget sharedtooldocker]
TabbedMode=false
[KisToolTransform]
filterId=Bicubic
[MainWindow]
State=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AAAAFABHAHIAaQBkAEQAbwBjAGsAZQByAAAAAAD/////AAABLQD////7AAAAHgBIAGkAcwB0AG8AZwByAGEAbQBEAG8AYwBrAGUAcgAAAAAA/////wAAAEcA////+wAAACoAQQBuAGkAbQBhAHQAaQBvAG4AQwB1AHIAdgBlAHMARABvAGMAawBlAHIAAAAAAP////8AAACMAP////sAAAAyAFMAdgBnAFMAeQBtAGIAbwBsAEMAbwBsAGwAZQBjAHQAaQBvAG4ARABvAGMAawBlAHIAAAAAAP////8AAACMAP////sAAAAWAFQAbwB1AGMAaABEAG8AYwBrAGUAcgAAAAJMAAABMQAAABMA////+wAAABoAQQByAHIAYQBuAGcAZQBEAG8AYwBrAGUAcgAAAAAA/////wAAAHoA////+wAAADoAYwBvAG0AaQBjAHMAXwBwAHIAbwBqAGUAYwB0AF8AbQBhAG4AYQBnAGUAcgBfAGQAbwBjAGsAZQByAAAAAAD/////AAAAuQD////7AAAAKgBxAHUAaQBjAGsAXwBzAGUAdAB0AGkAbgBnAHMAXwBkAG8AYwBrAGUAcgAAAAAA/////wAAAIwA////+wAAABYAUABhAGcAZQByAEQAbwBjAGsAZQByAAAAAAD/////AAAALQD////7AAAAJgBsAGEAcwB0AGQAbwBjAHUAbQBlAG4AdABzAGQAbwBjAGsAZQByAAAAAAD/////AAAAiQD///8AAAACAAAKAAAAALz8AQAAAAH7AAAAGgBUAG8AbwBsAEIAYQByAEQAbwBjAGsAZQByAAAAAAD/////AAAAAAAAAAAAAAADAAAAAAAAAAD8AQAAAAT7AAAAHABGAGwAaQBwAGIAbwBvAGsARABvAGMAawBlAHIAAAAAAP////8AAAAAAAAAAPsAAAAeAEEAbgBpAG0AYQB0AGkAbwBuAEQAbwBjAGsAZQByAAAAAAD/////AAABBQD////7AAAAIABPAG4AaQBvAG4AUwBrAGkAbgBzAEQAbwBjAGsAZQByAAAAAAD/////AAABNgD////7AAAAHABUAGkAbQBlAGwAaQBuAGUARABvAGMAawBlAHIAAAAAAP////8AAABVAP///wAABU0AAAPNAAAABAAAAAQAAAAIAAAACPwAAAABAAAAAgAAAAIAAAAWAG0AYQBpAG4AVABvAG8AbABCAGEAcgEAAAAA/////wAAAAAAAAAAAAAAHgBCAHIAdQBzAGgAZQBzAEEAbgBkAFMAdAB1AGYAZgEAAAC5/////wAAAAAAAAAA
[advancedColorSelector]
gamma=2.2000000000000002
hidePopupOnClickCheck=false
hsxSettingType=0
lumaB=0.0722
lumaG=0.71519999999999995
lumaR=0.21260000000000001
onDockerResize=0
shadeMyPaintType=HSV
zoomSelectorOptions=0
[calligra]
ColorSpaceExtensionsPlugins=\\0
ColorSpaceExtensionsPluginsDisabled=
ColorSpacePlugins=\\0
ColorSpacePluginsDisabled=
DockerPlugins=\\0
DockerPluginsDisabled=textdocumentinspection
FlakePlugins=,
ShapePlugins=,
ToolsBlacklist=CreatePathTool,KoPencilTool,ConnectionTool,KarbonFilterEffectsTool,KritaShape/KisToolText,ArtisticTextTool,TextTool
ToolPlugins=,,
ToolPluginsDisabled=
[KoShapeCollection]
QuickShapes=ArtisticText,TextShapeID,EllipseShape,RectangleShape
[colorhotkeys]
steps_blueyellow=10
steps_hue=36
steps_lightness=10
steps_redgreen=10
steps_saturation=10
[crashprevention]
CreatingCanvas=false
[hsxColorSlider]
hsiH=false
hsiI=false
hsiS=false
hslH=true
hslL=true
hslS=true
hsvH=false
hsvS=false
hsvV=false
hsyH=false
hsyS=false
hsyY=false
[krita]
State=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
ToolBarsMovable=Enabled
[krita][DockWidget AnimationCurvesDocker]
Collapsed=false
DockArea=2
Locked=false
height=421
width=448
xPosition=0
yPosition=0
[krita][DockWidget AnimationDocker]
Collapsed=false
DockArea=8
Locked=false
height=160
width=280
xPosition=0
yPosition=0
[krita][DockWidget ArtisticColorSelector]
Collapsed=false
DockArea=2
Locked=false
height=294
width=337
xPosition=0
yPosition=0
[krita][DockWidget ChannelDocker]
Collapsed=false
DockArea=2
Locked=false
height=30
width=100
xPosition=0
yPosition=0
[krita][DockWidget ColorSelectorNg]
Collapsed=false
DockArea=2
Locked=false
height=176
width=281
xPosition=0
yPosition=20
[krita][DockWidget ColorSlider]
Collapsed=false
DockArea=2
Locked=false
height=460
width=640
xPosition=0
yPosition=20
[krita][DockWidget CompositionDocker]
Collapsed=false
DockArea=2
Locked=false
height=300
width=400
xPosition=0
yPosition=0
[krita][DockWidget DigitalMixer]
Collapsed=false
DockArea=2
Locked=false
height=30
width=100
xPosition=0
yPosition=0
[krita][DockWidget GridDocker]
Collapsed=false
DockArea=2
Locked=false
height=342
width=441
xPosition=0
yPosition=0
[krita][DockWidget HistogramDocker]
Collapsed=false
DockArea=2
Locked=false
height=91
width=281
xPosition=0
yPosition=20
[krita][DockWidget History]
Collapsed=false
DockArea=2
Locked=false
height=460
width=640
xPosition=0
yPosition=20
[krita][DockWidget ImageDocker]
Collapsed=false
DockArea=2
Locked=false
height=300
width=399
xPosition=0
yPosition=0
[krita][DockWidget KisLayerBox]
DockArea=2
Locked=false
height=358
width=281
xPosition=0
yPosition=20
[krita][DockWidget LutDocker]
Collapsed=false
DockArea=2
Locked=false
height=286
width=357
xPosition=0
yPosition=0
[krita][DockWidget OnionSkinsDocker]
Collapsed=false
DockArea=8
Locked=false
height=210
width=356
xPosition=0
yPosition=0
[krita][DockWidget OverviewDocker]
Collapsed=false
DockArea=2
Locked=false
height=30
width=100
xPosition=0
yPosition=0
[krita][DockWidget PaletteDocker]
Collapsed=false
DockArea=2
Locked=false
height=219
width=256
xPosition=0
yPosition=0
[krita][DockWidget PatternDocker]
Collapsed=false
DockArea=2
Locked=false
height=30
width=100
xPosition=0
yPosition=0
[krita][DockWidget PresetDocker]
Collapsed=false
DockArea=2
Locked=false
height=460
width=640
xPosition=0
yPosition=20
[krita][DockWidget PresetHistory]
Collapsed=false
DockArea=2
Locked=false
height=30
width=100
xPosition=0
yPosition=0
[krita][DockWidget Shape Properties]
DockArea=2
Locked=false
height=480
width=640
xPosition=0
yPosition=0
[krita][DockWidget ShapeCollectionDocker]
Collapsed=false
DockArea=2
Locked=false
height=0
width=0
xPosition=0
yPosition=20
[krita][DockWidget SmallColorSelector]
DockArea=2
Locked=false
height=460
width=640
xPosition=0
yPosition=20
[krita][DockWidget SpecificColorSelector]
DockArea=2
Locked=false
height=460
width=640
xPosition=0
yPosition=20
[krita][DockWidget TasksetDocker]
Collapsed=false
DockArea=2
Locked=false
height=300
width=400
xPosition=0
yPosition=0
[krita][DockWidget TimelineDocker]
Collapsed=false
DockArea=8
Locked=false
height=30
width=100
xPosition=0
yPosition=0
[krita][DockWidget ToolBox]
DockArea=1
Locked=false
height=610
width=63
xPosition=0
yPosition=20
[krita][DockWidget sharedtooldocker]
Collapsed=false
DockArea=2
Locked=false
height=460
width=640
xPosition=0
yPosition=20
[krita][Toolbar mainToolBar]
ToolButtonStyle=IconOnly
[TemplateChooserDialog]
ShowCustomDocumentWidgetByDefault=true
LastReturnType=Custom Document
[theme]
Theme=Krita dark
[python]
enable_colorspace=true
enable_comics_project_management_tools=true
enable_documenttools=true
enable_exportlayers=true
enable_filtermanager=true
enable_lastdocumentsdocker=true
enable_quick_settings_docker=true
enable_scripter=true
enable_tenbrushes=true
enable_tenscripts=true
diff --git a/krita/data/templates/animation/Anim-Jp-EN.desktop b/krita/data/templates/animation/Anim-Jp-EN.desktop
index 3a0b5a48d4..aa69ed4919 100644
--- a/krita/data/templates/animation/Anim-Jp-EN.desktop
+++ b/krita/data/templates/animation/Anim-Jp-EN.desktop
@@ -1,31 +1,31 @@
[Desktop Entry]
Type=Link
URL=.source/Anim-Jp-EN.kra
Icon=template_animation
Name=Animation-Japanese-En
-Name[ar]=حركة يابانيّة (إنجليزيّ)
+Name[ar]=حركة يابانية (إنجليزي)
Name[ca]=Animació-Japonès-EN
Name[ca@valencia]=Animació-Japonés-EN
Name[de]=Animation-Japanisch-En
Name[el]=Εφέ-κίνησης-Ιαπωνικό-En
Name[en_GB]=Animation-Japanese-En
Name[es]=Animación-Japonés-En
Name[et]=Animation-Japanese-En
Name[eu]=Animazioa-Japoniarra-En
Name[fr]=Animation japonaise (en)
Name[gl]=Animación-xaponesa-en-inglés
Name[is]=Hreyfimynd-Japanska-En
Name[it]=Animazione-Giapponese-EN
Name[ja]=日本式アニメ(英語版)
Name[nl]=Animatie-Japans-En
Name[pl]=Animacja-Japońska-En
Name[pt]=Animação-Japonês-EN
Name[pt_BR]=Animation-Japanese-En
Name[ru]=Анимация-японская-англ
Name[sk]=Animation-Japanese-En
Name[sv]=Animering-japanska-en
Name[tr]=Canlandırma-Japonca-İngilizce
Name[uk]=Японська анімація (англійською)
Name[x-test]=xxAnimation-Japanese-Enxx
Name[zh_CN]=日式动画 (英文图层名)
Name[zh_TW]=動畫-Japanese-En
diff --git a/krita/data/templates/animation/Anim-Jp-JP.desktop b/krita/data/templates/animation/Anim-Jp-JP.desktop
index e752436215..50e6e6920a 100644
--- a/krita/data/templates/animation/Anim-Jp-JP.desktop
+++ b/krita/data/templates/animation/Anim-Jp-JP.desktop
@@ -1,31 +1,31 @@
[Desktop Entry]
Type=Link
URL=.source/Anim-Jp-JP.kra
Icon=template_animation
Name=Animation-Japanese-JP
-Name[ar]=حركة يابانيّة (يابانيّ)
+Name[ar]=حركة يابانية (ياباني)
Name[ca]=Animació-Japonès-JP
Name[ca@valencia]=Animació-Japonés-JP
Name[de]=Animation-Japanisch-JP
Name[el]=Εφέ-κίνησης-Ιαπωνικό-JP
Name[en_GB]=Animation-Japanese-JP
Name[es]=Animación-Japonés-JP
Name[et]=Animation-Japanese-JP
Name[eu]=Animazioa-Japoniarra-JP
Name[fr]=Animation japonaise (jp)
Name[gl]=Animación-xaponesa-en-xaponés
Name[is]=Hreyfimynd-Japanska-JP
Name[it]=Animazione-Giapponese-JP
Name[ja]=日本式アニメ(日本語版)
Name[nl]=Animatie-Japans-JP
Name[pl]=Animacja-Japońska-JP
Name[pt]=Animação-Japonês-JP
Name[pt_BR]=Animation-Japanese-JP
Name[ru]=Анимация-японская-японск
Name[sk]=Animation-Japanese-JP
Name[sv]=Animering-japanska-jp
Name[tr]=Canlandırma-Japonca-JP
Name[uk]=Японська анімація (японською)
Name[x-test]=xxAnimation-Japanese-JPxx
Name[zh_CN]=日本动画 (日式)
Name[zh_TW]=動畫-Japanese-JP
diff --git a/krita/data/templates/comics/Comics-USTemplate.desktop b/krita/data/templates/comics/Comics-USTemplate.desktop
index 369815f33d..fbe4455b43 100644
--- a/krita/data/templates/comics/Comics-USTemplate.desktop
+++ b/krita/data/templates/comics/Comics-USTemplate.desktop
@@ -1,82 +1,82 @@
[Desktop Entry]
Type=Link
URL=.source/Comics-USTemplate.kra
Icon=template_comics_empty
Name=US-style comics template
-Name[ar]=قالب هزليّات بنمط أمريكيّ
+Name[ar]=قالب هزليّات بنمط أمريكي
Name[bs]=Američki strip predložak
Name[ca]=plantilla de còmics d'estil americà
Name[ca@valencia]=plantilla de còmics d'estil americà
Name[cs]=Šablona komixu v americkém stylu
Name[da]=Tegneserieskabelon i amerikansk stil
Name[de]=US-Design-Comicvorlage
Name[el]=Πρότυπο κόμικς US-style
Name[en_GB]=US-style comics template
Name[es]=plantilla de cómic de estilo estadounidense
Name[et]=USA stiilis koomiksi mall
Name[eu]=AEB-estiloko komiki-txantiloia
Name[fi]=Yhdysvaltalaistyylinen sarjakuvapohja
Name[fr]=Modèle US de bande dessinée
Name[gl]=Formato estadounidense (2×3 viñetas)
Name[hu]=US-stílusú képregénysablon
Name[is]=Bandarískt teiknimyndasögusniðmát
Name[it]=Modello per fumetti in stile americano
Name[ja]=アメリカ式コミックテンプレート
Name[kk]=АҚШ-стильді комикс үлгісі
Name[ko]=미국식 만화 서식
Name[lt]=JAV stiliaus komiksų šablonas
Name[nb]=Tegneseriemal i USA-stil
Name[nds]=Amerikaansch Comicvörlaag
Name[nl]=sjabloon voor strips in US-stijl
Name[pl]=Szablon komiksów Amerykańskiego stylu
Name[pt]=Modelo de banda desenhada dos EUA
Name[pt_BR]=Modelo de quadrinhos no estilo americano
Name[ru]=Шаблон в американском стиле
Name[sk]=šablóna pre americké komixy
Name[sl]=Predloga za stripe v ameriškem slogu
Name[sv]=Seriemall med amerikansk stil
Name[tr]=US tarzı çizgi roman şablonu
Name[uk]=Шаблон коміксів у американському стилі
Name[wa]=Modele comics a l' amerikinnes
Name[x-test]=xxUS-style comics templatexx
Name[zh_CN]=美式漫画模板
Name[zh_TW]=美式漫畫範本
Comment=template for US-style comics
-Comment[ar]=قالب للهزليّات بالنّمط الأمريكيّ
+Comment[ar]=قالب للهزليّات بالنمط الأمريكي
Comment[bs]=predložak za stripove američkog stila
Comment[ca]=plantilla per a còmics d'estil americà
Comment[ca@valencia]=plantilla per a còmics d'estil americà
Comment[cs]=šablona pro komiksy v americkém stylu
Comment[da]=skabelon til tegneserier i amerikansk stil
Comment[de]=Vorlage für Comics im US-Stil
Comment[el]=πρότυπο για US-style κόμικς
Comment[en_GB]=template for US-style comics
Comment[es]=plantilla para cómics de estilo estadounidense
Comment[et]=USA stiilis koomiksi mall
Comment[eu]=AEB-estiloko komikietarako txantiloia
Comment[fi]=yhdysvaltalaistyylisen sarjakuvan pohja
Comment[fr]=Modèle US de bandes dessinées
Comment[gl]=Páxina de banda deseñada de formato estadounidense, con 2×3 viñetas regulares.
Comment[hu]=sablon a US-stílusú képregényekhez
Comment[is]=Sniðmát fyrir bandarískar comics-teiknimyndir
Comment[it]=modello per fumetti in stile americano
Comment[ja]=アメリカ式コミック用テンプレート
Comment[kk]=АҚШ-стильдегі комикс үлгісі
Comment[ko]=미국식 만화 서식
Comment[nb]=mal for tegneserier i US-stil
Comment[nds]=Vörlaag för amerikaansche Comics
Comment[nl]=sjabloon voor strips in US-stijl
Comment[pl]=szablon dla Amerykańskiego stylu komiksów
Comment[pt]=modelo de banda desenhada do estilo dos EUA
Comment[pt_BR]=Modelo de quadrinhos no estilo americano
Comment[ru]=Шаблон комиксов в американском стиле
Comment[sk]=šablóna pre americké komixy
Comment[sl]=predloga za stripe v ameriškem slogu
Comment[sv]=seriemall med amerikansk stil
Comment[tr]=US tarzı çizgi romanlar için şablon
Comment[uk]=шаблон для коміксів у американському стилі
Comment[wa]=Modele di bindes d' imådje al môde des comics amerikins
Comment[x-test]=xxtemplate for US-style comicsxx
Comment[zh_CN]=美式漫画模板
Comment[zh_TW]=US-風格的連環漫畫範本
X-Krita-Version=28
diff --git a/krita/data/templates/comics/Manga-JpTemplate.desktop b/krita/data/templates/comics/Manga-JpTemplate.desktop
index a83561a0e3..5b152f0a3a 100644
--- a/krita/data/templates/comics/Manga-JpTemplate.desktop
+++ b/krita/data/templates/comics/Manga-JpTemplate.desktop
@@ -1,83 +1,83 @@
[Desktop Entry]
Type=Link
URL=.source/Manga-JpTemplate.kra
Icon=template_comics_empty
Name=Manga template
Name[ar]=قالب مانغا
Name[bs]=Manga predložak
Name[ca]=Plantilla per a manga
Name[ca@valencia]=Plantilla per a manga
Name[cs]=Šablona Mangy
Name[da]=Manga-skabelon
Name[de]=Manga-Vorlage
Name[el]=Πρότυπο μάνγκα
Name[en_GB]=Manga template
Name[es]=Plantilla manga
Name[et]=Manga mall
Name[eu]=Manga-txantiloia
Name[fi]=Mangapohja
Name[fr]=Modèle de Manga
Name[gl]=Formato Manga
Name[hu]=Manga sablon
Name[ia]=Patrono de Manga
Name[is]=Manga sniðmát
Name[it]=Modello manga
Name[ja]=漫画テンプレート
Name[kk]=Үлгіні басқару
Name[ko]=일본식 만화 서식
Name[lt]=Manga šablonas
Name[nb]=Manga-mal
Name[nds]=Manga-Vörlaag
Name[nl]=Manga-sjabloon
Name[pl]=Szablon Mangi
Name[pt]=Modelo Manga
Name[pt_BR]=Modelo de mangá
Name[ru]=Шаблон манги
Name[sk]=Manga šablóna
Name[sl]=Predloga Manga
Name[sv]=Manga-mall
Name[tr]=Manga şablonu
Name[uk]=Шаблон манґи
Name[wa]=Modele di manga
Name[x-test]=xxManga templatexx
Name[zh_CN]=日式漫画模板
Name[zh_TW]=日本漫畫範本
Comment=template for Japanese Manga-style comics
-Comment[ar]=قالب للهزليّات بنمط المانغا اليابانيّة
+Comment[ar]=قالب للهزليّات بنمط المانغا اليابانية
Comment[bs]=predložak za japanske Manga stripove
Comment[ca]=plantilla per a còmics d'estil manga japonès
Comment[ca@valencia]=plantilla per a còmics d'estil manga japonés
Comment[cs]=šablona pro japonské komiksy ve stylu Manga
Comment[da]=skabelon til tegneserier i japansk Manga-stil
Comment[de]=Vorlage für Comics im Stil japanischer Mangas
Comment[el]=Πρότυπο για Ιαπωνικά μάνγκα κόμικς
Comment[en_GB]=template for Japanese Manga-style comics
Comment[es]=plantilla para cómics de estilo manga japonés
Comment[et]=Jaapani manga-stiilis koomiksi mall
Comment[eu]=Japoniako Manga-estiloko komikietarako txantiloia
Comment[fi]=japanilaisen mangatyylisen sarjakuvan pohja
Comment[fr]=Modèle de mangas japonais
Comment[gl]=Páxina de banda deseñada de formato Manga, con 2×3 viñetas non regulares.
Comment[hu]=sablon a japán Manga-stílusú képregényekhez
Comment[is]=Sniðmát fyrir japanskar Manga-teiknimyndir
Comment[it]=modello per fumetti in stile manga giapponese
Comment[ja]=日本式漫画用テンプレート
Comment[kk]=Жапондық манга-стильдегі комикс үлгісі
Comment[ko]=일본식 만화 서식
Comment[nb]=mal for japanske tegneserier i Manga-stil
Comment[nds]=Vörlaag för japaansche Manga-Comics
Comment[nl]=sjabloon voor strips in Japanse Manga-stijl
Comment[pl]=szablon dla Japońskiego stylu komiksów Mangi
Comment[pt]=modelo de banda desenhada Manga do estilo Japonês
Comment[pt_BR]=Modelo de quadrinhos no estilo mangá japonês
Comment[ru]=Шаблон комиксов в японском стиле манга
Comment[sk]=šablóna pre japonské manga komixy
Comment[sl]=predloge za stripe v japonskem slogu Manga
Comment[sv]=seriemall med japansk Manga-stil
Comment[tr]=Japon Manga çizgi romanları için şablon
Comment[uk]=шаблон японських коміксів у стилі манґа
Comment[wa]=Modele di bindes d' imådje al môde des mangas djaponès
Comment[x-test]=xxtemplate for Japanese Manga-style comicsxx
Comment[zh_CN]=日式漫画模板
Comment[zh_TW]=日本 Manga-風格的連環漫畫範本
X-Krita-Version=28
diff --git a/krita/data/templates/design/.directory b/krita/data/templates/design/.directory
index 6db049443c..832d83ba63 100644
--- a/krita/data/templates/design/.directory
+++ b/krita/data/templates/design/.directory
@@ -1,40 +1,40 @@
[Desktop Entry]
Name=Design Templates
-Name[ar]=قوالب التّصميم
+Name[ar]=قوالب التصميم
Name[bs]=Predlošci dizajna
Name[ca]=Plantilles de disseny
Name[ca@valencia]=Plantilles de disseny
Name[cs]=Návrhové šablony
Name[da]=Designskabeloner
Name[de]=Design-Vorlagen
Name[el]=Πρότυπα σχεδίασης
Name[en_GB]=Design Templates
Name[es]=Plantillas de diseño
Name[et]=Disainmallid
Name[eu]=Diseinu-txantiloiak
Name[fi]=Suunnittelupohjat
Name[fr]=Modèles design
Name[gl]=Modelos de deseño
Name[hu]=Tervező sablonok
Name[ia]=Patronos de dessigno
Name[is]=Hönnunarsniðmát
Name[it]=Modelli di stile
Name[ja]=デザインテンプレート
Name[kk]=Пішім үлгілері
Name[ko]=디자인 서식
Name[lt]=Dizaino šablonai
Name[nb]=Designmaler
Name[nl]=Design-sjablonen
Name[pl]=Szablony projekcyjne
Name[pt]=Modelos de Desenho
Name[pt_BR]=Modelos de design
Name[ru]=Шаблоны для дизайна
Name[sk]=Šablóny dizajnu
Name[sl]=Oblikovalske predloge
Name[sv]=Designmallar
Name[tr]=Tasarım Şablonları
Name[uk]=Шаблони компонування
Name[x-test]=xxDesign Templatesxx
Name[zh_CN]=设计模板
Name[zh_TW]=設計範本
X-KDE-DefaultTab=true
diff --git a/krita/data/templates/design/Designcinema16_10_2484x1200_96dpiRGB_8bit_.desktop b/krita/data/templates/design/Designcinema16_10_2484x1200_96dpiRGB_8bit_.desktop
index 44b1ec0f8b..319a23a526 100644
--- a/krita/data/templates/design/Designcinema16_10_2484x1200_96dpiRGB_8bit_.desktop
+++ b/krita/data/templates/design/Designcinema16_10_2484x1200_96dpiRGB_8bit_.desktop
@@ -1,38 +1,38 @@
[Desktop Entry]
Icon=template_ratio_1610
Name=Design cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
-Name[ar]=تصميم سينمائيّ ١٦:١٠ [ ٢٤٨٤×١٢٠٠ ، ٩٦ نقطة/بوصة ، ٨ بتّ ]
+Name[ar]=تصميم سينمائي ١٦:١٠ [ ٢٤٨٤×١٢٠٠ ، ٩٦ نقطة/بوصة ، ٨ بتّ ]
Name[bs]=Design cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[ca]=Disseny de cine 16:10 [2484x1200 / 96ppp RGB / 8bit]
Name[ca@valencia]=Disseny de cine 16:10 [2484x1200 / 96ppp RGB / 8bit]
Name[cs]=Návrh kino 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[da]=Design-cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[de]=Design-Kino 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[el]=Design cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[en_GB]=Design cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[es]=Diseño de cine 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[et]=Disainkino 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[eu]=Zinema-diseinua 16:10 [2484 x 1200, 96 dpi GBU, 8 bit]
Name[fr]=style cinéma 16:10 [ 2484x1200, 96dpi RGB, 8bit ]
Name[gl]=Deseño de cine 16:10 (2484×1200, 96 dpi RGB, 8 bits)
Name[hu]=Tervező mozi 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[is]=Hanna kvikmynd 16:10 [ 2484x1200 , 96pát RGB , 8bita ]
Name[it]=Stile cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[ja]=映画 16:10 [ 2484x1200、96dpi RGB、8 ビット ]
Name[kk]=Кино пішімі 106:1 [ 2484x1200 , 96 н/д RGB , 8бит ]
Name[nb]=Designkino 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[nl]=Design cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[pl]=Kino projekcyjne 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[pt]=Desenho de cinema 16:10 [ 2484x1200 , 96ppp RGB , 8-bits ]
Name[pt_BR]=Design de cinema 16:10 [ 2484x1200, 96dpi RGB, 8bits ]
Name[ru]=Дизайн кино 16:10 [ 2484x1200 , 96dpi RGB , 8 бит ]
Name[sk]=Design cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[sv]=Design film 16:10 [ 2484x1200, 96 punkter/tum RGB, 8 bitar ]
Name[tr]=Sineme tasarla 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Name[uk]=Компонування кіноекрана 16:10 [2484⨯1200, 96 т./д., RGB, 8 бітів]
Name[x-test]=xxDesign cinema 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]xx
Name[zh_CN]=16:10 电影荧幕设计模板 [ 2484x1200 像素, 96dpi RGB , 8 位 ]
Name[zh_TW]=設計電影院 16:10 [ 2484x1200 , 96dpi RGB , 8bit ]
Type=Link
URL[$e]=.source/Designcinema16_10_2484x1200_96dpiRGB_8bit_.kra
X-KDE-Hidden=false
diff --git a/krita/data/templates/design/Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.desktop b/krita/data/templates/design/Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.desktop
index f028942b5d..92ce996fa1 100644
--- a/krita/data/templates/design/Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.desktop
+++ b/krita/data/templates/design/Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.desktop
@@ -1,38 +1,38 @@
[Desktop Entry]
Icon=template_ratio_2391
Name=Design cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
-Name[ar]=تصميم سينمائيّ ٢٫٣٩:١ [ ٢٤٨٤×١٠٤٠ ، ٩٦ نقطة/بوصة ، ٨ بتّ ]
+Name[ar]=تصميم سينمائي ٢٫٣٩:١ [ ٢٤٨٤×١٠٤٠ ، ٩٦ نقطة/بوصة ، ٨ بتّ ]
Name[bs]=Design cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[ca]=Disseny de cine 2,39:1 [2484x1040 / 96ppp RGB / 8bit]
Name[ca@valencia]=Disseny de cine 2,39:1 [2484x1040 / 96ppp RGB / 8bit]
Name[cs]=Návrh kino 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[da]=Design-cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[de]=Design-Kino 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[el]=Design cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[en_GB]=Design cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[es]=Diseño de cine 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[et]=Disainkino 2,39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[eu]=Zinema-diseinua 2.39:1 [2484 x 1040, 96 dpi GBU, 8 bit]
Name[fr]=style cinéma 2.39:1 [ 2484x1040, 96dpi RGB, 8bit ]
Name[gl]=Deseño de cine 2.39:1 (2484×1040, 96 dpi RGB, 8 bits)
Name[hu]=Tervező mozi 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[is]=Hanna kvikmynd 2.39:1 [ 2484x1040 , 96pát RGB , 8bita ]
Name[it]=Stile cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[ja]=映画 2.39:1 [ 2484x1040、96dpi RGB、8 ビット ]
Name[kk]=Кино пішімі 2.39:1 [ 2484x1040 , 96 н/д RGB , 8бит ]
Name[nb]=Designkino 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[nl]=Design cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[pl]=Kino projekcyjne 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[pt]=Desenho de cinema 2,39:1 [ 2484x1040 , 96ppp RGB , 8-bits ]
Name[pt_BR]=Design de cinema 2.39:1 [ 2484x1040, 96dpi RGB, 8bits ]
Name[ru]=Дизайн кино 2.39:1 [ 2484x1040 , 96dpi RGB , 8 бит ]
Name[sk]=Design cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[sv]=Design film 2,39:1 [ 2484x1040, 96 punkter/tum RGB, 8 bitar ]
Name[tr]=Sineme tasarla 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Name[uk]=Компонування кіноекрана 2,39:1 [2484⨯1040, 96 т./д., RGB, 8 бітів]
Name[x-test]=xxDesign cinema 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]xx
Name[zh_CN]=2.39:1 电影荧幕设计模板 [ 2484x1040 像素, 96dpi RGB , 8 位]
Name[zh_TW]=設計電影院 2.39:1 [ 2484x1040 , 96dpi RGB , 8bit ]
Type=Link
URL[$e]=.source/Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.kra
X-KDE-Hidden=false
diff --git a/krita/krita.action b/krita/krita.action
index ec99ee5e8b..87c6cb96d4 100644
--- a/krita/krita.action
+++ b/krita/krita.action
@@ -1,3454 +1,3467 @@
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
Show system information for bug reports.
Show system information for bug reports.
Show system information for bug reports.
false
Rename Composition...
Rename Composition
Rename Composition
0
0
false
Update Composition
Update Composition
Update Composition
0
0
false
Use multiple of 2 for pixel scale
Use multiple of 2 for pixel scale
Use multiple of 2 for pixel scale
Use multiple of 2 for pixel scale
1
0
true
&Invert Selection
Invert current selection
Invert Selection
10000000000
100
Ctrl+Shift+I
false
Painting
lightness-increase
Make brush color lighter
Make brush color lighter
Make brush color lighter
0
0
L
false
lightness-decrease
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
opacity-increase
Increase opacity
Increase opacity
Increase opacity
0
0
O
false
opacity-decrease
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
0
true
symmetry-vertical
Vertical Mirror Tool
Vertical Mirror Tool
Vertical Mirror Tool
0
true
Hide Mirror X Line
Hide Mirror X Line
Hide Mirror X Line
10000
true
Hide Mirror Y Line
Hide Mirror Y Line
Hide Mirror Y Line
10000
true
Lock
Lock X Line
Lock X Line
10000
true
Lock Y Line
Lock Y Line
Lock Y Line
10000
true
Move to Canvas Center
Move to Canvas Center X
Move to Canvas Center X
10000
false
Move to Canvas Center Y
Move to Canvas Center Y
Move to Canvas Center Y
10000
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
brushsize-decrease
Decrease Brush Size
Decrease Brush Size
Decrease Brush Size
0
0
[
false
smoothing-basic
Brush Smoothing: Basic
Brush Smoothing: Basic
Brush Smoothing: Basic
false
brushsize-increase
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
&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
+
+
+ &Invert
+
+ Invert
+ Invert
+ 10000
+ 0
+ Ctrl+I
+ 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
Rectangle Tool
Rectangle Tool
Rectangle Tool
false
Multibrush Tool
Multibrush Tool
Multibrush Tool
Q
false
Colorize Mask Tool
Colorize Mask Tool
Colorize Mask Tool
Smart Patch Tool
Smart Patch Tool
Smart Patch Tool
Pan Tool
Pan Tool
Pan Tool
Select Shapes Tool
Select Shapes Tool
Select Shapes Tool
false
Color Picker
Select a color from the image or current layer
Select a color from the image or current layer
P
false
Outline Selection Tool
Outline Selection Tool
Outline Selection Tool
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 or double-click ends the curve.
Bezier Curve Tool. Shift-mouseclick or double-click 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
Zoom Tool
Zoom Tool
Zoom Tool
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
Assistant Tool
Assistant Tool
Assistant Tool
false
Text tool
Text tool
Text tool
false
Gradient Editing Tool
Gradient editing
Gradient editing
false
Reference Images Tool
Reference Images Tool
Reference Images Tool
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 Hard Overlay Blending Mode
Select Hard Overlay Blending Mode
Select Hard Overlay Blending Mode
0
0
Alt+Shift+P
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
addblankframe
Create Blank Frame
Add blank frame
Add blank frame
100000
0
false
addduplicateframe
Create Duplicate 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
Show in Timeline
true
Insert Keyframe Left
Insert keyframes to the left of selection, moving the tail of animation to the right.
100000
0
false
Insert Keyframe Right
Insert keyframes to the right of selection, moving the tail of animation to the right.
100000
0
false
Insert Multiple Keyframes
Insert several keyframes based on user parameters.
100000
0
false
Remove Frame and Pull
Remove keyframes moving the tail of animation to the left
100000
0
false
deletekeyframe
Remove Keyframe
Remove keyframes without moving anything around
100000
0
false
Insert Column Left
Insert column to the left of selection, moving the tail of animation to the right
100000
0
false
Insert Column Right
Insert column to the right of selection, moving the tail of animation to the right
100000
0
false
Insert Multiple Columns
Insert several columns based on user parameters.
100000
0
false
Remove Column and Pull
Remove columns moving the tail of animation to the left
100000
0
false
Remove Column
Remove columns without moving anything around
100000
0
false
Insert Hold Frame
Insert a hold frame after every keyframe
100000
0
false
Insert Multiple Hold Frames
Insert N hold frames after every keyframe
100000
0
false
Remove Hold Frame
Remove a hold frame after every keyframe
100000
0
false
Remove Multiple Hold Frames
Remove N hold frames after every keyframe
100000
0
false
Insert Hold Column
Insert a hold column into the frame at the current position
100000
0
false
Insert Multiple Hold Columns
Insert N hold columns into the frame at the current position
100000
0
false
Remove Hold Column
Remove a hold column from the frame at the current position
100000
0
false
Remove Multiple Hold Columns
Remove N hold columns from the frame at the current position
100000
0
false
Mirror Frames
Mirror frames' position
100000
0
false
Mirror Columns
Mirror columns' position
100000
0
false
Copy to Clipboard
Copy frames to clipboard
100000
0
false
Cut to Clipboard
Cut frames to clipboard
100000
0
false
Paste from Clipboard
Paste frames from clipboard
100000
0
false
Copy Columns to Clipboard
Copy columns to clipboard
100000
0
false
Cut Columns to Clipboard
Cut columns to clipboard
100000
0
false
Paste Columns from Clipboard
Paste columns from clipboard
100000
0
false
Set Start Time
100000
0
false
Set End Time
100000
0
false
Update Playback Range
100000
0
false
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
layer-locked
&Toggle layer lock
Toggle layer lock
Toggle layer lock
1000
0
false
visible
Toggle layer &visibility
Toggle layer visibility
Toggle layer visibility
1000
0
false
transparency-locked
Toggle layer &alpha
Toggle layer alpha
Toggle layer alpha
1000
0
false
transparency-enabled
Toggle layer alpha &inheritance
Toggle layer alpha inheritance
Toggle layer alpha inheritance
1000
0
false
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
1000
0
false
Cut Layer
Cut layer to clipboard
Cut layer to clipboard
1000
0
false
Paste Layer
Paste layer from clipboard
Paste layer from clipboard
1000
0
false
Quick Group
Create a group layer containing selected layers
Quick Group
1000
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 Vector Layer as SVG...
Save Vector Layer as SVG
Save Vector Layer as SVG
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
fileLayer
to &File Layer
Saves out the layers into a new image and then references that image.
Convert to File Layer
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
1000
1
false
object-rotate-right
Rotate &Layer 90° to the Right
Rotate Layer 90° to the Right
Rotate Layer 90° to the Right
1000
1
false
object-rotate-left
Rotate Layer &90° to the Left
Rotate Layer 90° to the Left
Rotate Layer 90° to the Left
1000
1
false
Rotate Layer &180°
Rotate Layer 180°
Rotate Layer 180°
1000
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
1000
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/krita4.xmlgui b/krita/krita4.xmlgui
index bbf3369399..d050f12037 100644
--- a/krita/krita4.xmlgui
+++ b/krita/krita4.xmlgui
@@ -1,386 +1,389 @@
&View
&Canvas
&Snap To
&Image
&Rotate
&Layer
New
&Import/Export
Import
&Convert
&Select
&Group
&Transform
&Rotate
S&plit
S&plit Alpha
&Select
+
+
+
Select &Opaque
Filte&r
&Tools
Scripts
Setti&ngs
&Help
File
Brushes and Stuff
diff --git a/krita/kritamenu.action b/krita/kritamenu.action
index cdfdfa9470..efc698bd37 100644
--- a/krita/kritamenu.action
+++ b/krita/kritamenu.action
@@ -1,1806 +1,1830 @@
File
document-new
&New
Create new document
New
0
0
Ctrl+N
false
document-open
&Open...
Open an existing document
Open
0
0
Ctrl+O
false
document-open-recent
Open &Recent
Open a document which was recently opened
Open Recent
1
0
false
document-save
&Save
Save
Save
1
0
Ctrl+S
false
document-save-as
Save &As...
Save document under a new name
Save As
1
0
Ctrl+Shift+S
false
Sessions...
Open session manager
Sessions
0
0
false
document-import
Open ex&isting Document as Untitled Document...
Open existing Document as Untitled Document
Open existing Document as Untitled Document
0
0
false
document-export
E&xport...
Export
Export
1
0
false
application-pdf
&Export as PDF...
Export as PDF
Export as PDF
1
0
false
Import animation frames...
Import animation frames
Import animation frames
1
0
false
&Render Animation...
Render Animation to GIF, Image Sequence or Video
Render Animation
1000
0
false
&Render Image Sequence Again
Render Animation to Image Sequence Again
Render Animation
1000
0
false
Save Incremental &Version
Save Incremental Version
Save Incremental Version
1
0
Ctrl+Alt+S
false
Save Incremental &Backup
Save Incremental Backup
Save Incremental Backup
1
0
F4
false
&Create Template From Image...
Create Template From Image
Create Template From Image
1
0
false
Create Copy &From Current Image
Create Copy From Current Image
Create Copy From Current Image
1
0
false
document-print
&Print...
Print document
Print
1
0
Ctrl+P
false
document-print-preview
Print Previe&w
Show a print preview of document
Print Preview
1
0
false
configure
&Document Information
Document Information
Document Information
1
0
false
&Close All
Close All
Close All
1
0
Ctrl+Shift+W
false
C&lose
Close
Close
1
0
false
&Quit
Quit application
Quit
0
0
Ctrl+Q
false
Edit
edit-undo
Undo
Undo last action
Undo
1
0
Ctrl+Z
false
edit-redo
Redo
Redo last undone action
Redo
1
0
Ctrl+Shift+Z
false
edit-cut
Cu&t
Cut selection to clipboard
Cut
0
0
Ctrl+X
false
edit-copy
&Copy
Copy selection to clipboard
Copy
0
0
Ctrl+C
false
C&opy (sharp)
Copy (sharp)
Copy (sharp)
100000000
0
false
Cut (&sharp)
Cut (sharp)
Cut (sharp)
100000000
0
false
Copy &merged
Copy merged
Copy merged
100000000
0
Ctrl+Shift+C
false
edit-paste
&Paste
Paste clipboard content
Paste
0
0
Ctrl+V
false
Paste at Cursor
Paste at cursor
Paste at cursor
0
0
Ctrl+Alt+V
false
Paste into &New Image
Paste into New Image
Paste into New Image
0
0
Ctrl+Shift+N
false
edit-clear
C&lear
Clear
Clear
1
0
Del
false
&Fill with Foreground Color
Fill with Foreground Color
Fill with Foreground Color
10000
1
Shift+Backspace
false
Fill &with Background Color
Fill with Background Color
Fill with Background Color
10000
1
Backspace
false
F&ill with Pattern
Fill with Pattern
Fill with Pattern
10000
1
false
Fill Special
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
Stro&ke selected shapes
Stroke selected shapes
Stroke selected shapes
1000000000
0
false
Stroke Selec&tion...
Stroke selection
Stroke selection
10000000000
0
false
Delete keyframe
Delete keyframe
Delete keyframe
100000
0
false
Window
window-new
&New Window
New Window
New Window
0
0
false
N&ext
Next
Next
10
0
false
Previous
Previous
Previous
false
View
&Show Canvas Only
Show just the canvas or the whole window
Show Canvas Only
0
0
Tab
true
view-fullscreen
F&ull Screen Mode
Display the window in full screen
Full Screen Mode
0
0
Ctrl+Shift+F
true
&Wrap Around Mode
Wrap Around Mode
Wrap Around Mode
1
0
W
true
&Instant Preview Mode
Instant Preview Mode
Instant Preview Mode
1
0
Shift+L
true
Soft Proofing
Turns on Soft Proofing
Turns on Soft Proofing
Ctrl+Y
true
Out of Gamut Warnings
Turns on warnings for colors out of proofed gamut, needs soft proofing to be turned on.
Turns on warnings for colors out of proofed gamut, needs soft proofing to be turned on.
Ctrl+Shift+Y
true
mirror-view
Mirror View
Mirror View
Mirror View
M
false
zoom-original
&Reset zoom
Reset zoom
Reset zoom
1
0
Ctrl+0
false
zoom-in
Zoom &In
Zoom In
0
0
Ctrl++
false
zoom-out
Zoom &Out
Zoom Out
0
0
Ctrl+-
false
rotate-canvas-right
Rotate &Canvas Right
Rotate Canvas Right
Rotate Canvas Right
1
0
Ctrl+]
false
rotate-canvas-left
Rotate Canvas &Left
Rotate Canvas Left
Rotate Canvas Left
1
0
Ctrl+[
false
rotation-reset
Reset Canvas Rotation
Reset Canvas Rotation
Reset Canvas Rotation
1
0
false
Show &Rulers
The rulers show the horizontal and vertical positions of the mouse on the image and can be used to position your mouse at the right place on the canvas. <p>Uncheck this to hide the rulers.</p>
Show Rulers
Show Rulers
1
0
true
Rulers Track Pointer
The rulers will track current mouse position and show it on screen. It can cause suptle performance slowdown
Rulers Track Pointer
Rulers Track Pointer
1
0
true
Show Guides
Show or hide guides
Show Guides
1
0
true
Lock Guides
Lock or unlock guides
Lock Guides
1
0
true
Snap to Guides
Snap cursor to guides position
Snap to Guides
1
0
true
Show Status &Bar
Show or hide the status bar
Show Status Bar
0
0
true
Show Pixel Grid
Show Pixel Grid
Show Pixel Grid
1000
0
true
view-grid
Show &Grid
Show Grid
Show Grid
1000
0
Ctrl+Shift+'
true
Snap To Grid
Snap To Grid
Snap To Grid
1000
Ctrl+Shift+;
true
Show Snap Options Popup
Show Snap Options Popup
Show Snap Options Popup
1000
Shift+s
false
Snap Orthogonal
Snap Orthogonal
Snap Orthogonal
1000
true
Snap Node
Snap Node
Snap Node
1000
true
Snap Extension
Snap Extension
Snap Extension
1000
true
Snap Intersection
Snap Intersection
Snap Intersection
1000
true
Snap Bounding Box
Snap Bounding Box
Snap Bounding Box
1000
true
Snap Image Bounds
Snap Image Bounds
Snap Image Bounds
1000
true
Snap Image Center
Snap Image Center
Snap Image Center
1000
true
S&how Painting Assistants
Show Painting Assistants
Show Painting Assistants
1000
0
true
Show &Assistant Previews
Show Assistant Previews
Show Assistant Previews
1000
0
true
S&how Reference Images
Show Reference Images
Show Reference Images
1000
0
true
Image
document-properties
&Properties...
Properties
Properties
1000
0
false
format-stroke-color
&Image Background Color and Transparency...
Change the background color of the image
Image Background Color and Transparency
1000
0
false
&Convert Image Color Space...
Convert Image Color Space
Convert Image Color Space
1000
0
false
trim-to-image
&Trim to Image Size
Trim to Image Size
Trim to Image Size
1
0
false
Trim to Current &Layer
Trim to Current Layer
Trim to Current Layer
100000
0
false
Trim to S&election
Trim to Selection
Trim to Selection
100000000
0
false
&Rotate Image...
Rotate Image
Rotate Image
1000
0
false
object-rotate-right
Rotate &Image 90° to the Right
Rotate Image 90° to the Right
Rotate Image 90° to the Right
1000
0
false
object-rotate-left
Rotate Image &90° to the Left
Rotate Image 90° to the Left
Rotate Image 90° to the Left
1000
0
false
Rotate Image &180°
Rotate Image 180°
Rotate Image 180°
1000
0
false
&Shear Image...
Shear Image
Shear Image
1000
0
false
symmetry-horizontal
&Mirror Image Horizontally
Mirror Image Horizontally
Mirror Image Horizontally
1000
0
false
symmetry-vertical
Mirror Image &Vertically
Mirror Image Vertically
Mirror Image Vertically
1000
0
false
Scale Image To &New Size...
Scale Image To New Size
Scale Image To New Size
1000
0
Ctrl+Alt+I
false
&Offset Image...
Offset Image
Offset Image
1000
0
false
R&esize Canvas...
Resize Canvas
Resize Canvas
1000
0
Ctrl+Alt+C
false
Im&age Split
Image Split
Image Split
1000
0
false
Separate Ima&ge...
Separate Image
Separate Image
1000
0
false
Select
edit-select-all
Select &All
Select All
Select All
0
0
Ctrl+A
false
edit-select-all
&Deselect
Deselect
Deselect
1100000000
0
Ctrl+Shift+A
false
&Reselect
Reselect
Reselect
0
0
Ctrl+Shift+D
false
&Invert Selection
Invert Selection
Invert Selection
10000
0
Ctrl+I
false
&Convert to Vector Selection
Convert to Vector Selection
Convert to Vector Selection
- 10000000000
+ 100000000000000000
+ 0
+
+ false
+
+
+
+
+ &Convert to Raster Selection
+
+ Convert to Raster Selection
+ Convert to Raster Selection
+ 10000000000000000
0
false
+
+
+ Edit Selection
+
+ Edit Selection
+ Edit Selection
+ 10000000000
+ 100
+
+ false
+
+
Convert Shapes to &Vector Selection
Convert Shapes to Vector Selection
Convert Shapes to Vector Selection
1000000000
0
false
&Feather Selection...
Feather Selection
Feather Selection
10000000000
100
Shift+F6
false
Dis&play Selection
Display Selection
Display Selection
1000
0
Ctrl+H
true
Sca&le...
Scale
Scale
100000000
100
false
S&elect from Color Range...
Select from Color Range
Select from Color Range
10000
100
false
Select &Opaque (Replace)
Select Opaque
Select Opaque
10000
100
false
Select Opaque (&Add)
Select Opaque (Add)
Select Opaque (Add)
10000
100
false
Select Opaque (&Subtract)
Select Opaque (Subtract)
Select Opaque (Subtract)
10000
100
false
Select Opaque (&Intersect)
Select Opaque (Intersect)
Select Opaque (Intersect)
10000
100
false
&Grow Selection...
Grow Selection
Grow Selection
10000000000
100
false
S&hrink Selection...
Shrink Selection
Shrink Selection
10000000000
100
false
&Border Selection...
Border Selection
Border Selection
10000000000
100
false
S&mooth
Smooth
Smooth
10000000000
100
false
Filter
&Apply Filter Again
Apply Filter Again
Apply Filter Again
0
0
Ctrl+F
false
Adjust
Adjust
Adjust
false
Artistic
Artistic
Artistic
false
Blur
Blur
Blur
false
Colors
Colors
Colors
false
Edge Detection
Edge Detection
Edge Detection
false
Enhance
Enhance
Enhance
false
Emboss
Emboss
Emboss
false
Map
Map
Map
false
Other
Other
Other
false
gmic
Start G'MIC-Qt
Start G'Mic-Qt
Start G'Mic-Qt
false
gmic
Re-apply the last G'MIC filter
Apply the last G'Mic-Qt action again
Apply the last G'Mic-Qt action again
false
Settings
configure
&Configure Krita...
Configure Krita
Configure Krita
0
0
false
&Manage Resources...
Manage Resources
Manage Resources
0
0
false
preferences-desktop-locale
Switch Application &Language...
Switch Application Language
Switch Application Language
false
&Show Dockers
Show Dockers
Show Dockers
0
0
true
configure
Configure Tool&bars...
Configure Toolbars
Configure Toolbars
0
0
false
Dockers
Dockers
Dockers
false
&Themes
Themes
Themes
false
im-user
Active Author Profile
Active Author Profile
Active Author Profile
configure-shortcuts
Configure S&hortcuts...
Configure Shortcuts
Configure Shortcuts
0
0
false
&Window
Window
Window
false
Help
help-contents
Krita &Handbook
Krita Handbook
Krita Handbook
F1
false
tools-report-bug
&Report Bug...
Report Bug
Report Bug
false
calligrakrita
&About Krita
About Krita
About Krita
false
kde
About &KDE
About KDE
About KDE
false
Brushes and Stuff
&Gradients
Gradients
Gradients
false
&Patterns
Patterns
Patterns
false
&Color
Color
Color
false
&Painter's Tools
Painter's Tools
Painter's Tools
false
Brush composite
Brush composite
Brush composite
false
Brush option slider 1
Brush option slider 1
Brush option slider 1
false
Brush option slider 2
Brush option slider 2
Brush option slider 2
false
Brush option slider 3
Brush option slider 3
Brush option slider 3
false
Mirror
Mirror
Mirror
false
Layouts
Select layout
false
Workspaces
Workspaces
Workspaces
false
diff --git a/krita/org.kde.krita.desktop b/krita/org.kde.krita.desktop
index 2db0c42745..0acd1b67a5 100644
--- a/krita/org.kde.krita.desktop
+++ b/krita/org.kde.krita.desktop
@@ -1,151 +1,151 @@
[Desktop Entry]
Name=Krita
Name[af]=Krita
Name[ar]=كريتا
Name[bg]=Krita
Name[br]=Krita
Name[bs]=Krita
Name[ca]=Krita
Name[ca@valencia]=Krita
Name[cs]=Krita
Name[cy]=Krita
Name[da]=Krita
Name[de]=Krita
Name[el]=Krita
Name[en_GB]=Krita
Name[eo]=Krita
Name[es]=Krita
Name[et]=Krita
Name[eu]=Krita
Name[fi]=Krita
Name[fr]=Krita
Name[fy]=Krita
Name[ga]=Krita
Name[gl]=Krita
Name[he]=Krita
Name[hi]=केरिता
Name[hne]=केरिता
Name[hr]=Krita
Name[hu]=Krita
Name[ia]=Krita
Name[is]=Krita
Name[it]=Krita
Name[ja]=Krita
Name[kk]=Krita
Name[ko]=Krita
Name[lt]=Krita
Name[lv]=Krita
Name[mr]=क्रिटा
Name[ms]=Krita
Name[nb]=Krita
Name[nds]=Krita
Name[ne]=क्रिता
Name[nl]=Krita
Name[pl]=Krita
Name[pt]=Krita
Name[pt_BR]=Krita
Name[ro]=Krita
Name[ru]=Krita
Name[se]=Krita
Name[sk]=Krita
Name[sl]=Krita
Name[sv]=Krita
Name[ta]=கிரிட்டா
Name[tg]=Krita
Name[tr]=Krita
Name[ug]=Krita
Name[uk]=Krita
Name[uz]=Krita
Name[uz@cyrillic]=Krita
Name[wa]=Krita
Name[xh]=Krita
Name[x-test]=xxKritaxx
Name[zh_CN]=Krita
Name[zh_TW]=Krita
Exec=krita %F
GenericName=Digital Painting
-GenericName[ar]=رسم رقميّ
+GenericName[ar]=رسم رقمي
GenericName[bs]=Digitalno Bojenje
GenericName[ca]=Dibuix digital
GenericName[ca@valencia]=Dibuix digital
GenericName[cs]=Digitální malování
GenericName[da]=Digital tegning
GenericName[de]=Digitales Malen
GenericName[el]=Ψηφιακή ζωγραφική
GenericName[en_GB]=Digital Painting
GenericName[es]=Pintura digital
GenericName[et]=Digitaalne joonistamine
GenericName[eu]=Margolan digitala
GenericName[fi]=Digitaalimaalaus
GenericName[fr]=Peinture numérique
GenericName[gl]=Debuxo dixital
GenericName[hu]=Digitális festészet
GenericName[ia]=Pintura Digital
GenericName[is]=Stafræn málun
GenericName[it]=Pittura digitale
GenericName[ja]=デジタルペインティング
GenericName[kk]=Цифрлық сурет салу
GenericName[lt]=Skaitmeninis piešimas
GenericName[mr]=डिजिटल पेंटिंग
GenericName[nb]=Digital maling
GenericName[nl]=Digitaal schilderen
GenericName[pl]=Cyfrowe malowanie
GenericName[pt]=Pintura Digital
GenericName[pt_BR]=Pintura digital
GenericName[ru]=Цифровая живопись
GenericName[sk]=Digitálne maľovanie
GenericName[sl]=Digitalno slikanje
GenericName[sv]=Digital målning
GenericName[tr]=Sayısal Boyama
GenericName[ug]=سىفىرلىق رەسىم سىزغۇ
GenericName[uk]=Цифрове малювання
GenericName[x-test]=xxDigital Paintingxx
GenericName[zh_CN]=数字绘画
GenericName[zh_TW]=數位繪畫
MimeType=application/x-krita;image/openraster;application/x-krita-paintoppreset;
Comment=Digital Painting
-Comment[ar]=رسم رقميّ
+Comment[ar]=رسم رقمي
Comment[bs]=Digitalno Bojenje
Comment[ca]=Dibuix digital
Comment[ca@valencia]=Dibuix digital
Comment[cs]=Digitální malování
Comment[da]=Digital tegning
Comment[de]=Digitales Malen
Comment[el]=Ψηφιακή ζωγραφική
Comment[en_GB]=Digital Painting
Comment[es]=Pintura digital
Comment[et]=Digitaalne joonistamine
Comment[eu]=Margolan digitala
Comment[fi]=Digitaalimaalaus
Comment[fr]=Peinture numérique
Comment[gl]=Debuxo dixital.
Comment[hu]=Digitális festészet
Comment[ia]=Pintura Digital
Comment[is]=Stafræn málun
Comment[it]=Pittura digitale
Comment[ja]=デジタルペインティング
Comment[kk]=Цифрлық сурет салу
Comment[lt]=Skaitmeninis piešimas
Comment[mr]=डिजिटल पेंटिंग
Comment[nb]=Digital maling
Comment[nl]=Digitaal schilderen
Comment[pl]=Cyfrowe malowanie
Comment[pt]=Pintura Digital
Comment[pt_BR]=Pintura digital
Comment[ru]=Цифровая живопись
Comment[sk]=Digitálne maľovanie
Comment[sl]=Digitalno slikanje
Comment[sv]=Digitalt målningsverktyg
Comment[tr]=Sayısal Boyama
Comment[ug]=سىفىرلىق رەسىم سىزغۇ
Comment[uk]=Цифрове малювання
Comment[x-test]=xxDigital Paintingxx
Comment[zh_CN]=数字绘画
Comment[zh_TW]=數位繪畫
Type=Application
Icon=calligrakrita
Categories=Qt;KDE;Graphics;
X-KDE-NativeMimeType=application/x-krita
X-KDE-ExtraNativeMimeTypes=
StartupNotify=true
X-Krita-Version=28
diff --git a/krita/pics/svg/dark_gamut-mask-off.svg b/krita/pics/svg/dark_gamut-mask-off.svg
new file mode 100644
index 0000000000..4ab54f6056
--- /dev/null
+++ b/krita/pics/svg/dark_gamut-mask-off.svg
@@ -0,0 +1,1563 @@
+
+
+
+
diff --git a/krita/pics/svg/dark_gamut-mask-on.svg b/krita/pics/svg/dark_gamut-mask-on.svg
new file mode 100644
index 0000000000..a095462f2d
--- /dev/null
+++ b/krita/pics/svg/dark_gamut-mask-on.svg
@@ -0,0 +1,1535 @@
+
+
+
+
diff --git a/krita/pics/svg/dark_infinity.svg b/krita/pics/svg/dark_infinity.svg
new file mode 100644
index 0000000000..7ea8b1bad6
--- /dev/null
+++ b/krita/pics/svg/dark_infinity.svg
@@ -0,0 +1,1501 @@
+
+
+
+
diff --git a/krita/pics/svg/dark_wheel-light.svg b/krita/pics/svg/dark_wheel-light.svg
new file mode 100644
index 0000000000..5c12b650d7
--- /dev/null
+++ b/krita/pics/svg/dark_wheel-light.svg
@@ -0,0 +1,1500 @@
+
+
+
+
diff --git a/krita/pics/svg/dark_wheel-rings.svg b/krita/pics/svg/dark_wheel-rings.svg
new file mode 100644
index 0000000000..597abca1bc
--- /dev/null
+++ b/krita/pics/svg/dark_wheel-rings.svg
@@ -0,0 +1,1489 @@
+
+
+
+
diff --git a/krita/pics/svg/dark_wheel-sectors.svg b/krita/pics/svg/dark_wheel-sectors.svg
new file mode 100644
index 0000000000..ac54831885
--- /dev/null
+++ b/krita/pics/svg/dark_wheel-sectors.svg
@@ -0,0 +1,1499 @@
+
+
+
+
diff --git a/krita/pics/svg/light_gamut-mask-off.svg b/krita/pics/svg/light_gamut-mask-off.svg
new file mode 100644
index 0000000000..8a69b44344
--- /dev/null
+++ b/krita/pics/svg/light_gamut-mask-off.svg
@@ -0,0 +1,1563 @@
+
+
+
+
diff --git a/krita/pics/svg/light_gamut-mask-on.svg b/krita/pics/svg/light_gamut-mask-on.svg
new file mode 100644
index 0000000000..fdce9a6afc
--- /dev/null
+++ b/krita/pics/svg/light_gamut-mask-on.svg
@@ -0,0 +1,1535 @@
+
+
+
+
diff --git a/krita/pics/svg/light_infinity.svg b/krita/pics/svg/light_infinity.svg
new file mode 100644
index 0000000000..74007c0772
--- /dev/null
+++ b/krita/pics/svg/light_infinity.svg
@@ -0,0 +1,1501 @@
+
+
+
+
diff --git a/krita/pics/svg/light_wheel-light.svg b/krita/pics/svg/light_wheel-light.svg
new file mode 100644
index 0000000000..1537ea0fe8
--- /dev/null
+++ b/krita/pics/svg/light_wheel-light.svg
@@ -0,0 +1,1500 @@
+
+
+
+
diff --git a/krita/pics/svg/light_wheel-rings.svg b/krita/pics/svg/light_wheel-rings.svg
new file mode 100644
index 0000000000..8f4cdbe5da
--- /dev/null
+++ b/krita/pics/svg/light_wheel-rings.svg
@@ -0,0 +1,1507 @@
+
+
+
+
diff --git a/krita/pics/svg/light_wheel-sectors.svg b/krita/pics/svg/light_wheel-sectors.svg
new file mode 100644
index 0000000000..20bad0dcab
--- /dev/null
+++ b/krita/pics/svg/light_wheel-sectors.svg
@@ -0,0 +1,1517 @@
+
+
+
+
diff --git a/krita/pics/svg/svg-icons.qrc b/krita/pics/svg/svg-icons.qrc
index d93584993c..0418ee66a3 100644
--- a/krita/pics/svg/svg-icons.qrc
+++ b/krita/pics/svg/svg-icons.qrc
@@ -1,152 +1,155 @@
-
-
-
+
+
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
dark_warning.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
light_warning.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
-
+ light_wheel-light.svg
+ light_wheel-rings.svg
+ light_wheel-sectors.svg
+ dark_wheel-light.svg
+ dark_wheel-rings.svg
+ dark_wheel-sectors.svg
+ dark_infinity.svg
+ light_infinity.svg
+ dark_gamut-mask-on.svg
+ dark_gamut-mask-off.svg
+ light_gamut-mask-off.svg
+ light_gamut-mask-on.svg
diff --git a/libs/basicflakes/tools/KoCreatePathTool.cpp b/libs/basicflakes/tools/KoCreatePathTool.cpp
index c2063193bb..731ca3849e 100644
--- a/libs/basicflakes/tools/KoCreatePathTool.cpp
+++ b/libs/basicflakes/tools/KoCreatePathTool.cpp
@@ -1,533 +1,583 @@
/* This file is part of the KDE project
*
* Copyright (C) 2006 Thorsten Zachmann
* Copyright (C) 2008-2010 Jan Hambrecht
*
* 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 "KoCreatePathTool.h"
#include "KoCreatePathTool_p.h"
#include
#include "KoPointerEvent.h"
#include "KoPathShape.h"
#include "KoSelection.h"
#include "KoDocumentResourceManager.h"
#include "KoShapePaintingContext.h"
#include "KoShapeStroke.h"
#include "KoCanvasBase.h"
#include "kis_int_parse_spin_box.h"
#include
#include "kis_canvas_resource_provider.h"
#include
+#include "KoPathPointTypeCommand.h"
#include
#include
#include
#include
#include
#include
KoCreatePathTool::KoCreatePathTool(KoCanvasBase *canvas)
: KoToolBase(*(new KoCreatePathToolPrivate(this, canvas)))
{
}
KoCreatePathTool::~KoCreatePathTool()
{
}
void KoCreatePathTool::paint(QPainter &painter, const KoViewConverter &converter)
{
Q_D(KoCreatePathTool);
if (pathStarted()) {
painter.save();
paintPath(*(d->shape), painter, converter);
painter.restore();
KisHandlePainterHelper helper =
KoShape::createHandlePainterHelper(&painter, d->shape, converter, d->handleRadius);
const bool firstPointActive = d->firstPoint == d->activePoint;
if (d->pointIsDragged || firstPointActive) {
const bool onlyPaintActivePoints = false;
KoPathPoint::PointTypes paintFlags = KoPathPoint::ControlPoint2;
if (d->activePoint->activeControlPoint1()) {
paintFlags |= KoPathPoint::ControlPoint1;
}
helper.setHandleStyle(KisHandleStyle::highlightedPrimaryHandles());
d->activePoint->paint(helper, paintFlags, onlyPaintActivePoints);
}
if (!firstPointActive) {
helper.setHandleStyle(d->mouseOverFirstPoint ?
KisHandleStyle::highlightedPrimaryHandles() :
KisHandleStyle::primarySelection());
d->firstPoint->paint(helper, KoPathPoint::Node);
}
}
if (d->hoveredPoint) {
KisHandlePainterHelper helper = KoShape::createHandlePainterHelper(&painter, d->hoveredPoint->parent(), converter, d->handleRadius);
helper.setHandleStyle(KisHandleStyle::highlightedPrimaryHandles());
d->hoveredPoint->paint(helper, KoPathPoint::Node);
}
painter.save();
KoShape::applyConversion(painter, converter);
canvas()->snapGuide()->paint(painter, converter);
painter.restore();
}
void KoCreatePathTool::paintPath(KoPathShape& pathShape, QPainter &painter, const KoViewConverter &converter)
{
Q_D(KoCreatePathTool);
painter.setTransform(pathShape.absoluteTransformation(&converter) * painter.transform());
painter.save();
KoShapePaintingContext paintContext; //FIXME
pathShape.paint(painter, converter, paintContext);
painter.restore();
if (pathShape.stroke()) {
painter.save();
pathShape.stroke()->paint(d->shape, painter, converter);
painter.restore();
}
}
void KoCreatePathTool::mousePressEvent(KoPointerEvent *event)
{
Q_D(KoCreatePathTool);
//Right click removes last point
if (event->button() == Qt::RightButton) {
removeLastPoint();
return;
}
const bool isOverFirstPoint = d->shape &&
handleGrabRect(d->firstPoint->point()).contains(event->point);
- bool haveCloseModifier = (listeningToModifiers() && (event->modifiers() & Qt::ShiftModifier));
+
+ const bool haveCloseModifier = d->enableClosePathShortcut &&
+ d->shape && d->shape->pointCount() > 2 &&
+ (event->modifiers() & Qt::ShiftModifier);
if ((event->button() == Qt::LeftButton) && haveCloseModifier && !isOverFirstPoint) {
endPathWithoutLastPoint();
return;
}
d->finishAfterThisPoint = false;
if (pathStarted()) {
if (isOverFirstPoint) {
d->activePoint->setPoint(d->firstPoint->point());
canvas()->updateCanvas(d->shape->boundingRect());
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
if (haveCloseModifier) {
d->shape->closeMerge();
// we are closing the path, so reset the existing start path point
d->existingStartPoint = 0;
// finish path
endPath();
} else {
// the path shape will get closed when the user releases
// the mouse button
d->finishAfterThisPoint = true;
}
} else {
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers());
// check whether we hit an start/end node of an existing path
d->existingEndPoint = d->endPointAtPosition(point);
if (d->existingEndPoint.isValid() && d->existingEndPoint != d->existingStartPoint) {
point = d->existingEndPoint.path->shapeToDocument(d->existingEndPoint.point->point());
d->activePoint->setPoint(point);
// finish path
endPath();
} else {
d->activePoint->setPoint(point);
canvas()->updateCanvas(d->shape->boundingRect());
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
}
}
} else {
KoPathShape *pathShape = new KoPathShape();
d->shape = pathShape;
pathShape->setShapeId(KoPathShapeId);
KoShapeStrokeSP stroke(new KoShapeStroke());
const qreal size = canvas()->resourceManager()->resource(KisCanvasResourceProvider::Size).toReal();
stroke->setLineWidth(canvas()->unit().fromUserValue(size));
stroke->setColor(canvas()->resourceManager()->foregroundColor().toQColor());
pathShape->setStroke(stroke);
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers());
// check whether we hit an start/end node of an existing path
d->existingStartPoint = d->endPointAtPosition(point);
if (d->existingStartPoint.isValid()) {
point = d->existingStartPoint.path->shapeToDocument(d->existingStartPoint.point->point());
}
d->activePoint = pathShape->moveTo(point);
d->firstPoint = d->activePoint;
canvas()->updateCanvas(handlePaintRect(point));
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
canvas()->snapGuide()->setAdditionalEditedShape(pathShape);
d->angleSnapStrategy = new AngleSnapStrategy(d->angleSnappingDelta, d->angleSnapStatus);
canvas()->snapGuide()->addCustomSnapStrategy(d->angleSnapStrategy);
}
d->dragStartPoint = event->point;
if (d->angleSnapStrategy)
d->angleSnapStrategy->setStartPoint(d->activePoint->point());
}
-bool KoCreatePathTool::listeningToModifiers()
-{
- Q_D(KoCreatePathTool);
- return d->listeningToModifiers;
-}
-
bool KoCreatePathTool::pathStarted()
{
Q_D(KoCreatePathTool);
return ((bool) d->shape);
}
bool KoCreatePathTool::tryMergeInPathShape(KoPathShape *pathShape)
{
return addPathShapeImpl(pathShape, true);
}
+void KoCreatePathTool::setEnableClosePathShortcut(bool value)
+{
+ Q_D(KoCreatePathTool);
+ d->enableClosePathShortcut = value;
+}
+
void KoCreatePathTool::mouseDoubleClickEvent(KoPointerEvent *event)
{
//remove handle
canvas()->updateCanvas(handlePaintRect(event->point));
endPathWithoutLastPoint();
}
void KoCreatePathTool::mouseMoveEvent(KoPointerEvent *event)
{
Q_D(KoCreatePathTool);
KoPathPoint *endPoint = d->endPointAtPosition(event->point);
if (d->hoveredPoint != endPoint) {
if (d->hoveredPoint) {
QPointF nodePos = d->hoveredPoint->parent()->shapeToDocument(d->hoveredPoint->point());
canvas()->updateCanvas(handlePaintRect(nodePos));
}
d->hoveredPoint = endPoint;
if (d->hoveredPoint) {
QPointF nodePos = d->hoveredPoint->parent()->shapeToDocument(d->hoveredPoint->point());
canvas()->updateCanvas(handlePaintRect(nodePos));
}
}
if (!pathStarted()) {
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
canvas()->snapGuide()->snap(event->point, event->modifiers());
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
d->mouseOverFirstPoint = false;
return;
}
d->mouseOverFirstPoint = handleGrabRect(d->firstPoint->point()).contains(event->point);
canvas()->updateCanvas(d->shape->boundingRect());
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
QPointF snappedPosition = canvas()->snapGuide()->snap(event->point, event->modifiers());
d->repaintActivePoint();
if (event->buttons() & Qt::LeftButton) {
if (d->pointIsDragged ||
!handleGrabRect(d->dragStartPoint).contains(event->point)) {
d->pointIsDragged = true;
QPointF offset = snappedPosition - d->activePoint->point();
d->activePoint->setControlPoint2(d->activePoint->point() + offset);
// pressing stops controls points moving symmetrically
if ((event->modifiers() & Qt::AltModifier) == 0) {
d->activePoint->setControlPoint1(d->activePoint->point() - offset);
}
d->repaintActivePoint();
}
} else {
d->activePoint->setPoint(snappedPosition);
+
+ if (!d->prevPointWasDragged && d->autoSmoothCurves) {
+ KoPathPointIndex index = d->shape->pathPointIndex(d->activePoint);
+ if (index.second > 0) {
+
+ KoPathPointIndex prevIndex(index.first, index.second - 1);
+ KoPathPoint *prevPoint = d->shape->pointByIndex(prevIndex);
+
+ if (prevPoint) {
+ KoPathPoint *prevPrevPoint = 0;
+
+ if (index.second > 1) {
+ KoPathPointIndex prevPrevIndex(index.first, index.second - 2);
+ prevPrevPoint = d->shape->pointByIndex(prevPrevIndex);
+ }
+
+ if (prevPrevPoint) {
+ const QPointF control1 = prevPoint->point() + 0.3 * (prevPrevPoint->point() - prevPoint->point());
+ prevPoint->setControlPoint1(control1);
+ }
+
+ const QPointF control2 = prevPoint->point() + 0.3 * (d->activePoint->point() - prevPoint->point());
+ prevPoint->setControlPoint2(control2);
+
+ const QPointF activeControl = d->activePoint->point() + 0.3 * (prevPoint->point() - d->activePoint->point());
+ d->activePoint->setControlPoint1(activeControl);
+
+ KoPathPointTypeCommand::makeCubicPointSmooth(prevPoint);
+ }
+ }
+ }
+
}
canvas()->updateCanvas(d->shape->boundingRect());
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
}
void KoCreatePathTool::mouseReleaseEvent(KoPointerEvent *event)
{
Q_D(KoCreatePathTool);
if (! d->shape || (event->buttons() & Qt::RightButton)) return;
- d->listeningToModifiers = true; // After the first press-and-release
d->repaintActivePoint();
+ d->prevPointWasDragged = d->pointIsDragged;
d->pointIsDragged = false;
KoPathPoint *lastActivePoint = d->activePoint;
if (!d->finishAfterThisPoint) {
d->activePoint = d->shape->lineTo(event->point);
canvas()->snapGuide()->setIgnoredPathPoints((QList() << d->activePoint));
}
// apply symmetric point property if applicable
if (lastActivePoint->activeControlPoint1() && lastActivePoint->activeControlPoint2()) {
QPointF diff1 = lastActivePoint->point() - lastActivePoint->controlPoint1();
QPointF diff2 = lastActivePoint->controlPoint2() - lastActivePoint->point();
if (qFuzzyCompare(diff1.x(), diff2.x()) && qFuzzyCompare(diff1.y(), diff2.y()))
lastActivePoint->setProperty(KoPathPoint::IsSymmetric);
}
if (d->finishAfterThisPoint) {
d->firstPoint->setControlPoint1(d->activePoint->controlPoint1());
delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint));
d->activePoint = d->firstPoint;
+
+ if (!d->prevPointWasDragged && d->autoSmoothCurves) {
+ KoPathPointTypeCommand::makeCubicPointSmooth(d->activePoint);
+ }
+
d->shape->closeMerge();
// we are closing the path, so reset the existing start path point
d->existingStartPoint = 0;
// finish path
endPath();
}
if (d->angleSnapStrategy && lastActivePoint->activeControlPoint2()) {
d->angleSnapStrategy->deactivate();
}
}
void KoCreatePathTool::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape) {
emit done();
} else {
event->ignore();
}
}
void KoCreatePathTool::endPath()
{
Q_D(KoCreatePathTool);
d->addPathShape();
}
void KoCreatePathTool::endPathWithoutLastPoint()
{
Q_D(KoCreatePathTool);
if (d->shape) {
QRectF dirtyRect = d->shape->boundingRect();
delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint));
canvas()->updateCanvas(dirtyRect);
d->addPathShape();
}
}
void KoCreatePathTool::cancelPath()
{
Q_D(KoCreatePathTool);
if (d->shape) {
canvas()->updateCanvas(handlePaintRect(d->firstPoint->point()));
canvas()->updateCanvas(d->shape->boundingRect());
d->firstPoint = 0;
d->activePoint = 0;
}
d->cleanUp();
}
void KoCreatePathTool::removeLastPoint()
{
Q_D(KoCreatePathTool);
if ((d->shape)) {
KoPathPointIndex lastPointIndex = d->shape->pathPointIndex(d->activePoint);
if (lastPointIndex.second > 1) {
lastPointIndex.second--;
delete d->shape->removePoint(lastPointIndex);
d->hoveredPoint = 0;
d->repaintActivePoint();
canvas()->updateCanvas(d->shape->boundingRect());
}
}
}
void KoCreatePathTool::activate(ToolActivation activation, const QSet &shapes)
{
KoToolBase::activate(activation, shapes);
Q_D(KoCreatePathTool);
useCursor(Qt::ArrowCursor);
// retrieve the actual global handle radius
d->handleRadius = handleRadius();
+ d->loadAutoSmoothValueFromConfig();
// reset snap guide
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
canvas()->snapGuide()->reset();
}
void KoCreatePathTool::deactivate()
{
cancelPath();
KoToolBase::deactivate();
}
void KoCreatePathTool::documentResourceChanged(int key, const QVariant & res)
{
Q_D(KoCreatePathTool);
switch (key) {
case KoDocumentResourceManager::HandleRadius: {
d->handleRadius = res.toUInt();
}
break;
default:
return;
}
}
bool KoCreatePathTool::addPathShapeImpl(KoPathShape *pathShape, bool tryMergeOnly)
{
Q_D(KoCreatePathTool);
KoPathShape *startShape = 0;
KoPathShape *endShape = 0;
pathShape->normalize();
// check if existing start/end points are still valid
d->existingStartPoint.validate(canvas());
d->existingEndPoint.validate(canvas());
if (d->connectPaths(pathShape, d->existingStartPoint, d->existingEndPoint)) {
if (d->existingStartPoint.isValid()) {
startShape = d->existingStartPoint.path;
}
if (d->existingEndPoint.isValid() && d->existingEndPoint != d->existingStartPoint) {
endShape = d->existingEndPoint.path;
}
}
if (tryMergeOnly && !startShape && !endShape) {
return false;
}
KUndo2Command *cmd = canvas()->shapeController()->addShape(pathShape, 0);
KIS_SAFE_ASSERT_RECOVER(cmd) {
canvas()->updateCanvas(pathShape->boundingRect());
delete pathShape;
return true;
}
KoSelection *selection = canvas()->shapeManager()->selection();
selection->deselectAll();
selection->select(pathShape);
if (startShape) {
pathShape->setBackground(startShape->background());
pathShape->setStroke(startShape->stroke());
} else if (endShape) {
pathShape->setBackground(endShape->background());
pathShape->setStroke(endShape->stroke());
}
if (startShape) {
canvas()->shapeController()->removeShape(startShape, cmd);
}
if (endShape && startShape != endShape) {
canvas()->shapeController()->removeShape(endShape, cmd);
}
canvas()->addCommand(cmd);
return true;
}
void KoCreatePathTool::addPathShape(KoPathShape *pathShape)
{
addPathShapeImpl(pathShape, false);
}
QList > KoCreatePathTool::createOptionWidgets()
{
Q_D(KoCreatePathTool);
QList > list;
+ QCheckBox *smoothCurves = new QCheckBox(i18n("Autosmooth curve"));
+ smoothCurves->setObjectName("smooth-curves-widget");
+ smoothCurves->setChecked(d->autoSmoothCurves);
+ connect(smoothCurves, SIGNAL(toggled(bool)), this, SLOT(autoSmoothCurvesChanged(bool)));
+ connect(this, SIGNAL(sigUpdateAutoSmoothCurvesGUI(bool)), smoothCurves, SLOT(setChecked(bool)));
+
+ list.append(smoothCurves);
+
QWidget *angleWidget = new QWidget();
angleWidget->setObjectName("Angle Constraints");
QGridLayout *layout = new QGridLayout(angleWidget);
layout->addWidget(new QLabel(i18n("Angle snapping delta:"), angleWidget), 0, 0);
QSpinBox *angleEdit = new KisIntParseSpinBox(angleWidget);
angleEdit->setValue(d->angleSnappingDelta);
angleEdit->setRange(1, 360);
angleEdit->setSingleStep(1);
angleEdit->setSuffix(QChar(Qt::Key_degree));
layout->addWidget(angleEdit, 0, 1);
layout->addWidget(new QLabel(i18n("Activate angle snap:"), angleWidget), 1, 0);
QCheckBox *angleSnap = new QCheckBox(angleWidget);
angleSnap->setChecked(false);
angleSnap->setCheckable(true);
layout->addWidget(angleSnap, 1, 1);
QWidget *specialSpacer = new QWidget();
specialSpacer->setObjectName("SpecialSpacer");
layout->addWidget(specialSpacer, 2, 1);
angleWidget->setWindowTitle(i18n("Angle Constraints"));
list.append(angleWidget);
connect(angleEdit, SIGNAL(valueChanged(int)), this, SLOT(angleDeltaChanged(int)));
connect(angleSnap, SIGNAL(stateChanged(int)), this, SLOT(angleSnapChanged(int)));
return list;
}
//have to include this because of Q_PRIVATE_SLOT
#include
diff --git a/libs/basicflakes/tools/KoCreatePathTool.h b/libs/basicflakes/tools/KoCreatePathTool.h
index 3924e354f1..b78cdb720b 100644
--- a/libs/basicflakes/tools/KoCreatePathTool.h
+++ b/libs/basicflakes/tools/KoCreatePathTool.h
@@ -1,113 +1,116 @@
/* This file is part of the KDE project
*
* Copyright (C) 2006 Thorsten Zachmann
* Copyright (C) 2008-2009 Jan Hambrecht
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KOCREATEPATHTOOL_H
#define KOCREATEPATHTOOL_H
#include "kritabasicflakes_export.h"
#include
#include
#include
class KoPathShape;
class KoShapeStroke;
class KoCreatePathToolPrivate;
#define KoCreatePathTool_ID "CreatePathTool"
/**
* Tool for creating path shapes.
*/
class KRITABASICFLAKES_EXPORT KoCreatePathTool : public KoToolBase
{
Q_OBJECT
public:
/**
* Constructor for the tool that allows you to create new paths by hand.
* @param canvas the canvas this tool will be working for.
*/
explicit KoCreatePathTool(KoCanvasBase * canvas);
~KoCreatePathTool() override;
/// reimplemented
void paint(QPainter &painter, const KoViewConverter &converter) override;
/// reimplemented
void mousePressEvent(KoPointerEvent *event) override;
/// reimplemented
void mouseDoubleClickEvent(KoPointerEvent *event) override;
/// reimplemented
void mouseMoveEvent(KoPointerEvent *event) override;
/// reimplemented
void mouseReleaseEvent(KoPointerEvent *event) override;
/// reimplemented
void keyPressEvent(QKeyEvent *event) override;
- /// For behavior as selection tool and with initial shift-key
- virtual bool listeningToModifiers();
-
/**
* Returns true if path has been started
*/
bool pathStarted();
bool tryMergeInPathShape(KoPathShape *pathShape);
+ void setEnableClosePathShortcut(bool value);
+
public Q_SLOTS:
/// reimplemented
void activate(ToolActivation activation, const QSet &shapes) override;
/// reimplemented
void deactivate() override;
/// reimplemented
void documentResourceChanged(int key, const QVariant & res) override;
+Q_SIGNALS:
+ void sigUpdateAutoSmoothCurvesGUI(bool value);
+
protected:
/**
* Add path shape to document.
* This method can be overridden and change the behaviour of the tool. In that case the subclass takes ownership of pathShape.
* It gets only called if there are two or more points in the path.
*/
virtual void addPathShape(KoPathShape* pathShape);
protected:
/**
* This method is called to paint the path. Decorations are drawn by KoCreatePathTool afterwards.
*/
virtual void paintPath(KoPathShape& pathShape, QPainter &painter, const KoViewConverter &converter);
void endPath();
void endPathWithoutLastPoint();
void cancelPath();
void removeLastPoint();
bool addPathShapeImpl(KoPathShape* pathShape, bool tryMergeOnly);
/// reimplemented
QList > createOptionWidgets() override;
private:
Q_DECLARE_PRIVATE(KoCreatePathTool)
Q_PRIVATE_SLOT(d_func(), void angleDeltaChanged(int))
Q_PRIVATE_SLOT(d_func(), void angleSnapChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void autoSmoothCurvesChanged(bool))
};
#endif
diff --git a/libs/basicflakes/tools/KoCreatePathTool_p.h b/libs/basicflakes/tools/KoCreatePathTool_p.h
index 2f68d9f479..4eb8e03052 100644
--- a/libs/basicflakes/tools/KoCreatePathTool_p.h
+++ b/libs/basicflakes/tools/KoCreatePathTool_p.h
@@ -1,429 +1,445 @@
/* This file is part of the KDE project
*
* Copyright (C) 2006 Thorsten Zachmann
* Copyright (C) 2008-2010 Jan Hambrecht
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KOCREATEPATHTOOL_P_H
#define KOCREATEPATHTOOL_P_H
#include "KoCreatePathTool.h"
#include "KoPathPoint.h"
#include "KoPathPointData.h"
#include "KoPathPointMergeCommand.h"
#include "KoParameterShape.h"
#include "KoShapeManager.h"
#include "KoSnapStrategy.h"
#include "KoToolBase_p.h"
#include
+#include "kis_config.h"
#include "math.h"
class KoStrokeConfigWidget;
class KoConverter;
/// Small helper to keep track of a path point and its parent path shape
struct PathConnectionPoint {
PathConnectionPoint()
: path(0), point(0) {
}
// reset state to invalid
void reset() {
path = 0;
point = 0;
}
PathConnectionPoint& operator =(KoPathPoint * pathPoint) {
if (!pathPoint || ! pathPoint->parent()) {
reset();
} else {
path = pathPoint->parent();
point = pathPoint;
}
return *this;
}
bool operator != (const PathConnectionPoint &rhs) const {
return rhs.path != path || rhs.point != point;
}
bool operator == (const PathConnectionPoint &rhs) const {
return rhs.path == path && rhs.point == point;
}
bool isValid() const {
return path && point;
}
// checks if the path and point are still valid
void validate(KoCanvasBase *canvas) {
// no point in validating an already invalid state
if (!isValid()) {
return;
}
// we need canvas to validate
if (!canvas) {
reset();
return;
}
// check if path is still part of the docment
if (!canvas->shapeManager()->shapes().contains(path)) {
reset();
return;
}
// check if point is still part of the path
if (path->pathPointIndex(point) == KoPathPointIndex(-1, -1)) {
reset();
return;
}
}
KoPathShape * path;
KoPathPoint * point;
};
inline qreal squareDistance(const QPointF &p1, const QPointF &p2)
{
qreal dx = p1.x() - p2.x();
qreal dy = p1.y() - p2.y();
return dx * dx + dy * dy;
}
class AngleSnapStrategy : public KoSnapStrategy
{
public:
explicit AngleSnapStrategy(qreal angleStep, bool active)
: KoSnapStrategy(KoSnapGuide::CustomSnapping), m_angleStep(angleStep), m_active(active) {
}
void setStartPoint(const QPointF &startPoint) {
m_startPoint = startPoint;
}
void setAngleStep(qreal angleStep) {
m_angleStep = qAbs(angleStep);
}
bool snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance) override {
Q_UNUSED(proxy);
if (!m_active)
return false;
QLineF line(m_startPoint, mousePosition);
qreal currentAngle = line.angle();
int prevStep = qAbs(currentAngle / m_angleStep);
int nextStep = prevStep + 1;
qreal prevAngle = prevStep * m_angleStep;
qreal nextAngle = nextStep * m_angleStep;
if (qAbs(currentAngle - prevAngle) <= qAbs(currentAngle - nextAngle)) {
line.setAngle(prevAngle);
} else {
line.setAngle(nextAngle);
}
qreal maxSquareSnapDistance = maxSnapDistance * maxSnapDistance;
qreal snapDistance = squareDistance(mousePosition, line.p2());
if (snapDistance > maxSquareSnapDistance)
return false;
setSnappedPosition(line.p2());
return true;
}
QPainterPath decoration(const KoViewConverter &converter) const override {
Q_UNUSED(converter);
QPainterPath decoration;
decoration.moveTo(m_startPoint);
decoration.lineTo(snappedPosition());
return decoration;
}
void deactivate() {
m_active = false;
}
void activate() {
m_active = true;
}
private:
QPointF m_startPoint;
qreal m_angleStep;
bool m_active;
};
class KoCreatePathToolPrivate : public KoToolBasePrivate
{
KoCreatePathTool * const q;
public:
KoCreatePathToolPrivate(KoCreatePathTool * const qq, KoCanvasBase* canvas)
: KoToolBasePrivate(qq, canvas),
q(qq),
shape(0),
activePoint(0),
firstPoint(0),
handleRadius(3),
mouseOverFirstPoint(false),
pointIsDragged(false),
finishAfterThisPoint(false),
hoveredPoint(0),
- listeningToModifiers(false),
angleSnapStrategy(0),
angleSnappingDelta(15),
- angleSnapStatus(false)
+ angleSnapStatus(false),
+ enableClosePathShortcut(true)
{
}
KoPathShape *shape;
KoPathPoint *activePoint;
KoPathPoint *firstPoint;
int handleRadius;
bool mouseOverFirstPoint;
bool pointIsDragged;
bool finishAfterThisPoint;
PathConnectionPoint existingStartPoint; ///< an existing path point we started a new path at
PathConnectionPoint existingEndPoint; ///< an existing path point we finished a new path at
KoPathPoint *hoveredPoint; ///< an existing path end point the mouse is hovering on
- bool listeningToModifiers; // Fine tune when to begin processing modifiers at the beginning of a stroke.
+ bool prevPointWasDragged = false;
+ bool autoSmoothCurves = false;
QPointF dragStartPoint;
AngleSnapStrategy *angleSnapStrategy;
int angleSnappingDelta;
bool angleSnapStatus;
+ bool enableClosePathShortcut;
void repaintActivePoint() const {
const bool isFirstPoint = (activePoint == firstPoint);
if (!isFirstPoint && !pointIsDragged)
return;
QRectF rect = activePoint->boundingRect(false);
// make sure that we have the second control point inside our
// update rect, as KoPathPoint::boundingRect will not include
// the second control point of the last path point if the path
// is not closed
const QPointF &point = activePoint->point();
const QPointF &controlPoint = activePoint->controlPoint2();
rect = rect.united(QRectF(point, controlPoint).normalized());
// when painting the first point we want the
// first control point to be painted as well
if (isFirstPoint) {
const QPointF &controlPoint = activePoint->controlPoint1();
rect = rect.united(QRectF(point, controlPoint).normalized());
}
QPointF border = q->canvas()->viewConverter()
->viewToDocument(QPointF(handleRadius, handleRadius));
rect.adjust(-border.x(), -border.y(), border.x(), border.y());
q->canvas()->updateCanvas(rect);
}
/// returns the nearest existing path point
KoPathPoint* endPointAtPosition(const QPointF &position) const {
QRectF roi = q->handleGrabRect(position);
QList shapes = q->canvas()->shapeManager()->shapesAt(roi);
KoPathPoint * nearestPoint = 0;
qreal minDistance = HUGE_VAL;
uint grabSensitivity = q->grabSensitivity();
qreal maxDistance = q->canvas()->viewConverter()->viewToDocumentX(grabSensitivity);
Q_FOREACH(KoShape * s, shapes) {
KoPathShape * path = dynamic_cast(s);
if (!path)
continue;
KoParameterShape *paramShape = dynamic_cast(s);
if (paramShape && paramShape->isParametricShape())
continue;
KoPathPoint * p = 0;
uint subpathCount = path->subpathCount();
for (uint i = 0; i < subpathCount; ++i) {
if (path->isClosedSubpath(i))
continue;
p = path->pointByIndex(KoPathPointIndex(i, 0));
// check start of subpath
qreal d = squareDistance(position, path->shapeToDocument(p->point()));
if (d < minDistance && d < maxDistance) {
nearestPoint = p;
minDistance = d;
}
// check end of subpath
p = path->pointByIndex(KoPathPointIndex(i, path->subpathPointCount(i) - 1));
d = squareDistance(position, path->shapeToDocument(p->point()));
if (d < minDistance && d < maxDistance) {
nearestPoint = p;
minDistance = d;
}
}
}
return nearestPoint;
}
/// Connects given path with the ones we hit when starting/finishing
bool connectPaths(KoPathShape *pathShape, const PathConnectionPoint &pointAtStart, const PathConnectionPoint &pointAtEnd) const {
KoPathShape * startShape = 0;
KoPathShape * endShape = 0;
KoPathPoint * startPoint = 0;
KoPathPoint * endPoint = 0;
if (pointAtStart.isValid()) {
startShape = pointAtStart.path;
startPoint = pointAtStart.point;
}
if (pointAtEnd.isValid()) {
endShape = pointAtEnd.path;
endPoint = pointAtEnd.point;
}
// at least one point must be valid
if (!startPoint && !endPoint)
return false;
// do not allow connecting to the same point twice
if (startPoint == endPoint)
endPoint = 0;
// we have hit an existing path point on start/finish
// what we now do is:
// 1. combine the new created path with the ones we hit on start/finish
// 2. merge the endpoints of the corresponding subpaths
uint newPointCount = pathShape->subpathPointCount(0);
KoPathPointIndex newStartPointIndex(0, 0);
KoPathPointIndex newEndPointIndex(0, newPointCount - 1);
KoPathPoint * newStartPoint = pathShape->pointByIndex(newStartPointIndex);
KoPathPoint * newEndPoint = pathShape->pointByIndex(newEndPointIndex);
// combine with the path we hit on start
KoPathPointIndex startIndex(-1, -1);
if (startShape && startPoint) {
startIndex = startShape->pathPointIndex(startPoint);
pathShape->combine(startShape);
pathShape->moveSubpath(0, pathShape->subpathCount() - 1);
}
// combine with the path we hit on finish
KoPathPointIndex endIndex(-1, -1);
if (endShape && endPoint) {
endIndex = endShape->pathPointIndex(endPoint);
if (endShape != startShape) {
endIndex.first += pathShape->subpathCount();
pathShape->combine(endShape);
}
}
// do we connect twice to a single subpath ?
bool connectToSingleSubpath = (startShape == endShape && startIndex.first == endIndex.first);
if (startIndex.second == 0 && !connectToSingleSubpath) {
pathShape->reverseSubpath(startIndex.first);
startIndex.second = pathShape->subpathPointCount(startIndex.first) - 1;
}
if (endIndex.second > 0 && !connectToSingleSubpath) {
pathShape->reverseSubpath(endIndex.first);
endIndex.second = 0;
}
// after combining we have a path where with the subpaths in the following
// order:
// 1. the subpaths of the pathshape we started the new path at
// 2. the subpath we just created
// 3. the subpaths of the pathshape we finished the new path at
// get the path points we want to merge, as these are not going to
// change while merging
KoPathPoint * existingStartPoint = pathShape->pointByIndex(startIndex);
KoPathPoint * existingEndPoint = pathShape->pointByIndex(endIndex);
// merge first two points
if (existingStartPoint) {
KoPathPointData pd1(pathShape, pathShape->pathPointIndex(existingStartPoint));
KoPathPointData pd2(pathShape, pathShape->pathPointIndex(newStartPoint));
KoPathPointMergeCommand cmd1(pd1, pd2);
cmd1.redo();
}
// merge last two points
if (existingEndPoint) {
KoPathPointData pd3(pathShape, pathShape->pathPointIndex(newEndPoint));
KoPathPointData pd4(pathShape, pathShape->pathPointIndex(existingEndPoint));
KoPathPointMergeCommand cmd2(pd3, pd4);
cmd2.redo();
}
return true;
}
void addPathShape() {
if (!shape) return;
if (shape->pointCount() < 2) {
cleanUp();
return;
}
// this is done so that nothing happens when the mouseReleaseEvent for the this event is received
KoPathShape *pathShape = shape;
shape = 0;
q->addPathShape(pathShape);
cleanUp();
return;
}
void cleanUp() {
// reset snap guide
q->canvas()->updateCanvas(q->canvas()->snapGuide()->boundingRect());
q->canvas()->snapGuide()->reset();
angleSnapStrategy = 0;
delete shape;
shape = 0;
existingStartPoint = 0;
existingEndPoint = 0;
hoveredPoint = 0;
- listeningToModifiers = false;
}
void angleDeltaChanged(int value) {
angleSnappingDelta = value;
if (angleSnapStrategy)
angleSnapStrategy->setAngleStep(angleSnappingDelta);
}
+ void autoSmoothCurvesChanged(bool value) {
+ autoSmoothCurves = value;
+
+ KisConfig cfg(false);
+ cfg.setAutoSmoothBezierCurves(value);
+ }
+
+ void loadAutoSmoothValueFromConfig() {
+ KisConfig cfg(true);
+ autoSmoothCurves = cfg.autoSmoothBezierCurves();
+
+ emit q->sigUpdateAutoSmoothCurvesGUI(autoSmoothCurves);
+ }
+
void angleSnapChanged(int angleSnap) {
angleSnapStatus = ! angleSnapStatus;
if (angleSnapStrategy) {
if (angleSnap == Qt::Checked)
angleSnapStrategy->activate();
else
angleSnapStrategy->deactivate();
}
}
};
#endif // KOCREATEPATHTOOL_P_H
diff --git a/libs/flake/CMakeLists.txt b/libs/flake/CMakeLists.txt
index 45507ef1e6..0547d07dc9 100644
--- a/libs/flake/CMakeLists.txt
+++ b/libs/flake/CMakeLists.txt
@@ -1,249 +1,251 @@
project(kritaflake)
include_directories(
${CMAKE_SOURCE_DIR}/libs/flake/commands
${CMAKE_SOURCE_DIR}/libs/flake/tools
${CMAKE_SOURCE_DIR}/libs/flake/svg
${CMAKE_SOURCE_DIR}/libs/flake/text
${CMAKE_BINARY_DIR}/libs/flake
)
add_subdirectory(styles)
add_subdirectory(tests)
set(kritaflake_SRCS
KoGradientHelper.cpp
KoFlake.cpp
KoCanvasBase.cpp
KoResourceManager_p.cpp
KoDerivedResourceConverter.cpp
KoResourceUpdateMediator.cpp
KoCanvasResourceManager.cpp
KoDocumentResourceManager.cpp
KoCanvasObserverBase.cpp
KoCanvasSupervisor.cpp
KoDockFactoryBase.cpp
KoDockRegistry.cpp
KoDataCenterBase.cpp
KoInsets.cpp
KoPathShape.cpp
KoPathPoint.cpp
KoPathSegment.cpp
KoSelection.cpp
KoSelectedShapesProxy.cpp
KoSelectedShapesProxySimple.cpp
KoShape.cpp
KoShapeAnchor.cpp
KoShapeControllerBase.cpp
KoShapeApplicationData.cpp
KoShapeContainer.cpp
KoShapeContainerModel.cpp
KoShapeGroup.cpp
KoShapeManager.cpp
KoShapePaintingContext.cpp
KoFrameShape.cpp
KoMarker.cpp
KoMarkerCollection.cpp
KoToolBase.cpp
KoCanvasController.cpp
KoCanvasControllerWidget.cpp
KoCanvasControllerWidgetViewport_p.cpp
KoShapeRegistry.cpp
KoDeferredShapeFactoryBase.cpp
KoToolFactoryBase.cpp
KoPathShapeFactory.cpp
KoShapeFactoryBase.cpp
KoShapeUserData.cpp
KoParameterShape.cpp
KoPointerEvent.cpp
KoShapeController.cpp
KoToolSelection.cpp
KoShapeLayer.cpp
KoPostscriptPaintDevice.cpp
KoInputDevice.cpp
KoToolManager_p.cpp
KoToolManager.cpp
KoToolRegistry.cpp
KoToolProxy.cpp
KoShapeSavingContext.cpp
KoShapeLoadingContext.cpp
KoLoadingShapeUpdater.cpp
KoPathShapeLoader.cpp
KoShapeStrokeModel.cpp
KoShapeStroke.cpp
KoShapeBackground.cpp
KoColorBackground.cpp
KoGradientBackground.cpp
KoOdfGradientBackground.cpp
KoHatchBackground.cpp
KoPatternBackground.cpp
KoVectorPatternBackground.cpp
KoShapeFillWrapper.cpp
KoShapeFillResourceConnector.cpp
KoShapeConfigWidgetBase.cpp
KoDrag.cpp
KoSvgPaste.cpp
KoDragOdfSaveHelper.cpp
KoShapeOdfSaveHelper.cpp
KoConnectionPoint.cpp
KoConnectionShape.cpp
KoConnectionShapeLoadingUpdater.cpp
KoConnectionShapeFactory.cpp
KoConnectionShapeConfigWidget.cpp
KoSnapGuide.cpp
KoSnapProxy.cpp
KoSnapStrategy.cpp
KoSnapData.cpp
KoShapeShadow.cpp
KoSharedLoadingData.cpp
KoSharedSavingData.cpp
KoViewConverter.cpp
KoInputDeviceHandler.cpp
KoInputDeviceHandlerEvent.cpp
KoInputDeviceHandlerRegistry.cpp
KoImageData.cpp
KoImageData_p.cpp
KoImageCollection.cpp
KoOdfWorkaround.cpp
KoFilterEffect.cpp
KoFilterEffectStack.cpp
KoFilterEffectFactoryBase.cpp
KoFilterEffectRegistry.cpp
KoFilterEffectConfigWidgetBase.cpp
KoFilterEffectRenderContext.cpp
KoFilterEffectLoadingContext.cpp
KoTextShapeDataBase.cpp
KoTosContainer.cpp
KoTosContainerModel.cpp
KoClipPath.cpp
KoClipMask.cpp
KoClipMaskPainter.cpp
KoCurveFit.cpp
+ KisGamutMaskViewConverter.cpp
commands/KoShapeGroupCommand.cpp
commands/KoShapeAlignCommand.cpp
commands/KoShapeBackgroundCommand.cpp
commands/KoShapeCreateCommand.cpp
commands/KoShapeDeleteCommand.cpp
commands/KoShapeDistributeCommand.cpp
commands/KoShapeLockCommand.cpp
commands/KoShapeMoveCommand.cpp
commands/KoShapeResizeCommand.cpp
commands/KoShapeShearCommand.cpp
commands/KoShapeSizeCommand.cpp
commands/KoShapeStrokeCommand.cpp
commands/KoShapeUngroupCommand.cpp
commands/KoShapeReorderCommand.cpp
commands/KoShapeKeepAspectRatioCommand.cpp
commands/KoPathBaseCommand.cpp
commands/KoPathPointMoveCommand.cpp
commands/KoPathControlPointMoveCommand.cpp
commands/KoPathPointTypeCommand.cpp
commands/KoPathPointRemoveCommand.cpp
commands/KoPathPointInsertCommand.cpp
commands/KoPathSegmentBreakCommand.cpp
commands/KoPathBreakAtPointCommand.cpp
commands/KoPathSegmentTypeCommand.cpp
commands/KoPathCombineCommand.cpp
commands/KoSubpathRemoveCommand.cpp
commands/KoSubpathJoinCommand.cpp
commands/KoParameterHandleMoveCommand.cpp
commands/KoParameterToPathCommand.cpp
commands/KoShapeTransformCommand.cpp
commands/KoPathFillRuleCommand.cpp
commands/KoConnectionShapeTypeCommand.cpp
commands/KoShapeShadowCommand.cpp
commands/KoPathReverseCommand.cpp
commands/KoShapeRenameCommand.cpp
commands/KoShapeRunAroundCommand.cpp
commands/KoPathPointMergeCommand.cpp
commands/KoShapeTransparencyCommand.cpp
commands/KoShapeClipCommand.cpp
commands/KoShapeUnclipCommand.cpp
commands/KoPathShapeMarkerCommand.cpp
commands/KoShapeConnectionChangeCommand.cpp
commands/KoMultiPathPointMergeCommand.cpp
commands/KoMultiPathPointJoinCommand.cpp
commands/KoKeepShapesSelectedCommand.cpp
commands/KoPathMergeUtils.cpp
html/HtmlSavingContext.cpp
html/HtmlWriter.cpp
tools/KoCreateShapeStrategy.cpp
tools/KoPathToolFactory.cpp
tools/KoPathTool.cpp
tools/KoPathToolSelection.cpp
tools/KoPathToolHandle.cpp
tools/PathToolOptionWidget.cpp
tools/KoPathPointRubberSelectStrategy.cpp
tools/KoPathPointMoveStrategy.cpp
tools/KoPathConnectionPointStrategy.cpp
tools/KoPathControlPointMoveStrategy.cpp
tools/KoParameterChangeStrategy.cpp
tools/KoZoomTool.cpp
tools/KoZoomToolFactory.cpp
tools/KoZoomToolWidget.cpp
tools/KoZoomStrategy.cpp
tools/KoInteractionTool.cpp
tools/KoInteractionStrategy.cpp
tools/KoInteractionStrategyFactory.cpp
tools/KoCreateShapesTool.cpp
tools/KoCreateShapesToolFactory.cpp
tools/KoShapeRubberSelectStrategy.cpp
tools/KoPathSegmentChangeStrategy.cpp
svg/KoShapePainter.cpp
svg/SvgUtil.cpp
svg/SvgGraphicContext.cpp
svg/SvgSavingContext.cpp
svg/SvgWriter.cpp
svg/SvgStyleWriter.cpp
svg/SvgShape.cpp
svg/SvgParser.cpp
svg/SvgStyleParser.cpp
svg/SvgGradientHelper.cpp
svg/SvgFilterHelper.cpp
svg/SvgCssHelper.cpp
svg/SvgClipPathHelper.cpp
svg/SvgLoadingContext.cpp
svg/SvgShapeFactory.cpp
svg/parsers/SvgTransformParser.cpp
text/KoSvgText.cpp
text/KoSvgTextProperties.cpp
text/KoSvgTextChunkShape.cpp
text/KoSvgTextShape.cpp
text/KoSvgTextShapeMarkupConverter.cpp
resources/KoSvgSymbolCollectionResource.cpp
+ resources/KoGamutMask.cpp
FlakeDebug.cpp
tests/MockShapes.cpp
)
ki18n_wrap_ui(kritaflake_SRCS
tools/PathToolOptionWidgetBase.ui
KoConnectionShapeConfigWidget.ui
tools/KoZoomToolWidget.ui
)
add_library(kritaflake SHARED ${kritaflake_SRCS})
generate_export_header(kritaflake BASE_NAME kritaflake)
target_include_directories(kritaflake
PUBLIC
$
$
$
$
)
target_link_libraries(kritaflake kritapigment kritawidgetutils kritaodf kritacommand KF5::WidgetsAddons Qt5::Svg)
set_target_properties(kritaflake PROPERTIES
VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
)
install(TARGETS kritaflake ${INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/libs/flake/KisGamutMaskViewConverter.cpp b/libs/flake/KisGamutMaskViewConverter.cpp
new file mode 100644
index 0000000000..e5c22e8b74
--- /dev/null
+++ b/libs/flake/KisGamutMaskViewConverter.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018 Anna Medonosova
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "KisGamutMaskViewConverter.h"
+
+#include
+#include
+#include
+
+#include
+
+//#define DEBUG_GAMUT_MASK_CONVERTER
+
+KisGamutMaskViewConverter::KisGamutMaskViewConverter()
+ : m_viewSize(1.0)
+ , m_maskSize(QSizeF(1,1))
+ , m_maskResolution(1)
+{
+ computeAndSetZoom();
+}
+
+KisGamutMaskViewConverter::~KisGamutMaskViewConverter()
+{
+}
+
+QPointF KisGamutMaskViewConverter::documentToView(const QPointF &documentPoint) const
+{
+ return QPointF(documentToViewX(documentPoint.x()), documentToViewY(documentPoint.y()));
+}
+
+
+QPointF KisGamutMaskViewConverter::viewToDocument(const QPointF &viewPoint) const
+{
+ return QPointF(viewToDocumentX(viewPoint.x()), viewToDocumentY(viewPoint.y()));
+}
+
+QRectF KisGamutMaskViewConverter::documentToView(const QRectF &documentRect) const
+{
+ return QRectF(documentToView(documentRect.topLeft()), documentToView(documentRect.size()));
+}
+
+QRectF KisGamutMaskViewConverter::viewToDocument(const QRectF &viewRect) const
+{
+ return QRectF(viewToDocument(viewRect.topLeft()), viewToDocument(viewRect.size()));
+}
+
+QSizeF KisGamutMaskViewConverter::documentToView(const QSizeF &documentSize) const
+{
+ return QSizeF(documentToViewX(documentSize.width()), documentToViewY(documentSize.height()));
+}
+
+QSizeF KisGamutMaskViewConverter::viewToDocument(const QSizeF &viewSize) const
+{
+ return QSizeF(viewToDocumentX(viewSize.width()), viewToDocumentY(viewSize.height()));
+}
+
+qreal KisGamutMaskViewConverter::documentToViewX(qreal documentX) const
+{
+ qreal translated = documentX * m_zoomLevel;
+
+#ifdef DEBUG_GAMUT_MASK_CONVERTER
+ debugFlake << "KisGamutMaskViewConverter::DocumentToViewX: "
+ << "documentX: " << documentX
+ << " -> translated: " << translated;
+#endif
+
+ return translated;
+}
+
+qreal KisGamutMaskViewConverter::documentToViewY(qreal documentY) const
+{
+ qreal translated = documentY * m_zoomLevel;
+
+#ifdef DEBUG_GAMUT_MASK_CONVERTER
+ debugFlake << "KisGamutMaskViewConverter::DocumentToViewY: "
+ << "documentY: " << documentY
+ << " -> translated: " << translated;
+#endif
+
+ return translated;
+}
+
+qreal KisGamutMaskViewConverter::viewToDocumentX(qreal viewX) const
+{
+ qreal translated = viewX / m_zoomLevel;
+
+#ifdef DEBUG_GAMUT_MASK_CONVERTER
+ debugFlake << "KisGamutMaskViewConverter::viewToDocumentX: "
+ << "viewX: " << viewX
+ << " -> translated: " << translated;
+#endif
+
+ return translated;
+}
+
+qreal KisGamutMaskViewConverter::viewToDocumentY(qreal viewY) const
+{
+ qreal translated = viewY / m_zoomLevel;
+
+#ifdef DEBUG_GAMUT_MASK_CONVERTER
+ debugFlake << "KisGamutMaskViewConverter::viewToDocumentY: "
+ << "viewY: " << viewY
+ << " -> translated: " << translated;
+#endif
+
+ return translated;
+}
+
+
+void KisGamutMaskViewConverter::setZoom(qreal zoom)
+{
+ if (qFuzzyCompare(zoom, qreal(0.0)) || qFuzzyCompare(zoom, qreal(1.0))) {
+ zoom = 1;
+ }
+
+#ifdef DEBUG_GAMUT_MASK_CONVERTER
+ debugFlake << "KisGamutMaskViewConverter::setZoom: setting to " << zoom;
+#endif
+
+ m_zoomLevel = zoom;
+}
+
+void KisGamutMaskViewConverter::zoom(qreal *zoomX, qreal *zoomY) const
+{
+ *zoomX = m_zoomLevel;
+ *zoomY = m_zoomLevel;
+}
+
+void KisGamutMaskViewConverter::setViewSize(QSize viewSize)
+{
+ m_viewSize = viewSize.width();
+
+ computeAndSetZoom();
+}
+
+void KisGamutMaskViewConverter::setMaskSize(QSizeF maskSize)
+{
+ m_maskSize = maskSize;
+ m_maskResolution = maskSize.width();
+
+ computeAndSetZoom();
+}
+
+void KisGamutMaskViewConverter::computeAndSetZoom()
+{
+ qreal zoom = m_viewSize / m_maskResolution;
+
+#ifdef DEBUG_GAMUT_MASK_CONVERTER
+ debugFlake << "KisGamutMaskViewConverter::computeAndSetZoom: "
+ << "m_viewSize: " << m_viewSize
+ << " m_maskSize: " << m_maskResolution;
+#endif
+
+ setZoom(zoom);
+}
diff --git a/libs/flake/KisGamutMaskViewConverter.h b/libs/flake/KisGamutMaskViewConverter.h
new file mode 100644
index 0000000000..447a785cc5
--- /dev/null
+++ b/libs/flake/KisGamutMaskViewConverter.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018 Anna Medonosova
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KISGAMUTMASKVIEWCONVERTER_H
+#define KISGAMUTMASKVIEWCONVERTER_H
+
+#include "kritaflake_export.h"
+
+#include
+#include
+#include
+
+class QPointF;
+class QRectF;
+
+/**
+ * @brief view convertor for gamut mask calculations and painting
+ */
+class KRITAFLAKE_EXPORT KisGamutMaskViewConverter : public KoViewConverter
+{
+public:
+ KisGamutMaskViewConverter();
+ ~KisGamutMaskViewConverter();
+
+ void setViewSize(QSize viewSize);
+ void setMaskSize(QSizeF maskSize);
+
+ QPointF documentToView(const QPointF &documentPoint) const override;
+ QPointF viewToDocument(const QPointF &viewPoint) const override;
+
+ QRectF documentToView(const QRectF &documentRect) const override;
+ QRectF viewToDocument(const QRectF &viewRect) const override;
+
+ QSizeF documentToView(const QSizeF& documentSize) const override;
+ QSizeF viewToDocument(const QSizeF& viewSize) const override;
+
+ qreal documentToViewX(qreal documentX) const override;
+ qreal documentToViewY(qreal documentY) const override;
+ qreal viewToDocumentX(qreal viewX) const override;
+ qreal viewToDocumentY(qreal viewY) const override;
+
+ void setZoom(qreal zoom) override;
+ void zoom(qreal *zoomX, qreal *zoomY) const override;
+
+private:
+ void computeAndSetZoom();
+
+ qreal m_zoomLevel; // 1.0 is 100%
+ int m_viewSize;
+ QSizeF m_maskSize;
+ qreal m_maskResolution;
+};
+
+#endif // KISGAMUTMASKVIEWCONVERTER_H
diff --git a/libs/flake/KoShapeFillResourceConnector.cpp b/libs/flake/KoShapeFillResourceConnector.cpp
index 809acbf8b0..5da240ccc2 100644
--- a/libs/flake/KoShapeFillResourceConnector.cpp
+++ b/libs/flake/KoShapeFillResourceConnector.cpp
@@ -1,96 +1,101 @@
/*
* Copyright (c) 2018 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 "KoShapeFillResourceConnector.h"
#include
#include
#include "kis_assert.h"
#include "kis_signal_auto_connection.h"
#include
#include
#include
#include
#include
struct KoShapeFillResourceConnector::Private
{
KoCanvasBase *canvas;
KisSignalAutoConnectionsStore resourceManagerConnections;
void applyShapeColoring(KoFlake::FillVariant fillVariant, const KoColor &color);
};
KoShapeFillResourceConnector::KoShapeFillResourceConnector(QObject *parent)
: QObject(parent),
m_d(new Private())
{
}
KoShapeFillResourceConnector::~KoShapeFillResourceConnector()
{
}
void KoShapeFillResourceConnector::connectToCanvas(KoCanvasBase *canvas)
{
m_d->resourceManagerConnections.clear();
m_d->canvas = 0;
KIS_SAFE_ASSERT_RECOVER_RETURN(!canvas || canvas->resourceManager());
KIS_SAFE_ASSERT_RECOVER_RETURN(!canvas || canvas->selectedShapesProxy());
m_d->canvas = canvas;
if (m_d->canvas) {
m_d->resourceManagerConnections.addConnection(
canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
this, SLOT(slotCanvasResourceChanged(int,QVariant)));
}
}
void KoShapeFillResourceConnector::disconnect()
{
connectToCanvas(0);
}
void KoShapeFillResourceConnector::slotCanvasResourceChanged(int key, const QVariant &value)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->canvas);
if (key == KoCanvasResourceManager::ForegroundColor) {
m_d->applyShapeColoring(KoFlake::Fill, value.value());
} else if (key == KoCanvasResourceManager::BackgroundColor) {
m_d->applyShapeColoring(KoFlake::StrokeFill, value.value());
}
}
void KoShapeFillResourceConnector::Private::applyShapeColoring(KoFlake::FillVariant fillVariant, const KoColor &color)
{
+ QList selectedEditableShapes = canvas->selectedShapesProxy()->selection()->selectedEditableShapes();
- KoShapeFillWrapper wrapper(canvas->selectedShapesProxy()->selection()->selectedEditableShapes(), fillVariant);
+ if (selectedEditableShapes.isEmpty()) {
+ return;
+ }
+
+ KoShapeFillWrapper wrapper(selectedEditableShapes, fillVariant);
KUndo2Command *command = wrapper.setColor(color.toQColor()); // TODO: do the conversion in a better way!
if (command) {
canvas->addCommand(command);
}
}
diff --git a/libs/flake/commands/KoPathPointTypeCommand.cpp b/libs/flake/commands/KoPathPointTypeCommand.cpp
index d61ac53e7b..57d4351bd7 100644
--- a/libs/flake/commands/KoPathPointTypeCommand.cpp
+++ b/libs/flake/commands/KoPathPointTypeCommand.cpp
@@ -1,224 +1,235 @@
/* This file is part of the KDE project
* Copyright (C) 2006,2008 Jan Hambrecht
* Copyright (C) 2006,2007 Thorsten Zachmann
*
* 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 "KoPathPointTypeCommand.h"
#include
#include
#include "KoPathSegment.h"
KoPathPointTypeCommand::KoPathPointTypeCommand(
const QList & pointDataList,
PointType pointType,
KUndo2Command *parent)
: KoPathBaseCommand(parent)
, m_pointType(pointType)
{
QList::const_iterator it(pointDataList.begin());
for (; it != pointDataList.end(); ++it) {
KoPathPoint *point = it->pathShape->pointByIndex(it->pointIndex);
if (point) {
PointData pointData(*it);
pointData.m_oldControlPoint1 = it->pathShape->shapeToDocument(point->controlPoint1());
pointData.m_oldControlPoint2 = it->pathShape->shapeToDocument(point->controlPoint2());
pointData.m_oldProperties = point->properties();
pointData.m_hadControlPoint1 = point->activeControlPoint1();
pointData.m_hadControlPoint2 = point->activeControlPoint2();
m_oldPointData.append(pointData);
m_shapes.insert(it->pathShape);
}
}
setText(kundo2_i18n("Set point type"));
}
KoPathPointTypeCommand::~KoPathPointTypeCommand()
{
}
void KoPathPointTypeCommand::redo()
{
KUndo2Command::redo();
repaint(false);
m_additionalPointData.clear();
QList::iterator it(m_oldPointData.begin());
for (; it != m_oldPointData.end(); ++it) {
KoPathPoint *point = it->m_pointData.pathShape->pointByIndex(it->m_pointData.pointIndex);
KoPathPoint::PointProperties properties = point->properties();
switch (m_pointType) {
case Line: {
point->removeControlPoint1();
point->removeControlPoint2();
break;
}
case Curve: {
KoPathPointIndex pointIndex = it->m_pointData.pointIndex;
KoPathPointIndex prevIndex;
KoPathPointIndex nextIndex;
KoPathShape * path = it->m_pointData.pathShape;
// get previous path node
if (pointIndex.second > 0)
prevIndex = KoPathPointIndex(pointIndex.first, pointIndex.second - 1);
else if (pointIndex.second == 0 && path->isClosedSubpath(pointIndex.first))
prevIndex = KoPathPointIndex(pointIndex.first, path->subpathPointCount(pointIndex.first) - 1);
// get next node
if (pointIndex.second < path->subpathPointCount(pointIndex.first) - 1)
nextIndex = KoPathPointIndex(pointIndex.first, pointIndex.second + 1);
else if (pointIndex.second < path->subpathPointCount(pointIndex.first) - 1
&& path->isClosedSubpath(pointIndex.first))
nextIndex = KoPathPointIndex(pointIndex.first, 0);
KoPathPoint * prevPoint = path->pointByIndex(prevIndex);
KoPathPoint * nextPoint = path->pointByIndex(nextIndex);
if (prevPoint && ! point->activeControlPoint1() && appendPointData(KoPathPointData(path, prevIndex))) {
KoPathSegment cubic = KoPathSegment(prevPoint, point).toCubic();
if (prevPoint->activeControlPoint2()) {
prevPoint->setControlPoint2(cubic.first()->controlPoint2());
point->setControlPoint1(cubic.second()->controlPoint1());
} else
point->setControlPoint1(cubic.second()->controlPoint1());
}
if (nextPoint && ! point->activeControlPoint2() && appendPointData(KoPathPointData(path, nextIndex))) {
KoPathSegment cubic = KoPathSegment(point, nextPoint).toCubic();
if (nextPoint->activeControlPoint1()) {
point->setControlPoint2(cubic.first()->controlPoint2());
nextPoint->setControlPoint1(cubic.second()->controlPoint1());
} else
point->setControlPoint2(cubic.first()->controlPoint2());
}
+ point->setProperties(properties);
break;
}
case Symmetric: {
properties &= ~KoPathPoint::IsSmooth;
properties |= KoPathPoint::IsSymmetric;
// calculate vector from node point to first control point and normalize it
QPointF directionC1 = point->controlPoint1() - point->point();
qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + directionC1.y() * directionC1.y());
directionC1 /= dirLengthC1;
// calculate vector from node point to second control point and normalize it
QPointF directionC2 = point->controlPoint2() - point->point();
qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + directionC2.y() * directionC2.y());
directionC2 /= dirLengthC2;
// calculate the average distance of the control points to the node point
qreal averageLength = 0.5 * (dirLengthC1 + dirLengthC2);
// compute position of the control points so that they lie on a line going through the node point
// the new distance of the control points is the average distance to the node point
point->setControlPoint1(point->point() + 0.5 * averageLength * (directionC1 - directionC2));
point->setControlPoint2(point->point() + 0.5 * averageLength * (directionC2 - directionC1));
+ point->setProperties(properties);
}
break;
case Smooth: {
- properties &= ~KoPathPoint::IsSymmetric;
- properties |= KoPathPoint::IsSmooth;
-
- // calculate vector from node point to first control point and normalize it
- QPointF directionC1 = point->controlPoint1() - point->point();
- qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + directionC1.y() * directionC1.y());
- directionC1 /= dirLengthC1;
- // calculate vector from node point to second control point and normalize it
- QPointF directionC2 = point->controlPoint2() - point->point();
- qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + directionC2.y() * directionC2.y());
- directionC2 /= dirLengthC2;
- // compute position of the control points so that they lie on a line going through the node point
- // the new distance of the control points is the average distance to the node point
- point->setControlPoint1(point->point() + 0.5 * dirLengthC1 * (directionC1 - directionC2));
- point->setControlPoint2(point->point() + 0.5 * dirLengthC2 * (directionC2 - directionC1));
+ makeCubicPointSmooth(point);
}
break;
case Corner:
default:
properties &= ~KoPathPoint::IsSymmetric;
properties &= ~KoPathPoint::IsSmooth;
+ point->setProperties(properties);
break;
}
- point->setProperties(properties);
}
repaint(true);
}
void KoPathPointTypeCommand::undo()
{
KUndo2Command::undo();
repaint(false);
/*
QList::iterator it(m_oldPointData.begin());
for (; it != m_oldPointData.end(); ++it)
{
KoPathShape *pathShape = it->m_pointData.pathShape;
KoPathPoint *point = pathShape->pointByIndex(it->m_pointData.pointIndex);
point->setProperties(it->m_oldProperties);
if (it->m_hadControlPoint1)
point->setControlPoint1(pathShape->documentToShape(it->m_oldControlPoint1));
else
point->removeControlPoint1();
if (it->m_hadControlPoint2)
point->setControlPoint2(pathShape->documentToShape(it->m_oldControlPoint2));
else
point->removeControlPoint2();
}
*/
undoChanges(m_oldPointData);
undoChanges(m_additionalPointData);
repaint(true);
}
+void KoPathPointTypeCommand::makeCubicPointSmooth(KoPathPoint *point)
+{
+ KoPathPoint::PointProperties properties = point->properties();
+
+ properties &= ~KoPathPoint::IsSymmetric;
+ properties |= KoPathPoint::IsSmooth;
+
+ // calculate vector from node point to first control point and normalize it
+ QPointF directionC1 = point->controlPoint1() - point->point();
+ qreal dirLengthC1 = sqrt(directionC1.x() * directionC1.x() + directionC1.y() * directionC1.y());
+ directionC1 /= dirLengthC1;
+ // calculate vector from node point to second control point and normalize it
+ QPointF directionC2 = point->controlPoint2() - point->point();
+ qreal dirLengthC2 = sqrt(directionC2.x() * directionC2.x() + directionC2.y() * directionC2.y());
+ directionC2 /= dirLengthC2;
+ // compute position of the control points so that they lie on a line going through the node point
+ // the new distance of the control points is the average distance to the node point
+ point->setControlPoint1(point->point() + 0.5 * dirLengthC1 * (directionC1 - directionC2));
+ point->setControlPoint2(point->point() + 0.5 * dirLengthC2 * (directionC2 - directionC1));
+
+ point->setProperties(properties);
+}
+
void KoPathPointTypeCommand::undoChanges(const QList &data)
{
QList::const_iterator it(data.begin());
for (; it != data.end(); ++it) {
KoPathShape *pathShape = it->m_pointData.pathShape;
KoPathPoint *point = pathShape->pointByIndex(it->m_pointData.pointIndex);
point->setProperties(it->m_oldProperties);
if (it->m_hadControlPoint1)
point->setControlPoint1(pathShape->documentToShape(it->m_oldControlPoint1));
else
point->removeControlPoint1();
if (it->m_hadControlPoint2)
point->setControlPoint2(pathShape->documentToShape(it->m_oldControlPoint2));
else
point->removeControlPoint2();
}
}
bool KoPathPointTypeCommand::appendPointData(KoPathPointData data)
{
KoPathPoint *point = data.pathShape->pointByIndex(data.pointIndex);
if (! point)
return false;
PointData pointData(data);
pointData.m_oldControlPoint1 = data.pathShape->shapeToDocument(point->controlPoint1());
pointData.m_oldControlPoint2 = data.pathShape->shapeToDocument(point->controlPoint2());
pointData.m_oldProperties = point->properties();
pointData.m_hadControlPoint1 = point->activeControlPoint1();
pointData.m_hadControlPoint2 = point->activeControlPoint2();
m_additionalPointData.append(pointData);
return true;
}
diff --git a/libs/flake/commands/KoPathPointTypeCommand.h b/libs/flake/commands/KoPathPointTypeCommand.h
index 849ec8b804..f025a2314f 100644
--- a/libs/flake/commands/KoPathPointTypeCommand.h
+++ b/libs/flake/commands/KoPathPointTypeCommand.h
@@ -1,79 +1,81 @@
/* This file is part of the KDE project
* Copyright (C) 2006,2008 Jan Hambrecht
* Copyright (C) 2006,2007 Thorsten Zachmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KOPATHPOINTTYPECOMMAND_H
#define KOPATHPOINTTYPECOMMAND_H
#include
#include
#include "KoPathBaseCommand.h"
#include "KoPathPoint.h"
#include "KoPathPointData.h"
#include "kritaflake_export.h"
/// The undo / redo command for changing the path point type.
class KRITAFLAKE_EXPORT KoPathPointTypeCommand : public KoPathBaseCommand
{
public:
/// The type of the point
enum PointType {
Corner,
Smooth,
Symmetric,
Line,
Curve
};
/**
* Command to change the type of the given points
* @param pointDataList List of point for changing the points
* @param pointType the new point type to set
* @param parent the parent command used for macro commands
*/
KoPathPointTypeCommand(const QList &pointDataList, PointType pointType, KUndo2Command *parent = 0);
~KoPathPointTypeCommand() override;
/// redo the command
void redo() override;
/// revert the actions done in redo
void undo() override;
+ static void makeCubicPointSmooth(KoPathPoint *point);
+
private:
// used for storing the data for undo
struct PointData {
PointData(const KoPathPointData pointData)
: m_pointData(pointData) {}
KoPathPointData m_pointData;
// old control points in document coordinates
QPointF m_oldControlPoint1;
QPointF m_oldControlPoint2;
KoPathPoint::PointProperties m_oldProperties;
bool m_hadControlPoint1;
bool m_hadControlPoint2;
};
bool appendPointData(KoPathPointData data);
void undoChanges(const QList &data);
PointType m_pointType;
QList m_oldPointData;
QList m_additionalPointData;
};
#endif // KOPATHPOINTTYPECOMMAND_H
diff --git a/libs/flake/resources/KoGamutMask.cpp b/libs/flake/resources/KoGamutMask.cpp
new file mode 100644
index 0000000000..80fd9de3f6
--- /dev/null
+++ b/libs/flake/resources/KoGamutMask.cpp
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2018 Anna Medonosova
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "KoGamutMask.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+KoGamutMaskShape::KoGamutMaskShape(KoShape* shape)
+ : m_maskShape(shape)
+ , m_shapePaintingContext(KoShapePaintingContext())
+{
+}
+
+KoGamutMaskShape::KoGamutMaskShape() {};
+KoGamutMaskShape::~KoGamutMaskShape() {};
+
+KoShape* KoGamutMaskShape::koShape()
+{
+ return m_maskShape;
+}
+
+bool KoGamutMaskShape::coordIsClear(const QPointF& coord, const KoViewConverter& viewConverter) const
+{
+ QPointF translatedPoint = viewConverter.viewToDocument(coord);
+
+ bool isClear = m_maskShape->hitTest(translatedPoint);
+
+ return isClear;
+}
+
+void KoGamutMaskShape::paint(QPainter &painter, const KoViewConverter& viewConverter)
+{
+ painter.save();
+ painter.setTransform(m_maskShape->absoluteTransformation(&viewConverter) * painter.transform());
+ m_maskShape->paint(painter, viewConverter, m_shapePaintingContext);
+ painter.restore();
+}
+
+void KoGamutMaskShape::paintStroke(QPainter &painter, const KoViewConverter &viewConverter)
+{
+ painter.save();
+ painter.setTransform(m_maskShape->absoluteTransformation(&viewConverter) * painter.transform());
+ m_maskShape->paintStroke(painter, viewConverter, m_shapePaintingContext);
+ painter.restore();
+
+}
+
+struct Q_DECL_HIDDEN KoGamutMask::Private {
+ QString name;
+ QString title;
+ QString description;
+ QByteArray data;
+ QVector maskShapes;
+ QVector previewShapes;
+ QSizeF maskSize;
+};
+
+KoGamutMask::KoGamutMask(const QString& filename)
+ : KoResource(filename)
+ , d(new Private())
+{
+ d->maskSize = QSizeF(144.0,144.0);
+}
+
+KoGamutMask::KoGamutMask()
+ : KoResource(QString())
+ , d(new Private())
+{
+ d->maskSize = QSizeF(144.0,144.0);
+}
+
+KoGamutMask::KoGamutMask(KoGamutMask* rhs)
+ : QObject(0)
+ , KoResource(QString())
+ , d(new Private())
+{
+ setFilename(rhs->filename());
+ setTitle(rhs->title());
+ setDescription(rhs->description());
+ d->maskSize = rhs->d->maskSize;
+
+ QList newShapes;
+ for(KoShape* sh: rhs->koShapes()) {
+ newShapes.append(sh->cloneShape());
+ }
+
+ setMaskShapes(newShapes);
+
+ setValid(true);
+}
+
+
+bool KoGamutMask::coordIsClear(const QPointF& coord, KoViewConverter &viewConverter, bool preview)
+{
+ QVector* shapeVector;
+
+ if (preview && !d->previewShapes.isEmpty()) {
+ shapeVector = &d->previewShapes;
+ } else {
+ shapeVector = &d->maskShapes;
+ }
+
+ for(KoGamutMaskShape* shape: *shapeVector) {
+ if (shape->coordIsClear(coord, viewConverter) == true) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void KoGamutMask::paint(QPainter &painter, KoViewConverter& viewConverter, bool preview)
+{
+ QVector* shapeVector;
+
+ if (preview && !d->previewShapes.isEmpty()) {
+ shapeVector = &d->previewShapes;
+ } else {
+ shapeVector = &d->maskShapes;
+ }
+
+ for(KoGamutMaskShape* shape: *shapeVector) {
+ shape->paint(painter, viewConverter);
+ }
+}
+
+void KoGamutMask::paintStroke(QPainter &painter, KoViewConverter &viewConverter, bool preview)
+{
+ QVector* shapeVector;
+
+ if (preview && !d->previewShapes.isEmpty()) {
+ shapeVector = &d->previewShapes;
+ } else {
+ shapeVector = &d->maskShapes;
+ }
+
+ for(KoGamutMaskShape* shape: *shapeVector) {
+ shape->paintStroke(painter, viewConverter);
+ }
+}
+
+bool KoGamutMask::load()
+{
+ QFile file(filename());
+ if (file.size() == 0) return false;
+ if (!file.open(QIODevice::ReadOnly)) {
+ warnFlake << "Can't open file " << filename();
+ return false;
+ }
+ bool res = loadFromDevice(&file);
+ file.close();
+ return res;
+}
+
+bool KoGamutMask::loadFromDevice(QIODevice *dev)
+{
+ if (!dev->isOpen()) dev->open(QIODevice::ReadOnly);
+
+ d->data = dev->readAll();
+
+ // TODO: test
+ KIS_ASSERT_RECOVER_RETURN_VALUE(d->data.size() != 0, false);
+
+ if (filename().isNull()) {
+ warnFlake << "Cannot load gamut mask" << name() << "there is no filename set";
+ return false;
+ }
+
+ if (d->data.isNull()) {
+ QFile file(filename());
+ if (file.size() == 0) {
+ warnFlake << "Cannot load gamut mask" << name() << "there is no data available";
+ return false;
+ }
+
+ file.open(QIODevice::ReadOnly);
+ d->data = file.readAll();
+ file.close();
+ }
+
+ QBuffer buf(&d->data);
+ buf.open(QBuffer::ReadOnly);
+
+ KoStore* store(KoStore::createStore(&buf, KoStore::Read, "application/x-krita-gamutmask", KoStore::Zip));
+ if (!store || store->bad()) return false;
+
+ bool storeOpened = store->open("gamutmask.svg");
+ if (!storeOpened) { return false; }
+
+ QByteArray data;
+ data.resize(store->size());
+ QByteArray ba = store->read(store->size());
+ store->close();
+
+ KoXmlDocument xmlDocument;
+ QString errorMsg;
+ int errorLine = 0;
+ int errorColumn = 0;
+
+ bool ok = xmlDocument.setContent(ba, false, &errorMsg, &errorLine, &errorColumn);
+ if (!ok) {
+
+ errorFlake << "Parsing error in " << filename() << "! Aborting!" << endl
+ << " In line: " << errorLine << ", column: " << errorColumn << endl
+ << " Error message: " << errorMsg << endl;
+ errorFlake << "Parsing error in the main document at line" << errorLine
+ << ", column" << errorColumn << endl
+ << "Error message: " << errorMsg;
+
+ return false;
+ }
+
+ KoDocumentResourceManager manager;
+ SvgParser parser(&manager);
+ parser.setResolution(QRectF(0,0,100,100), 72); // initialize with default values
+ QSizeF fragmentSize;
+
+ QList shapes = parser.parseSvg(xmlDocument.documentElement(), &fragmentSize);
+
+ d->maskSize = fragmentSize;
+
+ d->title = parser.documentTitle();
+ setName(d->title);
+ d->description = parser.documentDescription();
+
+ setMaskShapes(shapes);
+
+ if (store->open("preview.png")) {
+ KoStoreDevice previewDev(store);
+ previewDev.open(QIODevice::ReadOnly);
+
+ QImage preview = QImage();
+ preview.load(&previewDev, "PNG");
+ setImage(preview);
+
+ (void)store->close();
+ }
+
+ buf.close();
+
+ setValid(true);
+
+ return true;
+}
+
+void KoGamutMask::setMaskShapes(QList shapes)
+{
+ setMaskShapesToVector(shapes, d->maskShapes);
+}
+
+bool KoGamutMask::save()
+{
+ QFile file(filename());
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ return false;
+ }
+ saveToDevice(&file);
+ file.close();
+
+ return true;
+}
+
+QList KoGamutMask::koShapes() const
+{
+ QList shapes;
+ for(KoGamutMaskShape* maskShape: d->maskShapes) {
+ shapes.append(maskShape->koShape());
+ }
+
+ return shapes;
+}
+
+bool KoGamutMask::saveToDevice(QIODevice *dev) const
+{
+ KoStore* store(KoStore::createStore(dev, KoStore::Write, "application/x-krita-gamutmask", KoStore::Zip));
+ if (!store || store->bad()) return false;
+
+ QList shapes = koShapes();
+
+ std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex);
+
+ if (!store->open("gamutmask.svg")) {
+ return false;
+ }
+
+ KoStoreDevice storeDev(store);
+ storeDev.open(QIODevice::WriteOnly);
+
+ SvgWriter writer(shapes);
+ writer.setDocumentTitle(d->title);
+ writer.setDocumentDescription(d->description);
+
+ writer.save(storeDev, d->maskSize);
+
+ if (!store->close()) { return false; }
+
+
+ if (!store->open("preview.png")) {
+ return false;
+ }
+
+ KoStoreDevice previewDev(store);
+ previewDev.open(QIODevice::WriteOnly);
+
+ image().save(&previewDev, "PNG");
+ if (!store->close()) { return false; }
+
+ return store->finalize();
+}
+
+QString KoGamutMask::title()
+{
+ return d->title;
+}
+
+void KoGamutMask::setTitle(QString title)
+{
+ d->title = title;
+ setName(title);
+}
+
+QString KoGamutMask::description()
+{
+ return d->description;
+}
+
+void KoGamutMask::setDescription(QString description)
+{
+ d->description = description;
+}
+
+QSizeF KoGamutMask::maskSize()
+{
+ return d->maskSize;
+}
+
+void KoGamutMask::setPreviewMaskShapes(QList shapes)
+{
+ setMaskShapesToVector(shapes, d->previewShapes);
+}
+
+void KoGamutMask::setMaskShapesToVector(QList shapes, QVector &targetVector)
+{
+ targetVector.clear();
+
+ for(KoShape* sh: shapes) {
+ KoGamutMaskShape* maskShape = new KoGamutMaskShape(sh);
+ targetVector.append(maskShape);
+ }
+}
+
+// clean up when ending mask preview
+void KoGamutMask::clearPreview()
+{
+ d->previewShapes.clear();
+}
diff --git a/libs/flake/resources/KoGamutMask.h b/libs/flake/resources/KoGamutMask.h
new file mode 100644
index 0000000000..e55af16541
--- /dev/null
+++ b/libs/flake/resources/KoGamutMask.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018 Anna Medonosova
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KOGAMUTMASK_H
+#define KOGAMUTMASK_H
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+class KoViewConverter;
+
+class KoGamutMaskShape
+{
+public:
+ KoGamutMaskShape(KoShape* shape);
+ KoGamutMaskShape();
+ ~KoGamutMaskShape();
+
+ bool coordIsClear(const QPointF& coord, const KoViewConverter& viewConverter) const;
+ QPainterPath outline();
+ void paint(QPainter &painter, const KoViewConverter& viewConverter);
+ void paintStroke(QPainter &painter, const KoViewConverter& viewConverter);
+ KoShape* koShape();
+
+private:
+ KoShape* m_maskShape;
+ KoShapePaintingContext m_shapePaintingContext;
+};
+
+
+/**
+ * @brief The resource type for gamut masks used by the artistic color selector
+ */
+class KRITAFLAKE_EXPORT KoGamutMask : public QObject, public KoResource
+{
+ Q_OBJECT
+
+public:
+ KoGamutMask(const QString &filename);
+ KoGamutMask();
+ KoGamutMask(KoGamutMask *rhs);
+
+ bool coordIsClear(const QPointF& coord, KoViewConverter& viewConverter, bool preview);
+
+ bool load() override __attribute__((optimize(0)));
+ bool loadFromDevice(QIODevice *dev) override;
+ bool save() override;
+ bool saveToDevice(QIODevice* dev) const override;
+
+ void paint(QPainter &painter, KoViewConverter& viewConverter, bool preview);
+ void paintStroke(QPainter &painter, KoViewConverter& viewConverter, bool preview);
+
+ QString title();
+ void setTitle(QString title);
+
+ QString description();
+ void setDescription(QString description);
+
+ QSizeF maskSize();
+
+ void setMaskShapes(QList shapes);
+ void setPreviewMaskShapes(QList shapes);
+
+ QList koShapes() const;
+
+ void clearPreview();
+
+private:
+ void setMaskShapesToVector(QList shapes, QVector& targetVector);
+
+ struct Private;
+ Private* const d;
+};
+
+#endif // KOGAMUTMASK_H
diff --git a/libs/flake/svg/SvgWriter.cpp b/libs/flake/svg/SvgWriter.cpp
index 9cdf82133e..2e139c5bfd 100644
--- a/libs/flake/svg/SvgWriter.cpp
+++ b/libs/flake/svg/SvgWriter.cpp
@@ -1,302 +1,321 @@
/* This file is part of the KDE project
Copyright (C) 2002 Lars Siebold
Copyright (C) 2002-2003,2005 Rob Buis
Copyright (C) 2002,2005-2006 David Faure
Copyright (C) 2002 Werner Trobin
Copyright (C) 2002 Lennart Kudling
Copyright (C) 2004 Nicolas Goutte
Copyright (C) 2005 Boudewijn Rempt
Copyright (C) 2005 Raphael Langerhorst
Copyright (C) 2005 Thomas Zander
Copyright (C) 2005,2007-2008 Jan Hambrecht
Copyright (C) 2006 Inge Wallin
Copyright (C) 2006 Martin Pfeiffer
Copyright (C) 2006 Gábor Lehel
Copyright (C) 2006 Laurent Montel
Copyright (C) 2006 Christian Mueller
Copyright (C) 2006 Ariya Hidayat
Copyright (C) 2010 Thorsten Zachmann
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 "SvgWriter.h"
#include "SvgUtil.h"
#include "SvgSavingContext.h"
#include "SvgShape.h"
#include "SvgStyleWriter.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
SvgWriter::SvgWriter(const QList &layers)
: m_writeInlineImages(true)
{
Q_FOREACH (KoShapeLayer *layer, layers)
m_toplevelShapes.append(layer);
}
SvgWriter::SvgWriter(const QList &toplevelShapes)
: m_toplevelShapes(toplevelShapes)
, m_writeInlineImages(true)
{
}
SvgWriter::~SvgWriter()
{
}
bool SvgWriter::save(const QString &filename, const QSizeF &pageSize, bool writeInlineImages)
{
QFile fileOut(filename);
if (!fileOut.open(QIODevice::WriteOnly))
return false;
m_writeInlineImages = writeInlineImages;
const bool success = save(fileOut, pageSize);
m_writeInlineImages = true;
fileOut.close();
return success;
}
bool SvgWriter::save(QIODevice &outputDevice, const QSizeF &pageSize)
{
if (m_toplevelShapes.isEmpty()) {
return false;
}
QTextStream svgStream(&outputDevice);
svgStream.setCodec("UTF-8");
// standard header:
svgStream << "" << endl;
svgStream << "" << endl;
// add some PR. one line is more than enough.
svgStream << "" << endl;
svgStream << "" << endl;
return true;
}
bool SvgWriter::saveDetached(QIODevice &outputDevice)
{
if (m_toplevelShapes.isEmpty())
return false;
SvgSavingContext savingContext(outputDevice, m_writeInlineImages);
saveShapes(m_toplevelShapes, savingContext);
return true;
}
bool SvgWriter::saveDetached(SvgSavingContext &savingContext)
{
if (m_toplevelShapes.isEmpty())
return false;
saveShapes(m_toplevelShapes, savingContext);
return true;
}
void SvgWriter::saveShapes(const QList shapes, SvgSavingContext &savingContext)
{
// top level shapes
Q_FOREACH (KoShape *shape, shapes) {
KoShapeLayer *layer = dynamic_cast(shape);
if(layer) {
saveLayer(layer, savingContext);
} else {
KoShapeGroup *group = dynamic_cast(shape);
if (group)
saveGroup(group, savingContext);
else
saveShape(shape, savingContext);
}
}
}
void SvgWriter::saveLayer(KoShapeLayer *layer, SvgSavingContext &context)
{
context.shapeWriter().startElement("g");
context.shapeWriter().addAttribute("id", context.getID(layer));
QList sortedShapes = layer->shapes();
std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
Q_FOREACH (KoShape * shape, sortedShapes) {
KoShapeGroup * group = dynamic_cast(shape);
if (group)
saveGroup(group, context);
else
saveShape(shape, context);
}
context.shapeWriter().endElement();
}
void SvgWriter::saveGroup(KoShapeGroup * group, SvgSavingContext &context)
{
context.shapeWriter().startElement("g");
context.shapeWriter().addAttribute("id", context.getID(group));
SvgUtil::writeTransformAttributeLazy("transform", group->transformation(), context.shapeWriter());
SvgStyleWriter::saveSvgStyle(group, context);
QList sortedShapes = group->shapes();
std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
Q_FOREACH (KoShape * shape, sortedShapes) {
KoShapeGroup * childGroup = dynamic_cast(shape);
if (childGroup)
saveGroup(childGroup, context);
else
saveShape(shape, context);
}
context.shapeWriter().endElement();
}
void SvgWriter::saveShape(KoShape *shape, SvgSavingContext &context)
{
SvgShape *svgShape = dynamic_cast(shape);
if (svgShape && svgShape->saveSvg(context))
return;
KoPathShape * path = dynamic_cast(shape);
if (path) {
savePath(path, context);
} else {
// generic saving of shape via a switch element
saveGeneric(shape, context);
}
}
void SvgWriter::savePath(KoPathShape *path, SvgSavingContext &context)
{
context.shapeWriter().startElement("path");
context.shapeWriter().addAttribute("id", context.getID(path));
SvgUtil::writeTransformAttributeLazy("transform", path->transformation(), context.shapeWriter());
SvgStyleWriter::saveSvgStyle(path, context);
context.shapeWriter().addAttribute("d", path->toString(context.userSpaceTransform()));
context.shapeWriter().endElement();
}
void SvgWriter::saveGeneric(KoShape *shape, SvgSavingContext &context)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(shape);
const QRectF bbox = shape->boundingRect();
// paint shape to the image
KoShapePainter painter;
painter.setShapes(QList()<< shape);
// generate svg from shape
QBuffer svgBuffer;
QSvgGenerator svgGenerator;
svgGenerator.setOutputDevice(&svgBuffer);
/**
* HACK ALERT: Qt (and Krita 3.x) has a weird bug, it assumes that all font sizes are
* defined in 96 ppi resolution, even though your the resolution in QSvgGenerator
* is manually set to 72 ppi. So here we do a tricky thing: we set a fake resolution
* to (72 * 72 / 96) = 54 ppi, which guarantees that the text, when painted in 96 ppi,
* will be actually painted in 72 ppi.
*
* BUG: 389802
*/
if (shape->shapeId() == "TextShapeID") {
svgGenerator.setResolution(54);
}
QPainter svgPainter;
svgPainter.begin(&svgGenerator);
painter.paint(svgPainter, SvgUtil::toUserSpace(bbox).toRect(), bbox);
svgPainter.end();
// remove anything before the start of the svg element from the buffer
int startOfContent = svgBuffer.buffer().indexOf("