Просмотр исходного кода

Merge pull request #134 from bgrabitmap/dev-lazpaint

Dev lazpaint 7.0.9
circular17 5 лет назад
Родитель
Сommit
8892e25752
88 измененных файлов с 5227 добавлено и 2108 удалено
  1. 1 0
      lazpaint/dialog/filter/umotionblur.pas
  2. 23 24
      lazpaint/dialog/filter/uradialblur.lfm
  3. 1 0
      lazpaint/dialog/filter/uradialblur.pas
  4. 29 10
      lazpaint/dialog/ubrowseimages.pas
  5. 10 6
      lazpaint/dialog/uchoosecolorinterface.pas
  6. 9 4
      lazpaint/image/uimage.pas
  7. 32 10
      lazpaint/image/uimageaction.pas
  8. 71 5
      lazpaint/image/uimagediff.pas
  9. 2 8
      lazpaint/lazpaint.lpi
  10. 11 0
      lazpaint/lazpaintdialogs.inc
  11. 1 1
      lazpaint/lazpaintembeddedpack.lpk
  12. 68 26
      lazpaint/lazpaintinstance.pas
  13. 64 9
      lazpaint/lazpaintmainform.lfm
  14. 76 35
      lazpaint/lazpaintmainform.pas
  15. 48 17
      lazpaint/lazpainttype.pas
  16. 120 155
      lazpaint/maintoolbar.inc
  17. 5 1
      lazpaint/release/bin/i18n/lazpaint.ar.po
  18. 126 168
      lazpaint/release/bin/i18n/lazpaint.bg.po
  19. 5 1
      lazpaint/release/bin/i18n/lazpaint.cs.po
  20. 5 1
      lazpaint/release/bin/i18n/lazpaint.de.po
  21. 5 1
      lazpaint/release/bin/i18n/lazpaint.es.po
  22. 5 1
      lazpaint/release/bin/i18n/lazpaint.fi.po
  23. 5 1
      lazpaint/release/bin/i18n/lazpaint.fr.po
  24. 5 1
      lazpaint/release/bin/i18n/lazpaint.ja.po
  25. 133 134
      lazpaint/release/bin/i18n/lazpaint.kab.po
  26. 171 166
      lazpaint/release/bin/i18n/lazpaint.lv.po
  27. 6 2
      lazpaint/release/bin/i18n/lazpaint.nl.po
  28. 5 1
      lazpaint/release/bin/i18n/lazpaint.po
  29. 6 2
      lazpaint/release/bin/i18n/lazpaint.pt_BR.po
  30. 5 1
      lazpaint/release/bin/i18n/lazpaint.ru.po
  31. 5 1
      lazpaint/release/bin/i18n/lazpaint.sv.po
  32. 6 2
      lazpaint/release/bin/i18n/lazpaint.zh_CN.po
  33. 174 173
      lazpaint/release/bin/i18n/lclstrconsts.kab.po
  34. 180 171
      lazpaint/release/bin/i18n/lcresourcestring.bg.po
  35. 180 171
      lazpaint/release/bin/i18n/lcresourcestring.kab.po
  36. 35 26
      lazpaint/release/bin/i18n/lcresourcestring.lv.po
  37. 28 0
      lazpaint/release/changelog
  38. 28 0
      lazpaint/release/debian/linux32/DEBIAN/changelog
  39. 1 1
      lazpaint/release/debian/linux32/DEBIAN/control
  40. 28 0
      lazpaint/release/debian/linux64/DEBIAN/changelog
  41. 1 1
      lazpaint/release/debian/linux64/DEBIAN/control
  42. 2 2
      lazpaint/release/macOS/LazPaint.app/Contents/Info.plist
  43. 1 1
      lazpaint/release/macOS/makedmg.sh
  44. 1 1
      lazpaint/release/windows/lazpaint.iss
  45. 18 2
      lazpaint/release/windows/stage.bat
  46. 242 72
      lazpaint/tools/utool.pas
  47. 11 1
      lazpaint/tools/utooldeformationgrid.pas
  48. 103 36
      lazpaint/tools/utoolfloodfill.pas
  49. 26 11
      lazpaint/tools/utoollayer.pas
  50. 3 3
      lazpaint/tools/utoolphong.pas
  51. 19 34
      lazpaint/tools/utoolpolygon.pas
  52. 7 7
      lazpaint/tools/utoolselect.pas
  53. 41 77
      lazpaint/tools/utooltext.pas
  54. 258 156
      lazpaint/tools/utoolvectorial.pas
  55. 1 4
      lazpaint/ucommandline.pas
  56. 25 1
      lazpaint/uconfig.pas
  57. 31 0
      lazpaint/ufileextensions.pas
  58. 39 21
      lazpaint/uimageview.pas
  59. 72 49
      lazpaint/umainformlayout.pas
  60. 45 9
      lazpaint/umenu.pas
  61. 1 0
      lazpaint/upalettetoolbar.pas
  62. 1 1
      lazpaint/upython.pas
  63. 2 1
      lazpaint/uresourcestrings.pas
  64. 8 7
      lazpaintcontrols/lazpaintcontrols.lpk
  65. 1 1
      lazpaintcontrols/lazpaintcontrols.pas
  66. 24 7
      lazpaintcontrols/lcvectorclipboard.pas
  67. 35 5
      lazpaintcontrols/lcvectorialfill.pas
  68. 3 3
      lazpaintcontrols/lcvectorialfillinterface.pas
  69. 1018 0
      lazpaintcontrols/lcvectormultishape.pas
  70. 423 112
      lazpaintcontrols/lcvectororiginal.pas
  71. 51 31
      lazpaintcontrols/lcvectorpolyshapes.pas
  72. 126 86
      lazpaintcontrols/lcvectorrectshapes.pas
  73. 50 16
      lazpaintcontrols/lcvectortextshapes.pas
  74. 1 1
      scripts/channels_merge.py
  75. 1 1
      scripts/channels_split_hsl.py
  76. 1 1
      scripts/channels_split_rgb.py
  77. 10 0
      scripts/display_version.py
  78. 1 1
      scripts/layerfx_color_overlay.py
  79. 261 0
      scripts/layerfx_innerlight.py
  80. 261 0
      scripts/layerfx_innershadow.py
  81. 7 7
      scripts/layerfx_shadow.py
  82. 215 0
      scripts/layerfx_stroke.py
  83. 2 0
      scripts/lazpaint/command.py
  84. 45 0
      scripts/lazpaint/tools.py
  85. 12 0
      scripts/mask_from_alpha.py
  86. 1 1
      scripts/mask_new.py
  87. 1 1
      scripts/render_fractal_tree.py
  88. 1 1
      scripts/render_lava.py

+ 1 - 0
lazpaint/dialog/filter/umotionblur.pas

@@ -218,6 +218,7 @@ begin
   InPaintBoxMouseMove := false;
   InPaintBoxMouseMove := false;
   CheckOKCancelBtns(Button_OK{,Button_Cancel});
   CheckOKCancelBtns(Button_OK{,Button_Cancel});
   CheckFloatSpinEdit(SpinEdit_Distance);
   CheckFloatSpinEdit(SpinEdit_Distance);
+  SpinEdit_Distance.Constraints.MinWidth := DoScaleX(70, OriginalDPI);
 end;
 end;
 
 
 procedure TFMotionBlur.FormShow(Sender: TObject);
 procedure TFMotionBlur.FormShow(Sender: TObject);

+ 23 - 24
lazpaint/dialog/filter/uradialblur.lfm

@@ -1,6 +1,6 @@
 object FRadialBlur: TFRadialBlur
 object FRadialBlur: TFRadialBlur
   Left = 403
   Left = 403
-  Height = 70
+  Height = 82
   Top = 328
   Top = 328
   Width = 175
   Width = 175
   AutoSize = True
   AutoSize = True
@@ -13,43 +13,42 @@ object FRadialBlur: TFRadialBlur
   ChildSizing.VerticalSpacing = 8
   ChildSizing.VerticalSpacing = 8
   ChildSizing.Layout = cclLeftToRightThenTopToBottom
   ChildSizing.Layout = cclLeftToRightThenTopToBottom
   ChildSizing.ControlsPerLine = 1
   ChildSizing.ControlsPerLine = 1
-  ClientHeight = 70
+  ClientHeight = 82
   ClientWidth = 175
   ClientWidth = 175
   Font.Height = -12
   Font.Height = -12
   OnCloseQuery = FormCloseQuery
   OnCloseQuery = FormCloseQuery
   OnCreate = FormCreate
   OnCreate = FormCreate
   OnShow = FormShow
   OnShow = FormShow
   Position = poOwnerFormCenter
   Position = poOwnerFormCenter
-  LCLVersion = '1.6.0.4'
+  LCLVersion = '2.0.2.0'
   object Panel1: TPanel
   object Panel1: TPanel
     Left = 8
     Left = 8
-    Height = 23
+    Height = 27
     Top = 8
     Top = 8
-    Width = 114
+    Width = 126
     BevelOuter = bvNone
     BevelOuter = bvNone
     ChildSizing.HorizontalSpacing = 8
     ChildSizing.HorizontalSpacing = 8
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.ControlsPerLine = 2
     ChildSizing.ControlsPerLine = 2
-    ClientHeight = 23
-    ClientWidth = 114
+    ClientHeight = 27
+    ClientWidth = 126
     TabOrder = 0
     TabOrder = 0
     object Label_Radius: TLabel
     object Label_Radius: TLabel
       Left = 0
       Left = 0
-      Height = 23
+      Height = 27
       Top = 0
       Top = 0
-      Width = 41
+      Width = 48
       Caption = 'Radius :'
       Caption = 'Radius :'
       Layout = tlCenter
       Layout = tlCenter
       ParentColor = False
       ParentColor = False
     end
     end
     object SpinEdit_Radius: TFloatSpinEdit
     object SpinEdit_Radius: TFloatSpinEdit
-      Left = 49
-      Height = 23
+      Left = 56
+      Height = 27
       Top = 0
       Top = 0
-      Width = 65
-      Constraints.MinWidth = 65
+      Width = 70
+      Constraints.MinWidth = 70
       DecimalPlaces = 1
       DecimalPlaces = 1
-      Increment = 1
       MaxValue = 1000
       MaxValue = 1000
       MinValue = 0.1
       MinValue = 0.1
       OnChange = SpinEdit_RadiusChange
       OnChange = SpinEdit_RadiusChange
@@ -59,21 +58,21 @@ object FRadialBlur: TFRadialBlur
   end
   end
   object Panel2: TPanel
   object Panel2: TPanel
     Left = 8
     Left = 8
-    Height = 25
-    Top = 39
-    Width = 114
+    Height = 29
+    Top = 43
+    Width = 126
     BevelOuter = bvNone
     BevelOuter = bvNone
     ChildSizing.HorizontalSpacing = 8
     ChildSizing.HorizontalSpacing = 8
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.ControlsPerLine = 2
     ChildSizing.ControlsPerLine = 2
-    ClientHeight = 25
-    ClientWidth = 114
+    ClientHeight = 29
+    ClientWidth = 126
     TabOrder = 1
     TabOrder = 1
     object Button_OK: TButton
     object Button_OK: TButton
       Left = 0
       Left = 0
-      Height = 25
+      Height = 29
       Top = 0
       Top = 0
-      Width = 42
+      Width = 31
       AutoSize = True
       AutoSize = True
       Caption = 'OK'
       Caption = 'OK'
       Default = True
       Default = True
@@ -81,10 +80,10 @@ object FRadialBlur: TFRadialBlur
       TabOrder = 0
       TabOrder = 0
     end
     end
     object Button_Cancel: TButton
     object Button_Cancel: TButton
-      Left = 50
-      Height = 25
+      Left = 39
+      Height = 29
       Top = 0
       Top = 0
-      Width = 62
+      Width = 54
       AutoSize = True
       AutoSize = True
       Cancel = True
       Cancel = True
       Caption = 'Cancel'
       Caption = 'Cancel'

+ 1 - 0
lazpaint/dialog/filter/uradialblur.pas

@@ -95,6 +95,7 @@ begin
   blurType := rbNormal;
   blurType := rbNormal;
   CheckOKCancelBtns(Button_OK{,Button_Cancel});
   CheckOKCancelBtns(Button_OK{,Button_Cancel});
   CheckFloatSpinEdit(SpinEdit_Radius);
   CheckFloatSpinEdit(SpinEdit_Radius);
+  SpinEdit_Radius.Constraints.MinWidth := DoScaleX(70, OriginalDPI);
 end;
 end;
 
 
 procedure TFRadialBlur.FormShow(Sender: TObject);
 procedure TFRadialBlur.FormShow(Sender: TObject);

+ 29 - 10
lazpaint/dialog/ubrowseimages.pas

@@ -105,6 +105,7 @@ type
     function GetInitialFilename: string;
     function GetInitialFilename: string;
     function GetOpenLayerIcon: boolean;
     function GetOpenLayerIcon: boolean;
     function GetRememberStartDirectory: boolean;
     function GetRememberStartDirectory: boolean;
+    procedure SetDefaultExtensions(AValue: string);
     procedure SetFileExtensionFilter(AValue: string);
     procedure SetFileExtensionFilter(AValue: string);
     procedure SetFilterIndex(AValue: integer);
     procedure SetFilterIndex(AValue: integer);
     procedure SetInitialFilename(AValue: string);
     procedure SetInitialFilename(AValue: string);
@@ -134,6 +135,7 @@ type
     procedure SetShellMask;
     procedure SetShellMask;
     procedure DeleteSelectedFiles;
     procedure DeleteSelectedFiles;
     procedure SelectFile(AName: string);
     procedure SelectFile(AName: string);
+    procedure SelectDefaultExtensions;
     procedure PreviewValidate({%H-}ASender: TObject);
     procedure PreviewValidate({%H-}ASender: TObject);
     property CurrentFullname: string read GetCurrentFullname;
     property CurrentFullname: string read GetCurrentFullname;
     property CurrentDirectory: string read GetCurrentDirectory write SetCurrentDirectory;
     property CurrentDirectory: string read GetCurrentDirectory write SetCurrentDirectory;
@@ -151,7 +153,7 @@ type
     property IsSaveDialog: boolean read FIsSaveDialog write SetIsSaveDialog;
     property IsSaveDialog: boolean read FIsSaveDialog write SetIsSaveDialog;
     property OverwritePrompt: boolean read FOverwritePrompt write FOverwritePrompt;
     property OverwritePrompt: boolean read FOverwritePrompt write FOverwritePrompt;
     property DefaultExtension: string read FDefaultExtension write FDefaultExtension;
     property DefaultExtension: string read FDefaultExtension write FDefaultExtension;
-    property DefaultExtensions: string read FDefaultExtensions write FDefaultExtensions;
+    property DefaultExtensions: string read FDefaultExtensions write SetDefaultExtensions;
     property InitialFilename: string read GetInitialFilename write SetInitialFilename;
     property InitialFilename: string read GetInitialFilename write SetInitialFilename;
     property CurrentExtensionFilter: string read GetCurrentExtensionFilter;
     property CurrentExtensionFilter: string read GetCurrentExtensionFilter;
     property Filter: string read FFileExtensionFilter write SetFileExtensionFilter;
     property Filter: string read FFileExtensionFilter write SetFileExtensionFilter;
@@ -427,15 +429,6 @@ begin
   FreeAndNil(FChosenImage.bmp);
   FreeAndNil(FChosenImage.bmp);
   UpdatePreview;
   UpdatePreview;
   UpdateToolButtonOpen;
   UpdateToolButtonOpen;
-  if (FDefaultExtensions<>'') and (ComboBox_FileExtension.ItemIndex = -1) then
-  begin
-    for i := 0 to high(FFileExtensions) do
-      if FFileExtensions[i] = FDefaultExtensions then
-      begin
-        ComboBox_FileExtension.ItemIndex := i;
-        break;
-      end;
-  end;
   if IsSaveDialog then
   if IsSaveDialog then
   begin
   begin
     If not AdaptExtension then
     If not AdaptExtension then
@@ -761,6 +754,13 @@ begin
   result := CheckBox_UseDirectoryOnStartup.Checked;
   result := CheckBox_UseDirectoryOnStartup.Checked;
 end;
 end;
 
 
+procedure TFBrowseImages.SetDefaultExtensions(AValue: string);
+begin
+  if FDefaultExtensions=AValue then Exit;
+  FDefaultExtensions:=AValue;
+  SelectDefaultExtensions;
+end;
+
 procedure TFBrowseImages.SetFileExtensionFilter(AValue: string);
 procedure TFBrowseImages.SetFileExtensionFilter(AValue: string);
 begin
 begin
   if FFileExtensionFilter=AValue then Exit;
   if FFileExtensionFilter=AValue then Exit;
@@ -1129,8 +1129,12 @@ begin
     ComboBox_FileExtension.Items.Add(parsedExt[i*2]);
     ComboBox_FileExtension.Items.Add(parsedExt[i*2]);
   end;
   end;
   parsedExt.Free;
   parsedExt.Free;
+
   if ComboBox_FileExtension.Items.Count > 0 then
   if ComboBox_FileExtension.Items.Count > 0 then
+  begin
     ComboBox_FileExtension.ItemIndex := 0;
     ComboBox_FileExtension.ItemIndex := 0;
+    SelectDefaultExtensions;
+  end;
 end;
 end;
 
 
 procedure TFBrowseImages.SetShellMask;
 procedure TFBrowseImages.SetShellMask;
@@ -1212,6 +1216,21 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TFBrowseImages.SelectDefaultExtensions;
+var
+  i: Integer;
+begin
+  if FDefaultExtensions <> '' then
+  begin
+    for i := 0 to high(FFileExtensions) do
+      if FFileExtensions[i] = FDefaultExtensions then
+      begin
+        ComboBox_FileExtension.ItemIndex := i;
+        break;
+      end;
+  end;
+end;
+
 procedure TFBrowseImages.PreviewValidate(ASender: TObject);
 procedure TFBrowseImages.PreviewValidate(ASender: TObject);
 begin
 begin
   ValidateFileOrDir;
   ValidateFileOrDir;

+ 10 - 6
lazpaint/dialog/uchoosecolorinterface.pas

@@ -501,7 +501,7 @@ begin
 end;
 end;
 
 
 procedure TChooseColorInterface.DoSelect(X, Y: integer);
 procedure TChooseColorInterface.DoSelect(X, Y: integer);
-var pix: TBGRAPixel;
+var pix, newColor: TBGRAPixel;
   newLight: Word;
   newLight: Word;
 begin
 begin
   case FSelectZone of
   case FSelectZone of
@@ -518,10 +518,14 @@ begin
       pix := FColorCircle.bmpMaxlight.GetPixel(x-FColorCircle.Bounds.Left,y-FColorCircle.Bounds.top);
       pix := FColorCircle.bmpMaxlight.GetPixel(x-FColorCircle.Bounds.Left,y-FColorCircle.Bounds.top);
       if pix.alpha <> 0 then
       if pix.alpha <> 0 then
       begin
       begin
-        FCurrentColor := BGRA(pix.Red,pix.Green,pix.Blue,FCurrentColor.Alpha);
-        ColorX := x-FColorCircle.Bounds.Left;
-        ColorY := y-FColorCircle.Bounds.top;
-        UpdateColorview(False, True, True);
+        newColor := BGRA(pix.Red,pix.Green,pix.Blue,FCurrentColor.Alpha);
+        if not FCurrentColor.EqualsExactly(newColor) then
+        begin
+          FCurrentColor := newColor;
+          ColorX := x-FColorCircle.Bounds.Left;
+          ColorY := y-FColorCircle.Bounds.top;
+          UpdateColorview(False, True, True);
+        end;
       end;
       end;
     end;
     end;
   szLightScale:
   szLightScale:
@@ -980,7 +984,7 @@ var newcolorlight: word;
 begin
 begin
    newcolorlight := ColorLightOf(value);
    newcolorlight := ColorLightOf(value);
    newcurrentColor := ColorWithLight(value,$FFFF);
    newcurrentColor := ColorWithLight(value,$FFFF);
-   if (newcolorlight<>FColorLight) or (newcurrentcolor <> FCurrentColor) then
+   if (newcolorlight<>FColorLight) or not newcurrentcolor.EqualsExactly(FCurrentColor) then
    begin
    begin
      FColorLight := newcolorlight;
      FColorLight := newcolorlight;
      FCurrentColor := newcurrentcolor;
      FCurrentColor := newcurrentcolor;

+ 9 - 4
lazpaint/image/uimage.pas

@@ -48,6 +48,7 @@ type
     FRenderedImage: TBGRABitmap;
     FRenderedImage: TBGRABitmap;
     FRenderedImageInvalidated: TRect;
     FRenderedImageInvalidated: TRect;
     FOnImageChanged, FOnImageSaving, FOnImageExport: TLazPaintImageObservable;
     FOnImageChanged, FOnImageSaving, FOnImageExport: TLazPaintImageObservable;
+    FOnImageRenderChanged: TNotifyEvent;
     FUndoList: TComposedImageDifference;
     FUndoList: TComposedImageDifference;
     FUndoPos: integer;
     FUndoPos: integer;
     FRenderUpdateRectInPicCoord, FRenderUpdateRectInVSCoord: TRect;
     FRenderUpdateRectInPicCoord, FRenderUpdateRectInVSCoord: TRect;
@@ -160,7 +161,7 @@ type
     procedure LayerMayChangeCompletely(ALayer: TBGRABitmap);
     procedure LayerMayChangeCompletely(ALayer: TBGRABitmap);
     procedure SelectionMaskMayChange(ARect: TRect);
     procedure SelectionMaskMayChange(ARect: TRect);
     procedure SelectionMaskMayChangeCompletely;
     procedure SelectionMaskMayChangeCompletely;
-    procedure RenderMayChange(ARect: TRect; APicCoords: boolean = false);
+    procedure RenderMayChange(ARect: TRect; APicCoords: boolean = false; ANotify: boolean = true);
     procedure ResetRenderUpdateRect;
     procedure ResetRenderUpdateRect;
 
 
     // selection mask
     // selection mask
@@ -257,6 +258,7 @@ type
     property OnSelectedLayerIndexChanged: TOnCurrentLayerIndexChanged read FOnSelectedLayerIndexChanged write FOnSelectedLayerIndexChanged;
     property OnSelectedLayerIndexChanged: TOnCurrentLayerIndexChanged read FOnSelectedLayerIndexChanged write FOnSelectedLayerIndexChanged;
     property OnStackChanged: TOnStackChanged read FOnStackChanged write FOnStackChanged;
     property OnStackChanged: TOnStackChanged read FOnStackChanged write FOnStackChanged;
     property OnImageChanged: TLazPaintImageObservable read FOnImageChanged;
     property OnImageChanged: TLazPaintImageObservable read FOnImageChanged;
+    property OnImageRenderChanged: TNotifyEvent read FOnImageRenderChanged write FOnImageRenderChanged;
     property OnImageSaving: TLazPaintImageObservable read FOnImageSaving;
     property OnImageSaving: TLazPaintImageObservable read FOnImageSaving;
     property OnImageExport: TLazPaintImageObservable read FOnImageExport;
     property OnImageExport: TLazPaintImageObservable read FOnImageExport;
     property OnActionProgress: TLayeredActionProgressEvent read FOnActionProgress write SetOnActionProgress;
     property OnActionProgress: TLayeredActionProgressEvent read FOnActionProgress write SetOnActionProgress;
@@ -1076,7 +1078,8 @@ var
   r: TRect;
   r: TRect;
 begin
 begin
   r := FCurrentState.LayeredBitmap.RenderOriginalIfNecessary(AOriginal.Guid, FDraftOriginal);
   r := FCurrentState.LayeredBitmap.RenderOriginalIfNecessary(AOriginal.Guid, FDraftOriginal);
-  ImageMayChange(r, false);
+  if r.IsEmpty then OnImageChanged.NotifyObservers
+  else ImageMayChange(r, false);
   if Assigned(ADiff) then
   if Assigned(ADiff) then
   begin
   begin
     AddUndo(TVectorOriginalEmbeddedDifference.Create(CurrentState,AOriginal.Guid,ADiff,r));
     AddUndo(TVectorOriginalEmbeddedDifference.Create(CurrentState,AOriginal.Guid,ADiff,r));
@@ -1280,12 +1283,14 @@ begin
     OnImageChanged.NotifyObservers;
     OnImageChanged.NotifyObservers;
 end;
 end;
 
 
-procedure TLazPaintImage.RenderMayChange(ARect: TRect; APicCoords: boolean = false);
+procedure TLazPaintImage.RenderMayChange(ARect: TRect; APicCoords: boolean; ANotify: boolean);
 begin
 begin
   if APicCoords then
   if APicCoords then
      FRenderUpdateRectInPicCoord := RectUnion(FRenderUpdateRectInPicCoord,ARect)
      FRenderUpdateRectInPicCoord := RectUnion(FRenderUpdateRectInPicCoord,ARect)
   else
   else
-      FRenderUpdateRectInVSCoord := RectUnion(FRenderUpdateRectInVSCoord,ARect);
+     FRenderUpdateRectInVSCoord := RectUnion(FRenderUpdateRectInVSCoord,ARect);
+  if ANotify and Assigned(OnImageRenderChanged) then
+    OnImageRenderChanged(self);
 end;
 end;
 
 
 procedure TLazPaintImage.LayerBlendMayChange(AIndex: integer);
 procedure TLazPaintImage.LayerBlendMayChange(AIndex: integer);

+ 32 - 10
lazpaint/image/uimageaction.pas

@@ -106,7 +106,7 @@ implementation
 
 
 uses Controls, Dialogs, UResourceStrings, UObject3D,
 uses Controls, Dialogs, UResourceStrings, UObject3D,
      ULoadImage, UGraph, UClipboard, Types, BGRAGradientOriginal,
      ULoadImage, UGraph, UClipboard, Types, BGRAGradientOriginal,
-     BGRATransform, ULoading, math, LCVectorClipboard, LCVectorOriginal,
+     BGRATransform, ULoading, math, LCVectorClipboard, LCVectorOriginal, LCVectorRectShapes,
      BGRALayers, BGRAUTF8, UFileSystem;
      BGRALayers, BGRAUTF8, UFileSystem;
 
 
 { TImageActions }
 { TImageActions }
@@ -702,21 +702,43 @@ procedure TImageActions.FillBackground(AColor: TBGRAPixel);
 var tempBmp: TBGRABitmap;
 var tempBmp: TBGRABitmap;
     LayerAction: TLayerAction;
     LayerAction: TLayerAction;
     y: Integer;
     y: Integer;
+    orig: TVectorOriginal;
+    ab: TAffineBox;
+    backRect: TRectShape;
 begin
 begin
   if not Image.CheckNoAction then exit;
   if not Image.CheckNoAction then exit;
   LayerAction := nil;
   LayerAction := nil;
   try
   try
-    LayerAction := Image.CreateAction(True);
-    tempBmp := TBGRABitmap.Create(LayerAction.SelectedImageLayer.Width,1);
-    for y := 0 to LayerAction.SelectedImageLayer.Height-1 do
+    if Image.LayerOriginalClass[Image.CurrentLayerIndex] = TVectorOriginal then
     begin
     begin
-       tempBmp.Fill(AColor);
-       tempBmp.PutImage(0,-y,LayerAction.SelectedImageLayer,dmDrawWithTransparency);
-       LayerAction.SelectedImageLayer.PutImage(0,y,tempBmp,dmSet);
+      Image.CurrentState.DiscardOriginalDiff := false;
+      try
+        orig := Image.LayerOriginal[Image.CurrentLayerIndex] as TVectorOriginal;
+        backRect := TRectShape.Create(nil);
+        ab := AffineMatrixInverse(Image.LayerOriginalMatrix[Image.CurrentLayerIndex]) *
+              TAffineBox.AffineBox(rectF(-0.5, -0.5, Image.Width-0.5, Image.Height-0.5));
+        backRect.Origin := ab.Center;
+        backRect.XAxis := backRect.Origin + (ab.TopRight - ab.TopLeft)*0.5;
+        backRect.YAxis := backRect.Origin + (ab.BottomLeft - ab.TopLeft)*0.5;
+        backRect.BackFill.SolidColor := AColor;
+        orig.InsertShape(backRect, 0);
+      finally
+        Image.CurrentState.DiscardOriginalDiff := true;
+      end;
+    end else
+    begin
+      LayerAction := Image.CreateAction(True);
+      tempBmp := TBGRABitmap.Create(LayerAction.SelectedImageLayer.Width,1);
+      for y := 0 to LayerAction.SelectedImageLayer.Height-1 do
+      begin
+         tempBmp.Fill(AColor);
+         tempBmp.PutImage(0,-y,LayerAction.SelectedImageLayer,dmDrawWithTransparency);
+         LayerAction.SelectedImageLayer.PutImage(0,y,tempBmp,dmSet);
+      end;
+      tempBmp.Free;
+      image.LayerMayChangeCompletely(LayerAction.SelectedImageLayer);
+      LayerAction.Validate;
     end;
     end;
-    tempBmp.Free;
-    image.LayerMayChangeCompletely(LayerAction.SelectedImageLayer);
-    LayerAction.Validate;
   except
   except
     on ex:Exception do
     on ex:Exception do
       FInstance.ShowError('FillBackground',ex.Message);
       FInstance.ShowError('FillBackground',ex.Message);

+ 71 - 5
lazpaint/image/uimagediff.pas

@@ -340,10 +340,14 @@ type
     FPreviousLayerContent: TStoredLayer;
     FPreviousLayerContent: TStoredLayer;
     FPrevMatrix,FNextMatrix: TAffineMatrix;
     FPrevMatrix,FNextMatrix: TAffineMatrix;
     FSourceBounds: TRect;
     FSourceBounds: TRect;
+    FSourceLayerId: integer;
     FOriginalGuid: TGUID;
     FOriginalGuid: TGUID;
     function GetImageDifferenceKind: TImageDifferenceKind; override;
     function GetImageDifferenceKind: TImageDifferenceKind; override;
     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; virtual; abstract;
     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; virtual; abstract;
     function ShouldRenderOriginal: boolean; virtual;
     function ShouldRenderOriginal: boolean; virtual;
+    procedure StorePreviousLayer(AImgState: TImageState; ALayerIndex: integer;
+      AAlwaysStoreBitmap: boolean); virtual;
+    procedure CustomUnapplyto(AState: TState);
   public
   public
     constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
     constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
     function UsedMemory: int64; override;
     function UsedMemory: int64; override;
@@ -383,7 +387,14 @@ type
 
 
   TReplaceLayerByImageOriginalDifference = class(TReplaceLayerByOriginalDifference)
   TReplaceLayerByImageOriginalDifference = class(TReplaceLayerByOriginalDifference)
   protected
   protected
+    FSourceStoredInOriginal: boolean;
+    procedure StorePreviousLayer(AImgState: TImageState; ALayerIndex: integer;
+      AAlwaysStoreBitmap: boolean); override;
     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; override;
     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; override;
+  public
+    function UsedMemory: int64; override;
+    function TryCompress: boolean; override;
+    procedure UnapplyTo(AState: TState); override;
   end;
   end;
 
 
   { TReplaceLayerByVectorOriginalDifference }
   { TReplaceLayerByVectorOriginalDifference }
@@ -1130,6 +1141,15 @@ end;
 
 
 { TReplaceLayerByImageOriginalDifference }
 { TReplaceLayerByImageOriginalDifference }
 
 
+procedure TReplaceLayerByImageOriginalDifference.StorePreviousLayer(
+  AImgState: TImageState; ALayerIndex: integer; AAlwaysStoreBitmap: boolean);
+begin
+  if not AImgState.LayerOriginalDefined[ALayerIndex] then
+    FSourceStoredInOriginal:= true
+  else
+    inherited StorePreviousLayer(AImgState, ALayerIndex, AAlwaysStoreBitmap);
+end;
+
 function TReplaceLayerByImageOriginalDifference.CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal;
 function TReplaceLayerByImageOriginalDifference.CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal;
 var
 var
   source: TBGRABitmap;
   source: TBGRABitmap;
@@ -1150,6 +1170,40 @@ begin
   result := orig;
   result := orig;
 end;
 end;
 
 
+function TReplaceLayerByImageOriginalDifference.UsedMemory: int64;
+begin
+  if FSourceStoredInOriginal then
+    result := 0
+  else
+    Result:=inherited UsedMemory;
+end;
+
+function TReplaceLayerByImageOriginalDifference.TryCompress: boolean;
+begin
+  if FSourceStoredInOriginal then
+    result := false
+  else Result:=inherited TryCompress;
+end;
+
+procedure TReplaceLayerByImageOriginalDifference.UnapplyTo(AState: TState);
+var
+  imgState: TImageState;
+  layerIdx: Integer;
+  bmp: TBGRABitmap;
+begin
+  if FSourceStoredInOriginal then
+  begin
+    CustomUnapplyto(AState);
+    imgState := AState as TImageState;
+    layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(LayerId);
+    bmp := (imgState.LayeredBitmap.LayerOriginal[layerIdx] as TBGRALayerImageOriginal).GetImageCopy;
+    imgState.LayeredBitmap.SetLayerBitmap(layerIdx, bmp, True);
+    imgState.LayeredBitmap.LayerOffset[layerIdx] := Point(round(FPrevMatrix[1,3]), round(FPrevMatrix[2,3]));
+    imgState.LayeredBitmap.RemoveUnusedOriginals;
+  end else
+    inherited UnapplyTo(AState);
+end;
+
 { TSelectionTransformDifference }
 { TSelectionTransformDifference }
 
 
 function TSelectionTransformDifference.GetImageDifferenceKind: TImageDifferenceKind;
 function TSelectionTransformDifference.GetImageDifferenceKind: TImageDifferenceKind;
@@ -1255,7 +1309,7 @@ end;
 
 
 function TReplaceLayerByOriginalDifference.GetLayerId: integer;
 function TReplaceLayerByOriginalDifference.GetLayerId: integer;
 begin
 begin
-  result := FPreviousLayerContent.LayerId;
+  result := FSourceLayerId;
 end;
 end;
 
 
 function TReplaceLayerByOriginalDifference.GetImageDifferenceKind: TImageDifferenceKind;
 function TReplaceLayerByOriginalDifference.GetImageDifferenceKind: TImageDifferenceKind;
@@ -1268,6 +1322,17 @@ begin
   result := false;
   result := false;
 end;
 end;
 
 
+procedure TReplaceLayerByOriginalDifference.StorePreviousLayer(
+  AImgState: TImageState; ALayerIndex: integer; AAlwaysStoreBitmap: boolean);
+begin
+  FPreviousLayerContent := TStoredLayer.Create(AImgState.LayeredBitmap, ALayerIndex, AAlwaysStoreBitmap);
+end;
+
+procedure TReplaceLayerByOriginalDifference.CustomUnapplyto(AState: TState);
+begin
+  inherited UnapplyTo(AState);
+end;
+
 constructor TReplaceLayerByOriginalDifference.Create(
 constructor TReplaceLayerByOriginalDifference.Create(
   AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
   AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
 var
 var
@@ -1275,9 +1340,10 @@ var
 begin
 begin
   inherited Create(AFromState);
   inherited Create(AFromState);
   imgState := AFromState as TImageState;
   imgState := AFromState as TImageState;
-  FPreviousLayerContent := TStoredLayer.Create(imgState.LayeredBitmap, AIndex, AAlwaysStoreBitmap);
   FSourceBounds := imgState.LayeredBitmap.LayerBitmap[AIndex].GetImageBounds;
   FSourceBounds := imgState.LayeredBitmap.LayerBitmap[AIndex].GetImageBounds;
-  with FPreviousLayerContent.Offset do FPrevMatrix := AffineMatrixTranslation(x+FSourceBounds.Left,y+FSourceBounds.Top);
+  FSourceLayerId := imgState.LayeredBitmap.LayerUniqueId[AIndex];
+  with imgState.LayeredBitmap.LayerOffset[AIndex] do FPrevMatrix := AffineMatrixTranslation(x+FSourceBounds.Left,y+FSourceBounds.Top);
+  StorePreviousLayer(imgState, AIndex, AAlwaysStoreBitmap);
   FNextMatrix := FPrevMatrix;
   FNextMatrix := FPrevMatrix;
   ApplyTo(imgState);
   ApplyTo(imgState);
 end;
 end;
@@ -1300,7 +1366,7 @@ var
 begin
 begin
   inherited ApplyTo(AState);
   inherited ApplyTo(AState);
   imgState := AState as TImageState;
   imgState := AState as TImageState;
-  layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FPreviousLayerContent.LayerId);
+  layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FSourceLayerId);
   orig := CreateOriginal(imgState, layerIdx);
   orig := CreateOriginal(imgState, layerIdx);
   if FOriginalGuid <> GUID_NULL then orig.Guid := FOriginalGuid;
   if FOriginalGuid <> GUID_NULL then orig.Guid := FOriginalGuid;
   origIndex := imgState.LayeredBitmap.AddOriginal(orig, true);
   origIndex := imgState.LayeredBitmap.AddOriginal(orig, true);
@@ -1321,7 +1387,7 @@ procedure TReplaceLayerByOriginalDifference.UnapplyTo(AState: TState);
 var
 var
   imgState: TImageState;
   imgState: TImageState;
 begin
 begin
-  inherited UnapplyTo(AState);
+  CustomUnapplyto(AState);
   imgState := AState as TImageState;
   imgState := AState as TImageState;
   FPreviousLayerContent.Replace(imgState.LayeredBitmap);
   FPreviousLayerContent.Replace(imgState.LayeredBitmap);
 end;
 end;

+ 2 - 8
lazpaint/lazpaint.lpi

@@ -23,7 +23,7 @@
     <VersionInfo>
     <VersionInfo>
       <UseVersionInfo Value="True"/>
       <UseVersionInfo Value="True"/>
       <MajorVersionNr Value="7"/>
       <MajorVersionNr Value="7"/>
-      <RevisionNr Value="8"/>
+      <RevisionNr Value="9"/>
       <CharSet Value="04B0"/>
       <CharSet Value="04B0"/>
       <StringTable CompanyName="http://sourceforge.net/projects/lazpaint/" ProductName="LazPaint" InternalName="lazpaint" OriginalFilename="lazpaint.exe"/>
       <StringTable CompanyName="http://sourceforge.net/projects/lazpaint/" ProductName="LazPaint" InternalName="lazpaint" OriginalFilename="lazpaint.exe"/>
     </VersionInfo>
     </VersionInfo>
@@ -333,7 +333,7 @@
     <RequiredPackages Count="5">
     <RequiredPackages Count="5">
       <Item1>
       <Item1>
         <PackageName Value="BGRABitmapPack"/>
         <PackageName Value="BGRABitmapPack"/>
-        <MinVersion Major="10" Minor="6" Release="5" Valid="True"/>
+        <MinVersion Major="10" Minor="8" Valid="True"/>
       </Item1>
       </Item1>
       <Item2>
       <Item2>
         <PackageName Value="bgracontrols"/>
         <PackageName Value="bgracontrols"/>
@@ -978,12 +978,6 @@
       <UnitOutputDirectory Value="debug\$(TargetCPU)-$(TargetOS)"/>
       <UnitOutputDirectory Value="debug\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     </SearchPaths>
     <CodeGeneration>
     <CodeGeneration>
-      <Checks>
-        <RangeChecks Value="True"/>
-        <OverflowChecks Value="True"/>
-        <StackChecks Value="True"/>
-      </Checks>
-      <VerifyObjMethodCallValidity Value="True"/>
       <Optimizations>
       <Optimizations>
         <OptimizationLevel Value="0"/>
         <OptimizationLevel Value="0"/>
       </Optimizations>
       </Optimizations>

+ 11 - 0
lazpaint/lazpaintdialogs.inc

@@ -206,6 +206,17 @@ begin
       result := srCancelledByUser;
       result := srCancelledByUser;
 end;
 end;
 
 
+function TLazPaintInstance.ScriptLazPaintGetVersion(AVars: TVariableSet): TScriptResult;
+var
+  resList: TScriptVariableReference;
+begin
+  resList := AVars.AddIntegerList('Result');
+  AVars.AppendInteger(resList, LazPaintVersion div 1000000);
+  AVars.AppendInteger(resList, (LazPaintVersion div 10000) mod 100);
+  AVars.AppendInteger(resList, (LazPaintVersion div 100) mod 100);
+  result := srOk;
+end;
+
 function TLazPaintInstance.ScriptShowDirectoryDialog(AVars: TVariableSet): TScriptResult;
 function TLazPaintInstance.ScriptShowDirectoryDialog(AVars: TVariableSet): TScriptResult;
 var
 var
   chosenDir: string;
   chosenDir: string;

+ 1 - 1
lazpaint/lazpaintembeddedpack.lpk

@@ -26,7 +26,7 @@
         </Debugging>
         </Debugging>
       </Linking>
       </Linking>
     </CompilerOptions>
     </CompilerOptions>
-    <Version Major="7" Release="8"/>
+    <Version Major="7" Release="9"/>
     <Files Count="94">
     <Files Count="94">
       <Item1>
       <Item1>
         <Filename Value="lazpaintinstance.pas"/>
         <Filename Value="lazpaintinstance.pas"/>

+ 68 - 26
lazpaint/lazpaintinstance.pas

@@ -14,7 +14,7 @@ uses
   UColorintensity, UShiftColors, UColorize, uadjustcurves,
   UColorintensity, UShiftColors, UColorize, uadjustcurves,
   UCustomblur, uimagelist,
   UCustomblur, uimagelist,
 
 
-  ULoading, UImage, UTool, uconfig, IniFiles, UResourceStrings, UScripting,
+  ULoading, UImage, UImageAction, UTool, uconfig, IniFiles, UResourceStrings, UScripting,
   UScriptType;
   UScriptType;
 
 
 const
 const
@@ -56,6 +56,7 @@ type
     function ScriptImageCanvasSize(AVars: TVariableSet): TScriptResult;
     function ScriptImageCanvasSize(AVars: TVariableSet): TScriptResult;
     function ScriptImageRepeat(AVars: TVariableSet): TScriptResult;
     function ScriptImageRepeat(AVars: TVariableSet): TScriptResult;
     function ScriptImageResample(AParams: TVariableSet): TScriptResult;
     function ScriptImageResample(AParams: TVariableSet): TScriptResult;
+    function ScriptLazPaintGetVersion(AVars: TVariableSet): TScriptResult;
     function ScriptShowDirectoryDialog(AVars: TVariableSet): TScriptResult;
     function ScriptShowDirectoryDialog(AVars: TVariableSet): TScriptResult;
     procedure SelectionInstanceOnRun(AInstance: TLazPaintCustomInstance);
     procedure SelectionInstanceOnRun(AInstance: TLazPaintCustomInstance);
     procedure ToolFillChanged(Sender: TObject);
     procedure ToolFillChanged(Sender: TObject);
@@ -85,6 +86,7 @@ type
     FGridVisible: boolean;
     FGridVisible: boolean;
     FConfig: TLazPaintConfig;
     FConfig: TLazPaintConfig;
     FImage: TLazPaintImage;
     FImage: TLazPaintImage;
+    FImageAction: TImageActions;
     FToolManager : TToolManager;
     FToolManager : TToolManager;
     FEmbedded: boolean;
     FEmbedded: boolean;
     FDestroying: boolean;
     FDestroying: boolean;
@@ -138,6 +140,7 @@ type
     procedure SetChooseColorTarget(const AValue: TColorTarget); override;
     procedure SetChooseColorTarget(const AValue: TColorTarget); override;
     function GetConfig: TLazPaintConfig; override;
     function GetConfig: TLazPaintConfig; override;
     function GetImage: TLazPaintImage; override;
     function GetImage: TLazPaintImage; override;
+    function GetImageAction: TImageActions; override;
     function GetToolManager: TToolManager; override;
     function GetToolManager: TToolManager; override;
     procedure CreateLayerStack;
     procedure CreateLayerStack;
     procedure CreateToolBox;
     procedure CreateToolBox;
@@ -259,7 +262,7 @@ uses LCLType, Types, Forms, Dialogs, FileUtil, StdCtrls, LCLIntf, BGRAUTF8,
 
 
      URadialBlur, UMotionBlur, UEmboss, UTwirl, UWaveDisplacement,
      URadialBlur, UMotionBlur, UEmboss, UTwirl, UWaveDisplacement,
      unewimage, uresample, UPixelate, unoisefilter, ufilters,
      unewimage, uresample, UPixelate, unoisefilter, ufilters,
-     UImageAction, USharpen, uposterize, UPhongFilter, UFilterFunction,
+     USharpen, uposterize, UPhongFilter, UFilterFunction,
      uprint, USaveOption, UFormRain,
      uprint, USaveOption, UFormRain,
 
 
      ugraph, LCScaleDPI, ucommandline, uabout, UPython, UVolatileScrollBar;
      ugraph, LCScaleDPI, ucommandline, uabout, UPython, UVolatileScrollBar;
@@ -367,6 +370,7 @@ begin
   ScriptContext.RegisterScriptFunction('ShowMessage',@ScriptShowMessage,ARegister);
   ScriptContext.RegisterScriptFunction('ShowMessage',@ScriptShowMessage,ARegister);
   ScriptContext.RegisterScriptFunction('ShowDirectoryDialog',@ScriptShowDirectoryDialog,ARegister);
   ScriptContext.RegisterScriptFunction('ShowDirectoryDialog',@ScriptShowDirectoryDialog,ARegister);
   ScriptContext.RegisterScriptFunction('InputBox',@ScriptInputBox,ARegister);
   ScriptContext.RegisterScriptFunction('InputBox',@ScriptInputBox,ARegister);
+  ScriptContext.RegisterScriptFunction('LazPaintGetVersion',@ScriptLazPaintGetVersion,ARegister);
 end;
 end;
 
 
 function TLazPaintInstance.ScriptFileGetTemporaryName(AVars: TVariableSet): TScriptResult;
 function TLazPaintInstance.ScriptFileGetTemporaryName(AVars: TVariableSet): TScriptResult;
@@ -424,6 +428,7 @@ begin
   FToolManager.OnFillChanged:= @ToolFillChanged;
   FToolManager.OnFillChanged:= @ToolFillChanged;
   FSelectionEditConfig := nil;
   FSelectionEditConfig := nil;
   FTextureEditConfig := nil;
   FTextureEditConfig := nil;
+  FImageAction := TImageActions.Create(self);
 end;
 end;
 
 
 procedure TLazPaintInstance.FormsNeeded;
 procedure TLazPaintInstance.FormsNeeded;
@@ -466,6 +471,11 @@ begin
   Result:= FImage;
   Result:= FImage;
 end;
 end;
 
 
+function TLazPaintInstance.GetImageAction: TImageActions;
+begin
+  result := FImageAction;
+end;
+
 function TLazPaintInstance.GetToolManager: TToolManager;
 function TLazPaintInstance.GetToolManager: TToolManager;
 begin
 begin
   Result:= FToolManager;
   Result:= FToolManager;
@@ -657,8 +667,13 @@ var
   delay: Integer;
   delay: Integer;
 begin
 begin
   if AProgressPercent < 100 then delay := 10000 else delay := 1000;
   if AProgressPercent < 100 then delay := 10000 else delay := 1000;
-  MessagePopup(rsActionInProgress+'... '+inttostr(AProgressPercent)+'%', delay);
-  UpdateWindows;
+  if Assigned(FMain) then FMain.UpdatingPopup:= true;
+  try
+    MessagePopup(rsActionInProgress+'... '+inttostr(AProgressPercent)+'%', delay);
+    UpdateWindows;
+  finally
+    if Assigned(FMain) then FMain.UpdatingPopup:= false;
+  end;
 end;
 end;
 
 
 function TLazPaintInstance.GetInitialized: boolean;
 function TLazPaintInstance.GetInitialized: boolean;
@@ -796,8 +811,13 @@ procedure TLazPaintInstance.OnLayeredBitmapLoadStartHandler(AFilenameUTF8: strin
 begin
 begin
   if FLoadingLayers = nil then FLoadingLayers := TFLoading.Create(nil);
   if FLoadingLayers = nil then FLoadingLayers := TFLoading.Create(nil);
   if (AFilenameUTF8 = '<Stream>') and (FLoadingFilename <> '') then AFilenameUTF8 := FLoadingFilename;
   if (AFilenameUTF8 = '<Stream>') and (FLoadingFilename <> '') then AFilenameUTF8 := FLoadingFilename;
-  FLoadingLayers.ShowMessage(rsOpening+' ' +AFilenameUTF8+'...');
-  UpdateWindows;
+  if Assigned(FMain) then FMain.UpdatingPopup:= true;
+  try
+    FLoadingLayers.ShowMessage(rsOpening+' ' +AFilenameUTF8+'...');
+    UpdateWindows;
+  finally
+    if Assigned(FMain) then FMain.UpdatingPopup:= false;
+  end;
 end;
 end;
 
 
 procedure TLazPaintInstance.OnLayeredBitmapLoadProgressHandler(
 procedure TLazPaintInstance.OnLayeredBitmapLoadProgressHandler(
@@ -805,8 +825,13 @@ procedure TLazPaintInstance.OnLayeredBitmapLoadProgressHandler(
 begin
 begin
   if FLoadingLayers <> nil then
   if FLoadingLayers <> nil then
   begin
   begin
-    FLoadingLayers.ShowMessage(rsLoading+' (' +inttostr(APercentage)+'%)');
-    UpdateWindows;
+    if Assigned(FMain) then FMain.UpdatingPopup:= true;
+    try
+      FLoadingLayers.ShowMessage(rsLoading+' (' +inttostr(APercentage)+'%)');
+      UpdateWindows;
+    finally
+      if Assigned(FMain) then FMain.UpdatingPopup:= false;
+    end;
   end;
   end;
 end;
 end;
 
 
@@ -814,8 +839,13 @@ procedure TLazPaintInstance.OnLayeredBitmapLoadedHandler;
 begin
 begin
   if FLoadingLayers <> nil then
   if FLoadingLayers <> nil then
   begin
   begin
-    FreeAndNil(FLoadingLayers);
-    UpdateWindows;
+    if Assigned(FMain) then FMain.UpdatingPopup:= true;
+    try
+      FreeAndNil(FLoadingLayers);
+      UpdateWindows;
+    finally
+      if Assigned(FMain) then FMain.UpdatingPopup:= false;
+    end;
   end;
   end;
 end;
 end;
 
 
@@ -823,8 +853,13 @@ procedure TLazPaintInstance.OnLayeredBitmapSavedHandler();
 begin
 begin
   if FLoadingLayers <> nil then
   if FLoadingLayers <> nil then
   begin
   begin
-    FreeAndNil(FLoadingLayers);
-    UpdateWindows;
+    if Assigned(FMain) then FMain.UpdatingPopup:= true;
+    try
+      FreeAndNil(FLoadingLayers);
+      UpdateWindows;
+    finally
+      if Assigned(FMain) then FMain.UpdatingPopup:= false;
+    end;
   end;
   end;
 end;
 end;
 
 
@@ -833,8 +868,13 @@ procedure TLazPaintInstance.OnLayeredBitmapSaveProgressHandler(
 begin
 begin
   if FLoadingLayers <> nil then
   if FLoadingLayers <> nil then
   begin
   begin
-    FLoadingLayers.ShowMessage(rsSave+' (' +inttostr(APercentage)+'%)');
-    UpdateWindows;
+    if Assigned(FMain) then FMain.UpdatingPopup:= true;
+    try
+      FLoadingLayers.ShowMessage(rsSave+' (' +inttostr(APercentage)+'%)');
+      UpdateWindows;
+    finally
+      if Assigned(FMain) then FMain.UpdatingPopup:= false;
+    end;
   end;
   end;
 end;
 end;
 
 
@@ -843,8 +883,13 @@ procedure TLazPaintInstance.OnLayeredBitmapSaveStartHandler(
 begin
 begin
   if FLoadingLayers = nil then FLoadingLayers := TFLoading.Create(nil);
   if FLoadingLayers = nil then FLoadingLayers := TFLoading.Create(nil);
   if (AFilenameUTF8 = '<Stream>') and (FSavingFilename <> '') then AFilenameUTF8 := FSavingFilename;
   if (AFilenameUTF8 = '<Stream>') and (FSavingFilename <> '') then AFilenameUTF8 := FSavingFilename;
-  FLoadingLayers.ShowMessage(rsSave+' ' +AFilenameUTF8+'...');
-  UpdateWindows;
+  if Assigned(FMain) then FMain.UpdatingPopup:= true;
+  try
+    FLoadingLayers.ShowMessage(rsSave+' ' +AFilenameUTF8+'...');
+    UpdateWindows;
+  finally
+    if Assigned(FMain) then FMain.UpdatingPopup:= false;
+  end;
 end;
 end;
 
 
 procedure TLazPaintInstance.PythonBusy(Sender: TObject);
 procedure TLazPaintInstance.PythonBusy(Sender: TObject);
@@ -993,7 +1038,6 @@ procedure TLazPaintInstance.SetGridVisible(const AValue: boolean);
 begin
 begin
   FGridVisible := AValue;
   FGridVisible := AValue;
   Image.RenderMayChange(rect(0,0,Image.Width,Image.Height),True);
   Image.RenderMayChange(rect(0,0,Image.Width,Image.Height),True);
-  NotifyImageChange(False,EmptyRect);
 end;
 end;
 
 
 function TLazPaintInstance.GetChooseColorVisible: boolean;
 function TLazPaintInstance.GetChooseColorVisible: boolean;
@@ -1074,11 +1118,9 @@ begin
 end;
 end;
 
 
 procedure TLazPaintInstance.AssignBitmap(bmp: TBGRABitmap);
 procedure TLazPaintInstance.AssignBitmap(bmp: TBGRABitmap);
-var imageActions: TimageActions;
 begin
 begin
-  imageActions := TImageActions.Create(self);
-  imageActions.SetCurrentBitmap(bmp.Duplicate as TBGRABitmap, False);
-  imageActions.Free;
+  if Assigned(FImageAction) then
+    FImageAction.SetCurrentBitmap(bmp.Duplicate as TBGRABitmap, False);
 end;
 end;
 
 
 procedure TLazPaintInstance.EditBitmap(var bmp: TBGRABitmap; ConfigStream: TStream; ATitle: String; AOnRun: TLazPaintInstanceEvent; AOnExit: TLazPaintInstanceEvent; ABlackAndWhite: boolean);
 procedure TLazPaintInstance.EditBitmap(var bmp: TBGRABitmap; ConfigStream: TStream; ATitle: String; AOnRun: TLazPaintInstanceEvent; AOnExit: TLazPaintInstanceEvent; ABlackAndWhite: boolean);
@@ -1138,16 +1180,13 @@ begin
 end;
 end;
 
 
 procedure TLazPaintInstance.EditSelection;
 procedure TLazPaintInstance.EditSelection;
-var imageActions: TimageActions;
 begin
 begin
-  imageActions := TImageActions.Create(self);
   try
   try
-    imageActions.EditSelection(@EditSelectionHandler);
+    TImageActions(ImageAction).EditSelection(@EditSelectionHandler);
   except
   except
     on ex: Exception do
     on ex: Exception do
       ShowError('EditSelection',ex.Message);
       ShowError('EditSelection',ex.Message);
   end;
   end;
-  imageActions.Free;
 end;
 end;
 
 
 function TLazPaintInstance.EditTexture(ASource: TBGRABitmap): TBGRABitmap;
 function TLazPaintInstance.EditTexture(ASource: TBGRABitmap): TBGRABitmap;
@@ -1241,7 +1280,6 @@ end;
 procedure TLazPaintInstance.SetFullscreen(AValue: boolean);
 procedure TLazPaintInstance.SetFullscreen(AValue: boolean);
 begin
 begin
   if (AValue = FFullscreen) or not MainFormVisible or (FMain.WindowState = wsMinimized) then exit;
   if (AValue = FFullscreen) or not MainFormVisible or (FMain.WindowState = wsMinimized) then exit;
-  if AValue then DockLayersAndColors:= false;
   FFullscreen := AValue;
   FFullscreen := AValue;
   if AValue then
   if AValue then
   begin
   begin
@@ -1359,6 +1397,7 @@ end;
 
 
 destructor TLazPaintInstance.Destroy;
 destructor TLazPaintInstance.Destroy;
 begin
 begin
+  FreeAndNil(FImageAction);
   RegisterScripts(False);
   RegisterScripts(False);
 
 
   FDestroying := true;
   FDestroying := true;
@@ -1462,17 +1501,20 @@ begin
   if Assigned(FLayerStack) and (AInfo.layerstackHidden > 0) then
   if Assigned(FLayerStack) and (AInfo.layerstackHidden > 0) then
   begin
   begin
     FLayerStack.Show;
     FLayerStack.Show;
+    FLayerStack.BringToFront;
     FLayerStack.InvalidateStack(False);
     FLayerStack.InvalidateStack(False);
     dec(FTopMostInfo.layerstackHidden);
     dec(FTopMostInfo.layerstackHidden);
   end;
   end;
   if Assigned(FChooseColor) and (AInfo.choosecolorHidden > 0) then
   if Assigned(FChooseColor) and (AInfo.choosecolorHidden > 0) then
   begin
   begin
     FChooseColor.Show;
     FChooseColor.Show;
+    FChooseColor.BringToFront;
     dec(FTopMostInfo.choosecolorHidden);
     dec(FTopMostInfo.choosecolorHidden);
   end;
   end;
   if Assigned(FFormToolbox) and (AInfo.toolboxHidden > 0) then
   if Assigned(FFormToolbox) and (AInfo.toolboxHidden > 0) then
   begin
   begin
     FFormToolbox.Show;
     FFormToolbox.Show;
+    FFormToolbox.BringToFront;
     dec(FTopMostInfo.toolboxHidden);
     dec(FTopMostInfo.toolboxHidden);
   end;
   end;
 end;
 end;

+ 64 - 9
lazpaint/lazpaintmainform.lfm

@@ -214,7 +214,7 @@ object FMain: TFMain
       Height = 20
       Height = 20
       Hint = 'Color difference'
       Hint = 'Color difference'
       Top = 1
       Top = 1
-      Width = 34
+      Width = 36
       Alignment = taCenter
       Alignment = taCenter
       AutoSize = False
       AutoSize = False
       Caption = '100%'
       Caption = '100%'
@@ -228,9 +228,9 @@ object FMain: TFMain
     Left = 608
     Left = 608
     Height = 36
     Height = 36
     Top = 144
     Top = 144
-    Width = 98
+    Width = 105
     ClientHeight = 36
     ClientHeight = 36
-    ClientWidth = 98
+    ClientWidth = 105
     Font.Height = -12
     Font.Height = -12
     ParentColor = False
     ParentColor = False
     ParentFont = False
     ParentFont = False
@@ -252,7 +252,7 @@ object FMain: TFMain
       Height = 20
       Height = 20
       Hint = 'Pen width'
       Hint = 'Pen width'
       Top = 2
       Top = 2
-      Width = 46
+      Width = 53
       AllowNegativeValues = False
       AllowNegativeValues = False
       BarExponent = 1
       BarExponent = 1
       Increment = 1
       Increment = 1
@@ -718,9 +718,9 @@ object FMain: TFMain
     Left = 608
     Left = 608
     Height = 36
     Height = 36
     Top = 8
     Top = 8
-    Width = 72
+    Width = 75
     ClientHeight = 36
     ClientHeight = 36
-    ClientWidth = 72
+    ClientWidth = 75
     Font.Height = -12
     Font.Height = -12
     ParentColor = False
     ParentColor = False
     ParentFont = False
     ParentFont = False
@@ -731,7 +731,7 @@ object FMain: TFMain
       Height = 20
       Height = 20
       Hint = 'Coordinates'
       Hint = 'Coordinates'
       Top = 2
       Top = 2
-      Width = 62
+      Width = 66
       Alignment = taCenter
       Alignment = taCenter
       AutoSize = False
       AutoSize = False
       Caption = '9999x9999'
       Caption = '9999x9999'
@@ -2304,7 +2304,7 @@ object FMain: TFMain
     end
     end
   end
   end
   object Panel_PerspectiveOption: TPanel
   object Panel_PerspectiveOption: TPanel
-    Left = 479
+    Left = 432
     Height = 36
     Height = 36
     Top = 152
     Top = 152
     Width = 65
     Width = 65
@@ -2603,7 +2603,7 @@ object FMain: TFMain
     end
     end
   end
   end
   object Panel_Ratio: TPanel
   object Panel_Ratio: TPanel
-    Left = 288
+    Left = 272
     Height = 36
     Height = 36
     Top = 152
     Top = 152
     Width = 147
     Width = 147
@@ -3118,6 +3118,61 @@ object FMain: TFMain
       AllowedFillTypes = [vftSolid, vftGradient, vftTexture]
       AllowedFillTypes = [vftSolid, vftGradient, vftTexture]
     end
     end
   end
   end
+  object Panel_Donate: TPanel
+    Left = 512
+    Height = 36
+    Top = 152
+    Width = 44
+    ClientHeight = 36
+    ClientWidth = 44
+    Font.Height = -12
+    ParentColor = False
+    ParentFont = False
+    TabOrder = 32
+    object ToolBar25: TToolBar
+      Left = 1
+      Height = 22
+      Top = 1
+      Width = 24
+      Align = alNone
+      AutoSize = True
+      EdgeBorders = []
+      Font.Height = -12
+      Images = ImageList16
+      ParentFont = False
+      TabOrder = 0
+      object ToolButton_Donate: TToolButton
+        Left = 1
+        Hint = 'Donate...'
+        Top = 0
+        ImageIndex = 110
+        OnClick = ToolButton_DonateClick
+      end
+    end
+  end
+  object Panel_OutlineFill: TPanel
+    Left = 480
+    Height = 36
+    Top = 240
+    Width = 88
+    ClientHeight = 36
+    ClientWidth = 88
+    Font.Height = -12
+    ParentColor = False
+    ParentFont = False
+    PopupMenu = PopupToolbar
+    TabOrder = 33
+    object VectorialFill_Outline: TLCVectorialFillControl
+      Left = 2
+      Height = 40
+      Top = 1
+      Width = 80
+      AutoSize = True
+      ToolIconSize = 16
+      VerticalPadding = 4
+      AllowedFillTypes = [vftSolid, vftGradient, vftTexture]
+    end
+  end
   object ImageList16: TBGRAImageList
   object ImageList16: TBGRAImageList
     left = 40
     left = 40
     top = 496
     top = 496

+ 76 - 35
lazpaint/lazpaintmainform.pas

@@ -13,7 +13,7 @@ uses
   Graphics, Dialogs, Menus, ExtDlgs, ComCtrls, ActnList, StdCtrls, ExtCtrls,
   Graphics, Dialogs, Menus, ExtDlgs, ComCtrls, ActnList, StdCtrls, ExtCtrls,
   Buttons, types, LCLType, BGRAImageList, BCTrackbarUpdown, BCComboBox, BCButton,
   Buttons, types, LCLType, BGRAImageList, BCTrackbarUpdown, BCComboBox, BCButton,
 
 
-  BGRABitmap, BGRABitmapTypes, BGRALayers, BGRASVGOriginal, BGRAGradientScanner,
+  BGRABitmap, BGRABitmapTypes, BGRALayers, BGRASVGOriginal, BGRAGradientScanner, BGRAGradientOriginal,
 
 
   LazPaintType, UMainFormLayout, UTool, UImage, UImageAction, UZoom, UImageView,
   LazPaintType, UMainFormLayout, UTool, UImage, UImageAction, UZoom, UImageView,
   UImageObservation, UConfig, LCScaleDPI, UResourceStrings, UMenu, uscripting,
   UImageObservation, UConfig, LCScaleDPI, UResourceStrings, UMenu, uscripting,
@@ -29,6 +29,10 @@ type
     FileExport: TAction;
     FileExport: TAction;
     ExportPictureDialog: TSaveDialog;
     ExportPictureDialog: TSaveDialog;
     MenuScript: TMenuItem;
     MenuScript: TMenuItem;
+    Panel_OutlineFill: TPanel;
+    Panel_Donate: TPanel;
+    ToolButton_Donate: TToolButton;
+    ToolBar25: TToolBar;
     ToolOpenedCurve: TAction;
     ToolOpenedCurve: TAction;
     ToolPolyline: TAction;
     ToolPolyline: TAction;
     FileRunScript: TAction;
     FileRunScript: TAction;
@@ -55,6 +59,7 @@ type
     Tool_EraseSharpen: TToolButton;
     Tool_EraseSharpen: TToolButton;
     Tool_EraseLighten: TToolButton;
     Tool_EraseLighten: TToolButton;
     Tool_EraseDarken: TToolButton;
     Tool_EraseDarken: TToolButton;
+    VectorialFill_Outline: TLCVectorialFillControl;
     VectorialFill_Pen: TLCVectorialFillControl;
     VectorialFill_Pen: TLCVectorialFillControl;
     VectorialFill_Back: TLCVectorialFillControl;
     VectorialFill_Back: TLCVectorialFillControl;
     Panel_BackFill: TPanel;
     Panel_BackFill: TPanel;
@@ -536,6 +541,7 @@ type
     procedure GridNb_SpinEditChange(Sender: TObject; AByUser: boolean);
     procedure GridNb_SpinEditChange(Sender: TObject; AByUser: boolean);
     procedure TimerArrangeTimer(Sender: TObject);
     procedure TimerArrangeTimer(Sender: TObject);
     procedure TimerHideFillTimer(Sender: TObject);
     procedure TimerHideFillTimer(Sender: TObject);
+    procedure ToolButton_DonateClick(Sender: TObject);
     procedure VectorialFill_TextureClick(Sender: TObject);
     procedure VectorialFill_TextureClick(Sender: TObject);
     procedure PaintBox_PenPreviewPaint(Sender: TObject);
     procedure PaintBox_PenPreviewPaint(Sender: TObject);
     procedure PaintBox_PictureMouseDown(Sender: TObject; Button: TMouseButton;
     procedure PaintBox_PictureMouseDown(Sender: TObject; Button: TMouseButton;
@@ -637,9 +643,7 @@ type
       {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
       {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
     procedure SpinEdit_PenWidthChange(Sender: TObject; AByUser: boolean);
     procedure SpinEdit_PenWidthChange(Sender: TObject; AByUser: boolean);
     procedure Tool_CloseShapeClick(Sender: TObject);
     procedure Tool_CloseShapeClick(Sender: TObject);
-    procedure VectorialFill_BackChooseColor({%H-}ASender: TObject; AButton: TMouseButton;
-              AColorIndex: integer; var {%H-}AColorValue: TBGRAPixel; out AHandled: boolean);
-    procedure VectorialFill_PenChooseColor({%H-}ASender: TObject; AButton: TMouseButton;
+    procedure VectorialFill_ChooseColor({%H-}ASender: TObject; AButton: TMouseButton;
               AColorIndex: integer; var {%H-}AColorValue: TBGRAPixel; out AHandled: boolean);
               AColorIndex: integer; var {%H-}AColorValue: TBGRAPixel; out AHandled: boolean);
     procedure SpinEdit_ArrowSizeChange(Sender: TObject; AByUser: boolean);
     procedure SpinEdit_ArrowSizeChange(Sender: TObject; AByUser: boolean);
     procedure SpinEdit_ToleranceChange(Sender: TObject; AByUser: boolean);
     procedure SpinEdit_ToleranceChange(Sender: TObject; AByUser: boolean);
@@ -684,20 +688,14 @@ type
     procedure ManagerToolbarChanged(Sender: TObject);
     procedure ManagerToolbarChanged(Sender: TObject);
     procedure Perspective_RepeatClick(Sender: TObject);
     procedure Perspective_RepeatClick(Sender: TObject);
     function ScriptShowColorDialog(AVars: TVariableSet): TScriptResult;
     function ScriptShowColorDialog(AVars: TVariableSet): TScriptResult;
-    procedure VectorialFill_BackAdjustToShape(Sender: TObject);
-    procedure VectorialFill_BackChange(Sender: TObject);
-    procedure VectorialFill_BackEditGradTexPoints(Sender: TObject);
-    procedure VectorialFill_BackResize(Sender: TObject);
-    procedure VectorialFill_BackTypeChange(Sender: TObject);
-    procedure VectorialFill_PenAdjustToShape(Sender: TObject);
-    procedure VectorialFill_PenChange(Sender: TObject);
-    procedure VectorialFill_PenEditGradTexPoints(Sender: TObject);
-    procedure VectorialFill_PenResize(Sender: TObject);
-    procedure VectorialFill_PenTypeChange(Sender: TObject);
-    procedure VectorialFill_ShowBackFill(Sender: TObject; {%H-}Shift: TShiftState;
-      {%H-}X, {%H-}Y: Integer);
-    procedure VectorialFill_ShowPenFill(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
-      {%H-}Y: Integer);
+    procedure VectorialFill_Change(Sender: TObject);
+    procedure VectorialFill_TypeChange(Sender: TObject);
+    procedure VectorialFill_Resize(Sender: TObject);
+    procedure VectorialFill_EditGradTexPoints(Sender: TObject);
+    procedure VectorialFill_AdjustToShape(Sender: TObject);
+    procedure VectorialFill_ShowBackFill(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
+    procedure VectorialFill_ShowPenFill(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
+    procedure VectorialFill_ShowOutlineFill(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
   private
   private
     { private declarations }
     { private declarations }
     FLayout: TMainFormLayout;
     FLayout: TMainFormLayout;
@@ -734,7 +732,6 @@ type
     FShowSelectionNormal: boolean;
     FShowSelectionNormal: boolean;
     FLazPaintInstance: TLazPaintCustomInstance;
     FLazPaintInstance: TLazPaintCustomInstance;
     Config: TLazPaintConfig;
     Config: TLazPaintConfig;
-    FImageActions: TImageActions;
     StartDirectory: string;
     StartDirectory: string;
     previousToolImg: integer;
     previousToolImg: integer;
     currentToolLabel: string;
     currentToolLabel: string;
@@ -751,8 +748,11 @@ type
 
 
     function GetCurrentPressure: single;
     function GetCurrentPressure: single;
     function GetDarkTheme: boolean;
     function GetDarkTheme: boolean;
+    function GetImageAction: TImageActions;
+    function GetUpdatingPopup: boolean;
     function GetUseImageBrowser: boolean;
     function GetUseImageBrowser: boolean;
     procedure SetDarkTheme(AValue: boolean);
     procedure SetDarkTheme(AValue: boolean);
+    procedure SetUpdatingPopup(AValue: boolean);
     procedure UpdateStatusText;
     procedure UpdateStatusText;
     procedure CreateToolbarElements;
     procedure CreateToolbarElements;
     function GetCurrentToolAction: TAction;
     function GetCurrentToolAction: TAction;
@@ -807,11 +807,11 @@ type
     function ShowColorDialogFor(ATarget: TColorTarget): boolean;
     function ShowColorDialogFor(ATarget: TColorTarget): boolean;
     procedure ShowPenPreview(ShouldRepaint: boolean= False);
     procedure ShowPenPreview(ShouldRepaint: boolean= False);
     procedure HidePenPreview(ATimeMs: Integer = 300; AClearTime: boolean = false);
     procedure HidePenPreview(ATimeMs: Integer = 300; AClearTime: boolean = false);
-    procedure ShowPenFill;
-    procedure ShowBackFill;
+    procedure ShowFill(AFillControl: TLCVectorialFillControl; APanel: TPanel);
     procedure HideFill(ATimeMs: Integer = 300; AClearTime: boolean = false);
     procedure HideFill(ATimeMs: Integer = 300; AClearTime: boolean = false);
     procedure OnPaintHandler;
     procedure OnPaintHandler;
     procedure OnImageChangedHandler({%H-}AEvent: TLazPaintImageObservationEvent);
     procedure OnImageChangedHandler({%H-}AEvent: TLazPaintImageObservationEvent);
+    procedure OnImageRenderChanged(sender: TObject);
     procedure LabelAutosize(ALabel: TLabel);
     procedure LabelAutosize(ALabel: TLabel);
     procedure AskMergeSelection(ACaption: string);
     procedure AskMergeSelection(ACaption: string);
     procedure ReleaseMouseButtons(Shift: TShiftState);
     procedure ReleaseMouseButtons(Shift: TShiftState);
@@ -889,6 +889,8 @@ type
     property CurrentPressure: single read GetCurrentPressure;
     property CurrentPressure: single read GetCurrentPressure;
     property DarkTheme: boolean read GetDarkTheme write SetDarkTheme;
     property DarkTheme: boolean read GetDarkTheme write SetDarkTheme;
     property Initialized: boolean read FInitialized;
     property Initialized: boolean read FInitialized;
+    property UpdatingPopup: boolean read GetUpdatingPopup write SetUpdatingPopup;
+    property ImageAction: TImageActions read GetImageAction;
   end;
   end;
 
 
 implementation
 implementation
@@ -993,7 +995,6 @@ begin
   end;
   end;
   FLayout.ToolBoxPopup := nil;
   FLayout.ToolBoxPopup := nil;
   RegisterScripts(False);
   RegisterScripts(False);
-  FreeAndNil(FImageActions);
 
 
   If Assigned(ToolManager) then
   If Assigned(ToolManager) then
   begin
   begin
@@ -1029,8 +1030,13 @@ begin
   FreeAndNil(FBrowseImages);
   FreeAndNil(FBrowseImages);
   FreeAndNil(FBrowseTextures);
   FreeAndNil(FBrowseTextures);
   FreeAndNil(FBrowseBrushes);
   FreeAndNil(FBrowseBrushes);
-  if Assigned(FSaveImage) and Config.DefaultRememberSaveFormat then
-    Config.SetSaveExtensions(FSaveImage.DefaultExtensions);
+  if Config.DefaultRememberSaveFormat then
+  begin
+    if Assigned(FSaveImage) and Config.DefaultRememberSaveFormat and Config.DefaultUseImageBrowser then
+      Config.SetSaveExtensions(FSaveImage.DefaultExtensions)
+    else
+      Config.SetSaveExtensions(GetExtensionFilterByIndex([eoWritable], SavePictureDialog1.FilterIndex));
+  end;
   FreeAndNil(FSaveImage);
   FreeAndNil(FSaveImage);
   FreeAndNil(FSaveSelection);
   FreeAndNil(FSaveSelection);
 
 
@@ -1066,10 +1072,19 @@ begin
     FLoadInitialDir := Config.DefaultStartupSourceDirectory;
     FLoadInitialDir := Config.DefaultStartupSourceDirectory;
   FileRememberSaveFormat.Checked:= Config.DefaultRememberSaveFormat;
   FileRememberSaveFormat.Checked:= Config.DefaultRememberSaveFormat;
 
 
+  if Config.DefaultRememberSaveFormat then
+  begin
+    SavePictureDialog1.FilterIndex := GetExtensionFilterIndex([eoWritable], Config.DefaultSaveExtensions);
+    ExportPictureDialog.FilterIndex:= SavePictureDialog1.FilterIndex;
+  end else
+  begin
+    SavePictureDialog1.FilterIndex := 1;
+    ExportPictureDialog.FilterIndex:= 1;
+  end;
+
   FImageView := TImageView.Create(LazPaintInstance, Zoom,
   FImageView := TImageView.Create(LazPaintInstance, Zoom,
                 {$IFDEF USEPAINTBOXPICTURE}PaintBox_Picture.Canvas{$ELSE}self.Canvas{$ENDIF});
                 {$IFDEF USEPAINTBOXPICTURE}PaintBox_Picture.Canvas{$ELSE}self.Canvas{$ENDIF});
 
 
-  FImageActions := TImageActions.Create(LazPaintInstance);
   LazPaintInstance.EmbeddedResult := mrNone;
   LazPaintInstance.EmbeddedResult := mrNone;
 
 
   Image.OnSelectedLayerIndexChanged:= @PictureSelectedLayerIndexChanged;
   Image.OnSelectedLayerIndexChanged:= @PictureSelectedLayerIndexChanged;
@@ -1104,7 +1119,7 @@ begin
   InitToolbarElements;
   InitToolbarElements;
 
 
   Image.CurrentFilenameUTF8 := '';
   Image.CurrentFilenameUTF8 := '';
-  FImageActions.SetCurrentBitmap(TBGRABitmap.Create(Config.DefaultImageWidth,Config.DefaultImageHeight,Config.DefaultImageBackgroundColor), false);
+  ImageAction.SetCurrentBitmap(TBGRABitmap.Create(Config.DefaultImageWidth,Config.DefaultImageHeight,Config.DefaultImageBackgroundColor), false);
   image.ClearUndo;
   image.ClearUndo;
   image.SetSavedFlag(0, -1, 0);
   image.SetSavedFlag(0, -1, 0);
 
 
@@ -1138,6 +1153,7 @@ begin
   RegisterScripts(True);
   RegisterScripts(True);
 
 
   Image.OnImageChanged.AddObserver(@OnImageChangedHandler);
   Image.OnImageChanged.AddObserver(@OnImageChangedHandler);
+  Image.OnImageRenderChanged := @OnImageRenderChanged;
   Image.OnQueryExitToolHandler := @OnQueryExitToolHandler;
   Image.OnQueryExitToolHandler := @OnQueryExitToolHandler;
   Image.Zoom := Zoom;
   Image.Zoom := Zoom;
   UpdateWindowCaption;
   UpdateWindowCaption;
@@ -1160,7 +1176,7 @@ begin
       Panel_ShapeOption,Panel_PenWidth,Panel_PenStyle,Panel_JoinStyle,
       Panel_ShapeOption,Panel_PenWidth,Panel_PenStyle,Panel_JoinStyle,
       Panel_CloseShape,Panel_LineCap,Panel_Aliasing,
       Panel_CloseShape,Panel_LineCap,Panel_Aliasing,
       Panel_SplineStyle,Panel_Eraser,Panel_Tolerance,Panel_Text,Panel_Altitude,Panel_TextShadow,Panel_TextOutline,
       Panel_SplineStyle,Panel_Eraser,Panel_Tolerance,Panel_Text,Panel_Altitude,Panel_TextShadow,Panel_TextOutline,
-      Panel_PhongShape,Panel_PerspectiveOption,Panel_Brush,Panel_Ratio],Panel_ToolbarBackground);
+      Panel_OutlineFill,Panel_PhongShape,Panel_PerspectiveOption,Panel_Brush,Panel_Ratio,Panel_Donate],Panel_ToolbarBackground);
     m.ImageList := LazPaintInstance.Icons[ScaleY(16, 96)];
     m.ImageList := LazPaintInstance.Icons[ScaleY(16, 96)];
     m.Apply;
     m.Apply;
     FLayout.Menu := m;
     FLayout.Menu := m;
@@ -2016,7 +2032,7 @@ begin
   end;
   end;
   if Open3DObjectDialog.Execute then
   if Open3DObjectDialog.Execute then
   begin
   begin
-    FImageActions.Import3DObject(Open3DObjectDialog.FileName);
+    ImageAction.Import3DObject(Open3DObjectDialog.FileName);
     Config.SetDefault3dObjectDirectory(ExtractFilePath(Open3DObjectDialog.FileName));
     Config.SetDefault3dObjectDirectory(ExtractFilePath(Open3DObjectDialog.FileName));
   end;
   end;
   LazPaintInstance.ShowTopmost(topmostInfo);
   LazPaintInstance.ShowTopmost(topmostInfo);
@@ -2079,7 +2095,7 @@ begin
       end;
       end;
     end;
     end;
   end;
   end;
-  if FImageActions.LoadSelection(selectionFileName, @loadedImage) then
+  if ImageAction.LoadSelection(selectionFileName, @loadedImage) then
   begin
   begin
     FSaveSelectionInitialFilename := selectionFileName;
     FSaveSelectionInitialFilename := selectionFileName;
     if Assigned(Scripting.RecordingFunctionParameters) then
     if Assigned(Scripting.RecordingFunctionParameters) then
@@ -2314,11 +2330,11 @@ begin
                   for i := 0 to high(loadedLayers) do
                   for i := 0 to high(loadedLayers) do
                   if Assigned(loadedLayers[i].bmp) then
                   if Assigned(loadedLayers[i].bmp) then
                   begin
                   begin
-                    FImageActions.AddLayerFromBitmap(loadedLayers[i].bmp,ExtractFileName(loadedLayers[i].filename));
+                    ImageAction.AddLayerFromBitmap(loadedLayers[i].bmp,ExtractFileName(loadedLayers[i].filename));
                     loadedLayers[i].bmp := nil;
                     loadedLayers[i].bmp := nil;
                   end else
                   end else
                   begin
                   begin
-                    FImageActions.AddLayerFromOriginal(loadedLayers[i].orig,ExtractFileName(loadedLayers[i].filename));
+                    ImageAction.AddLayerFromOriginal(loadedLayers[i].orig,ExtractFileName(loadedLayers[i].filename));
                     loadedLayers[i].orig := nil;
                     loadedLayers[i].orig := nil;
                   end;
                   end;
                 end;
                 end;
@@ -2547,13 +2563,13 @@ begin
   begin
   begin
     if Assigned(loadedImage) and (length(chosenFiles)=1) then
     if Assigned(loadedImage) and (length(chosenFiles)=1) then
     begin
     begin
-      layerLoaded := length(FImageActions.TryAddLayerFromFile(chosenFiles[0], loadedImage)) > 0;
+      layerLoaded := length(ImageAction.TryAddLayerFromFile(chosenFiles[0], loadedImage)) > 0;
     end else
     end else
     begin
     begin
       FreeAndNil(loadedImage);
       FreeAndNil(loadedImage);
       for i := 0 to high(chosenFiles) do
       for i := 0 to high(chosenFiles) do
         begin
         begin
-          if length(FImageActions.TryAddLayerFromFile(chosenFiles[i])) > 0 then
+          if length(ImageAction.TryAddLayerFromFile(chosenFiles[i])) > 0 then
             layerLoaded := true;
             layerLoaded := true;
         end;
         end;
     end;
     end;
@@ -3091,7 +3107,7 @@ begin
                     end
                     end
                     else
                     else
                     begin
                     begin
-                      FImageActions.RemoveSelection;
+                      ImageAction.RemoveSelection;
                       texMapBounds := newTexture.GetImageBounds;
                       texMapBounds := newTexture.GetImageBounds;
                       BGRAReplace(newTexture, newTexture.GetPart(texMapBounds));
                       BGRAReplace(newTexture, newTexture.GetPart(texMapBounds));
                       ToolManager.BackFill.SetTexture(newTexture, AffineMatrixIdentity,
                       ToolManager.BackFill.SetTexture(newTexture, AffineMatrixIdentity,
@@ -3192,7 +3208,7 @@ begin
                   mrYes:
                   mrYes:
                     begin
                     begin
                       ToolManager.ToolCloseDontReopen;
                       ToolManager.ToolCloseDontReopen;
-                      FImageActions.RetrieveSelection;
+                      ImageAction.RetrieveSelection;
                       ToolManager.ToolOpen;
                       ToolManager.ToolOpen;
                     end;
                     end;
                 end;
                 end;
@@ -3927,6 +3943,11 @@ begin
     btnRightDown := false;
     btnRightDown := false;
     if ToolManager.ToolUp then PaintPictureNow;
     if ToolManager.ToolUp then PaintPictureNow;
   end;
   end;
+  if not (ssMiddle in Shift) and btnMiddleDown then
+  begin
+    btnMiddleDown := false;
+    if ToolManager.ToolUp then PaintPictureNow;
+  end;
   if not btnLeftDown and not btnRightDown then
   if not btnLeftDown and not btnRightDown then
   begin
   begin
     CanCompressOrUpdateStack := true;
     CanCompressOrUpdateStack := true;
@@ -4379,6 +4400,11 @@ begin
   if AEvent.DelayedStackUpdate then FUpdateStackWhenIdle := true;
   if AEvent.DelayedStackUpdate then FUpdateStackWhenIdle := true;
 end;
 end;
 
 
+procedure TFMain.OnImageRenderChanged(sender: TObject);
+begin
+  InvalidatePicture;
+end;
+
 procedure TFMain.UpdateEditPicture(ADelayed: boolean = false);
 procedure TFMain.UpdateEditPicture(ADelayed: boolean = false);
 begin
 begin
   if ToolManager.ToolUpdate then
   if ToolManager.ToolUpdate then
@@ -4590,6 +4616,11 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TFMain.SetUpdatingPopup(AValue: boolean);
+begin
+  FImageView.UpdatingPopup := AValue;
+end;
+
 function TFMain.GetCurrentPressure: single;
 function TFMain.GetCurrentPressure: single;
 begin
 begin
   if Assigned(FTablet) and FTablet.Present and FTablet.Entering and (FTablet.Max > 0) then
   if Assigned(FTablet) and FTablet.Present and FTablet.Entering and (FTablet.Max > 0) then
@@ -4604,6 +4635,16 @@ begin
   else result := false;
   else result := false;
 end;
 end;
 
 
+function TFMain.GetImageAction: TImageActions;
+begin
+  result := TImageActions(LazPaintInstance.ImageAction);
+end;
+
+function TFMain.GetUpdatingPopup: boolean;
+begin
+  result := FImageView.UpdatingPopup;
+end;
+
 function TFMain.GetScriptContext: TScriptContext;
 function TFMain.GetScriptContext: TScriptContext;
 begin
 begin
   result := LazPaintInstance.ScriptContext;
   result := LazPaintInstance.ScriptContext;

+ 48 - 17
lazpaint/lazpainttype.pas

@@ -10,7 +10,7 @@ uses
   {$IFDEF LINUX}, InterfaceBase{$ENDIF};
   {$IFDEF LINUX}, InterfaceBase{$ENDIF};
 
 
 const
 const
-  LazPaintVersion = 7000800;
+  LazPaintVersion = 7000900;
 
 
   function LazPaintVersionStr: string;
   function LazPaintVersionStr: string;
 
 
@@ -109,7 +109,8 @@ function IsOnlyRenderChange(const ARect:TRect): boolean;
 type
 type
     ArrayOfBGRABitmap = array of TBGRABitmap;
     ArrayOfBGRABitmap = array of TBGRABitmap;
     TColorTarget = (ctForeColorSolid, ctForeColorStartGrad, ctForeColorEndGrad,
     TColorTarget = (ctForeColorSolid, ctForeColorStartGrad, ctForeColorEndGrad,
-                    ctBackColorSolid, ctBackColorStartGrad, ctBackColorEndGrad);
+                    ctBackColorSolid, ctBackColorStartGrad, ctBackColorEndGrad,
+                    ctOutlineColorSolid, ctOutlineColorStartGrad, ctOutlineColorEndGrad);
     TFlipOption = (foAuto, foWholePicture, foSelection, foCurrentLayer);
     TFlipOption = (foAuto, foWholePicture, foSelection, foCurrentLayer);
 
 
     PImageEntry = ^TImageEntry;
     PImageEntry = ^TImageEntry;
@@ -174,6 +175,7 @@ type
 
 
     function GetConfig: TLazPaintConfig; virtual; abstract;
     function GetConfig: TLazPaintConfig; virtual; abstract;
     function GetImage: TLazPaintImage; virtual; abstract;
     function GetImage: TLazPaintImage; virtual; abstract;
+    function GetImageAction: TObject; virtual; abstract;
     function GetToolManager: TToolManager; virtual; abstract;
     function GetToolManager: TToolManager; virtual; abstract;
     procedure SetBlackAndWhite(AValue: boolean); virtual;
     procedure SetBlackAndWhite(AValue: boolean); virtual;
     function GetZoomFactor: single; virtual;
     function GetZoomFactor: single; virtual;
@@ -321,6 +323,7 @@ type
     property ChooseColorTarget: TColorTarget read GetChooseColorTarget write setChooseColorTarget;
     property ChooseColorTarget: TColorTarget read GetChooseColorTarget write setChooseColorTarget;
     property Config: TLazPaintConfig read GetConfig;
     property Config: TLazPaintConfig read GetConfig;
     property Image: TLazPaintImage read GetImage;
     property Image: TLazPaintImage read GetImage;
+    property ImageAction: TObject read GetImageAction;
     property ZoomFactor: single read GetZoomFactor;
     property ZoomFactor: single read GetZoomFactor;
     property ToolManager: TToolManager read GetToolManager;
     property ToolManager: TToolManager read GetToolManager;
     property Embedded: boolean read GetEmbedded;
     property Embedded: boolean read GetEmbedded;
@@ -645,30 +648,40 @@ begin
 end;
 end;
 
 
 function TLazPaintCustomInstance.GetColor(ATarget: TColorTarget): TBGRAPixel;
 function TLazPaintCustomInstance.GetColor(ATarget: TColorTarget): TBGRAPixel;
+  function GetStartColor(AFill: TVectorialFill): TBGRAPixel;
+  begin
+    if AFill.FillType = vftGradient then
+      result := AFill.Gradient.StartColor
+      else result := AFill.AverageColor;
+  end;
+  function GetEndColor(AFill: TVectorialFill): TBGRAPixel;
+  begin
+    if AFill.FillType = vftGradient then
+      result := AFill.Gradient.EndColor
+      else result := AFill.AverageColor;
+  end;
+
 begin
 begin
   case ATarget of
   case ATarget of
-    ctForeColorSolid: result := ToolManager.ForeColor;
-    ctForeColorStartGrad: if ToolManager.ForeFill.FillType = vftGradient then
-                            result := ToolManager.ForeFill.Gradient.StartColor
-                          else result := ToolManager.ForeColor;
-    ctForeColorEndGrad: if ToolManager.ForeFill.FillType = vftGradient then
-                          result := ToolManager.ForeFill.Gradient.EndColor
-                        else result := ToolManager.ForeColor;
-    ctBackColorSolid: result := ToolManager.BackColor;
-    ctBackColorStartGrad: if ToolManager.BackFill.FillType = vftGradient then
-                            result := ToolManager.BackFill.Gradient.StartColor
-                          else result := ToolManager.BackColor;
-    ctBackColorEndGrad: if ToolManager.BackFill.FillType = vftGradient then
-                          result := ToolManager.BackFill.Gradient.EndColor
-                        else result := ToolManager.BackColor;
+    ctForeColorSolid: result := ToolManager.ForeFill.AverageColor;
+    ctForeColorStartGrad: result := GetStartColor(ToolManager.ForeFill);
+    ctForeColorEndGrad: result := GetEndColor(ToolManager.ForeFill);
+    ctBackColorSolid: result := ToolManager.BackFill.AverageColor;
+    ctBackColorStartGrad: result := GetStartColor(ToolManager.BackFill);
+    ctBackColorEndGrad: result := GetEndColor(ToolManager.BackFill);
+    ctOutlineColorSolid: result := ToolManager.OutlineFill.AverageColor;
+    ctOutlineColorStartGrad: result := GetStartColor(ToolManager.OutlineFill);
+    ctOutlineColorEndGrad: result := GetEndColor(ToolManager.OutlineFill);
   else
   else
     result := BGRAPixelTransparent;
     result := BGRAPixelTransparent;
   end;
   end;
+  if BlackAndWhite then result := BGRAToGrayscale(result);
 end;
 end;
 
 
 procedure TLazPaintCustomInstance.SetColor(ATarget: TColorTarget;
 procedure TLazPaintCustomInstance.SetColor(ATarget: TColorTarget;
   AColor: TBGRAPixel);
   AColor: TBGRAPixel);
 begin
 begin
+  if BlackAndWhite then AColor := BGRAToGrayscale(AColor);
   case ATarget of
   case ATarget of
     ctForeColorSolid: if ToolManager.ForeFill.FillType = vftSolid then
     ctForeColorSolid: if ToolManager.ForeFill.FillType = vftSolid then
                         ToolManager.ForeColor := AColor;
                         ToolManager.ForeColor := AColor;
@@ -682,6 +695,12 @@ begin
                             ToolManager.BackFill.Gradient.StartColor := AColor;
                             ToolManager.BackFill.Gradient.StartColor := AColor;
     ctBackColorEndGrad: if ToolManager.BackFill.FillType = vftGradient then
     ctBackColorEndGrad: if ToolManager.BackFill.FillType = vftGradient then
                           ToolManager.BackFill.Gradient.EndColor := AColor;
                           ToolManager.BackFill.Gradient.EndColor := AColor;
+    ctOutlineColorSolid: if ToolManager.OutlineFill.FillType = vftSolid then
+                        ToolManager.OutlineColor := AColor;
+    ctOutlineColorStartGrad: if ToolManager.OutlineFill.FillType = vftGradient then
+                            ToolManager.OutlineFill.Gradient.StartColor := AColor;
+    ctOutlineColorEndGrad: if ToolManager.OutlineFill.FillType = vftGradient then
+                          ToolManager.OutlineFill.Gradient.EndColor := AColor;
   end;
   end;
 end;
 end;
 
 
@@ -693,9 +712,21 @@ end;
 
 
 procedure TLazPaintCustomInstance.ShowMessage(ACaption: string; AMessage: string; ADlgType: TMsgDlgType = mtInformation);
 procedure TLazPaintCustomInstance.ShowMessage(ACaption: string; AMessage: string; ADlgType: TMsgDlgType = mtInformation);
 var top: TTopMostInfo;
 var top: TTopMostInfo;
+  elems: TStringList;
+  res: TModalResult;
 begin
 begin
   top := HideTopmost;
   top := HideTopmost;
-  QuestionDlg(ACaption,AMessage,ADlgType,[mrOk,rsOkay],'');
+  elems := TStringList.Create;
+  elems.Delimiter:= #9;
+  elems.StrictDelimiter:= true;
+  elems.DelimitedText:= AMessage;
+  if (elems.Count = 3) and (elems[1] = rsDownload) then
+  begin
+    res := QuestionDlg(ACaption,elems[0],ADlgType,[mrOk,rsDownload,mrCancel,rsCancel],'');
+    if res = mrOk then OpenURL(elems[2]);
+  end else
+    QuestionDlg(ACaption,AMessage,ADlgType,[mrOk,rsOkay],'');
+  elems.Free;
   ShowTopmost(top);
   ShowTopmost(top);
 end;
 end;
 
 

+ 120 - 155
lazpaint/maintoolbar.inc

@@ -1,4 +1,31 @@
 procedure TFMain.CreateToolbarElements;
 procedure TFMain.CreateToolbarElements;
+
+  procedure InitVectorialFill(vf: TLCVectorialFillControl; grad: TBGRALayerGradientOriginal;
+      lbl: TLabel; pnl: TPanel; mouseMove: TMouseMoveEvent);
+  begin
+    vf.PopupMenu := nil;
+    vf.VerticalPadding:= DoScaleY(6, OriginalDPI);
+    vf.OnChooseColor :=  @VectorialFill_ChooseColor;
+    vf.OnTextureClick := @VectorialFill_TextureClick;
+    vf.OnFillChange:=    @VectorialFill_Change;
+    vf.AutoSize := False;
+    vf.OnFillTypeChange:=    @VectorialFill_TypeChange;
+    vf.OnAdjustToShape:=     @VectorialFill_AdjustToShape;
+    vf.OnEditGradTexPoints:= @VectorialFill_EditGradTexPoints;
+    vf.OnResize:= @VectorialFill_Resize;
+    with grad do
+    begin
+      vf.GradStartColor:= StartColor;
+      vf.GradEndColor:= EndColor;
+      vf.GradientType:= GradientType;
+      vf.GradRepetition:= Repetition;
+      vf.GradInterpolation:= ColorInterpolation;
+    end;
+    if Assigned(lbl) then lbl.OnMouseMove:= mouseMove;
+    pnl.OnMouseMove:= mouseMove;
+    vf.OnMouseMove:= mouseMove;
+  end;
+
 var
 var
   ps: TPenStyle;
   ps: TPenStyle;
 begin
 begin
@@ -8,48 +35,12 @@ begin
   Panel_ToolbarBackground.PopupMenu := PopupToolbar;
   Panel_ToolbarBackground.PopupMenu := PopupToolbar;
   Perspective_Repeat.OnClick:=@Perspective_RepeatClick;
   Perspective_Repeat.OnClick:=@Perspective_RepeatClick;
   Perspective_TwoPlanes.OnClick := @Perspective_TwoPlanesClick;
   Perspective_TwoPlanes.OnClick := @Perspective_TwoPlanesClick;
-  Panel_PenFill.PopupMenu := nil;
-  Panel_BackFill.PopupMenu := nil;
-  VectorialFill_Pen.VerticalPadding:= DoScaleY(6, OriginalDPI);
-  VectorialFill_Back.VerticalPadding:= DoScaleY(6, OriginalDPI);
-  VectorialFill_Pen.OnChooseColor := @VectorialFill_PenChooseColor;
-  VectorialFill_Back.OnChooseColor := @VectorialFill_BackChooseColor;
-  VectorialFill_Pen.OnTextureClick := @VectorialFill_TextureClick;
-  VectorialFill_Back.OnTextureClick := @VectorialFill_TextureClick;
-  VectorialFill_Pen.OnFillChange:=@VectorialFill_PenChange;
-  VectorialFill_Back.OnFillChange:=@VectorialFill_BackChange;
-  VectorialFill_Pen.AutoSize := False;
-  VectorialFill_Back.AutoSize := False;
-  VectorialFill_Pen.OnFillTypeChange:=@VectorialFill_PenTypeChange;
-  VectorialFill_Back.OnFillTypeChange:=@VectorialFill_BackTypeChange;
-  VectorialFill_Pen.OnAdjustToShape:=@VectorialFill_PenAdjustToShape;
-  VectorialFill_Back.OnAdjustToShape:=@VectorialFill_BackAdjustToShape;
-  VectorialFill_Pen.OnEditGradTexPoints:=@VectorialFill_PenEditGradTexPoints;
-  VectorialFill_Back.OnEditGradTexPoints:=@VectorialFill_BackEditGradTexPoints;
-  VectorialFill_Pen.OnResize:=@VectorialFill_PenResize;
-  VectorialFill_Back.OnResize:=@VectorialFill_BackResize;
-  with ToolManager.ForeLastGradient do
-  begin
-    VectorialFill_Pen.GradStartColor:= StartColor;
-    VectorialFill_Pen.GradEndColor:= EndColor;
-    VectorialFill_Pen.GradientType:= GradientType;
-    VectorialFill_Pen.GradRepetition:= Repetition;
-    VectorialFill_Pen.GradInterpolation:= ColorInterpolation;
-  end;
-  with ToolManager.BackLastGradient do
-  begin
-    VectorialFill_Back.GradStartColor:= StartColor;
-    VectorialFill_Back.GradEndColor:= EndColor;
-    VectorialFill_Back.GradientType:= GradientType;
-    VectorialFill_Back.GradRepetition:= Repetition;
-    VectorialFill_Back.GradInterpolation:= ColorInterpolation;
-  end;
-  Label_Pen.OnMouseMove:=@VectorialFill_ShowPenFill;
-  Panel_PenFill.OnMouseMove:=@VectorialFill_ShowPenFill;
-  VectorialFill_Pen.OnMouseMove:=@VectorialFill_ShowPenFill;
-  Label_Back.OnMouseMove:=@VectorialFill_ShowBackFill;
-  Panel_BackFill.OnMouseMove:=@VectorialFill_ShowBackFill;
-  VectorialFill_Back.OnMouseMove:=@VectorialFill_ShowBackFill;
+  InitVectorialFill(VectorialFill_Pen, ToolManager.ForeLastGradient, Label_Pen, Panel_PenFill, @VectorialFill_ShowPenFill);
+  VectorialFill_Pen.SolidColor := ToolManager.ForeColor;
+  InitVectorialFill(VectorialFill_Back, ToolManager.BackLastGradient, Label_Back, Panel_BackFill, @VectorialFill_ShowBackFill);
+  VectorialFill_Back.SolidColor := ToolManager.BackColor;
+  InitVectorialFill(VectorialFill_Outline, ToolManager.OutlineLastGradient, nil, Panel_OutlineFill, @VectorialFill_ShowOutlineFill);
+  VectorialFill_Outline.SolidColor := ToolManager.OutlineColor;
   Image_SwapColors.OnMouseDown := @Image_SwapColorsMouseDown;
   Image_SwapColors.OnMouseDown := @Image_SwapColorsMouseDown;
   Tool_DrawShapeBorder.OnClick := @Tool_DrawShapeBorderClick;
   Tool_DrawShapeBorder.OnClick := @Tool_DrawShapeBorderClick;
   Tool_Aliasing.OnClick := @Tool_AliasingClick;
   Tool_Aliasing.OnClick := @Tool_AliasingClick;
@@ -319,8 +310,10 @@ begin
   ToolManager.FillControls.Add(Panel_SwapColor);
   ToolManager.FillControls.Add(Panel_SwapColor);
   ToolManager.FillControls.Add(Panel_BackFill);
   ToolManager.FillControls.Add(Panel_BackFill);
   ToolManager.FillControls.Add(Panel_ColorDiff);
   ToolManager.FillControls.Add(Panel_ColorDiff);
+  ToolManager.OutlineFillControls.Add(Panel_OutlineFill);
   ToolManager.BrushControls.Add(Panel_Brush);
   ToolManager.BrushControls.Add(Panel_Brush);
   ToolManager.RatioControls.Add(Panel_Ratio);
   ToolManager.RatioControls.Add(Panel_Ratio);
+  ToolManager.DonateControls.Add(Panel_Donate);
 end;
 end;
 
 
 procedure TFMain.UpdateToolOptions;
 procedure TFMain.UpdateToolOptions;
@@ -561,10 +554,13 @@ begin
   UpdateAllowedFillTypes;
   UpdateAllowedFillTypes;
   VectorialFill_Pen.CanAdjustToShape := ToolManager.ToolProvideCommand(tcForeAdjustToShape);
   VectorialFill_Pen.CanAdjustToShape := ToolManager.ToolProvideCommand(tcForeAdjustToShape);
   VectorialFill_Back.CanAdjustToShape := ToolManager.ToolProvideCommand(tcBackAdjustToShape);
   VectorialFill_Back.CanAdjustToShape := ToolManager.ToolProvideCommand(tcBackAdjustToShape);
+  VectorialFill_Outline.CanAdjustToShape := ToolManager.ToolProvideCommand(tcOutlineAdjustToShape);
   VectorialFill_Pen.CanEditGradTexPoints := ToolManager.ToolProvideCommand(tcForeEditGradTexPoints);
   VectorialFill_Pen.CanEditGradTexPoints := ToolManager.ToolProvideCommand(tcForeEditGradTexPoints);
   VectorialFill_Back.CanEditGradTexPoints := ToolManager.ToolProvideCommand(tcBackEditGradTexPoints);
   VectorialFill_Back.CanEditGradTexPoints := ToolManager.ToolProvideCommand(tcBackEditGradTexPoints);
+  VectorialFill_Outline.CanEditGradTexPoints := ToolManager.ToolProvideCommand(tcOutlineEditGradTexPoints);
   VectorialFill_Pen.EditingGradTexPoints := ToolManager.IsForeEditGradTexPoints;
   VectorialFill_Pen.EditingGradTexPoints := ToolManager.IsForeEditGradTexPoints;
   VectorialFill_Back.EditingGradTexPoints := ToolManager.IsBackEditGradTexPoints;
   VectorialFill_Back.EditingGradTexPoints := ToolManager.IsBackEditGradTexPoints;
+  VectorialFill_Outline.EditingGradTexPoints := ToolManager.IsOutlineEditGradTexPoints;
 end;
 end;
 
 
 procedure TFMain.QueryArrange;
 procedure TFMain.QueryArrange;
@@ -733,8 +729,15 @@ begin
   TimerHideFill.Enabled := false;
   TimerHideFill.Enabled := false;
   VectorialFill_Pen.Height := VectorialFill_Pen.ToolIconSize + VectorialFill_Pen.VerticalPadding;
   VectorialFill_Pen.Height := VectorialFill_Pen.ToolIconSize + VectorialFill_Pen.VerticalPadding;
   VectorialFill_Back.Height := VectorialFill_Back.ToolIconSize + VectorialFill_Back.VerticalPadding;
   VectorialFill_Back.Height := VectorialFill_Back.ToolIconSize + VectorialFill_Back.VerticalPadding;
+  VectorialFill_Outline.Height := VectorialFill_Outline.ToolIconSize + VectorialFill_Outline.VerticalPadding;
   Panel_PenFill.Height := Panel_SwapColor.Height;
   Panel_PenFill.Height := Panel_SwapColor.Height;
   Panel_BackFill.Height := Panel_SwapColor.Height;
   Panel_BackFill.Height := Panel_SwapColor.Height;
+  Panel_OutlineFill.Height := Panel_SwapColor.Height;
+end;
+
+procedure TFMain.ToolButton_DonateClick(Sender: TObject);
+begin
+  LazPaintInstance.Donate;
 end;
 end;
 
 
 procedure TFMain.SpinEdit_GridNbExit(Sender: TObject);
 procedure TFMain.SpinEdit_GridNbExit(Sender: TObject);
@@ -812,20 +815,20 @@ begin
 end;
 end;
 
 
 procedure TFMain.UpdateChooseColors;
 procedure TFMain.UpdateChooseColors;
+  procedure UpdateFor(AFillControl: TLCVectorialFillControl; ATargetSolid, ATargetStart, ATargetEnd: TColorTarget);
+  begin
+    if (AFillControl.FillType = vftSolid) and
+       (LazPaintInstance.ChooseColorTarget in [ATargetStart, ATargetEnd]) then
+      LazPaintInstance.ChooseColorTarget := ATargetSolid else
+    if (AFillControl.FillType = vftGradient) and
+       (LazPaintInstance.ChooseColorTarget = ATargetSolid) then
+      LazPaintInstance.ChooseColorTarget := ATargetStart;
+  end;
+
 begin
 begin
-  if (VectorialFill_Back.FillType = vftSolid) and
-     (LazPaintInstance.ChooseColorTarget in [ctBackColorStartGrad,ctBackColorEndGrad]) then
-    LazPaintInstance.ChooseColorTarget := ctBackColorSolid else
-  if (VectorialFill_Back.FillType = vftGradient) and
-     (LazPaintInstance.ChooseColorTarget = ctBackColorSolid) then
-    LazPaintInstance.ChooseColorTarget := ctBackColorStartGrad else
-  if (VectorialFill_Pen.FillType = vftSolid) and
-     (LazPaintInstance.ChooseColorTarget in [ctForeColorStartGrad,ctForeColorEndGrad]) then
-    LazPaintInstance.ChooseColorTarget := ctForeColorSolid else
-  if (VectorialFill_Pen.FillType = vftGradient) and
-     (LazPaintInstance.ChooseColorTarget = ctForeColorSolid) then
-    LazPaintInstance.ChooseColorTarget := ctForeColorStartGrad else
-      LazPaintInstance.ColorToFChooseColor;
+  UpdateFor(VectorialFill_Back, ctBackColorSolid, ctBackColorStartGrad, ctBackColorEndGrad);
+  UpdateFor(VectorialFill_Pen, ctForeColorSolid, ctForeColorStartGrad, ctForeColorEndGrad);
+  UpdateFor(VectorialFill_Outline, ctOutlineColorSolid, ctOutlineColorStartGrad, ctOutlineColorEndGrad);
 end;
 end;
 
 
 procedure TFMain.UpdateAllowedFillTypes;
 procedure TFMain.UpdateAllowedFillTypes;
@@ -896,137 +899,107 @@ begin
   result := Assigned(ActiveControl) and (ActiveControl.Name = 'EColor');
   result := Assigned(ActiveControl) and (ActiveControl.Name = 'EColor');
 end;
 end;
 
 
-procedure TFMain.VectorialFill_BackChange(Sender: TObject);
-var
-  tempFill: TVectorialFill;
-begin
-  if FInFillChange then exit;
-  FInFillChange:= true;
-
-  if ToolManager.BackFill.FillType <> VectorialFill_Back.FillType then
-  begin
-    tempFill := TVectorialFill.Create;
-    VectorialFill_Back.UpdateFillExceptGeometry(tempFill);
-    tempFill.FitGeometry(ToolManager.SuggestGradientBox);
-    ToolManager.BackFill.Assign(tempFill);
-    tempFill.Free;
-  end else
-    VectorialFill_Back.UpdateFillExceptGeometry(ToolManager.BackFill);
-
-  UpdateChooseColors;
-  UpdateEditPicture;
-  FInFillChange:= false;
-end;
-
-procedure TFMain.VectorialFill_BackEditGradTexPoints(Sender: TObject);
-begin
-  ToolManager.ToolCommand(tcBackEditGradTexPoints);
-end;
-
-procedure TFMain.VectorialFill_BackResize(Sender: TObject);
-begin
-  QueryArrange;
-end;
-
-procedure TFMain.VectorialFill_BackTypeChange(Sender: TObject);
-begin
-  DarkThemeInstance.Apply(VectorialFill_Back, DarkTheme);
-  VectorialFill_Back.Width := VectorialFill_Back.PreferredSize.cx;
-end;
-
-procedure TFMain.VectorialFill_BackAdjustToShape(Sender: TObject);
+procedure TFMain.VectorialFill_EditGradTexPoints(Sender: TObject);
 begin
 begin
-  ToolManager.ToolCommand(tcBackAdjustToShape);
+  if Sender = VectorialFill_Pen then ToolManager.ToolCommand(tcForeEditGradTexPoints)
+  else if Sender = VectorialFill_Back then ToolManager.ToolCommand(tcBackEditGradTexPoints)
+  else if Sender = VectorialFill_Outline then ToolManager.ToolCommand(tcOutlineEditGradTexPoints);
 end;
 end;
 
 
-procedure TFMain.VectorialFill_PenAdjustToShape(Sender: TObject);
+procedure TFMain.VectorialFill_AdjustToShape(Sender: TObject);
 begin
 begin
-  ToolManager.ToolCommand(tcForeAdjustToShape);
+  if Sender = VectorialFill_Pen then ToolManager.ToolCommand(tcForeAdjustToShape)
+  else if Sender = VectorialFill_Back then ToolManager.ToolCommand(tcBackAdjustToShape)
+  else if Sender = VectorialFill_Outline then ToolManager.ToolCommand(tcOutlineAdjustToShape);
 end;
 end;
 
 
-procedure TFMain.VectorialFill_PenChange(Sender: TObject);
+procedure TFMain.VectorialFill_Change(Sender: TObject);
 var
 var
-  tempFill: TVectorialFill;
+  tempFill, targetFill: TVectorialFill;
+  vf: TLCVectorialFillControl;
 begin
 begin
   if FInFillChange then exit;
   if FInFillChange then exit;
   FInFillChange:= true;
   FInFillChange:= true;
+  vf := Sender as TLCVectorialFillControl;
+  if vf = VectorialFill_Pen then targetFill := ToolManager.ForeFill
+  else if vf = VectorialFill_Back then targetFill := ToolManager.BackFill
+  else if vf = VectorialFill_Outline then targetFill := ToolManager.OutlineFill
+  else exit;
 
 
-  if ToolManager.ForeFill.FillType <> VectorialFill_Pen.FillType then
+  if targetFill.FillType <> vf.FillType then
   begin
   begin
     tempFill := TVectorialFill.Create;
     tempFill := TVectorialFill.Create;
-    VectorialFill_Pen.UpdateFillExceptGeometry(tempFill);
+    vf.UpdateFillExceptGeometry(tempFill);
     tempFill.FitGeometry(ToolManager.SuggestGradientBox);
     tempFill.FitGeometry(ToolManager.SuggestGradientBox);
-    ToolManager.ForeFill.Assign(tempFill);
+    targetFill.Assign(tempFill);
     tempFill.Free;
     tempFill.Free;
   end else
   end else
-    VectorialFill_Pen.UpdateFillExceptGeometry(ToolManager.ForeFill);
+    vf.UpdateFillExceptGeometry(targetFill);
 
 
   UpdateChooseColors;
   UpdateChooseColors;
   UpdateEditPicture;
   UpdateEditPicture;
   FInFillChange:= false;
   FInFillChange:= false;
 end;
 end;
 
 
-procedure TFMain.VectorialFill_PenEditGradTexPoints(Sender: TObject);
-begin
-  ToolManager.ToolCommand(tcForeEditGradTexPoints);
-end;
-
-procedure TFMain.VectorialFill_PenResize(Sender: TObject);
+procedure TFMain.VectorialFill_Resize(Sender: TObject);
 begin
 begin
   QueryArrange;
   QueryArrange;
 end;
 end;
 
 
-procedure TFMain.VectorialFill_PenTypeChange(Sender: TObject);
+procedure TFMain.VectorialFill_TypeChange(Sender: TObject);
+var
+  vf: TLCVectorialFillControl;
 begin
 begin
-  DarkThemeInstance.Apply(VectorialFill_Pen, DarkTheme);
-  VectorialFill_Pen.Width := VectorialFill_Pen.PreferredSize.cx;
+  vf := Sender as TLCVectorialFillControl;
+  DarkThemeInstance.Apply(vf, DarkTheme);
+  vf.Width := vf.PreferredSize.cx;
 end;
 end;
 
 
-procedure TFMain.VectorialFill_ShowBackFill(Sender: TObject;
-  Shift: TShiftState; X, Y: Integer);
+procedure TFMain.VectorialFill_ShowBackFill(Sender: TObject; Shift: TShiftState; X, Y: Integer);
 begin
 begin
-  ShowBackFill;
+  ShowFill(VectorialFill_Back, Panel_BackFill);
 end;
 end;
 
 
-procedure TFMain.VectorialFill_ShowPenFill(Sender: TObject; Shift: TShiftState;
-  X, Y: Integer);
+procedure TFMain.VectorialFill_ShowPenFill(Sender: TObject; Shift: TShiftState; X, Y: Integer);
 begin
 begin
-  ShowPenFill;
+  ShowFill(VectorialFill_Pen, Panel_PenFill);
 end;
 end;
 
 
-procedure TFMain.VectorialFill_PenChooseColor(ASender: TObject; AButton: TMouseButton;
-  AColorIndex: integer; var AColorValue: TBGRAPixel; out AHandled: boolean);
-var
-  target: TColorTarget;
+procedure TFMain.VectorialFill_ShowOutlineFill(Sender: TObject; Shift: TShiftState; X, Y: Integer);
 begin
 begin
-  AHandled := true;
-  case AColorIndex of
-    -1: target := ctForeColorSolid;
-    0: target := ctForeColorStartGrad;
-    1: target := ctForeColorEndGrad;
-    else exit;
-  end;
-  if LazPaintInstance.ChooseColorVisible and (AButton = mbLeft) then
-    LazPaintInstance.ChooseColorTarget := target
-  else
-  begin
-    if ShowColorDialogFor(target) then
-      AColorValue := LazPaintInstance.GetColor(target);
-  end;
+  ShowFill(VectorialFill_Outline, Panel_OutlineFill);
 end;
 end;
 
 
-procedure TFMain.VectorialFill_BackChooseColor(ASender: TObject; AButton: TMouseButton;
+procedure TFMain.VectorialFill_ChooseColor(ASender: TObject; AButton: TMouseButton;
   AColorIndex: integer; var AColorValue: TBGRAPixel; out AHandled: boolean);
   AColorIndex: integer; var AColorValue: TBGRAPixel; out AHandled: boolean);
 var
 var
   target: TColorTarget;
   target: TColorTarget;
 begin
 begin
+  AHandled := false;
+  if ASender = VectorialFill_Pen then
+    case AColorIndex of
+      -1: target := ctForeColorSolid;
+      0: target := ctForeColorStartGrad;
+      1: target := ctForeColorEndGrad;
+      else exit;
+    end
+  else if ASender = VectorialFill_Back then
+    case AColorIndex of
+      -1: target := ctBackColorSolid;
+      0: target := ctBackColorStartGrad;
+      1: target := ctBackColorEndGrad;
+      else exit;
+    end
+  else if ASender = VectorialFill_Outline then
+    case AColorIndex of
+      -1: target := ctOutlineColorSolid;
+      0: target := ctOutlineColorStartGrad;
+      1: target := ctOutlineColorEndGrad;
+      else exit;
+    end
+  else exit;
+
   AHandled := true;
   AHandled := true;
-  case AColorIndex of
-    -1: target := ctBackColorSolid;
-    0: target := ctBackColorStartGrad;
-    1: target := ctBackColorEndGrad;
-    else exit;
-  end;
   if LazPaintInstance.ChooseColorVisible and (AButton = mbLeft) then
   if LazPaintInstance.ChooseColorVisible and (AButton = mbLeft) then
     LazPaintInstance.ChooseColorTarget := target
     LazPaintInstance.ChooseColorTarget := target
   else
   else
@@ -1489,19 +1462,11 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TFMain.ShowPenFill;
-begin
-  VectorialFill_Pen.BringToFront;
-  VectorialFill_Pen.Height := VectorialFill_Pen.PreferredSize.cy;
-  Panel_PenFill.Height := VectorialFill_Pen.Top+VectorialFill_Pen.Height+DoScaleY(3, OriginalDPI);
-  HideFill(3000, true);
-end;
-
-procedure TFMain.ShowBackFill;
+procedure TFMain.ShowFill(AFillControl: TLCVectorialFillControl; APanel: TPanel);
 begin
 begin
-  VectorialFill_Back.BringToFront;
-  VectorialFill_Back.Height := VectorialFill_Back.PreferredSize.cy;
-  Panel_BackFill.Height := VectorialFill_Back.Top+VectorialFill_Back.height+DoScaleY(3, OriginalDPI);
+  AFillControl.BringToFront;
+  AFillControl.Height := AFillControl.PreferredSize.cy;
+  APanel.Height := AFillControl.Top + AFillControl.Height + DoScaleY(3, OriginalDPI);
   HideFill(3000, true);
   HideFill(3000, true);
 end;
 end;
 
 

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.ar.po

@@ -3112,6 +3112,10 @@ msgstr ""
 msgid "Information"
 msgid "Information"
 msgstr "معلومات"
 msgstr "معلومات"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "تحميل"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3359,7 +3363,7 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

Разница между файлами не показана из-за своего большого размера
+ 126 - 168
lazpaint/release/bin/i18n/lazpaint.bg.po


+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.cs.po

@@ -3110,6 +3110,10 @@ msgstr ""
 msgid "Information"
 msgid "Information"
 msgstr "Informace"
 msgstr "Informace"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Stažení"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3357,7 +3361,7 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.de.po

@@ -3126,6 +3126,10 @@ msgstr "Unendlichkeit"
 msgid "Information"
 msgid "Information"
 msgstr "Information"
 msgstr "Information"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Herunterladen"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3373,7 +3377,7 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr "Erwartete Python-Version %1, aber %2 gefunden."
 msgstr "Erwartete Python-Version %1, aber %2 gefunden."
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.es.po

@@ -3112,6 +3112,10 @@ msgstr "Infinito"
 msgid "Information"
 msgid "Information"
 msgstr "Información"
 msgstr "Información"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Descargar"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3368,7 +3372,7 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr "Se esperaba la versión de Python %1 pero se encontró %2."
 msgstr "Se esperaba la versión de Python %1 pero se encontró %2."
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.fi.po

@@ -3101,6 +3101,10 @@ msgstr ""
 msgid "Information"
 msgid "Information"
 msgstr ""
 msgstr ""
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Ladata"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3348,7 +3352,7 @@ msgid "px"
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.fr.po

@@ -3122,6 +3122,10 @@ msgstr "Infinité"
 msgid "Information"
 msgid "Information"
 msgstr "Informations"
 msgstr "Informations"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Télécharger"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3378,7 +3382,7 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr "Version %1 de Python attendue mais %2 trouvée."
 msgstr "Version %1 de Python attendue mais %2 trouvée."
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.ja.po

@@ -3111,6 +3111,10 @@ msgstr ""
 msgid "Information"
 msgid "Information"
 msgstr ""
 msgstr ""
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "ダウンロード"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3358,7 +3362,7 @@ msgid "px"
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

Разница между файлами не показана из-за своего большого размера
+ 133 - 134
lazpaint/release/bin/i18n/lazpaint.kab.po


Разница между файлами не показана из-за своего большого размера
+ 171 - 166
lazpaint/release/bin/i18n/lazpaint.lv.po


+ 6 - 2
lazpaint/release/bin/i18n/lazpaint.nl.po

@@ -3141,6 +3141,10 @@ msgstr "Oneindigheid"
 msgid "Information"
 msgid "Information"
 msgstr "Informatie"
 msgstr "Informatie"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Downloaden"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3388,8 +3392,8 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
-msgstr "Verwachte python-versie %1 maar %2 gevonden."
+msgid "Expected Python version %1 but %2 found."
+msgstr "Verwachte Python-versie %1 maar %2 gevonden."
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk
 msgid "RAM disk"
 msgid "RAM disk"

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.po

@@ -3101,6 +3101,10 @@ msgstr ""
 msgid "Information"
 msgid "Information"
 msgstr ""
 msgstr ""
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr ""
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3357,7 +3361,7 @@ msgid "px"
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 6 - 2
lazpaint/release/bin/i18n/lazpaint.pt_BR.po

@@ -3127,6 +3127,10 @@ msgstr "Infinidade"
 msgid "Information"
 msgid "Information"
 msgstr "informações"
 msgstr "informações"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Baixar"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3374,8 +3378,8 @@ msgid "px"
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
-msgstr "Versão python esperada %1, mas %2 encontrada."
+msgid "Expected Python version %1 but %2 found."
+msgstr "Versão Python esperada %1, mas %2 encontrada."
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk
 msgid "RAM disk"
 msgid "RAM disk"

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.ru.po

@@ -3106,6 +3106,10 @@ msgstr ""
 msgid "Information"
 msgid "Information"
 msgstr ""
 msgstr ""
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "скачать"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3353,7 +3357,7 @@ msgid "px"
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr ""
 msgstr ""
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 5 - 1
lazpaint/release/bin/i18n/lazpaint.sv.po

@@ -3095,6 +3095,10 @@ msgstr "Oändlig"
 msgid "Information"
 msgid "Information"
 msgstr "Information"
 msgstr "Information"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "Ladda ner"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3342,7 +3346,7 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
+msgid "Expected Python version %1 but %2 found."
 msgstr "Python version %1 var förväntad men hittade %2."
 msgstr "Python version %1 var förväntad men hittade %2."
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk

+ 6 - 2
lazpaint/release/bin/i18n/lazpaint.zh_CN.po

@@ -3111,6 +3111,10 @@ msgstr "无限"
 msgid "Information"
 msgid "Information"
 msgstr "信息"
 msgstr "信息"
 
 
+#: uresourcestrings.rsdownload
+msgid "Download"
+msgstr "下载"
+
 #: uresourcestrings.rsintensity
 #: uresourcestrings.rsintensity
 msgctxt "uresourcestrings.rsintensity"
 msgctxt "uresourcestrings.rsintensity"
 msgid "Intensity"
 msgid "Intensity"
@@ -3367,8 +3371,8 @@ msgid "px"
 msgstr "px"
 msgstr "px"
 
 
 #: uresourcestrings.rspythonunexpectedversion
 #: uresourcestrings.rspythonunexpectedversion
-msgid "Expected python version %1 but %2 found."
-msgstr "需要 python 版本 %1 但找到 %2。"
+msgid "Expected Python version %1 but %2 found."
+msgstr "需要 Python 版本 %1 但找到 %2。"
 
 
 #: uresourcestrings.rsramdisk
 #: uresourcestrings.rsramdisk
 msgid "RAM disk"
 msgid "RAM disk"

Разница между файлами не показана из-за своего большого размера
+ 174 - 173
lazpaint/release/bin/i18n/lclstrconsts.kab.po


+ 180 - 171
lazpaint/release/bin/i18n/lcresourcestring.bg.po

@@ -1,171 +1,180 @@
-msgid ""
-msgstr "Content-Type: text/plain; charset=UTF-8"
-
-#: lcresourcestring.rsadjusttoshape
-msgid "Adjust to shape"
-msgstr ""
-
-#: lcresourcestring.rscigsbnegative
-msgid "Corr. HSL CCW"
-msgstr ""
-
-#: lcresourcestring.rscigsbpositive
-msgid "Corr. HSL CW"
-msgstr ""
-
-#: lcresourcestring.rscilinearhslnegative
-msgid "HSL CCW"
-msgstr ""
-
-#: lcresourcestring.rscilinearhslpositive
-msgid "HSL CW"
-msgstr ""
-
-#: lcresourcestring.rscilinearrgb
-msgid "RGB"
-msgstr ""
-
-#: lcresourcestring.rscistdrgb
-msgid "sRGB"
-msgstr ""
-
-#: lcresourcestring.rscolor
-msgid "Color"
-msgstr "Цвят"
-
-#: lcresourcestring.rscolorinterpolation
-msgid "Color interpolation"
-msgstr ""
-
-#: lcresourcestring.rseditgradtexpoints
-msgid "Edit gradient/texture points"
-msgstr ""
-
-#: lcresourcestring.rsendopacity
-msgid "End opacity"
-msgstr ""
-
-#: lcresourcestring.rsgradientangular
-msgid "Angular"
-msgstr ""
-
-#: lcresourcestring.rsgradientdiamond
-msgid "Diamond"
-msgstr ""
-
-#: lcresourcestring.rsgradientfill
-msgid "Gradient fill"
-msgstr "Преливане"
-
-#: lcresourcestring.rsgradientlinear
-msgid "Linear"
-msgstr "Линейно"
-
-#: lcresourcestring.rsgradientradial
-msgid "Radial"
-msgstr "Лъчево"
-
-#: lcresourcestring.rsgradientreflected
-msgid "Reflected"
-msgstr "Отражателно"
-
-#: lcresourcestring.rsgradientrepetition
-msgid "Gradient repetition"
-msgstr ""
-
-#: lcresourcestring.rsgrpad
-msgid "Pad"
-msgstr ""
-
-#: lcresourcestring.rsgrreflect
-msgid "Reflect"
-msgstr ""
-
-#: lcresourcestring.rsgrrepeat
-msgid "Repeat"
-msgstr ""
-
-#: lcresourcestring.rsgrsine
-msgid "Sine"
-msgstr "Синусоидално"
-
-#: lcresourcestring.rsincompatibletype
-msgid "Incompatible type"
-msgstr ""
-
-#: lcresourcestring.rsindexoutofbounds
-msgid "Index out of bounds"
-msgstr ""
-
-#: lcresourcestring.rslightposition
-msgid "Light position"
-msgstr "Разположение на светлината"
-
-#: lcresourcestring.rsloadtexture
-msgid "Load texture"
-msgstr ""
-
-#: lcresourcestring.rsnofill
-msgid "No fill"
-msgstr ""
-
-#: lcresourcestring.rsnottexturefill
-msgid "It is not a texture fill"
-msgstr ""
-
-#: lcresourcestring.rsopacity
-msgid "Opacity"
-msgstr "Прозрачност"
-
-#: lcresourcestring.rspreview
-msgid "Preview"
-msgstr ""
-
-#: lcresourcestring.rsshapeclassnotspecified
-msgid "Shape class not specified"
-msgstr ""
-
-#: lcresourcestring.rsshapenotfound
-msgid "Shape not found"
-msgstr ""
-
-#: lcresourcestring.rssolidcolor
-msgid "Solid color"
-msgstr ""
-
-#: lcresourcestring.rsstartopacity
-msgid "Start opacity"
-msgstr ""
-
-#: lcresourcestring.rsswapcolors
-msgid "Swap colors"
-msgstr "Превключване на цвета"
-
-#: lcresourcestring.rstexturefill
-msgid "Texture fill"
-msgstr ""
-
-#: lcresourcestring.rstexturerepetition
-msgid "Texture repetition"
-msgstr ""
-
-#: lcresourcestring.rstrnone
-msgid "No repetition"
-msgstr ""
-
-#: lcresourcestring.rstrrepeatboth
-msgid "Repeat both"
-msgstr ""
-
-#: lcresourcestring.rstrrepeatx
-msgid "Repeat X"
-msgstr ""
-
-#: lcresourcestring.rstrrepeaty
-msgid "Repeat Y"
-msgstr ""
-
-#: lcresourcestring.rsunknownshapeclass
-msgid "Unknown shape class \"%1\""
-msgstr ""
-
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: bg\n"
+"X-Generator: Poedit 2.2.3\n"
+
+#: lcresourcestring.rsadjusttoshape
+msgid "Adjust to shape"
+msgstr "Нагласяне според формата"
+
+#: lcresourcestring.rscigsbnegative
+msgid "Corr. HSL CCW"
+msgstr "Попр. НОО ОЧС"
+
+#: lcresourcestring.rscigsbpositive
+msgid "Corr. HSL CW"
+msgstr "Попр. НОО ЧС"
+
+#: lcresourcestring.rscilinearhslnegative
+msgid "HSL CCW"
+msgstr "НОО ОЧС"
+
+#: lcresourcestring.rscilinearhslpositive
+msgid "HSL CW"
+msgstr "НОО ЧС"
+
+#: lcresourcestring.rscilinearrgb
+msgid "RGB"
+msgstr "ЧЗС"
+
+#: lcresourcestring.rscistdrgb
+msgid "sRGB"
+msgstr ""
+
+#: lcresourcestring.rscolor
+msgid "Color"
+msgstr "Цвят"
+
+#: lcresourcestring.rscolorinterpolation
+msgid "Color interpolation"
+msgstr ""
+
+#: lcresourcestring.rseditgradtexpoints
+msgid "Edit gradient/texture points"
+msgstr ""
+
+#: lcresourcestring.rsendopacity
+msgid "End opacity"
+msgstr "Крайна прозрачност"
+
+#: lcresourcestring.rsgradientangular
+msgid "Angular"
+msgstr "Ъглово"
+
+#: lcresourcestring.rsgradientdiamond
+msgid "Diamond"
+msgstr "Ромбовидно"
+
+#: lcresourcestring.rsgradientfill
+msgid "Gradient fill"
+msgstr "Преливане"
+
+#: lcresourcestring.rsgradientlinear
+msgid "Linear"
+msgstr "Линейно"
+
+#: lcresourcestring.rsgradientradial
+msgid "Radial"
+msgstr "Лъчево"
+
+#: lcresourcestring.rsgradientreflected
+msgid "Reflected"
+msgstr "Отражателно"
+
+#: lcresourcestring.rsgradientrepetition
+msgid "Gradient repetition"
+msgstr "Повтаряне на преливането"
+
+#: lcresourcestring.rsgrpad
+msgid "Pad"
+msgstr ""
+
+#: lcresourcestring.rsgrreflect
+msgid "Reflect"
+msgstr "Отразяване"
+
+#: lcresourcestring.rsgrrepeat
+msgid "Repeat"
+msgstr "Повтаряне"
+
+#: lcresourcestring.rsgrsine
+msgid "Sine"
+msgstr "Синусоидално"
+
+#: lcresourcestring.rsincompatibletype
+msgid "Incompatible type"
+msgstr "Несъвместим вид"
+
+#: lcresourcestring.rsindexoutofbounds
+msgid "Index out of bounds"
+msgstr "Указателят е извън границите"
+
+#: lcresourcestring.rslightposition
+msgid "Light position"
+msgstr "Разположение на светлината"
+
+#: lcresourcestring.rsloadtexture
+msgid "Load texture"
+msgstr ""
+
+#: lcresourcestring.rsnofill
+msgid "No fill"
+msgstr "Без запълване"
+
+#: lcresourcestring.rsnottexturefill
+msgid "It is not a texture fill"
+msgstr ""
+
+#: lcresourcestring.rsopacity
+msgid "Opacity"
+msgstr "Прозрачност"
+
+#: lcresourcestring.rspreview
+msgid "Preview"
+msgstr "Преглед"
+
+#: lcresourcestring.rsshapeclassnotspecified
+msgid "Shape class not specified"
+msgstr ""
+
+#: lcresourcestring.rsshapenotfound
+msgid "Shape not found"
+msgstr "Формата не е намерена"
+
+#: lcresourcestring.rssolidcolor
+msgid "Solid color"
+msgstr "Плътен цвят"
+
+#: lcresourcestring.rsstartopacity
+msgid "Start opacity"
+msgstr "Начална прозрачност"
+
+#: lcresourcestring.rsswapcolors
+msgid "Swap colors"
+msgstr "Превключване на цвета"
+
+#: lcresourcestring.rstexturefill
+msgid "Texture fill"
+msgstr ""
+
+#: lcresourcestring.rstexturerepetition
+msgid "Texture repetition"
+msgstr ""
+
+#: lcresourcestring.rstrnone
+msgid "No repetition"
+msgstr "Без повтаряне"
+
+#: lcresourcestring.rstrrepeatboth
+msgid "Repeat both"
+msgstr "Повтаряне и по двете"
+
+#: lcresourcestring.rstrrepeatx
+msgid "Repeat X"
+msgstr "Повтаряне по X"
+
+#: lcresourcestring.rstrrepeaty
+msgid "Repeat Y"
+msgstr "Повтаряне по Y"
+
+#: lcresourcestring.rsunknownshapeclass
+msgid "Unknown shape class \"%1\""
+msgstr ""

+ 180 - 171
lazpaint/release/bin/i18n/lcresourcestring.kab.po

@@ -1,171 +1,180 @@
-msgid ""
-msgstr "Content-Type: text/plain; charset=UTF-8"
-
-#: lcresourcestring.rsadjusttoshape
-msgid "Adjust to shape"
-msgstr ""
-
-#: lcresourcestring.rscigsbnegative
-msgid "Corr. HSL CCW"
-msgstr ""
-
-#: lcresourcestring.rscigsbpositive
-msgid "Corr. HSL CW"
-msgstr ""
-
-#: lcresourcestring.rscilinearhslnegative
-msgid "HSL CCW"
-msgstr ""
-
-#: lcresourcestring.rscilinearhslpositive
-msgid "HSL CW"
-msgstr ""
-
-#: lcresourcestring.rscilinearrgb
-msgid "RGB"
-msgstr ""
-
-#: lcresourcestring.rscistdrgb
-msgid "sRGB"
-msgstr ""
-
-#: lcresourcestring.rscolor
-msgid "Color"
-msgstr "Ini"
-
-#: lcresourcestring.rscolorinterpolation
-msgid "Color interpolation"
-msgstr ""
-
-#: lcresourcestring.rseditgradtexpoints
-msgid "Edit gradient/texture points"
-msgstr ""
-
-#: lcresourcestring.rsendopacity
-msgid "End opacity"
-msgstr ""
-
-#: lcresourcestring.rsgradientangular
-msgid "Angular"
-msgstr ""
-
-#: lcresourcestring.rsgradientdiamond
-msgid "Diamond"
-msgstr "Am dyaman"
-
-#: lcresourcestring.rsgradientfill
-msgid "Gradient fill"
-msgstr "Tafesna n yini"
-
-#: lcresourcestring.rsgradientlinear
-msgid "Linear"
-msgstr "Tamziregt"
-
-#: lcresourcestring.rsgradientradial
-msgid "Radial"
-msgstr "Tazenẓarant"
-
-#: lcresourcestring.rsgradientreflected
-msgid "Reflected"
-msgstr "Ittusenddeden"
-
-#: lcresourcestring.rsgradientrepetition
-msgid "Gradient repetition"
-msgstr ""
-
-#: lcresourcestring.rsgrpad
-msgid "Pad"
-msgstr ""
-
-#: lcresourcestring.rsgrreflect
-msgid "Reflect"
-msgstr ""
-
-#: lcresourcestring.rsgrrepeat
-msgid "Repeat"
-msgstr ""
-
-#: lcresourcestring.rsgrsine
-msgid "Sine"
-msgstr ""
-
-#: lcresourcestring.rsincompatibletype
-msgid "Incompatible type"
-msgstr ""
-
-#: lcresourcestring.rsindexoutofbounds
-msgid "Index out of bounds"
-msgstr ""
-
-#: lcresourcestring.rslightposition
-msgid "Light position"
-msgstr "Ideg n tafat"
-
-#: lcresourcestring.rsloadtexture
-msgid "Load texture"
-msgstr "Sali-d tizḍi"
-
-#: lcresourcestring.rsnofill
-msgid "No fill"
-msgstr ""
-
-#: lcresourcestring.rsnottexturefill
-msgid "It is not a texture fill"
-msgstr ""
-
-#: lcresourcestring.rsopacity
-msgid "Opacity"
-msgstr "Tiḍullest"
-
-#: lcresourcestring.rspreview
-msgid "Preview"
-msgstr "Tamuɣli"
-
-#: lcresourcestring.rsshapeclassnotspecified
-msgid "Shape class not specified"
-msgstr ""
-
-#: lcresourcestring.rsshapenotfound
-msgid "Shape not found"
-msgstr ""
-
-#: lcresourcestring.rssolidcolor
-msgid "Solid color"
-msgstr ""
-
-#: lcresourcestring.rsstartopacity
-msgid "Start opacity"
-msgstr ""
-
-#: lcresourcestring.rsswapcolors
-msgid "Swap colors"
-msgstr "Senfel initen"
-
-#: lcresourcestring.rstexturefill
-msgid "Texture fill"
-msgstr ""
-
-#: lcresourcestring.rstexturerepetition
-msgid "Texture repetition"
-msgstr ""
-
-#: lcresourcestring.rstrnone
-msgid "No repetition"
-msgstr ""
-
-#: lcresourcestring.rstrrepeatboth
-msgid "Repeat both"
-msgstr ""
-
-#: lcresourcestring.rstrrepeatx
-msgid "Repeat X"
-msgstr ""
-
-#: lcresourcestring.rstrrepeaty
-msgid "Repeat Y"
-msgstr ""
-
-#: lcresourcestring.rsunknownshapeclass
-msgid "Unknown shape class \"%1\""
-msgstr ""
-
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: Yacine Bouklif <[email protected]>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: kab\n"
+"X-Generator: Poedit 2.3\n"
+
+#: lcresourcestring.rsadjusttoshape
+msgid "Adjust to shape"
+msgstr "Sezg ɣer talɣa"
+
+#: lcresourcestring.rscigsbnegative
+msgid "Corr. HSL CCW"
+msgstr "HSL yettuseɣtin di tnila mgal tamrilt"
+
+#: lcresourcestring.rscigsbpositive
+msgid "Corr. HSL CW"
+msgstr "HSL yettuseɣtin di tnila n temrilt"
+
+#: lcresourcestring.rscilinearhslnegative
+msgid "HSL CCW"
+msgstr "HSL di tnila mgal tamrilt"
+
+#: lcresourcestring.rscilinearhslpositive
+msgid "HSL CW"
+msgstr "HSL di tnila n temrilt"
+
+#: lcresourcestring.rscilinearrgb
+msgid "RGB"
+msgstr "RGB"
+
+#: lcresourcestring.rscistdrgb
+msgid "sRGB"
+msgstr "sRGB"
+
+#: lcresourcestring.rscolor
+msgid "Color"
+msgstr "Ini"
+
+#: lcresourcestring.rscolorinterpolation
+msgid "Color interpolation"
+msgstr "Asenṭeḍ n yini"
+
+#: lcresourcestring.rseditgradtexpoints
+msgid "Edit gradient/texture points"
+msgstr "Ẓreg tinqiḍin n ufesniw/tizḍi"
+
+#: lcresourcestring.rsendopacity
+msgid "End opacity"
+msgstr "Tiḍullest n taggara"
+
+#: lcresourcestring.rsgradientangular
+msgid "Angular"
+msgstr "Uɣmir"
+
+#: lcresourcestring.rsgradientdiamond
+msgid "Diamond"
+msgstr "Am dyaman"
+
+#: lcresourcestring.rsgradientfill
+msgid "Gradient fill"
+msgstr "Taččart s ufesniw"
+
+#: lcresourcestring.rsgradientlinear
+msgid "Linear"
+msgstr "Imzireg"
+
+#: lcresourcestring.rsgradientradial
+msgid "Radial"
+msgstr "Azenẓaran"
+
+#: lcresourcestring.rsgradientreflected
+msgid "Reflected"
+msgstr "Ittusendded"
+
+#: lcresourcestring.rsgradientrepetition
+msgid "Gradient repetition"
+msgstr "Allus n ufesniw"
+
+#: lcresourcestring.rsgrpad
+msgid "Pad"
+msgstr "Aččar"
+
+#: lcresourcestring.rsgrreflect
+msgid "Reflect"
+msgstr "Sended"
+
+#: lcresourcestring.rsgrrepeat
+msgid "Repeat"
+msgstr "Ales"
+
+#: lcresourcestring.rsgrsine
+msgid "Sine"
+msgstr "Asinus"
+
+#: lcresourcestring.rsincompatibletype
+msgid "Incompatible type"
+msgstr "Anaw amyagan"
+
+#: lcresourcestring.rsindexoutofbounds
+msgid "Index out of bounds"
+msgstr "Amatar iɛedda tilisa"
+
+#: lcresourcestring.rslightposition
+msgid "Light position"
+msgstr "Ideg n tafat"
+
+#: lcresourcestring.rsloadtexture
+msgid "Load texture"
+msgstr "Sali-d tizḍi"
+
+#: lcresourcestring.rsnofill
+msgid "No fill"
+msgstr "Ulac taččart"
+
+#: lcresourcestring.rsnottexturefill
+msgid "It is not a texture fill"
+msgstr "Mačči d taččart s tizḍi"
+
+#: lcresourcestring.rsopacity
+msgid "Opacity"
+msgstr "Tiḍullest"
+
+#: lcresourcestring.rspreview
+msgid "Preview"
+msgstr "Tadlayt"
+
+#: lcresourcestring.rsshapeclassnotspecified
+msgid "Shape class not specified"
+msgstr "Taserkemt n talɣa ur d-ttunefk ara"
+
+#: lcresourcestring.rsshapenotfound
+msgid "Shape not found"
+msgstr "Talɣa ur tettwaf ara"
+
+#: lcresourcestring.rssolidcolor
+msgid "Solid color"
+msgstr "Ini amsari"
+
+#: lcresourcestring.rsstartopacity
+msgid "Start opacity"
+msgstr "Tiḍullest n tazwara"
+
+#: lcresourcestring.rsswapcolors
+msgid "Swap colors"
+msgstr "Semmeskel initen"
+
+#: lcresourcestring.rstexturefill
+msgid "Texture fill"
+msgstr "Taččart s tizḍi"
+
+#: lcresourcestring.rstexturerepetition
+msgid "Texture repetition"
+msgstr "Allus n tizḍi"
+
+#: lcresourcestring.rstrnone
+msgid "No repetition"
+msgstr "Ulac allus"
+
+#: lcresourcestring.rstrrepeatboth
+msgid "Repeat both"
+msgstr "Ales di sin"
+
+#: lcresourcestring.rstrrepeatx
+msgid "Repeat X"
+msgstr "Ales X"
+
+#: lcresourcestring.rstrrepeaty
+msgid "Repeat Y"
+msgstr "Ales Y"
+
+#: lcresourcestring.rsunknownshapeclass
+msgid "Unknown shape class \"%1\""
+msgstr "Taserkemt n talɣa tarussint \"%1\""

+ 35 - 26
lazpaint/release/bin/i18n/lcresourcestring.lv.po

@@ -1,9 +1,19 @@
 msgid ""
 msgid ""
-msgstr "Content-Type: text/plain; charset=UTF-8"
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: Kārlis Kalviškis <[email protected]>\n"
+"Language-Team: \n"
+"Language: lv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.2.1\n"
 
 
 #: lcresourcestring.rsadjusttoshape
 #: lcresourcestring.rsadjusttoshape
 msgid "Adjust to shape"
 msgid "Adjust to shape"
-msgstr ""
+msgstr "Pielāgot objektam"
 
 
 #: lcresourcestring.rscigsbnegative
 #: lcresourcestring.rscigsbnegative
 msgid "Corr. HSL CCW"
 msgid "Corr. HSL CCW"
@@ -35,19 +45,19 @@ msgstr "Krāsa"
 
 
 #: lcresourcestring.rscolorinterpolation
 #: lcresourcestring.rscolorinterpolation
 msgid "Color interpolation"
 msgid "Color interpolation"
-msgstr ""
+msgstr "Krāsu pārejas veids"
 
 
 #: lcresourcestring.rseditgradtexpoints
 #: lcresourcestring.rseditgradtexpoints
 msgid "Edit gradient/texture points"
 msgid "Edit gradient/texture points"
-msgstr ""
+msgstr "Labot izvietojuma punktus"
 
 
 #: lcresourcestring.rsendopacity
 #: lcresourcestring.rsendopacity
 msgid "End opacity"
 msgid "End opacity"
-msgstr ""
+msgstr "Beigu redzamība"
 
 
 #: lcresourcestring.rsgradientangular
 #: lcresourcestring.rsgradientangular
 msgid "Angular"
 msgid "Angular"
-msgstr ""
+msgstr "Leņķiska"
 
 
 #: lcresourcestring.rsgradientdiamond
 #: lcresourcestring.rsgradientdiamond
 msgid "Diamond"
 msgid "Diamond"
@@ -71,19 +81,19 @@ msgstr "Spoguļveida"
 
 
 #: lcresourcestring.rsgradientrepetition
 #: lcresourcestring.rsgradientrepetition
 msgid "Gradient repetition"
 msgid "Gradient repetition"
-msgstr ""
+msgstr "Toņu pārejas atkārtošanās"
 
 
 #: lcresourcestring.rsgrpad
 #: lcresourcestring.rsgrpad
 msgid "Pad"
 msgid "Pad"
-msgstr ""
+msgstr "Aizpilda"
 
 
 #: lcresourcestring.rsgrreflect
 #: lcresourcestring.rsgrreflect
 msgid "Reflect"
 msgid "Reflect"
-msgstr ""
+msgstr "Spoguļskats"
 
 
 #: lcresourcestring.rsgrrepeat
 #: lcresourcestring.rsgrrepeat
 msgid "Repeat"
 msgid "Repeat"
-msgstr ""
+msgstr "Atkārtojas"
 
 
 #: lcresourcestring.rsgrsine
 #: lcresourcestring.rsgrsine
 msgid "Sine"
 msgid "Sine"
@@ -91,11 +101,11 @@ msgstr "Viļnveida"
 
 
 #: lcresourcestring.rsincompatibletype
 #: lcresourcestring.rsincompatibletype
 msgid "Incompatible type"
 msgid "Incompatible type"
-msgstr ""
+msgstr "Nesaderīgs veids"
 
 
 #: lcresourcestring.rsindexoutofbounds
 #: lcresourcestring.rsindexoutofbounds
 msgid "Index out of bounds"
 msgid "Index out of bounds"
-msgstr ""
+msgstr "Vērtība ārpus atļautā"
 
 
 #: lcresourcestring.rslightposition
 #: lcresourcestring.rslightposition
 msgid "Light position"
 msgid "Light position"
@@ -107,11 +117,11 @@ msgstr "Ielasīt virsmas rakstu"
 
 
 #: lcresourcestring.rsnofill
 #: lcresourcestring.rsnofill
 msgid "No fill"
 msgid "No fill"
-msgstr ""
+msgstr "Bez pildījuma"
 
 
 #: lcresourcestring.rsnottexturefill
 #: lcresourcestring.rsnottexturefill
 msgid "It is not a texture fill"
 msgid "It is not a texture fill"
-msgstr ""
+msgstr "Nav aizpildīts ar rakstu"
 
 
 #: lcresourcestring.rsopacity
 #: lcresourcestring.rsopacity
 msgid "Opacity"
 msgid "Opacity"
@@ -123,19 +133,19 @@ msgstr "Priekšskatīt"
 
 
 #: lcresourcestring.rsshapeclassnotspecified
 #: lcresourcestring.rsshapeclassnotspecified
 msgid "Shape class not specified"
 msgid "Shape class not specified"
-msgstr ""
+msgstr "Nav norādīta objekta klase"
 
 
 #: lcresourcestring.rsshapenotfound
 #: lcresourcestring.rsshapenotfound
 msgid "Shape not found"
 msgid "Shape not found"
-msgstr ""
+msgstr "Objekts netika atrasts"
 
 
 #: lcresourcestring.rssolidcolor
 #: lcresourcestring.rssolidcolor
 msgid "Solid color"
 msgid "Solid color"
-msgstr ""
+msgstr "Viendabīga krāsa"
 
 
 #: lcresourcestring.rsstartopacity
 #: lcresourcestring.rsstartopacity
 msgid "Start opacity"
 msgid "Start opacity"
-msgstr ""
+msgstr "Sākuma redzamība"
 
 
 #: lcresourcestring.rsswapcolors
 #: lcresourcestring.rsswapcolors
 msgid "Swap colors"
 msgid "Swap colors"
@@ -143,29 +153,28 @@ msgstr "Apmainīt krāsas vietām"
 
 
 #: lcresourcestring.rstexturefill
 #: lcresourcestring.rstexturefill
 msgid "Texture fill"
 msgid "Texture fill"
-msgstr ""
+msgstr "Aizpildīt ar rakstu"
 
 
 #: lcresourcestring.rstexturerepetition
 #: lcresourcestring.rstexturerepetition
 msgid "Texture repetition"
 msgid "Texture repetition"
-msgstr ""
+msgstr "Raksta atkārtošana"
 
 
 #: lcresourcestring.rstrnone
 #: lcresourcestring.rstrnone
 msgid "No repetition"
 msgid "No repetition"
-msgstr ""
+msgstr "Neatkārtot"
 
 
 #: lcresourcestring.rstrrepeatboth
 #: lcresourcestring.rstrrepeatboth
 msgid "Repeat both"
 msgid "Repeat both"
-msgstr ""
+msgstr "Atkārtot abējādi"
 
 
 #: lcresourcestring.rstrrepeatx
 #: lcresourcestring.rstrrepeatx
 msgid "Repeat X"
 msgid "Repeat X"
-msgstr ""
+msgstr "Atkārtot uz sāniem"
 
 
 #: lcresourcestring.rstrrepeaty
 #: lcresourcestring.rstrrepeaty
 msgid "Repeat Y"
 msgid "Repeat Y"
-msgstr ""
+msgstr "Atkārtot uz augšu/leju"
 
 
 #: lcresourcestring.rsunknownshapeclass
 #: lcresourcestring.rsunknownshapeclass
 msgid "Unknown shape class \"%1\""
 msgid "Unknown shape class \"%1\""
-msgstr ""
-
+msgstr "Nepazīstama objekta klase \"%1\""

+ 28 - 0
lazpaint/release/changelog

@@ -145,3 +145,31 @@ lazpaint (7.0.8) unstable; urgency=low
 
 
 -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 
 
+lazpaint (7.0.9) unstable; urgency=low
+
+  * interface: less flickering during action progress
+  * interface: minor scaling improvements
+  * interface: ensure toolwindows in front when restoring app
+  * interface: dark theme for status bar
+  * interface: add Donate tool button
+  * interface: add Python download button if missing
+  * interface: separate color for background and outline
+  * interface: don't undock windows when going fullscreen
+  * interface: fix remember save file extension
+  * translation: added Latvian
+  * translation: completed Kabyle and Bulgarian
+  * tool: fix updating transparent colors
+  * tool: fix release of middle mouse button
+  * tool: optimize layer transform
+  * tool: added font aliasing option
+  * tool: replace layer by gradient if it is opaque
+  * tool: floodfill using vector if possible
+  * tool: fix gradient undo/redo
+  * tool: multiselection of shapes
+  * tool: fix text editor handling of keys
+  * script: sort in menus
+  * script: added inner shadow/light
+  * script: added version function
+
+-- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
+

+ 28 - 0
lazpaint/release/debian/linux32/DEBIAN/changelog

@@ -145,3 +145,31 @@ lazpaint (7.0.8) unstable; urgency=low
 
 
 -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 
 
+lazpaint (7.0.9) unstable; urgency=low
+
+  * interface: less flickering during action progress
+  * interface: minor scaling improvements
+  * interface: ensure toolwindows in front when restoring app
+  * interface: dark theme for status bar
+  * interface: add Donate tool button
+  * interface: add Python download button if missing
+  * interface: separate color for background and outline
+  * interface: don't undock windows when going fullscreen
+  * interface: fix remember save file extension
+  * translation: added Latvian
+  * translation: completed Kabyle and Bulgarian
+  * tool: fix updating transparent colors
+  * tool: fix release of middle mouse button
+  * tool: optimize layer transform
+  * tool: added font aliasing option
+  * tool: replace layer by gradient if it is opaque
+  * tool: floodfill using vector if possible
+  * tool: fix gradient undo/redo
+  * tool: multiselection of shapes
+  * tool: fix text editor handling of keys
+  * script: sort in menus
+  * script: added inner shadow/light
+  * script: added version function
+
+-- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
+

+ 1 - 1
lazpaint/release/debian/linux32/DEBIAN/control

@@ -1,5 +1,5 @@
 Package: lazpaint
 Package: lazpaint
-Version: 7.0.8
+Version: 7.0.9
 Section: base
 Section: base
 Priority: optional
 Priority: optional
 Architecture: i386
 Architecture: i386

+ 28 - 0
lazpaint/release/debian/linux64/DEBIAN/changelog

@@ -145,3 +145,31 @@ lazpaint (7.0.8) unstable; urgency=low
 
 
 -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 
 
+lazpaint (7.0.9) unstable; urgency=low
+
+  * interface: less flickering during action progress
+  * interface: minor scaling improvements
+  * interface: ensure toolwindows in front when restoring app
+  * interface: dark theme for status bar
+  * interface: add Donate tool button
+  * interface: add Python download button if missing
+  * interface: separate color for background and outline
+  * interface: don't undock windows when going fullscreen
+  * interface: fix remember save file extension
+  * translation: added Latvian
+  * translation: completed Kabyle and Bulgarian
+  * tool: fix updating transparent colors
+  * tool: fix release of middle mouse button
+  * tool: optimize layer transform
+  * tool: added font aliasing option
+  * tool: replace layer by gradient if it is opaque
+  * tool: floodfill using vector if possible
+  * tool: fix gradient undo/redo
+  * tool: multiselection of shapes
+  * tool: fix text editor handling of keys
+  * script: sort in menus
+  * script: added inner shadow/light
+  * script: added version function
+
+-- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
+

+ 1 - 1
lazpaint/release/debian/linux64/DEBIAN/control

@@ -1,5 +1,5 @@
 Package: lazpaint
 Package: lazpaint
-Version: 7.0.8
+Version: 7.0.9
 Section: base
 Section: base
 Priority: optional
 Priority: optional
 Architecture: amd64
 Architecture: amd64

+ 2 - 2
lazpaint/release/macOS/LazPaint.app/Contents/Info.plist

@@ -19,9 +19,9 @@
     <key>CFBundleSignature</key>
     <key>CFBundleSignature</key>
     <string>lazp</string>
     <string>lazp</string>
     <key>CFBundleShortVersionString</key>
     <key>CFBundleShortVersionString</key>
-    <string>7.0.8</string>
+    <string>7.0.9</string>
     <key>CFBundleVersion</key>
     <key>CFBundleVersion</key>
-    <string>7.0.8</string>
+    <string>7.0.9</string>
     <key>CSResourcesFileMapped</key>
     <key>CSResourcesFileMapped</key>
     <true/>
     <true/>
     <key>CFBundleDocumentTypes</key>
     <key>CFBundleDocumentTypes</key>

+ 1 - 1
lazpaint/release/macOS/makedmg.sh

@@ -12,7 +12,7 @@ fi
 
 
 
 
 appname=LazPaint
 appname=LazPaint
-appversion=7.0.8
+appversion=7.0.9
 pkgversion=0
 pkgversion=0
 appnamenospaces=lazpaint
 appnamenospaces=lazpaint
 appbundle="$appname.app"
 appbundle="$appname.app"

+ 1 - 1
lazpaint/release/windows/lazpaint.iss

@@ -1,7 +1,7 @@
 #define MyAppName "LazPaint"
 #define MyAppName "LazPaint"
 #define MyAppOutputName "lazpaint"
 #define MyAppOutputName "lazpaint"
 #define MyInstallerSuffix "_setup_win32_win64"
 #define MyInstallerSuffix "_setup_win32_win64"
-#define MyAppVersion "7.0.8"
+#define MyAppVersion "7.0.9"
 #define MyAppPublisher "Circular, Fabien Wang, Lainz and others"
 #define MyAppPublisher "Circular, Fabien Wang, Lainz and others"
 #define MyAppURL "http://sourceforge.net/projects/lazpaint/"
 #define MyAppURL "http://sourceforge.net/projects/lazpaint/"
 #define MyAppExeName "lazpaint.exe"
 #define MyAppExeName "lazpaint.exe"

+ 18 - 2
lazpaint/release/windows/stage.bat

@@ -5,10 +5,14 @@ echo Cleaning previous staging files...
 if exist lazpaint32 del /s /q lazpaint32 >nul
 if exist lazpaint32 del /s /q lazpaint32 >nul
 if exist lazpaint32\i18n rmdir lazpaint32\i18n
 if exist lazpaint32\i18n rmdir lazpaint32\i18n
 if exist lazpaint32\models rmdir lazpaint32\models
 if exist lazpaint32\models rmdir lazpaint32\models
+if exist lazpaint32\scripts\lazpaint rmdir lazpaint32\scripts\lazpaint
+if exist lazpaint32\scripts rmdir lazpaint32\scripts
 if exist lazpaint32 rmdir lazpaint32
 if exist lazpaint32 rmdir lazpaint32
 if exist lazpaint64 del /s /q lazpaint64 >nul
 if exist lazpaint64 del /s /q lazpaint64 >nul
 if exist lazpaint64\i18n rmdir lazpaint64\i18n
 if exist lazpaint64\i18n rmdir lazpaint64\i18n
 if exist lazpaint64\models rmdir lazpaint64\models
 if exist lazpaint64\models rmdir lazpaint64\models
+if exist lazpaint64\scripts\lazpaint rmdir lazpaint64\scripts\lazpaint
+if exist lazpaint64\scripts rmdir lazpaint64\scripts
 if exist lazpaint64 rmdir lazpaint64
 if exist lazpaint64 rmdir lazpaint64
 
 
 echo Binary found:
 echo Binary found:
@@ -19,13 +23,19 @@ echo Staging 32-bit version...
 if not exist lazpaint32 mkdir lazpaint32
 if not exist lazpaint32 mkdir lazpaint32
 copy ..\bin\lazpaint32.exe lazpaint32\lazpaint.exe >nul
 copy ..\bin\lazpaint32.exe lazpaint32\lazpaint.exe >nul
 copy dcraw\dcraw32.exe lazpaint32\dcraw.exe >nul
 copy dcraw\dcraw32.exe lazpaint32\dcraw.exe >nul
+copy libwebp\libwebp32.dll lazpaint32 >nul
 copy ..\bin\readme.txt lazpaint32 >nul
 copy ..\bin\readme.txt lazpaint32 >nul
 copy ..\bin\*.ini lazpaint32 >nul
 copy ..\bin\*.ini lazpaint32 >nul
 if not exist lazpaint32\i18n mkdir lazpaint32\i18n
 if not exist lazpaint32\i18n mkdir lazpaint32\i18n
 copy ..\bin\i18n\lazpaint.* lazpaint32\i18n >nul
 copy ..\bin\i18n\lazpaint.* lazpaint32\i18n >nul
+copy ..\bin\i18n\lcresourcestring.* lazpaint32\i18n >nul
 copy ..\bin\i18n\lclstrconsts.* lazpaint32\i18n >nul
 copy ..\bin\i18n\lclstrconsts.* lazpaint32\i18n >nul
 if not exist lazpaint32\models mkdir lazpaint32\models
 if not exist lazpaint32\models mkdir lazpaint32\models
 copy ..\bin\models lazpaint32\models >nul
 copy ..\bin\models lazpaint32\models >nul
+if not exist lazpaint32\scripts mkdir lazpaint32\scripts
+copy ..\..\..\scripts lazpaint32\scripts >nul
+if not exist lazpaint32\scripts\lazpaint mkdir lazpaint32\scripts\lazpaint
+copy ..\..\..\scripts\lazpaint lazpaint32\scripts\lazpaint >nul
 goto donebin32
 goto donebin32
 :missingbin32
 :missingbin32
 echo Error: 32-bit binary not found
 echo Error: 32-bit binary not found
@@ -36,13 +46,19 @@ echo Staging 64-bit version...
 if not exist lazpaint64 mkdir lazpaint64
 if not exist lazpaint64 mkdir lazpaint64
 copy ..\bin\lazpaint_x64.exe lazpaint64\lazpaint.exe >nul
 copy ..\bin\lazpaint_x64.exe lazpaint64\lazpaint.exe >nul
 copy dcraw\dcraw_x64.exe lazpaint64\dcraw.exe >nul
 copy dcraw\dcraw_x64.exe lazpaint64\dcraw.exe >nul
-copy ..\bin\readme.txt lazpaint32 >nul
-copy ..\bin\*.ini lazpaint32 >nul
+copy libwebp\libwebp64.dll lazpaint64 >nul
+copy ..\bin\readme.txt lazpaint64 >nul
+copy ..\bin\*.ini lazpaint64 >nul
 if not exist lazpaint64\i18n mkdir lazpaint64\i18n
 if not exist lazpaint64\i18n mkdir lazpaint64\i18n
 copy ..\bin\i18n\lazpaint.* lazpaint64\i18n >nul
 copy ..\bin\i18n\lazpaint.* lazpaint64\i18n >nul
+copy ..\bin\i18n\lcresourcestring.* lazpaint64\i18n >nul
 copy ..\bin\i18n\lclstrconsts.* lazpaint64\i18n >nul
 copy ..\bin\i18n\lclstrconsts.* lazpaint64\i18n >nul
 if not exist lazpaint64\models mkdir lazpaint64\models
 if not exist lazpaint64\models mkdir lazpaint64\models
 copy ..\bin\models lazpaint64\models >nul
 copy ..\bin\models lazpaint64\models >nul
+if not exist lazpaint64\scripts mkdir lazpaint64\scripts
+copy ..\..\..\scripts lazpaint64\scripts >nul
+if not exist lazpaint64\scripts\lazpaint mkdir lazpaint64\scripts\lazpaint
+copy ..\..\..\scripts\lazpaint lazpaint64\scripts\lazpaint >nul
 goto donebin64
 goto donebin64
 :missingbin64
 :missingbin64
 echo Error: 64-bit binary not found
 echo Error: 64-bit binary not found

+ 242 - 72
lazpaint/tools/utool.pas

@@ -35,9 +35,10 @@ const
 function StrToPaintToolType(const s: ansistring): TPaintToolType;
 function StrToPaintToolType(const s: ansistring): TPaintToolType;
 
 
 type
 type
-  TContextualToolbar = (ctPenFill, ctBackFill, ctPenWidth, ctPenStyle, ctAliasing, ctShape, ctEraserOption, ctTolerance,
-    ctDeformation, ctCloseShape, ctLineCap, ctJoinStyle, ctSplineStyle, ctText, ctTextShadow,
-    ctPhong, ctAltitude, ctPerspective, ctBrush, ctRatio);
+  TContextualToolbar = (ctPenFill, ctPenWidth, ctPenStyle, ctJoinStyle, ctLineCap,
+    ctCloseShape, ctSplineStyle, ctShape, ctRatio, ctBackFill,
+    ctBrush, ctEraserOption, ctAliasing, ctTolerance, ctDeformation, ctPerspective,
+    ctText, ctOutlineWidth, ctOutlineFill, ctTextShadow, ctPhong, ctAltitude);
   TContextualToolbars = set of TContextualToolbar;
   TContextualToolbars = set of TContextualToolbar;
 
 
 type
 type
@@ -47,7 +48,8 @@ type
   TEraserMode = (emEraseAlpha, emSharpen, emSoften, emLighten, emDarken);
   TEraserMode = (emEraseAlpha, emSharpen, emSoften, emLighten, emDarken);
   TToolCommand = (tcCut, tcCopy, tcPaste, tcDelete, tcFinish, tcMoveUp, tcMoveDown, tcMoveToFront, tcMoveToBack,
   TToolCommand = (tcCut, tcCopy, tcPaste, tcDelete, tcFinish, tcMoveUp, tcMoveDown, tcMoveToFront, tcMoveToBack,
     tcAlignLeft, tcCenterHorizontally, tcAlignRight, tcAlignTop, tcCenterVertically, tcAlignBottom,
     tcAlignLeft, tcCenterHorizontally, tcAlignRight, tcAlignTop, tcCenterVertically, tcAlignBottom,
-    tcShapeToSpline, tcForeAdjustToShape, tcBackAdjustToShape, tcForeEditGradTexPoints, tcBackEditGradTexPoints);
+    tcShapeToSpline, tcForeAdjustToShape, tcBackAdjustToShape, tcOutlineAdjustToShape,
+    tcForeEditGradTexPoints, tcBackEditGradTexPoints, tcOutlineEditGradTexPoints);
 
 
   TDeformationGridMode = (gmDeform, gmMovePointWithoutDeformation);
   TDeformationGridMode = (gmDeform, gmMovePointWithoutDeformation);
 
 
@@ -100,8 +102,10 @@ type
     function GetCurrentLayerKind: TLayerKind;
     function GetCurrentLayerKind: TLayerKind;
     function GetIsForeEditGradTexPoints: boolean; virtual;
     function GetIsForeEditGradTexPoints: boolean; virtual;
     function GetIsBackEditGradTexPoints: boolean; virtual;
     function GetIsBackEditGradTexPoints: boolean; virtual;
+    function GetIsOutlineEditGradTexPoints: boolean; virtual;
     function GetAllowedBackFillTypes: TVectorialFillTypes; virtual;
     function GetAllowedBackFillTypes: TVectorialFillTypes; virtual;
     function GetAllowedForeFillTypes: TVectorialFillTypes; virtual;
     function GetAllowedForeFillTypes: TVectorialFillTypes; virtual;
+    function GetAllowedOutlineFillTypes: TVectorialFillTypes; virtual;
     property ShiftState: TShiftState read FShiftState;
     property ShiftState: TShiftState read FShiftState;
   public
   public
     ToolUpdateNeeded: boolean;
     ToolUpdateNeeded: boolean;
@@ -142,8 +146,10 @@ type
     property ForeUniversalBrush: TUniversalBrush read GetForeUniversalBrush;
     property ForeUniversalBrush: TUniversalBrush read GetForeUniversalBrush;
     property IsForeEditGradTexPoints: boolean read GetIsForeEditGradTexPoints;
     property IsForeEditGradTexPoints: boolean read GetIsForeEditGradTexPoints;
     property IsBackEditGradTexPoints: boolean read GetIsBackEditGradTexPoints;
     property IsBackEditGradTexPoints: boolean read GetIsBackEditGradTexPoints;
+    property IsOutlineEditGradTexPoints: boolean read GetIsOutlineEditGradTexPoints;
     property AllowedForeFillTypes: TVectorialFillTypes read GetAllowedForeFillTypes;
     property AllowedForeFillTypes: TVectorialFillTypes read GetAllowedForeFillTypes;
     property AllowedBackFillTypes: TVectorialFillTypes read GetAllowedBackFillTypes;
     property AllowedBackFillTypes: TVectorialFillTypes read GetAllowedBackFillTypes;
+    property AllowedOutlineFillTypes: TVectorialFillTypes read GetAllowedOutlineFillTypes;
   end;
   end;
 
 
   { TReadonlyTool }
   { TReadonlyTool }
@@ -192,11 +198,12 @@ type
     FSleepingToolType: TPaintToolType;
     FSleepingToolType: TPaintToolType;
     FReturnValidatesHintShown: boolean;
     FReturnValidatesHintShown: boolean;
     FOnToolChangedHandler: TOnToolChangedHandler;
     FOnToolChangedHandler: TOnToolChangedHandler;
+    FOnToolRenderChanged: TNotifyEvent;
     FOnToolbarChanged: TNotifyEvent;
     FOnToolbarChanged: TNotifyEvent;
     FOnPopupToolHandler: TOnPopupToolHandler;
     FOnPopupToolHandler: TOnPopupToolHandler;
 
 
-    FForeFill, FBackFill: TVectorialFill;
-    FForeLastGradient, FBackLastGradient: TBGRALayerGradientOriginal;
+    FForeFill, FBackFill, FOutlineFill: TVectorialFill;
+    FForeLastGradient, FBackLastGradient, FOutlineLastGradient: TBGRALayerGradientOriginal;
     FEraserMode: TEraserMode;
     FEraserMode: TEraserMode;
     FEraserAlpha: byte;
     FEraserAlpha: byte;
     FBrushInfoList: TList;
     FBrushInfoList: TList;
@@ -252,10 +259,11 @@ type
     FOnFloodFillOptionChanged: TNotifyEvent;
     FOnFloodFillOptionChanged: TNotifyEvent;
     FOnPerspectiveOptionChanged: TNotifyEvent;
     FOnPerspectiveOptionChanged: TNotifyEvent;
 
 
-    procedure BackFillChange({%H-}ASender: TObject;
+    procedure FillChange(ASender: TObject;
       var {%H-}ADiff: TCustomVectorialFillDiff);
       var {%H-}ADiff: TCustomVectorialFillDiff);
     function GetAllowedBackFillTypes: TVectorialFillTypes;
     function GetAllowedBackFillTypes: TVectorialFillTypes;
     function GetAllowedForeFillTypes: TVectorialFillTypes;
     function GetAllowedForeFillTypes: TVectorialFillTypes;
+    function GetAllowedOutlineFillTypes: TVectorialFillTypes;
     function GetCursor: TCursor;
     function GetCursor: TCursor;
     function GetBackColor: TBGRAPixel;
     function GetBackColor: TBGRAPixel;
     function GetBrushAt(AIndex: integer): TLazPaintBrush;
     function GetBrushAt(AIndex: integer): TLazPaintBrush;
@@ -263,19 +271,19 @@ type
     function GetBrushInfo: TLazPaintBrush;
     function GetBrushInfo: TLazPaintBrush;
     function GetForeColor: TBGRAPixel;
     function GetForeColor: TBGRAPixel;
     function GetMaxDeformationGridSize: TSize;
     function GetMaxDeformationGridSize: TSize;
+    function GetOutlineColor: TBGRAPixel;
     function GetShapeOptionAliasing: boolean;
     function GetShapeOptionAliasing: boolean;
     function GetPenWidth: single;
     function GetPenWidth: single;
     function GetToolSleeping: boolean;
     function GetToolSleeping: boolean;
     function GetTextFontName: string;
     function GetTextFontName: string;
     function GetTextFontSize: single;
     function GetTextFontSize: single;
     function GetTextFontStyle: TFontStyles;
     function GetTextFontStyle: TFontStyles;
-    procedure ForeFillChange({%H-}ASender: TObject;
-      var {%H-}ADiff: TCustomVectorialFillDiff);
     function ScriptGetAliasing(AVars: TVariableSet): TScriptResult;
     function ScriptGetAliasing(AVars: TVariableSet): TScriptResult;
     function ScriptGetArrowEnd(AVars: TVariableSet): TScriptResult;
     function ScriptGetArrowEnd(AVars: TVariableSet): TScriptResult;
     function ScriptGetArrowSize(AVars: TVariableSet): TScriptResult;
     function ScriptGetArrowSize(AVars: TVariableSet): TScriptResult;
     function ScriptGetArrowStart(AVars: TVariableSet): TScriptResult;
     function ScriptGetArrowStart(AVars: TVariableSet): TScriptResult;
     function ScriptGetBackColor(AVars: TVariableSet): TScriptResult;
     function ScriptGetBackColor(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineColor(AVars: TVariableSet): TScriptResult;
     function ScriptGetBrushCount(AVars: TVariableSet): TScriptResult;
     function ScriptGetBrushCount(AVars: TVariableSet): TScriptResult;
     function ScriptGetBrushIndex(AVars: TVariableSet): TScriptResult;
     function ScriptGetBrushIndex(AVars: TVariableSet): TScriptResult;
     function ScriptGetBrushSpacing(AVars: TVariableSet): TScriptResult;
     function ScriptGetBrushSpacing(AVars: TVariableSet): TScriptResult;
@@ -299,12 +307,18 @@ type
     function ScriptGetForeGradientRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeGradientRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeGradientType(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeGradientType(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeGradientColors(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeGradientColors(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineGradientInterpolation(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineGradientRepetition(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineGradientType(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineGradientColors(AVars: TVariableSet): TScriptResult;
     function ScriptGetTextureRepetition(AVars: TVariableSet; AFill: TVectorialFill): TScriptResult;
     function ScriptGetTextureRepetition(AVars: TVariableSet; AFill: TVectorialFill): TScriptResult;
     function ScriptGetTextureOpacity(AVars: TVariableSet; AFill: TVectorialFill): TScriptResult;
     function ScriptGetTextureOpacity(AVars: TVariableSet; AFill: TVectorialFill): TScriptResult;
     function ScriptGetBackTextureRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptGetBackTextureRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptGetBackTextureOpacity(AVars: TVariableSet): TScriptResult;
     function ScriptGetBackTextureOpacity(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeTextureRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeTextureRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeTextureOpacity(AVars: TVariableSet): TScriptResult;
     function ScriptGetForeTextureOpacity(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineTextureRepetition(AVars: TVariableSet): TScriptResult;
+    function ScriptGetOutlineTextureOpacity(AVars: TVariableSet): TScriptResult;
     function ScriptGetJoinStyle(AVars: TVariableSet): TScriptResult;
     function ScriptGetJoinStyle(AVars: TVariableSet): TScriptResult;
     function ScriptGetLightPosition(AVars: TVariableSet): TScriptResult;
     function ScriptGetLightPosition(AVars: TVariableSet): TScriptResult;
     function ScriptGetLineCap(AVars: TVariableSet): TScriptResult;
     function ScriptGetLineCap(AVars: TVariableSet): TScriptResult;
@@ -327,6 +341,7 @@ type
     function ScriptSetArrowSize(AVars: TVariableSet): TScriptResult;
     function ScriptSetArrowSize(AVars: TVariableSet): TScriptResult;
     function ScriptSetArrowStart(AVars: TVariableSet): TScriptResult;
     function ScriptSetArrowStart(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackColor(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackColor(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineColor(AVars: TVariableSet): TScriptResult;
     function ScriptSetBrushIndex(AVars: TVariableSet): TScriptResult;
     function ScriptSetBrushIndex(AVars: TVariableSet): TScriptResult;
     function ScriptSetBrushSpacing(AVars: TVariableSet): TScriptResult;
     function ScriptSetBrushSpacing(AVars: TVariableSet): TScriptResult;
     function ScriptSetDeformationGridMode(AVars: TVariableSet): TScriptResult;
     function ScriptSetDeformationGridMode(AVars: TVariableSet): TScriptResult;
@@ -345,6 +360,10 @@ type
     function ScriptSetBackGradientRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackGradientRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackGradientType(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackGradientType(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackGradientColors(AVars: TVariableSet): TScriptResult;
     function ScriptSetBackGradientColors(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineGradientInterpolation(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineGradientRepetition(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineGradientType(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineGradientColors(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeGradientInterpolation(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeGradientInterpolation(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeGradientRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeGradientRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeGradientType(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeGradientType(AVars: TVariableSet): TScriptResult;
@@ -358,6 +377,9 @@ type
     function ScriptSetForeTexture(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeTexture(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeTextureRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeTextureRepetition(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeTextureOpacity(AVars: TVariableSet): TScriptResult;
     function ScriptSetForeTextureOpacity(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineTexture(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineTextureRepetition(AVars: TVariableSet): TScriptResult;
+    function ScriptSetOutlineTextureOpacity(AVars: TVariableSet): TScriptResult;
     function ScriptSetJoinStyle(AVars: TVariableSet): TScriptResult;
     function ScriptSetJoinStyle(AVars: TVariableSet): TScriptResult;
     function ScriptSetLightPosition(AVars: TVariableSet): TScriptResult;
     function ScriptSetLightPosition(AVars: TVariableSet): TScriptResult;
     function ScriptSetLineCap(AVars: TVariableSet): TScriptResult;
     function ScriptSetLineCap(AVars: TVariableSet): TScriptResult;
@@ -391,6 +413,7 @@ type
     procedure SetLightAltitude(AValue: integer);
     procedure SetLightAltitude(AValue: integer);
     procedure SetLightPosition(AValue: TPointF);
     procedure SetLightPosition(AValue: TPointF);
     procedure SetLineCap(AValue: TPenEndCap);
     procedure SetLineCap(AValue: TPenEndCap);
+    procedure SetOutlineColor(AValue: TBGRAPixel);
     procedure SetPerspectiveOptions(AValue: TPerspectiveOptions);
     procedure SetPerspectiveOptions(AValue: TPerspectiveOptions);
     procedure SetPhongShapeAltitude(AValue: integer);
     procedure SetPhongShapeAltitude(AValue: integer);
     procedure SetPhongShapeBorderSize(AValue: integer);
     procedure SetPhongShapeBorderSize(AValue: integer);
@@ -420,8 +443,8 @@ type
     ShapeControls, PenStyleControls, JoinStyleControls, SplineStyleControls,
     ShapeControls, PenStyleControls, JoinStyleControls, SplineStyleControls,
     CloseShapeControls, LineCapControls, DeformationControls,
     CloseShapeControls, LineCapControls, DeformationControls,
     TextControls, TextShadowControls, PhongControls, AltitudeControls,
     TextControls, TextShadowControls, PhongControls, AltitudeControls,
-    PerspectiveControls,FillControls,
-    BrushControls, RatioControls: TList;
+    PerspectiveControls,FillControls,OutlineFillControls,
+    BrushControls, RatioControls, DonateControls: TList;
 
 
     constructor Create(AImage: TLazPaintImage; AConfigProvider: IConfigProvider;
     constructor Create(AImage: TLazPaintImage; AConfigProvider: IConfigProvider;
       ABitmapToVirtualScreen: TBitmapToVirtualScreenFunction = nil;
       ABitmapToVirtualScreen: TBitmapToVirtualScreenFunction = nil;
@@ -466,9 +489,10 @@ type
     function DisplayFilledSelection: boolean;
     function DisplayFilledSelection: boolean;
     function IsForeEditGradTexPoints: boolean;
     function IsForeEditGradTexPoints: boolean;
     function IsBackEditGradTexPoints: boolean;
     function IsBackEditGradTexPoints: boolean;
+    function IsOutlineEditGradTexPoints: boolean;
     procedure QueryExitTool;
     procedure QueryExitTool;
 
 
-    procedure RenderTool(formBitmap: TBGRABitmap);
+    function RenderTool(formBitmap: TBGRABitmap): TRect;
     function GetRenderBounds(VirtualScreenWidth, VirtualScreenHeight: integer): TRect;
     function GetRenderBounds(VirtualScreenWidth, VirtualScreenHeight: integer): TRect;
     function SuggestGradientBox: TAffineBox;
     function SuggestGradientBox: TAffineBox;
 
 
@@ -484,6 +508,7 @@ type
     procedure SetDeformationGridSize(ASize: TSize);
     procedure SetDeformationGridSize(ASize: TSize);
 
 
     property Image: TLazPaintImage read FImage;
     property Image: TLazPaintImage read FImage;
+    property Scripting: TScriptContext read FScriptContext;
     property BlackAndWhite: boolean read FBlackAndWhite write FBlackAndWhite;
     property BlackAndWhite: boolean read FBlackAndWhite write FBlackAndWhite;
     property CurrentTool: TGenericTool read FCurrentTool;
     property CurrentTool: TGenericTool read FCurrentTool;
     property ToolCurrentCursorPos: TPointF read FToolCurrentCursorPos;
     property ToolCurrentCursorPos: TPointF read FToolCurrentCursorPos;
@@ -494,10 +519,14 @@ type
     property AllowedForeFillTypes: TVectorialFillTypes read GetAllowedForeFillTypes;
     property AllowedForeFillTypes: TVectorialFillTypes read GetAllowedForeFillTypes;
     property BackFill: TVectorialFill read FBackFill;
     property BackFill: TVectorialFill read FBackFill;
     property AllowedBackFillTypes: TVectorialFillTypes read GetAllowedBackFillTypes;
     property AllowedBackFillTypes: TVectorialFillTypes read GetAllowedBackFillTypes;
+    property OutlineFill: TVectorialFill read FOutlineFill;
+    property AllowedOutlineFillTypes: TVectorialFillTypes read GetAllowedOutlineFillTypes;
     property ForeColor: TBGRAPixel read GetForeColor write SetForeColor;
     property ForeColor: TBGRAPixel read GetForeColor write SetForeColor;
     property BackColor: TBGRAPixel read GetBackColor write SetBackColor;
     property BackColor: TBGRAPixel read GetBackColor write SetBackColor;
+    property OutlineColor: TBGRAPixel read GetOutlineColor write SetOutlineColor;
     property ForeLastGradient: TBGRALayerGradientOriginal read FForeLastGradient;
     property ForeLastGradient: TBGRALayerGradientOriginal read FForeLastGradient;
     property BackLastGradient: TBGRALayerGradientOriginal read FBackLastGradient;
     property BackLastGradient: TBGRALayerGradientOriginal read FBackLastGradient;
+    property OutlineLastGradient: TBGRALayerGradientOriginal read FOutlineLastGradient;
     property EraserMode: TEraserMode read FEraserMode write SetEraserMode;
     property EraserMode: TEraserMode read FEraserMode write SetEraserMode;
     property EraserAlpha: byte read FEraserAlpha write SetEraserAlpha;
     property EraserAlpha: byte read FEraserAlpha write SetEraserAlpha;
     property PenWidth: single read GetPenWidth write SetPenWidth;
     property PenWidth: single read GetPenWidth write SetPenWidth;
@@ -541,6 +570,7 @@ type
     property PerspectiveOptions: TPerspectiveOptions read FPerspectiveOptions write SetPerspectiveOptions;
     property PerspectiveOptions: TPerspectiveOptions read FPerspectiveOptions write SetPerspectiveOptions;
 
 
     property OnToolChanged: TOnToolChangedHandler read FOnToolChangedHandler write FOnToolChangedHandler;
     property OnToolChanged: TOnToolChangedHandler read FOnToolChangedHandler write FOnToolChangedHandler;
+    property OnToolRenderChanged: TNotifyEvent read FOnToolRenderChanged write FOnToolRenderChanged;
     property OnToolbarChanged: TNotifyEvent read FOnToolbarChanged write FOnToolbarChanged;
     property OnToolbarChanged: TNotifyEvent read FOnToolbarChanged write FOnToolbarChanged;
     property OnPopup: TOnPopupToolHandler read FOnPopupToolHandler write FOnPopupToolHandler;
     property OnPopup: TOnPopupToolHandler read FOnPopupToolHandler write FOnPopupToolHandler;
     property OnEraserChanged: TNotifyEvent read FOnEraserChanged write FOnEraserChanged;
     property OnEraserChanged: TNotifyEvent read FOnEraserChanged write FOnEraserChanged;
@@ -573,7 +603,7 @@ function ToolPopupMessageToStr(AMessage :TToolPopupMessage; AKey: Word = 0): str
 implementation
 implementation
 
 
 uses UGraph, LCScaleDPI, LazPaintType, UCursors, BGRATextFX, ULoading, UResourceStrings,
 uses UGraph, LCScaleDPI, LazPaintType, UCursors, BGRATextFX, ULoading, UResourceStrings,
-  BGRATransform, LCVectorOriginal, BGRASVGOriginal, math, ULoadImage;
+  BGRATransform, LCVectorOriginal, BGRASVGOriginal, math, ULoadImage, LCVectorTextShapes;
 
 
 function StrToPaintToolType(const s: ansistring): TPaintToolType;
 function StrToPaintToolType(const s: ansistring): TPaintToolType;
 var pt: TPaintToolType;
 var pt: TPaintToolType;
@@ -792,11 +822,21 @@ begin
   result := [vftSolid,vftGradient,vftTexture];
   result := [vftSolid,vftGradient,vftTexture];
 end;
 end;
 
 
+function TGenericTool.GetAllowedOutlineFillTypes: TVectorialFillTypes;
+begin
+  result := [vftSolid,vftGradient,vftTexture];
+end;
+
 function TGenericTool.GetIsBackEditGradTexPoints: boolean;
 function TGenericTool.GetIsBackEditGradTexPoints: boolean;
 begin
 begin
   result := false;
   result := false;
 end;
 end;
 
 
+function TGenericTool.GetIsOutlineEditGradTexPoints: boolean;
+begin
+  result := false;
+end;
+
 function TGenericTool.GetIsForeEditGradTexPoints: boolean;
 function TGenericTool.GetIsForeEditGradTexPoints: boolean;
 begin
 begin
   result := false;
   result := false;
@@ -1075,63 +1115,45 @@ function TGenericTool.ToolKeyDown(var key: Word): TRect;
 var
 var
   key2: Word;
   key2: Word;
 begin
 begin
-  if (Key = VK_SNAP) or (Key = VK_SNAP2) then
-  begin
-    key2 := VK_CONTROL;
-    result := DoToolKeyDown(key2);
-    if key2 = 0 then key := 0;
-  end else
-    result := DoToolKeyDown(key);
-
   if key = VK_SHIFT then
   if key = VK_SHIFT then
   begin
   begin
     Include(FShiftState, ssShift);
     Include(FShiftState, ssShift);
-    key := 0;
+    //do not reset Key to preserve typing ^o or "o
   end else
   end else
+  if (key = VK_MENU) then
+    Include(FShiftState, ssAlt);
+
   if (Key = VK_SNAP) or (Key = VK_SNAP2) then
   if (Key = VK_SNAP) or (Key = VK_SNAP2) then
   begin
   begin
+    key2 := VK_CONTROL;
     Include(FShiftState, ssSnap);
     Include(FShiftState, ssSnap);
-    key := 0;
+    result := DoToolKeyDown(key2);
+    if key2 = 0 then key := 0;
   end else
   end else
-  if (key = VK_MENU) then
-  begin
-    Include(FShiftState, ssAlt);
-    key := 0;
-  end;
+    result := DoToolKeyDown(key);
 end;
 end;
 
 
 function TGenericTool.ToolKeyUp(var key: Word): TRect;
 function TGenericTool.ToolKeyUp(var key: Word): TRect;
 var
 var
-  handled: Boolean;
   key2: word;
   key2: word;
 begin
 begin
   if (key = VK_SHIFT) and (ssShift in FShiftState) then
   if (key = VK_SHIFT) and (ssShift in FShiftState) then
   begin
   begin
     Exclude(FShiftState, ssShift);
     Exclude(FShiftState, ssShift);
-    handled := true;
-  end else
-  if ((key = VK_SNAP) or (key = VK_SNAP2)) and (ssSnap in FShiftState) then
-  begin
-    Exclude(FShiftState, ssSnap);
-    handled := true;
+    //do not reset key to preserve typing ^o or "o
   end else
   end else
   if (key = VK_MENU) and (ssAlt in FShiftState) then
   if (key = VK_MENU) and (ssAlt in FShiftState) then
-  begin
     Exclude(FShiftState, ssAlt);
     Exclude(FShiftState, ssAlt);
-    handled := true;
-  end else
-    handled := false;
 
 
   //propagate in all cases to know when keys are released for unicode input
   //propagate in all cases to know when keys are released for unicode input
   if (Key = VK_SNAP) or (Key = VK_SNAP2) then
   if (Key = VK_SNAP) or (Key = VK_SNAP2) then
   begin
   begin
     key2 := VK_CONTROL;
     key2 := VK_CONTROL;
+    Exclude(FShiftState, ssSnap);
     result := DoToolKeyUp(key2);
     result := DoToolKeyUp(key2);
     if key2 = 0 then key := 0;
     if key2 = 0 then key := 0;
   end else
   end else
     result := DoToolKeyUp(key);
     result := DoToolKeyUp(key);
-
-  if handled then key := 0;
 end;
 end;
 
 
 function TGenericTool.ToolKeyPress(var key: TUTF8Char): TRect;
 function TGenericTool.ToolKeyPress(var key: TUTF8Char): TRect;
@@ -1365,6 +1387,11 @@ begin
   if Assigned(FOnLineCapChanged) then FOnLineCapChanged(self);
   if Assigned(FOnLineCapChanged) then FOnLineCapChanged(self);
 end;
 end;
 
 
+procedure TToolManager.SetOutlineColor(AValue: TBGRAPixel);
+begin
+  FOutlineFill.SolidColor := AValue;
+end;
+
 procedure TToolManager.SetPerspectiveOptions(AValue: TPerspectiveOptions);
 procedure TToolManager.SetPerspectiveOptions(AValue: TPerspectiveOptions);
 begin
 begin
   if FPerspectiveOptions=AValue then Exit;
   if FPerspectiveOptions=AValue then Exit;
@@ -1611,16 +1638,26 @@ begin
   if toolCursor <> crDefault then result := toolCursor;
   if toolCursor <> crDefault then result := toolCursor;
 end;
 end;
 
 
-procedure TToolManager.BackFillChange(ASender: TObject;
+procedure TToolManager.FillChange(ASender: TObject;
   var ADiff: TCustomVectorialFillDiff);
   var ADiff: TCustomVectorialFillDiff);
 begin
 begin
   if FInToolUpdate or FInSwapFill then exit;
   if FInToolUpdate or FInSwapFill then exit;
   ToolUpdate;
   ToolUpdate;
   if Assigned(FOnFillChanged) then FOnFillChanged(self);
   if Assigned(FOnFillChanged) then FOnFillChanged(self);
-  if FBackFill.FillType = vftGradient then
+  if (ASender = FBackFill) and (FBackFill.FillType = vftGradient) then
   begin
   begin
     FBackLastGradient.Free;
     FBackLastGradient.Free;
     FBackLastGradient := FBackFill.Gradient.Duplicate as TBGRALayerGradientOriginal;
     FBackLastGradient := FBackFill.Gradient.Duplicate as TBGRALayerGradientOriginal;
+  end else
+  if (ASender = FForeFill) and (FForeFill.FillType = vftGradient) then
+  begin
+    FForeLastGradient.Free;
+    FForeLastGradient := FForeFill.Gradient.Duplicate as TBGRALayerGradientOriginal;
+  end else
+  if (ASender = FOutlineFill) and (FOutlineFill.FillType = vftGradient) then
+  begin
+    FOutlineLastGradient.Free;
+    FOutlineLastGradient := FOutlineFill.Gradient.Duplicate as TBGRALayerGradientOriginal;
   end;
   end;
 end;
 end;
 
 
@@ -1636,6 +1673,12 @@ begin
   else result := [vftSolid,vftGradient,vftTexture];
   else result := [vftSolid,vftGradient,vftTexture];
 end;
 end;
 
 
+function TToolManager.GetAllowedOutlineFillTypes: TVectorialFillTypes;
+begin
+  if Assigned(CurrentTool) then result := CurrentTool.AllowedOutlineFillTypes
+  else result := [vftSolid,vftGradient,vftTexture];
+end;
+
 function TToolManager.GetForeColor: TBGRAPixel;
 function TToolManager.GetForeColor: TBGRAPixel;
 begin
 begin
   if BlackAndWhite then
   if BlackAndWhite then
@@ -1650,6 +1693,14 @@ begin
   result.cy := Max(MinDeformationGridSize,Min(image.Height div 2,50)+1);
   result.cy := Max(MinDeformationGridSize,Min(image.Height div 2,50)+1);
 end;
 end;
 
 
+function TToolManager.GetOutlineColor: TBGRAPixel;
+begin
+  if BlackAndWhite then
+    result := BGRAToGrayscale(FOutlineFill.AverageColor)
+  else
+    result := FOutlineFill.AverageColor;
+end;
+
 function TToolManager.GetShapeOptionAliasing: boolean;
 function TToolManager.GetShapeOptionAliasing: boolean;
 begin
 begin
   result := toAliasing in FShapeOptions;
   result := toAliasing in FShapeOptions;
@@ -1681,19 +1732,6 @@ begin
   result := FTextFontStyle;
   result := FTextFontStyle;
 end;
 end;
 
 
-procedure TToolManager.ForeFillChange(ASender: TObject;
-  var ADiff: TCustomVectorialFillDiff);
-begin
-  if FInToolUpdate or FInSwapFill then exit;
-  ToolUpdate;
-  if Assigned(FOnFillChanged) then FOnFillChanged(self);
-  if FForeFill.FillType = vftGradient then
-  begin
-    FForeLastGradient.Free;
-    FForeLastGradient := FForeFill.Gradient.Duplicate as TBGRALayerGradientOriginal;
-  end;
-end;
-
 function TToolManager.ScriptGetAliasing(AVars: TVariableSet): TScriptResult;
 function TToolManager.ScriptGetAliasing(AVars: TVariableSet): TScriptResult;
 begin
 begin
   AVars.Booleans['Result'] := toAliasing in ShapeOptions;
   AVars.Booleans['Result'] := toAliasing in ShapeOptions;
@@ -1724,6 +1762,12 @@ begin
   result := srOk;
   result := srOk;
 end;
 end;
 
 
+function TToolManager.ScriptGetOutlineColor(AVars: TVariableSet): TScriptResult;
+begin
+  AVars.Pixels['Result'] := OutlineColor;
+  result := srOk;
+end;
+
 function TToolManager.ScriptGetBrushCount(AVars: TVariableSet): TScriptResult;
 function TToolManager.ScriptGetBrushCount(AVars: TVariableSet): TScriptResult;
 begin
 begin
   AVars.Integers['Result'] := BrushCount;
   AVars.Integers['Result'] := BrushCount;
@@ -1897,6 +1941,26 @@ begin
   result := ScriptGetGradientColors(AVars, FForeFill);
   result := ScriptGetGradientColors(AVars, FForeFill);
 end;
 end;
 
 
+function TToolManager.ScriptGetOutlineGradientInterpolation(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptGetGradientInterpolation(AVars, FOutlineFill);
+end;
+
+function TToolManager.ScriptGetOutlineGradientRepetition(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptGetGradientRepetition(AVars, FOutlineFill);
+end;
+
+function TToolManager.ScriptGetOutlineGradientType(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptGetGradientType(AVars, FOutlineFill);
+end;
+
+function TToolManager.ScriptGetOutlineGradientColors(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptGetGradientColors(AVars, FOutlineFill);
+end;
+
 function TToolManager.ScriptGetTextureRepetition(AVars: TVariableSet;
 function TToolManager.ScriptGetTextureRepetition(AVars: TVariableSet;
   AFill: TVectorialFill): TScriptResult;
   AFill: TVectorialFill): TScriptResult;
 begin
 begin
@@ -1940,6 +2004,16 @@ begin
   result := ScriptGetTextureOpacity(AVars, ForeFill);
   result := ScriptGetTextureOpacity(AVars, ForeFill);
 end;
 end;
 
 
+function TToolManager.ScriptGetOutlineTextureRepetition(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptGetTextureRepetition(AVars, OutlineFill);
+end;
+
+function TToolManager.ScriptGetOutlineTextureOpacity(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptGetTextureOpacity(AVars, OutlineFill);
+end;
+
 function TToolManager.ScriptGetJoinStyle(AVars: TVariableSet): TScriptResult;
 function TToolManager.ScriptGetJoinStyle(AVars: TVariableSet): TScriptResult;
 begin
 begin
   result := srOk;
   result := srOk;
@@ -2158,6 +2232,12 @@ begin
   result := srOk;
   result := srOk;
 end;
 end;
 
 
+function TToolManager.ScriptSetOutlineColor(AVars: TVariableSet): TScriptResult;
+begin
+  OutlineColor := AVars.Pixels['Color'];
+  result := srOk;
+end;
+
 function TToolManager.ScriptSetBrushIndex(AVars: TVariableSet): TScriptResult;
 function TToolManager.ScriptSetBrushIndex(AVars: TVariableSet): TScriptResult;
 var
 var
   index: Int64;
   index: Int64;
@@ -2310,8 +2390,8 @@ begin
     AFill.Gradient.GradientType:= gt
     AFill.Gradient.GradientType:= gt
   else
   else
   begin
   begin
-    if AFill = BackFill then
-      lastGrad := FBackLastGradient
+    if AFill = BackFill then lastGrad := FBackLastGradient
+    else if AFill = OutlineFill then lastGrad := FOutlineLastGradient
     else lastGrad := FForeLastGradient;
     else lastGrad := FForeLastGradient;
 
 
     lastGrad.GradientType:= gt;
     lastGrad.GradientType:= gt;
@@ -2343,8 +2423,8 @@ begin
     AFill.Gradient.SetColors(TVariableSet.GetPixelAt(colors, 0), TVariableSet.GetPixelAt(colors, 1))
     AFill.Gradient.SetColors(TVariableSet.GetPixelAt(colors, 0), TVariableSet.GetPixelAt(colors, 1))
   else
   else
   begin
   begin
-    if AFill = BackFill then
-      lastGrad := FBackLastGradient
+    if AFill = BackFill then lastGrad := FBackLastGradient
+    else if AFill = OutlineFill then lastGrad := FOutlineLastGradient
     else lastGrad := FForeLastGradient;
     else lastGrad := FForeLastGradient;
 
 
     b := SuggestGradientBox;
     b := SuggestGradientBox;
@@ -2380,6 +2460,26 @@ begin
   result := ScriptSetGradientColors(AVars, FBackFill);
   result := ScriptSetGradientColors(AVars, FBackFill);
 end;
 end;
 
 
+function TToolManager.ScriptSetOutlineGradientInterpolation(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetGradientInterpolation(AVars, FOutlineFill);
+end;
+
+function TToolManager.ScriptSetOutlineGradientRepetition(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetGradientRepetition(AVars, FOutlineFill);
+end;
+
+function TToolManager.ScriptSetOutlineGradientType(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetGradientType(AVars, FOutlineFill);
+end;
+
+function TToolManager.ScriptSetOutlineGradientColors(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetGradientColors(AVars, FOutlineFill);
+end;
+
 function TToolManager.ScriptSetForeGradientInterpolation(AVars: TVariableSet): TScriptResult;
 function TToolManager.ScriptSetForeGradientInterpolation(AVars: TVariableSet): TScriptResult;
 begin
 begin
   result := ScriptSetGradientInterpolation(AVars, FForeFill);
   result := ScriptSetGradientInterpolation(AVars, FForeFill);
@@ -2473,6 +2573,21 @@ begin
   result := ScriptSetTextureOpacity(AVars, ForeFill);
   result := ScriptSetTextureOpacity(AVars, ForeFill);
 end;
 end;
 
 
+function TToolManager.ScriptSetOutlineTexture(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetTexture(AVars, OutlineFill);
+end;
+
+function TToolManager.ScriptSetOutlineTextureRepetition(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetTextureRepetition(AVars, OutlineFill);
+end;
+
+function TToolManager.ScriptSetOutlineTextureOpacity(AVars: TVariableSet): TScriptResult;
+begin
+  result := ScriptSetTextureOpacity(AVars, OutlineFill);
+end;
+
 function TToolManager.ScriptSetJoinStyle(AVars: TVariableSet): TScriptResult;
 function TToolManager.ScriptSetJoinStyle(AVars: TVariableSet): TScriptResult;
 begin
 begin
   result := srOk;
   result := srOk;
@@ -2711,15 +2826,26 @@ begin
   RegisterScriptFunctions(True);
   RegisterScriptFunctions(True);
 
 
   FForeFill := TVectorialFill.Create;
   FForeFill := TVectorialFill.Create;
+  FForeFill.TransparentMode := tmAlphaZeroOnly;
   FForeFill.SolidColor := BGRABlack;
   FForeFill.SolidColor := BGRABlack;
-  FForeFill.OnChange:=@ForeFillChange;
-  FBackFill := TVectorialFill.Create;
-  FBackFill.SolidColor := CSSSkyBlue;
-  FBackFill.OnChange:=@BackFillChange;
+  FForeFill.OnChange:= @FillChange;
   FForeLastGradient:= TBGRALayerGradientOriginal.Create;
   FForeLastGradient:= TBGRALayerGradientOriginal.Create;
   FForeLastGradient.ColorInterpolation:= ciLinearRGB;
   FForeLastGradient.ColorInterpolation:= ciLinearRGB;
+
+  FBackFill := TVectorialFill.Create;
+  FBackFill.TransparentMode := tmAlphaZeroOnly;
+  FBackFill.SolidColor := CSSSkyBlue;
+  FBackFill.OnChange:= @FillChange;
   FBackLastGradient:= TBGRALayerGradientOriginal.Create;
   FBackLastGradient:= TBGRALayerGradientOriginal.Create;
   FBackLastGradient.ColorInterpolation:= ciLinearRGB;
   FBackLastGradient.ColorInterpolation:= ciLinearRGB;
+
+  FOutlineFill := TVectorialFill.Create;
+  FOutlineFill.TransparentMode := tmAlphaZeroOnly;
+  FOutlineFill.SolidColor := CSSRed;
+  FOutlineFill.OnChange:= @FillChange;
+  FOutlineLastGradient:= TBGRALayerGradientOriginal.Create;
+  FOutlineLastGradient.ColorInterpolation:= ciLinearRGB;
+
   FNormalPenWidth := 5;
   FNormalPenWidth := 5;
   FEraserWidth := 10;
   FEraserWidth := 10;
   FEraserAlpha := 255;
   FEraserAlpha := 255;
@@ -2740,7 +2866,7 @@ begin
   FTextOutlineWidth := 2;
   FTextOutlineWidth := 2;
   FTextShadow := false;
   FTextShadow := false;
   FTextFontSize := 10;
   FTextFontSize := 10;
-  FTextFontName := 'Arial';
+  FTextFontName := TTextShape.DefaultFontName;
   FTextFontStyle:= [];
   FTextFontStyle:= [];
   FTextAlign := taLeftJustify;
   FTextAlign := taLeftJustify;
   FTextPhong := False;
   FTextPhong := False;
@@ -2773,8 +2899,10 @@ begin
   AltitudeControls := TList.Create;
   AltitudeControls := TList.Create;
   PerspectiveControls := TList.Create;
   PerspectiveControls := TList.Create;
   FillControls := TList.Create;
   FillControls := TList.Create;
+  OutlineFillControls := TList.Create;
   BrushControls := TList.Create;
   BrushControls := TList.Create;
   RatioControls := TList.Create;
   RatioControls := TList.Create;
+  DonateControls := TList.Create;
 
 
   FCurrentToolType := ptHand;
   FCurrentToolType := ptHand;
   FCurrentTool := PaintTools[ptHand].Create(Self);
   FCurrentTool := PaintTools[ptHand].Create(Self);
@@ -2804,8 +2932,10 @@ begin
   AltitudeControls.Free;
   AltitudeControls.Free;
   PerspectiveControls.Free;
   PerspectiveControls.Free;
   FillControls.Free;
   FillControls.Free;
+  OutlineFillControls.Free;
   BrushControls.Free;
   BrushControls.Free;
   RatioControls.Free;
   RatioControls.Free;
+  DonateControls.Free;
 
 
   for i := 0 to BrushCount do
   for i := 0 to BrushCount do
     BrushAt[i].Free;
     BrushAt[i].Free;
@@ -2813,8 +2943,10 @@ begin
 
 
   FForeFill.Free;
   FForeFill.Free;
   FBackFill.Free;
   FBackFill.Free;
+  FOutlineFill.Free;
   FForeLastGradient.Free;
   FForeLastGradient.Free;
   FBackLastGradient.Free;
   FBackLastGradient.Free;
+  FOutlineLastGradient.Free;
 
 
   RegisterScriptFunctions(False);
   RegisterScriptFunctions(False);
   inherited Destroy;
   inherited Destroy;
@@ -2831,8 +2963,10 @@ begin
     exit;
     exit;
   ForeColor := Config.DefaultToolForeColor;
   ForeColor := Config.DefaultToolForeColor;
   BackColor := Config.DefaultToolBackColor;
   BackColor := Config.DefaultToolBackColor;
+  OutlineColor := Config.DefaultToolOutlineColor;
   AssignGradientFromConfigStr(FForeLastGradient, Config.DefaultToolForeGradient);
   AssignGradientFromConfigStr(FForeLastGradient, Config.DefaultToolForeGradient);
   AssignGradientFromConfigStr(FBackLastGradient, Config.DefaultToolBackGradient);
   AssignGradientFromConfigStr(FBackLastGradient, Config.DefaultToolBackGradient);
+  AssignGradientFromConfigStr(FOutlineLastGradient, Config.DefaultToolOutlineGradient);
   FNormalPenWidth := Config.DefaultToolPenWidth;
   FNormalPenWidth := Config.DefaultToolPenWidth;
   FEraserWidth := Config.DefaultToolEraserWidth;
   FEraserWidth := Config.DefaultToolEraserWidth;
   if Assigned(FOnPenWidthChanged) then FOnPenWidthChanged(self);
   if Assigned(FOnPenWidthChanged) then FOnPenWidthChanged(self);
@@ -2869,8 +3003,10 @@ begin
     exit;
     exit;
   if ForeFill.FillType = vftSolid then Config.SetDefaultToolForeColor(ForeColor);
   if ForeFill.FillType = vftSolid then Config.SetDefaultToolForeColor(ForeColor);
   if BackFill.FillType = vftSolid then Config.SetDefaultToolBackColor(BackColor);
   if BackFill.FillType = vftSolid then Config.SetDefaultToolBackColor(BackColor);
+  if OutlineFill.FillType = vftSolid then Config.SetDefaultToolOutlineColor(OutlineColor);
   Config.SetDefaultToolForeGradient(GradientToConfigStr(FForeLastGradient));
   Config.SetDefaultToolForeGradient(GradientToConfigStr(FForeLastGradient));
   Config.SetDefaultToolBackGradient(GradientToConfigStr(FBackLastGradient));
   Config.SetDefaultToolBackGradient(GradientToConfigStr(FBackLastGradient));
+  Config.SetDefaultToolOutlineGradient(GradientToConfigStr(FOutlineLastGradient));
   Config.SetDefaultToolPenWidth(FNormalPenWidth);
   Config.SetDefaultToolPenWidth(FNormalPenWidth);
   Config.SetDefaultToolEraserWidth(FEraserWidth);
   Config.SetDefaultToolEraserWidth(FEraserWidth);
   Config.SetDefaultToolOptionDrawShape(toDrawShape in ShapeOptions);
   Config.SetDefaultToolOptionDrawShape(toDrawShape in ShapeOptions);
@@ -2995,11 +3131,11 @@ begin
     if not IsSelectingTool then
     if not IsSelectingTool then
       Image.ReleaseEmptySelection;
       Image.ReleaseEmptySelection;
 
 
-    Image.RenderMayChange(rect(0,0,Image.Width,Image.Height),True);
-
     UpdateContextualToolbars;
     UpdateContextualToolbars;
     If Assigned(FOnToolChangedHandler) then
     If Assigned(FOnToolChangedHandler) then
       FOnToolChangedHandler(self, FCurrentToolType);
       FOnToolChangedHandler(self, FCurrentToolType);
+    If Assigned(FOnToolRenderChanged) then
+      FOnToolRenderChanged(self);
   end;
   end;
   FShouldExitTool:= false;
   FShouldExitTool:= false;
 end;
 end;
@@ -3046,12 +3182,19 @@ begin
   OrResult(SetControlsVisible(EraserControls, ctEraserOption in contextualToolbars));
   OrResult(SetControlsVisible(EraserControls, ctEraserOption in contextualToolbars));
   OrResult(SetControlsVisible(ToleranceControls, ctTolerance in contextualToolbars));
   OrResult(SetControlsVisible(ToleranceControls, ctTolerance in contextualToolbars));
   OrResult(SetControlsVisible(DeformationControls, ctDeformation in contextualToolbars));
   OrResult(SetControlsVisible(DeformationControls, ctDeformation in contextualToolbars));
-  OrResult(SetControlsVisible(TextControls, ctText in contextualToolbars));
+  if (ctText in contextualToolbars) and not (ctOutlineWidth in contextualToolbars) then
+    OrResult(SetControlsVisible(TextControls, True, 'Panel_Text')) else
+  if (ctOutlineWidth in contextualToolbars) and not (ctText in contextualToolbars) then
+    OrResult(SetControlsVisible(TextControls, True, 'Panel_TextOutline'))
+  else
+    OrResult(SetControlsVisible(TextControls, (ctText in contextualToolbars) and (ctOutlineWidth in contextualToolbars)));
+  OrResult(SetControlsVisible(OutlineFillControls, ctOutlineFill in contextualToolbars));
   OrResult(SetControlsVisible(TextShadowControls, ctTextShadow in contextualToolbars));
   OrResult(SetControlsVisible(TextShadowControls, ctTextShadow in contextualToolbars));
   OrResult(SetControlsVisible(PhongControls, ctPhong in contextualToolbars));
   OrResult(SetControlsVisible(PhongControls, ctPhong in contextualToolbars));
   OrResult(SetControlsVisible(AltitudeControls, ctAltitude in contextualToolbars));
   OrResult(SetControlsVisible(AltitudeControls, ctAltitude in contextualToolbars));
   OrResult(SetControlsVisible(PerspectiveControls, ctPerspective in contextualToolbars));
   OrResult(SetControlsVisible(PerspectiveControls, ctPerspective in contextualToolbars));
   OrResult(SetControlsVisible(RatioControls, ctRatio in contextualToolbars));
   OrResult(SetControlsVisible(RatioControls, ctRatio in contextualToolbars));
+  OrResult(SetControlsVisible(DonateControls, FCurrentToolType = ptHand));
 
 
   if result and Assigned(FOnToolbarChanged) then FOnToolbarChanged(self);
   if result and Assigned(FOnToolbarChanged) then FOnToolbarChanged(self);
 end;
 end;
@@ -3084,6 +3227,8 @@ begin
   FScriptContext.RegisterScriptFunction('ToolGetForeColor', @ScriptGetForeColor, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetForeColor', @ScriptGetForeColor, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetBackColor', @ScriptSetBackColor, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetBackColor', @ScriptSetBackColor, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackColor', @ScriptGetBackColor, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackColor', @ScriptGetBackColor, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineColor', @ScriptSetOutlineColor, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineColor', @ScriptGetOutlineColor, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetEraserMode', @ScriptSetEraserMode, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetEraserMode', @ScriptSetEraserMode, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetEraserMode', @ScriptGetEraserMode, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetEraserMode', @ScriptGetEraserMode, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetEraserAlpha', @ScriptSetEraserAlpha, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetEraserAlpha', @ScriptSetEraserAlpha, ARegister);
@@ -3147,6 +3292,14 @@ begin
   FScriptContext.RegisterScriptFunction('ToolGetBackGradientInterpolation', @ScriptGetBackGradientInterpolation, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackGradientInterpolation', @ScriptGetBackGradientInterpolation, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetBackGradientColors', @ScriptSetBackGradientColors, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetBackGradientColors', @ScriptSetBackGradientColors, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackGradientColors', @ScriptGetBackGradientColors, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackGradientColors', @ScriptGetBackGradientColors, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineGradientType', @ScriptSetOutlineGradientType, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineGradientType', @ScriptGetOutlineGradientType, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineGradientRepetition', @ScriptSetOutlineGradientRepetition, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineGradientRepetition', @ScriptGetOutlineGradientRepetition, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineGradientInterpolation', @ScriptSetOutlineGradientInterpolation, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineGradientInterpolation', @ScriptGetOutlineGradientInterpolation, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineGradientColors', @ScriptSetOutlineGradientColors, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineGradientColors', @ScriptGetOutlineGradientColors, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetForeTexture', @ScriptSetForeTexture, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetForeTexture', @ScriptSetForeTexture, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetForeTextureRepetition', @ScriptSetForeTextureRepetition, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetForeTextureRepetition', @ScriptSetForeTextureRepetition, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetForeTextureRepetition', @ScriptGetForeTextureRepetition, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetForeTextureRepetition', @ScriptGetForeTextureRepetition, ARegister);
@@ -3157,6 +3310,11 @@ begin
   FScriptContext.RegisterScriptFunction('ToolGetBackTextureRepetition', @ScriptGetBackTextureRepetition, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackTextureRepetition', @ScriptGetBackTextureRepetition, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetBackTextureOpacity', @ScriptSetBackTextureOpacity, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetBackTextureOpacity', @ScriptSetBackTextureOpacity, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackTextureOpacity', @ScriptGetBackTextureOpacity, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetBackTextureOpacity', @ScriptGetBackTextureOpacity, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineTexture', @ScriptSetOutlineTexture, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineTextureRepetition', @ScriptSetOutlineTextureRepetition, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineTextureRepetition', @ScriptGetOutlineTextureRepetition, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetOutlineTextureOpacity', @ScriptSetOutlineTextureOpacity, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetOutlineTextureOpacity', @ScriptGetOutlineTextureOpacity, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetPhongShapeAltitude', @ScriptSetPhongShapeAltitude, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetPhongShapeAltitude', @ScriptSetPhongShapeAltitude, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetPhongShapeAltitude', @ScriptGetPhongShapeAltitude, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetPhongShapeAltitude', @ScriptGetPhongShapeAltitude, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetPhongShapeBorderSize', @ScriptSetPhongShapeBorderSize, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetPhongShapeBorderSize', @ScriptSetPhongShapeBorderSize, ARegister);
@@ -3183,10 +3341,11 @@ begin
     FCurrentTool := FSleepingTool;
     FCurrentTool := FSleepingTool;
     FSleepingTool := nil;
     FSleepingTool := nil;
     FCurrentToolType := FSleepingToolType;
     FCurrentToolType := FSleepingToolType;
-    Image.RenderMayChange(rect(0,0,Image.Width,Image.Height),True);
     UpdateContextualToolbars;
     UpdateContextualToolbars;
     If Assigned(FOnToolChangedHandler) then
     If Assigned(FOnToolChangedHandler) then
       FOnToolChangedHandler(self, FCurrentToolType);
       FOnToolChangedHandler(self, FCurrentToolType);
+    If Assigned(FOnToolRenderChanged) then
+      FOnToolRenderChanged(self);
   end;
   end;
 end;
 end;
 
 
@@ -3301,6 +3460,7 @@ end;
 procedure TToolManager.SetTextFont(AName: string; ASize: single;
 procedure TToolManager.SetTextFont(AName: string; ASize: single;
   AStyle: TFontStyles);
   AStyle: TFontStyles);
 begin
 begin
+  if AName = '' then AName := FTextFontName;
   if (FTextFontName <> AName) or
   if (FTextFontName <> AName) or
     (FTextFontSize <> ASize) or
     (FTextFontSize <> ASize) or
     (FTextFontStyle <> AStyle) then
     (FTextFontStyle <> AStyle) then
@@ -3510,6 +3670,9 @@ begin
     FInTool := true;
     FInTool := true;
     try
     try
       FCurrentTool := PaintTools[FCurrentToolType].Create(self);
       FCurrentTool := PaintTools[FCurrentToolType].Create(self);
+      UpdateContextualToolbars;
+      If Assigned(FOnToolRenderChanged) then
+        FOnToolRenderChanged(self);
     finally
     finally
       FInTool := false;
       FInTool := false;
     end;
     end;
@@ -3579,22 +3742,29 @@ begin
   else result := false;
   else result := false;
 end;
 end;
 
 
+function TToolManager.IsOutlineEditGradTexPoints: boolean;
+begin
+  if Assigned(CurrentTool) then result := CurrentTool.IsOutlineEditGradTexPoints
+  else result := false;
+end;
+
 procedure TToolManager.QueryExitTool;
 procedure TToolManager.QueryExitTool;
 begin
 begin
   FShouldExitTool:= true;
   FShouldExitTool:= true;
 end;
 end;
 
 
-procedure TToolManager.RenderTool(formBitmap: TBGRABitmap);
+function TToolManager.RenderTool(formBitmap: TBGRABitmap): TRect;
 begin
 begin
   if ToolCanBeUsed and Assigned(CurrentTool) and not FInTool then
   if ToolCanBeUsed and Assigned(CurrentTool) and not FInTool then
   begin
   begin
     FInTool := true;
     FInTool := true;
     try
     try
-      Image.RenderMayChange(CurrentTool.Render(formBitmap,formBitmap.Width,formBitmap.Height, @InternalBitmapToVirtualScreen));
+      result := CurrentTool.Render(formBitmap,formBitmap.Width,formBitmap.Height, @InternalBitmapToVirtualScreen);
     finally
     finally
       FInTool := false;
       FInTool := false;
     end;
     end;
-  end;
+  end else
+    result := EmptyRect;
 end;
 end;
 
 
 function TToolManager.GetRenderBounds(VirtualScreenWidth, VirtualScreenHeight: integer): TRect;
 function TToolManager.GetRenderBounds(VirtualScreenWidth, VirtualScreenHeight: integer): TRect;

+ 11 - 1
lazpaint/tools/utooldeformationgrid.pas

@@ -74,6 +74,7 @@ type
     function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF): TRect;
     function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF): TRect;
       override;
       override;
     function DoToolKeyDown(var key: Word): TRect; override;
     function DoToolKeyDown(var key: Word): TRect; override;
+    function DoToolKeyUp(var key: Word): TRect; override;
     function GetIsSelectingTool: boolean; override;
     function GetIsSelectingTool: boolean; override;
     function GetTexture: TBGRABitmap; virtual;
     function GetTexture: TBGRABitmap; virtual;
     function GetTextureRepetition: TTextureRepetition; virtual;
     function GetTextureRepetition: TTextureRepetition; virtual;
@@ -727,7 +728,16 @@ begin
       manager.QueryExitTool;
       manager.QueryExitTool;
       key := 0;
       key := 0;
     end;
     end;
-  end;
+  end else
+  if (Key = VK_SHIFT) or (Key = VK_MENU) then
+    UpdateBoundsMode(result);
+end;
+
+function TToolTextureMapping.DoToolKeyUp(var key: Word): TRect;
+begin
+  Result:= EmptyRect;
+  if (Key = VK_SHIFT) or (Key = VK_MENU) then
+    UpdateBoundsMode(result);
 end;
 end;
 
 
 function TToolTextureMapping.ToolUp: TRect;
 function TToolTextureMapping.ToolUp: TRect;

+ 103 - 36
lazpaint/tools/utoolfloodfill.pas

@@ -25,6 +25,7 @@ type
 
 
   TToolGradient = class(TVectorialTool)
   TToolGradient = class(TVectorialTool)
   protected
   protected
+    function ShapeClass: TVectorShapeAny; override;
     function CreateShape: TVectorShape; override;
     function CreateShape: TVectorShape; override;
     procedure DrawCustomShape(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
     procedure DrawCustomShape(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
     procedure AssignShapeStyle({%H-}AMatrix: TAffineMatrix; {%H-}AAlwaysFit: boolean); override;
     procedure AssignShapeStyle({%H-}AMatrix: TAffineMatrix; {%H-}AAlwaysFit: boolean); override;
@@ -40,13 +41,18 @@ type
 implementation
 implementation
 
 
 uses ugraph, LazPaintType, BGRAGradientScanner, LCVectorRectShapes,
 uses ugraph, LazPaintType, BGRAGradientScanner, LCVectorRectShapes,
-  BGRATransform, UImageDiff, BGRAPen;
+  BGRATransform, UImageDiff, BGRAPen, UScripting, BGRABlend;
 
 
 { TToolGradient }
 { TToolGradient }
 
 
+function TToolGradient.ShapeClass: TVectorShapeAny;
+begin
+  result := TRectShape;
+end;
+
 function TToolGradient.CreateShape: TVectorShape;
 function TToolGradient.CreateShape: TVectorShape;
 begin
 begin
-  result := TRectShape.Create(nil);
+  result := inherited CreateShape;
   result.PenFill.Clear;
   result.PenFill.Clear;
   result.BackFill.SetGradient(TBGRALayerGradientOriginal.Create,true);
   result.BackFill.SetGradient(TBGRALayerGradientOriginal.Create,true);
   result.Usermode := vsuEditBackFill;
   result.Usermode := vsuEditBackFill;
@@ -82,7 +88,8 @@ function TToolGradient.ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDi
 var
 var
   gradientOrig: TBGRALayerCustomOriginal;
   gradientOrig: TBGRALayerCustomOriginal;
 begin
 begin
-  if Manager.Image.CurrentLayerEmpty then
+  if (FShape.BackFill.FillType = vftGradient) and
+    (Manager.Image.CurrentLayerEmpty or FShape.BackFill.Gradient.IsOpaque) then
   begin
   begin
     gradientOrig := FShape.BackFill.Gradient.Duplicate;
     gradientOrig := FShape.BackFill.Gradient.Duplicate;
     result := TReplaceLayerByCustomOriginalDifference.Create(Manager.Image.CurrentState,
     result := TReplaceLayerByCustomOriginalDifference.Create(Manager.Image.CurrentState,
@@ -123,47 +130,107 @@ var
   diff: TCustomImageDifference;
   diff: TCustomImageDifference;
   rectShape: TRectShape;
   rectShape: TRectShape;
   homogeneous: Boolean;
   homogeneous: Boolean;
+  params: TVariableSet;
+  vectOrig: TVectorOriginal;
+  i: Integer;
+  ptOrig: TPointF;
+  newColor: TBGRAPixel;
 begin
 begin
+  result := OnlyRenderChange;
   homogeneous := toolDest.Equals(toolDest.GetPixel(0,0));
   homogeneous := toolDest.Equals(toolDest.GetPixel(0,0));
-  if Manager.Image.SelectionMaskEmpty and homogeneous then
+  if Manager.Image.SelectionMaskEmpty then
   begin
   begin
-    CancelAction;
-    if rightBtn then f := Manager.BackFill.Duplicate
-    else f := Manager.ForeFill.Duplicate;
-    try
-      f.ApplyOpacity(Manager.GetPressureB);
-      f.FitGeometry(SuggestGradientBox);
-      case f.FillType of
-      vftGradient: orig := f.Gradient.Duplicate;
-      else
+    if homogeneous then
+    begin
+      CancelAction;
+      if rightBtn then f := Manager.BackFill.Duplicate
+      else f := Manager.ForeFill.Duplicate;
+      try
+        f.ApplyOpacity(Manager.GetPressureB);
+        f.FitGeometry(SuggestGradientBox);
+        case f.FillType of
+        vftGradient: orig := f.Gradient.Duplicate;
+        else
+          begin
+            orig := TVectorOriginal.Create;
+            rectShape := TRectShape.Create(nil);
+            rectShape.QuickDefine(PointF(-0.5,-0.5), PointF(Manager.Image.Width-0.5,Manager.Image.Height-0.5));
+            rectShape.PenStyle := ClearPenStyle;
+            rectShape.BackFill.Assign(f);
+            TVectorOriginal(orig).AddShape(rectShape);
+          end;
+        end;
+        diff := TReplaceLayerByCustomOriginalDifference.Create(Manager.Image.CurrentState,
+                      Manager.Image.CurrentLayerIndex, false, orig);
+        Manager.Image.AddUndo(diff);
+        Manager.Image.ImageMayChangeCompletely;
+      finally
+        f.Free;
+      end;
+      exit;
+    end else
+    if GetCurrentLayerKind = lkVectorial then
+    begin
+      if rightBtn then f := Manager.BackFill else f := Manager.ForeFill;
+      if f.FillType = vftSolid then
+      begin
+        vectOrig := TVectorOriginal(Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex]);
+        ptOrig := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]) * ptF;
+        for i := vectOrig.ShapeCount-1 downto 0 do
         begin
         begin
-          orig := TVectorOriginal.Create;
-          rectShape := TRectShape.Create(nil);
-          rectShape.QuickDefine(PointF(-0.5,-0.5), PointF(Manager.Image.Width-0.5,Manager.Image.Height-0.5));
-          rectShape.PenStyle := ClearPenStyle;
-          rectShape.BackFill.Assign(f);
-          TVectorOriginal(orig).AddShape(rectShape);
+          if (vsfPenFill in vectOrig.Shape[i].MultiFields) and
+            vectOrig.Shape[i].PointInPen(ptOrig) then
+          begin
+            if not (vectOrig.Shape[i].PenFill.FillType = vftSolid) then break;
+            CancelAction;
+            Manager.Image.CurrentState.DiscardOriginalDiff:= false;
+            try
+              newColor := vectOrig.Shape[i].PenFill.SolidColor;
+              DrawPixelsInline(@newColor, f.SolidColor, 1);
+              vectOrig.Shape[i].PenFill.SetSolid(newColor);
+            finally
+              Manager.Image.CurrentState.DiscardOriginalDiff:= true;
+            end;
+            exit;
+          end;
+          if (vsfBackFill in vectOrig.Shape[i].MultiFields) and
+            vectOrig.Shape[i].PointInBack(ptOrig) then
+          begin
+            if not (vectOrig.Shape[i].BackFill.FillType = vftSolid) then break;
+            CancelAction;
+            Manager.Image.CurrentState.DiscardOriginalDiff:= false;
+            try
+              newColor := vectOrig.Shape[i].BackFill.SolidColor;
+              DrawPixelsInline(@newColor, f.SolidColor, 1);
+              vectOrig.Shape[i].BackFill.SetSolid(newColor);
+            finally
+              Manager.Image.CurrentState.DiscardOriginalDiff:= true;
+            end;
+            exit;
+          end;
+        end;
+        if (toolDest.GetPixel(pt.X,pt.Y).alpha = 0)
+          and Assigned(Manager.Scripting) then
+        begin
+          CancelAction;
+          params := TVariableSet.Create('ImageFillBackground');
+          params.Pixels['BackColor'] := f.SolidColor;
+          Manager.Scripting.CallScriptFunction(params);
+          params.Free;
+          exit;
         end;
         end;
       end;
       end;
-      diff := TReplaceLayerByCustomOriginalDifference.Create(Manager.Image.CurrentState,
-                    Manager.Image.CurrentLayerIndex, false, orig);
-      Manager.Image.AddUndo(diff);
-      Manager.Image.ImageMayChangeCompletely;
-    finally
-      f.Free;
     end;
     end;
-  end else
-  begin
-    if rightBtn then b := GetBackUniversalBrush
-    else b := GetForeUniversalBrush;
-    if homogeneous then toolDest.Fill(b)
-      else toolDest.FloodFill(pt.X, pt.Y, b,
-                    ffProgressive in Manager.FloodFillOptions, Manager.Tolerance*$101);
-    ReleaseUniversalBrushes;
-    Action.NotifyChange(toolDest, rect(0,0,toolDest.Width,toolDest.Height));
-    ValidateAction;
   end;
   end;
-  result := OnlyRenderChange;
+
+  if rightBtn then b := GetBackUniversalBrush
+  else b := GetForeUniversalBrush;
+  if homogeneous then toolDest.Fill(b)
+    else toolDest.FloodFill(pt.X, pt.Y, b,
+                  ffProgressive in Manager.FloodFillOptions, Manager.Tolerance*$101);
+  ReleaseUniversalBrushes;
+  Action.NotifyChange(toolDest, rect(0,0,toolDest.Width,toolDest.Height));
+  ValidateAction;
 end;
 end;
 
 
 function TToolFloodFill.GetContextualToolbars: TContextualToolbars;
 function TToolFloodFill.GetContextualToolbars: TContextualToolbars;

+ 26 - 11
lazpaint/tools/utoollayer.pas

@@ -7,7 +7,7 @@ interface
 uses
 uses
   Classes, SysUtils, UTool, BGRABitmap, BGRABitmapTypes,
   Classes, SysUtils, UTool, BGRABitmap, BGRABitmapTypes,
   BGRATransform, BGRALayers, ULayerAction, UImageDiff,
   BGRATransform, BGRALayers, ULayerAction, UImageDiff,
-  UImageType;
+  UImageType, UStateType;
 
 
 type
 type
   { TToolMoveLayer }
   { TToolMoveLayer }
@@ -197,9 +197,14 @@ begin
   begin
   begin
     if UseOriginal then
     if UseOriginal then
     begin
     begin
-      FLayerBounds := Manager.Image.LayerOriginal[idx].GetRenderBounds(
-                        Rect(-VeryBigValue,-VeryBigValue,VeryBigValue,VeryBigValue),
-                        AffineMatrixIdentity);
+      if Manager.Image.LayerOriginal[idx] is TVectorOriginal then
+        FLayerBounds := TVectorOriginal(Manager.Image.LayerOriginal[idx]).GetAlignBounds(
+                          Rect(-VeryBigValue,-VeryBigValue,VeryBigValue,VeryBigValue),
+                          AffineMatrixIdentity)
+      else
+        FLayerBounds := Manager.Image.LayerOriginal[idx].GetRenderBounds(
+                          Rect(-VeryBigValue,-VeryBigValue,VeryBigValue,VeryBigValue),
+                          AffineMatrixIdentity);
       if FLayerBounds.Left = -VeryBigValue then FLayerBounds.Left := 0;
       if FLayerBounds.Left = -VeryBigValue then FLayerBounds.Left := 0;
       if FLayerBounds.Top = -VeryBigValue then FLayerBounds.Top := 0;
       if FLayerBounds.Top = -VeryBigValue then FLayerBounds.Top := 0;
       if FLayerBounds.Right = VeryBigValue then FLayerBounds.Right := Manager.Image.Width;
       if FLayerBounds.Right = VeryBigValue then FLayerBounds.Right := Manager.Image.Width;
@@ -570,17 +575,22 @@ end;
 procedure TToolTransformLayer.ValidateTransform;
 procedure TToolTransformLayer.ValidateTransform;
 var
 var
   transform: TAffineMatrix;
   transform: TAffineMatrix;
+  layerIdx: Integer;
+  invTransformDiff: TCustomImageDifference;
+  r: TRect;
 begin
 begin
   if FOriginalInit then
   if FOriginalInit then
   begin
   begin
     if Assigned(FBackupLayer) then
     if Assigned(FBackupLayer) then
     begin
     begin
-      transform := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
-      Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] := FInitialOriginalMatrix;
-      Manager.Image.CurrentState.LayeredBitmap.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] := transform;
-      Manager.Image.CurrentState.LayeredBitmap.RenderLayerFromOriginal(Manager.Image.CurrentLayerIndex);
+      layerIdx := Manager.Image.CurrentLayerIndex;
+      transform := Manager.Image.LayerOriginalMatrix[layerIdx];
+      invTransformDiff := Manager.Image.CurrentState.ComputeLayerMatrixDifference(layerIdx,
+                          transform, FInitialOriginalMatrix);
       FBackupLayer.nextMatrix := transform;
       FBackupLayer.nextMatrix := transform;
+      Manager.Image.AddUndo(invTransformDiff);
       Manager.Image.AddUndo(FBackupLayer);
       Manager.Image.AddUndo(FBackupLayer);
+      Manager.Image.CurrentState.LayeredBitmap.RenderLayerFromOriginalIfNecessary(layerIdx, false, r);
       FBackupLayer := nil;
       FBackupLayer := nil;
     end;
     end;
     FOriginalInit := false;
     FOriginalInit := false;
@@ -717,9 +727,14 @@ begin
   begin
   begin
     if Manager.Image.LayerOriginalDefined[idx] then
     if Manager.Image.LayerOriginalDefined[idx] then
     begin
     begin
-      FOriginalBounds := Manager.Image.LayerOriginal[idx].GetRenderBounds(
-                        Rect(-VeryBigValue,-VeryBigValue,VeryBigValue,VeryBigValue),
-                        AffineMatrixIdentity);
+      if Manager.Image.LayerOriginal[idx] is TVectorOriginal then
+        FOriginalBounds := TVectorOriginal(Manager.Image.LayerOriginal[idx]).GetAlignBounds(
+                          Rect(-VeryBigValue,-VeryBigValue,VeryBigValue,VeryBigValue),
+                          AffineMatrixIdentity)
+      else
+        FOriginalBounds := Manager.Image.LayerOriginal[idx].GetRenderBounds(
+                          Rect(-VeryBigValue,-VeryBigValue,VeryBigValue,VeryBigValue),
+                          AffineMatrixIdentity);
       if FOriginalBounds.Left = -VeryBigValue then FOriginalBounds.Left := 0;
       if FOriginalBounds.Left = -VeryBigValue then FOriginalBounds.Left := 0;
       if FOriginalBounds.Top = -VeryBigValue then FOriginalBounds.Top := 0;
       if FOriginalBounds.Top = -VeryBigValue then FOriginalBounds.Top := 0;
       if FOriginalBounds.Right = VeryBigValue then FOriginalBounds.Right := Manager.Image.Width;
       if FOriginalBounds.Right = VeryBigValue then FOriginalBounds.Right := Manager.Image.Width;

+ 3 - 3
lazpaint/tools/utoolphong.pas

@@ -16,7 +16,7 @@ type
     FMatrix: TAffineMatrix;
     FMatrix: TAffineMatrix;
     procedure ShapeChange({%H-}ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff); override;
     procedure ShapeChange({%H-}ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff); override;
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
-    function CreateShape: TVectorShape; override;
+    function ShapeClass: TVectorShapeAny; override;
   public
   public
     constructor Create(AManager: TToolManager); override;
     constructor Create(AManager: TToolManager); override;
     function GetContextualToolbars: TContextualToolbars; override;
     function GetContextualToolbars: TContextualToolbars; override;
@@ -61,9 +61,9 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TToolPhong.CreateShape: TVectorShape;
+function TToolPhong.ShapeClass: TVectorShapeAny;
 begin
 begin
-  result := TPhongShape.Create(nil);
+  result := TPhongShape;
 end;
 end;
 
 
 initialization
 initialization

+ 19 - 34
lazpaint/tools/utoolpolygon.pas

@@ -16,19 +16,15 @@ type
 
 
   TToolRectangle = class(TVectorialTool)
   TToolRectangle = class(TVectorialTool)
   protected
   protected
-    function CreateShape: TVectorShape; override;
-  public
-    function GetContextualToolbars: TContextualToolbars; override;
+    function ShapeClass: TVectorShapeAny; override;
   end;
   end;
 
 
   { TToolEllipse }
   { TToolEllipse }
 
 
   TToolEllipse = class(TVectorialTool)
   TToolEllipse = class(TVectorialTool)
   protected
   protected
-    function CreateShape: TVectorShape; override;
+    function ShapeClass: TVectorShapeAny; override;
     function GetGridMatrix: TAffineMatrix; override;
     function GetGridMatrix: TAffineMatrix; override;
-  public
-    function GetContextualToolbars: TContextualToolbars; override;
   end;
   end;
 
 
   { TToolPolygon }
   { TToolPolygon }
@@ -36,6 +32,7 @@ type
   TToolPolygon = class(TVectorialTool)
   TToolPolygon = class(TVectorialTool)
   protected
   protected
     initiallyClosed : boolean;
     initiallyClosed : boolean;
+    function ShapeClass: TVectorShapeAny; override;
     function CreateShape: TVectorShape; override;
     function CreateShape: TVectorShape; override;
     function ShouldCloseShape: boolean; virtual;
     function ShouldCloseShape: boolean; virtual;
     procedure UpdateManagerCloseShape({%H-}AClose: boolean); virtual;
     procedure UpdateManagerCloseShape({%H-}AClose: boolean); virtual;
@@ -47,7 +44,6 @@ type
   public
   public
     function ToolUp: TRect; override;
     function ToolUp: TRect; override;
     function ToolKeyPress(var key: TUTF8Char): TRect; override;
     function ToolKeyPress(var key: TUTF8Char): TRect; override;
-    function GetContextualToolbars: TContextualToolbars; override;
   end;
   end;
 
 
   { TToolPolyline }
   { TToolPolyline }
@@ -73,13 +69,13 @@ type
     function GetCurrentMode: TToolSplineMode;
     function GetCurrentMode: TToolSplineMode;
     procedure SetCurrentMode(AValue: TToolSplineMode);
     procedure SetCurrentMode(AValue: TToolSplineMode);
   protected
   protected
+    function ShapeClass: TVectorShapeAny; override;
     function CreateShape: TVectorShape; override;
     function CreateShape: TVectorShape; override;
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
     procedure UpdateUserMode; override;
     procedure UpdateUserMode; override;
   public
   public
     constructor Create(AManager: TToolManager); override;
     constructor Create(AManager: TToolManager); override;
     function ToolKeyPress(var key: TUTF8Char): TRect; override;
     function ToolKeyPress(var key: TUTF8Char): TRect; override;
-    function GetContextualToolbars: TContextualToolbars; override;
     property CurrentMode: TToolSplineMode read GetCurrentMode write SetCurrentMode;
     property CurrentMode: TToolSplineMode read GetCurrentMode write SetCurrentMode;
   end;
   end;
 
 
@@ -166,9 +162,9 @@ end;
 
 
 { TToolEllipse }
 { TToolEllipse }
 
 
-function TToolEllipse.CreateShape: TVectorShape;
+function TToolEllipse.ShapeClass: TVectorShapeAny;
 begin
 begin
-  result := TEllipseShape.Create(nil);
+  result := TEllipseShape;
 end;
 end;
 
 
 function TToolEllipse.GetGridMatrix: TAffineMatrix;
 function TToolEllipse.GetGridMatrix: TAffineMatrix;
@@ -176,21 +172,11 @@ begin
   Result:= AffineMatrixScale(0.5, 0.5);
   Result:= AffineMatrixScale(0.5, 0.5);
 end;
 end;
 
 
-function TToolEllipse.GetContextualToolbars: TContextualToolbars;
-begin
-  Result:= [ctPenFill,ctBackFill,ctShape,ctPenWidth,ctPenStyle];
-end;
-
 { TToolRectangle }
 { TToolRectangle }
 
 
-function TToolRectangle.CreateShape: TVectorShape;
-begin
-  result := TRectShape.Create(nil);
-end;
-
-function TToolRectangle.GetContextualToolbars: TContextualToolbars;
+function TToolRectangle.ShapeClass: TVectorShapeAny;
 begin
 begin
-  Result:= [ctPenFill,ctBackFill,ctShape,ctPenWidth,ctPenStyle,ctJoinStyle];
+  result := TRectShape;
 end;
 end;
 
 
 { TToolSpline }
 { TToolSpline }
@@ -209,6 +195,11 @@ begin
   UpdateUserMode;
   UpdateUserMode;
 end;
 end;
 
 
+function TToolSpline.ShapeClass: TVectorShapeAny;
+begin
+  result := TCurveShape;
+end;
+
 procedure TToolSpline.UpdateUserMode;
 procedure TToolSpline.UpdateUserMode;
 var
 var
   c: TCurveShape;
   c: TCurveShape;
@@ -233,8 +224,7 @@ end;
 
 
 function TToolSpline.CreateShape: TVectorShape;
 function TToolSpline.CreateShape: TVectorShape;
 begin
 begin
-  result := TCurveShape.Create(nil);
-  result.Usermode := vsuCreate;
+  result := inherited CreateShape;
   TCurveShape(result).CosineAngle:= EasyBezierMinimumDotProduct;
   TCurveShape(result).CosineAngle:= EasyBezierMinimumDotProduct;
   if not FCurveModeHintShown then
   if not FCurveModeHintShown then
   begin
   begin
@@ -269,16 +259,16 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TToolSpline.GetContextualToolbars: TContextualToolbars;
+{ TToolPolygon }
+
+function TToolPolygon.ShapeClass: TVectorShapeAny;
 begin
 begin
-  Result:= [ctPenFill,ctBackFill,ctShape,ctCloseShape,ctPenWidth,ctPenStyle,ctLineCap,ctSplineStyle];
+  result := TPolylineShape;
 end;
 end;
 
 
-{ TToolPolygon }
-
 function TToolPolygon.CreateShape: TVectorShape;
 function TToolPolygon.CreateShape: TVectorShape;
 begin
 begin
-  result := TPolylineShape.Create(nil);
+  result := inherited CreateShape;
   initiallyClosed := ShouldCloseShape;
   initiallyClosed := ShouldCloseShape;
 end;
 end;
 
 
@@ -366,11 +356,6 @@ begin
     result := ptF;
     result := ptF;
 end;
 end;
 
 
-function TToolPolygon.GetContextualToolbars: TContextualToolbars;
-begin
-  Result:= [ctPenFill,ctBackFill,ctShape,ctCloseShape,ctPenWidth,ctPenStyle,ctJoinStyle,ctLineCap];
-end;
-
 initialization
 initialization
 
 
   RegisterTool(ptRect,TToolRectangle);
   RegisterTool(ptRect,TToolRectangle);

+ 7 - 7
lazpaint/tools/utoolselect.pas

@@ -29,7 +29,7 @@ type
 
 
   TToolSelectRect = class(TVectorialSelectTool)
   TToolSelectRect = class(TVectorialSelectTool)
   protected
   protected
-    function CreateShape: TVectorShape; override;
+    function ShapeClass: TVectorShapeAny; override;
   public
   public
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
     function GetContextualToolbars: TContextualToolbars; override;
     function GetContextualToolbars: TContextualToolbars; override;
@@ -39,7 +39,7 @@ type
 
 
   TToolSelectEllipse = class(TVectorialSelectTool)
   TToolSelectEllipse = class(TVectorialSelectTool)
   protected
   protected
-    function CreateShape: TVectorShape; override;
+    function ShapeClass: TVectorShapeAny; override;
     function GetGridMatrix: TAffineMatrix; override;
     function GetGridMatrix: TAffineMatrix; override;
   public
   public
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
@@ -149,7 +149,7 @@ procedure AssignSelectShapeStyle(AShape: TVectorShape; ASwapColor: boolean);
 var
 var
   f: TVectorShapeFields;
   f: TVectorShapeFields;
 begin
 begin
-  f:= AShape.Fields;
+  f:= AShape.MultiFields;
   if vsfPenFill in f then AShape.PenFill.Clear;
   if vsfPenFill in f then AShape.PenFill.Clear;
   if vsfPenStyle in f Then AShape.PenStyle := ClearPenStyle;
   if vsfPenStyle in f Then AShape.PenStyle := ClearPenStyle;
   if vsfBackFill in f then
   if vsfBackFill in f then
@@ -266,9 +266,9 @@ end;
 
 
 { TToolSelectRect }
 { TToolSelectRect }
 
 
-function TToolSelectRect.CreateShape: TVectorShape;
+function TToolSelectRect.ShapeClass: TVectorShapeAny;
 begin
 begin
-  result := TRectShape.Create(nil);
+  result := TRectShape;
 end;
 end;
 
 
 function TToolSelectRect.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
 function TToolSelectRect.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
@@ -309,9 +309,9 @@ end;
 
 
 { TToolSelectEllipse }
 { TToolSelectEllipse }
 
 
-function TToolSelectEllipse.CreateShape: TVectorShape;
+function TToolSelectEllipse.ShapeClass: TVectorShapeAny;
 begin
 begin
-  result := TEllipseShape.Create(nil);
+  result := TEllipseShape;
 end;
 end;
 
 
 function TToolSelectEllipse.GetGridMatrix: TAffineMatrix;
 function TToolSelectEllipse.GetGridMatrix: TAffineMatrix;

+ 41 - 77
lazpaint/tools/utooltext.pas

@@ -18,7 +18,7 @@ type
     FPrevShadow: boolean;
     FPrevShadow: boolean;
     FPrevShadowOffset: TPoint;
     FPrevShadowOffset: TPoint;
     FPrevShadowRadius: single;
     FPrevShadowRadius: single;
-    function CreateShape: TVectorShape; override;
+    function ShapeClass: TVectorShapeAny; override;
     function AlwaysRasterizeShape: boolean; override;
     function AlwaysRasterizeShape: boolean; override;
     procedure IncludeShadowBounds(var ARect: TRect);
     procedure IncludeShadowBounds(var ARect: TRect);
     function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; ADraft: boolean): TRect; override;
     function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; ADraft: boolean): TRect; override;
@@ -28,10 +28,6 @@ type
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
     procedure QuickDefineEnd; override;
     procedure QuickDefineEnd; override;
     function RoundCoordinate(constref ptF: TPointF): TPointF; override;
     function RoundCoordinate(constref ptF: TPointF): TPointF; override;
-    function ForeGradTexMode: TVectorShapeUsermode; override;
-    function BackGradTexMode: TVectorShapeUsermode; override;
-    function ShapeForeFill: TVectorialFill; override;
-    function ShapeBackFill: TVectorialFill; override;
     function DoToolKeyDown(var key: Word): TRect; override;
     function DoToolKeyDown(var key: Word): TRect; override;
   public
   public
     constructor Create(AManager: TToolManager); override;
     constructor Create(AManager: TToolManager); override;
@@ -47,9 +43,9 @@ uses LCVectorTextShapes, BGRALayerOriginal, BGRATransform, BGRAGrayscaleMask,
 
 
 { TToolText }
 { TToolText }
 
 
-function TToolText.CreateShape: TVectorShape;
+function TToolText.ShapeClass: TVectorShapeAny;
 begin
 begin
-  result := TTextShape.Create(nil);
+  result := TTextShape;
 end;
 end;
 
 
 function TToolText.AlwaysRasterizeShape: boolean;
 function TToolText.AlwaysRasterizeShape: boolean;
@@ -150,9 +146,8 @@ var
   r: TRect;
   r: TRect;
   toolDest: TBGRABitmap;
   toolDest: TBGRABitmap;
   zoom: Single;
   zoom: Single;
-  gradBox: TAffineBox;
-  fitMode: TFitMode;
 begin
 begin
+  inherited AssignShapeStyle(AMatrix, AAlwaysFit);
   FMatrix := AMatrix;
   FMatrix := AMatrix;
   with TTextShape(FShape) do
   with TTextShape(FShape) do
   begin
   begin
@@ -160,27 +155,7 @@ begin
     FontEmHeight:= zoom*Manager.TextFontSize*Manager.Image.DPI/72;
     FontEmHeight:= zoom*Manager.TextFontSize*Manager.Image.DPI/72;
     FontName:= Manager.TextFontName;
     FontName:= Manager.TextFontName;
     FontStyle:= Manager.TextFontStyle;
     FontStyle:= Manager.TextFontStyle;
-    gradBox := self.SuggestGradientBox;
-
-    if AAlwaysFit then fitMode := fmAlways else fitMode := ForeFitMode;
-    if FSwapColor then
-      AssignFill(FShape.PenFill, Manager.BackFill, gradBox, fitMode)
-    else
-      AssignFill(FShape.PenFill, Manager.ForeFill, gradBox, fitMode);
-
-    if Manager.TextOutline and (Manager.TextOutlineWidth>0) and
-       (Manager.BackColor.alpha > 0) then
-    begin
-      if AAlwaysFit then fitMode := fmAlways else fitMode := BackFitMode;
-      if FSwapColor then
-        AssignFill(FShape.OutlineFill, Manager.ForeFill, gradBox, fitMode)
-      else
-        AssignFill(FShape.OutlineFill, Manager.BackFill, gradBox, fitMode);
-      OutlineWidth := Manager.TextOutlineWidth;
-    end
-    else
-      OutlineFill.Clear;
-
+    Aliased := Manager.ShapeOptionAliasing;
     LightPosition := AMatrix*Manager.LightPosition;
     LightPosition := AMatrix*Manager.LightPosition;
     AltitudePercent:= Manager.PhongShapeAltitude;
     AltitudePercent:= Manager.PhongShapeAltitude;
     ParagraphAlignment:= Manager.TextAlign;
     ParagraphAlignment:= Manager.TextAlign;
@@ -206,38 +181,6 @@ begin
   result := PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5);
   result := PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5);
 end;
 end;
 
 
-function TToolText.ForeGradTexMode: TVectorShapeUsermode;
-begin
-  if FSwapColor then result := vsuEditOutlineFill else
-    result := vsuEditPenFill;
-end;
-
-function TToolText.BackGradTexMode: TVectorShapeUsermode;
-begin
-  if FSwapColor then result := vsuEditPenFill else
-    result := vsuEditOutlineFill;
-end;
-
-function TToolText.ShapeForeFill: TVectorialFill;
-begin
-  if Assigned(FShape) then
-  begin
-    if FSwapColor then result := FShape.OutlineFill else
-      result := FShape.PenFill;
-  end else
-    result := nil;
-end;
-
-function TToolText.ShapeBackFill: TVectorialFill;
-begin
-  if Assigned(FShape) then
-  begin
-    if FSwapColor then result := FShape.PenFill else
-      result := FShape.OutlineFill;
-  end else
-    result := nil;
-end;
-
 constructor TToolText.Create(AManager: TToolManager);
 constructor TToolText.Create(AManager: TToolManager);
 begin
 begin
   inherited Create(AManager);
   inherited Create(AManager);
@@ -246,7 +189,7 @@ end;
 
 
 function TToolText.GetContextualToolbars: TContextualToolbars;
 function TToolText.GetContextualToolbars: TContextualToolbars;
 begin
 begin
-  Result:= [ctPenFill,ctBackFill,ctText];
+  Result:= [ctPenFill,ctText,ctOutlineFill,ctOutlineWidth,ctAliasing];
   if Manager.TextPhong then include(result, ctAltitude);
   if Manager.TextPhong then include(result, ctAltitude);
 end;
 end;
 
 
@@ -263,38 +206,59 @@ begin
   end else
   end else
   if (Key = VK_ESCAPE) and Assigned(FShape) then
   if (Key = VK_ESCAPE) and Assigned(FShape) then
   begin
   begin
-    result := ValidateShape;
+    if FShape.Usermode = vsuEditText then
+      FShape.Usermode := vsuEdit
+    else
+      result := ValidateShape;
     Key := 0;
     Key := 0;
   end else
   end else
   if (Key = VK_RETURN) and Assigned(FShape) then
   if (Key = VK_RETURN) and Assigned(FShape) then
   begin
   begin
     handled := false;
     handled := false;
     FShape.KeyDown(ShiftState, skReturn, handled);
     FShape.KeyDown(ShiftState, skReturn, handled);
-    if handled then Key := 0;
+    if not handled then ValidateShape;
+    Key := 0;
   end else
   end else
     Result:=inherited DoToolKeyDown(key);
     Result:=inherited DoToolKeyDown(key);
 end;
 end;
 
 
 function TToolText.ToolCommand(ACommand: TToolCommand): boolean;
 function TToolText.ToolCommand(ACommand: TToolCommand): boolean;
 begin
 begin
-  case ACommand of
-  tcCopy: Result:= Assigned(FShape) and TTextShape(FShape).CopySelection;
-  tcCut: Result:= Assigned(FShape) and TTextShape(FShape).CutSelection;
-  tcPaste: Result:= Assigned(FShape) and TTextShape(FShape).PasteSelection;
-  tcDelete: Result:= Assigned(FShape) and TTextShape(FShape).DeleteSelection;
+  if Assigned(FShape) and (FShape.Usermode = vsuEditText) then
+    case ACommand of
+    tcCopy: Result:= TTextShape(FShape).CopySelection;
+    tcCut: Result:= TTextShape(FShape).CutSelection;
+    tcPaste: Result:= TTextShape(FShape).PasteSelection;
+    tcDelete: Result:= TTextShape(FShape).DeleteSelection;
+    else
+      result := inherited ToolCommand(ACommand);
+    end
   else
   else
-    result := inherited ToolCommand(ACommand);
-  end;
+    case ACommand of
+    tcDelete:
+      if Assigned(FShape) then
+      begin
+        CancelShape;
+        result := true;
+      end else result := false;
+    else result := inherited ToolCommand(ACommand);
+    end;
 end;
 end;
 
 
 function TToolText.ToolProvideCommand(ACommand: TToolCommand): boolean;
 function TToolText.ToolProvideCommand(ACommand: TToolCommand): boolean;
 begin
 begin
-  case ACommand of
-  tcCopy,tcCut,tcDelete: result := Assigned(FShape) and TTextShape(FShape).HasSelection;
-  tcPaste: result := Assigned(FShape);
+  if Assigned(FShape) and (FShape.Usermode = vsuEditText) then
+    case ACommand of
+    tcCopy,tcCut,tcDelete: result := TTextShape(FShape).HasSelection;
+    tcPaste: result := true;
+    else
+      result := inherited ToolProvideCommand(ACommand);
+    end
   else
   else
-    result := inherited ToolProvideCommand(ACommand);
-  end;
+    case ACommand of
+    tcDelete: result := Assigned(FShape);
+    else result := inherited ToolProvideCommand(ACommand);
+    end;
 end;
 end;
 
 
 initialization
 initialization

+ 258 - 156
lazpaint/tools/utoolvectorial.pas

@@ -7,7 +7,7 @@ interface
 uses
 uses
   Classes, SysUtils, LCLType, BGRABitmap, BGRABitmapTypes,
   Classes, SysUtils, LCLType, BGRABitmap, BGRABitmapTypes,
   BGRALayerOriginal, BGRAGraphics, LCVectorOriginal, LCVectorialFill,
   BGRALayerOriginal, BGRAGraphics, LCVectorOriginal, LCVectorialFill,
-  UTool, UImageType, ULayerAction, LCVectorRectShapes,
+  UTool, UImageType, ULayerAction, LCVectorRectShapes, LCVectorMultishape,
   BGRAGradientOriginal, UStateType;
   BGRAGradientOriginal, UStateType;
 
 
 type
 type
@@ -40,7 +40,8 @@ type
     FLastShapeTransform: TAffineMatrix;
     FLastShapeTransform: TAffineMatrix;
     FUseOriginal: boolean;
     FUseOriginal: boolean;
     function AlwaysRasterizeShape: boolean; virtual;
     function AlwaysRasterizeShape: boolean; virtual;
-    function CreateShape: TVectorShape; virtual; abstract;
+    function CreateShape: TVectorShape; virtual;
+    function ShapeClass: TVectorShapeAny; virtual; abstract;
     function UseOriginal: boolean; virtual;
     function UseOriginal: boolean; virtual;
     function HasBrush: boolean; virtual;
     function HasBrush: boolean; virtual;
     function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; {%H-}ADraft: boolean): TRect; virtual;
     function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; {%H-}ADraft: boolean): TRect; virtual;
@@ -72,12 +73,16 @@ type
     procedure ShapeValidated; virtual;
     procedure ShapeValidated; virtual;
     function ForeGradTexMode: TVectorShapeUsermode; virtual;
     function ForeGradTexMode: TVectorShapeUsermode; virtual;
     function BackGradTexMode: TVectorShapeUsermode; virtual;
     function BackGradTexMode: TVectorShapeUsermode; virtual;
-    function ShapeForeFill: TVectorialFill; virtual;
-    function ShapeBackFill: TVectorialFill; virtual;
+    function OutlineGradTexMode: TVectorShapeUsermode; virtual;
     function ForeFitMode: TFitMode;
     function ForeFitMode: TFitMode;
     function BackFitMode: TFitMode;
     function BackFitMode: TFitMode;
+    function OutlineFitMode: TFitMode;
+    function ManagerForeFill: TVectorialFill;
+    function ManagerBackFill: TVectorialFill;
+    function ManagerOutlineFill: TVectorialFill;
     function GetIsForeEditGradTexPoints: boolean; override;
     function GetIsForeEditGradTexPoints: boolean; override;
     function GetIsBackEditGradTexPoints: boolean; override;
     function GetIsBackEditGradTexPoints: boolean; override;
+    function GetIsOutlineEditGradTexPoints: boolean; override;
     function GetGridMatrix: TAffineMatrix; virtual;
     function GetGridMatrix: TAffineMatrix; virtual;
     property Editor: TBGRAOriginalEditor read GetEditor;
     property Editor: TBGRAOriginalEditor read GetEditor;
   public
   public
@@ -89,6 +94,7 @@ type
     function ToolCommand(ACommand: TToolCommand): boolean; override;
     function ToolCommand(ACommand: TToolCommand): boolean; override;
     function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
     function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
     function SuggestGradientBox: TAffineBox; override;
     function SuggestGradientBox: TAffineBox; override;
+    function GetContextualToolbars: TContextualToolbars; override;
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
     property IsIdle: boolean read GetIsIdle;
     property IsIdle: boolean read GetIsIdle;
     property IsHandDrawing: boolean read GetIsHandDrawing;
     property IsHandDrawing: boolean read GetIsHandDrawing;
@@ -145,12 +151,13 @@ type
     function InvalidEditMode: boolean;
     function InvalidEditMode: boolean;
     function ForeGradTexMode: TVectorShapeUsermode; virtual;
     function ForeGradTexMode: TVectorShapeUsermode; virtual;
     function BackGradTexMode: TVectorShapeUsermode; virtual;
     function BackGradTexMode: TVectorShapeUsermode; virtual;
-    function ShapeForeFill: TVectorialFill; virtual;
-    function ShapeBackFill: TVectorialFill; virtual;
+    function OutlineGradTexMode: TVectorShapeUsermode; virtual;
     function ForeFitMode: TFitMode;
     function ForeFitMode: TFitMode;
     function BackFitMode: TFitMode;
     function BackFitMode: TFitMode;
+    function OutlineFitMode: TFitMode;
     function GetIsForeEditGradTexPoints: boolean; override;
     function GetIsForeEditGradTexPoints: boolean; override;
     function GetIsBackEditGradTexPoints: boolean; override;
     function GetIsBackEditGradTexPoints: boolean; override;
+    function GetIsOutlineEditGradTexPoints: boolean; override;
     function GetAllowedBackFillTypes: TVectorialFillTypes; override;
     function GetAllowedBackFillTypes: TVectorialFillTypes; override;
     function GetStatusText: string; override;
     function GetStatusText: string; override;
   public
   public
@@ -220,6 +227,35 @@ begin
   end;
   end;
 end;
 end;
 
 
+function ContextualToolbarsFromShape(AShapeClass: TVectorShapeAny; AShape: TVectorShape): TContextualToolbars;
+var
+  f: TVectorShapeFields;
+begin
+  result:= [ctPenFill, ctBackFill];
+  if Assigned(AShape) then
+    f := AShape.MultiFields
+    else f := AShapeClass.Fields;
+  if vsfPenWidth in f then result += [ctPenWidth];
+  if vsfPenStyle in f then result += [ctPenStyle];
+  if vsfJoinStyle in f then result += [ctJoinStyle];
+  if [vsfPenStyle,vsfPenFill,vsfBackFill] <= f then result += [ctShape];
+  if vsfOutlineFill in f then
+  begin
+    result += [ctOutlineFill];
+    if not (vsfBackFill in f) then result -= [ctBackFill];
+  end;
+  if vsfOutlineWidth in f then result += [ctOutlineWidth];
+
+  if AShapeClass = TCurveShape then result := result + [ctShape,ctCloseShape,ctLineCap,ctSplineStyle]
+  else if AShapeClass = TPolylineShape then result := result + [ctShape,ctCloseShape,ctLineCap]
+  else if AShapeClass = TPhongShape then result := result + [ctPhong,ctAltitude]
+  else if AShapeClass = TTextShape then
+  begin
+    result := result + [ctText,ctAliasing];
+    if TTextShape(AShape).PenPhong then include(result, ctAltitude);
+  end;
+end;
+
 procedure AlignShape(AShape: TVectorShape; ACommand: TToolCommand; const AMatrix: TAffineMatrix; const ARect: TRect);
 procedure AlignShape(AShape: TVectorShape; ACommand: TToolCommand; const AMatrix: TAffineMatrix; const ARect: TRect);
 begin
 begin
   case ACommand of
   case ACommand of
@@ -376,45 +412,35 @@ var
   zoom: single;
   zoom: single;
   m: TAffineMatrix;
   m: TAffineMatrix;
   doFill, doDraw: Boolean;
   doFill, doDraw: Boolean;
+  f: TVectorShapeFields;
 begin
 begin
   m := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
   m := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
   zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
   zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
   if AShape.Usermode in [vsuEditBackFill, vsuEditPenFill] then
   if AShape.Usermode in [vsuEditBackFill, vsuEditPenFill] then
     AShape.Usermode := vsuEdit;
     AShape.Usermode := vsuEdit;
   opt := Manager.ShapeOptions;
   opt := Manager.ShapeOptions;
-  if AShape.Fields*[vsfPenFill,vsfBackFill,vsfPenStyle] = [vsfPenFill,vsfBackFill,vsfPenStyle] then
-  begin
-    if AShape.BackFill.FillType = vftNone then
-    begin;
-      exclude(opt,toFillShape);
-      doFill := false;
-    end
-    else
-    begin
-      include(opt,toFillShape);
-      doFill := true;
-    end;
-    ps := BGRAToPenStyle(AShape.PenStyle);
-    if (ps = psClear) or (AShape.PenFill.FillType = vftNone) then
-    begin
-      exclude(opt,toDrawShape);
-      doDraw := false;
-    end
-    else
-    begin
-      include(opt,toDrawShape);
-      Manager.PenStyle := ps;
-      doDraw := true;
-    end;
-  end else
+  f := AShape.MultiFields;
+  doDraw := vsfPenFill in f;
+  doFill := vsfBackFill in f;
+  if vsfPenStyle in f then
   begin
   begin
-    doDraw := vsfPenFill in AShape.Fields;
-    doFill := vsfBackFill in AShape.Fields;
+    doDraw := AShape.PenVisible;
+    if doDraw then doFill := AShape.BackVisible;
+
+    if not doFill then
+      exclude(opt,toFillShape)
+      else include(opt,toFillShape);
+    if not doDraw then
+      exclude(opt,toDrawShape)
+      else
+      begin
+        include(opt,toDrawShape);
+        Manager.PenStyle := ps;
+      end;
   end;
   end;
-
   if doDraw then
   if doDraw then
   begin
   begin
-    if AShape.PenFill.FillType = vftNone then
+    if not AShape.PenVisible then
       Manager.ForeColor := BGRA(Manager.ForeColor.red,
       Manager.ForeColor := BGRA(Manager.ForeColor.red,
         Manager.ForeColor.green,Manager.ForeColor.blue,0)
         Manager.ForeColor.green,Manager.ForeColor.blue,0)
     else
     else
@@ -422,17 +448,23 @@ begin
   end;
   end;
   if doFill then
   if doFill then
   begin
   begin
-    if AShape.BackFill.FillType = vftNone then
+    if not AShape.BackVisible then
       Manager.BackColor := BGRA(Manager.BackColor.red,
       Manager.BackColor := BGRA(Manager.BackColor.red,
         Manager.BackColor.green,Manager.BackColor.blue,0)
         Manager.BackColor.green,Manager.BackColor.blue,0)
     else
     else
       Manager.BackFill.Assign(AShape.BackFill);
       Manager.BackFill.Assign(AShape.BackFill);
   end;
   end;
+  if not AShape.OutlineVisible then
+    Manager.SetTextOutline(false, Manager.TextOutlineWidth) else
+  begin
+    Manager.SetTextOutline(true, AShape.OutlineWidth*zoom);
+    Manager.OutlineFill.Assign(AShape.OutlineFill);
+  end;
 
 
   if toDrawShape in opt then
   if toDrawShape in opt then
   begin
   begin
-    if vsfPenWidth in AShape.Fields then Manager.PenWidth := AShape.PenWidth*zoom;
-    if vsfJoinStyle in AShape.Fields then Manager.JoinStyle:= AShape.JoinStyle;
+    if vsfPenWidth in f then Manager.PenWidth := AShape.PenWidth*zoom;
+    if vsfJoinStyle in f then Manager.JoinStyle:= AShape.JoinStyle;
     if AShape is TCustomPolypointShape then
     if AShape is TCustomPolypointShape then
     begin
     begin
       if TCustomPolypointShape(AShape).Closed then
       if TCustomPolypointShape(AShape).Closed then
@@ -447,7 +479,6 @@ begin
     if AShape is TCurveShape then
     if AShape is TCurveShape then
       Manager.SplineStyle := TCurveShape(AShape).SplineStyle;
       Manager.SplineStyle := TCurveShape(AShape).SplineStyle;
   end;
   end;
-  Manager.ShapeOptions := opt;
 
 
   if AShape is TTextShape then
   if AShape is TTextShape then
   with TTextShape(AShape) do
   with TTextShape(AShape) do
@@ -456,15 +487,13 @@ begin
     Manager.LightPosition := m*LightPosition;
     Manager.LightPosition := m*LightPosition;
     Manager.PhongShapeAltitude := round(AltitudePercent);
     Manager.PhongShapeAltitude := round(AltitudePercent);
     Manager.TextAlign:= ParagraphAlignment;
     Manager.TextAlign:= ParagraphAlignment;
-    Manager.SetTextFont(FontName,round(FontEmHeight*zoom*72/Manager.Image.DPI),FontStyle);
+    Manager.SetTextFont(FontName, FontEmHeight*zoom*72/Manager.Image.DPI, FontStyle);
     Manager.TextShadow:= false;
     Manager.TextShadow:= false;
-    if OutlineFill.FillType = vftNone then
-      Manager.SetTextOutline(false, Manager.TextOutlineWidth) else
-    begin
-      Manager.SetTextOutline(true, OutlineWidth);
-      Manager.BackFill.Assign(OutlineFill);
-    end;
+    if Aliased then
+      include(opt,toAliasing)
+      else exclude(opt,toAliasing);
   end;
   end;
+  Manager.ShapeOptions := opt;
 
 
   if AShape is TPhongShape then
   if AShape is TPhongShape then
   with TPhongShape(AShape) do
   with TPhongShape(AShape) do
@@ -603,52 +632,64 @@ var
   m: TAffineMatrix;
   m: TAffineMatrix;
   zoom: Single;
   zoom: Single;
   gradBox: TAffineBox;
   gradBox: TAffineBox;
+  f: TVectorShapeFields;
+  shape: TVectorShape;
 begin
 begin
+  shape := nil;
   case GetEditMode of
   case GetEditMode of
   esmShape:
   esmShape:
-    with GetVectorOriginal do
     try
     try
       BindOriginalEvent(true);
       BindOriginalEvent(true);
-      gradBox := SelectedShape.SuggestGradientBox(AffineMatrixIdentity);
+      shape := GetVectorOriginal.SelectedShape;
+      shape.BeginUpdate;
+      gradBox := shape.SuggestGradientBox(AffineMatrixIdentity);
       m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
       m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
       zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
       zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
-      if SelectedShape.Fields*[vsfPenFill,vsfBackFill,vsfPenStyle] = [vsfPenFill,vsfBackFill,vsfPenStyle] then
+      f := shape.MultiFields;
+      if f*[vsfPenFill,vsfBackFill,vsfPenStyle] = [vsfPenFill,vsfBackFill,vsfPenStyle] then
       begin
       begin
         doDraw := toDrawShape in Manager.ShapeOptions;
         doDraw := toDrawShape in Manager.ShapeOptions;
         doFill := toFillShape in Manager.ShapeOptions;
         doFill := toFillShape in Manager.ShapeOptions;
 
 
         if doDraw then
         if doDraw then
-          SelectedShape.PenStyle := PenStyleToBGRA(Manager.PenStyle)
+          shape.PenStyle := PenStyleToBGRA(Manager.PenStyle)
         else
         else
-          SelectedShape.PenStyle := ClearPenStyle;
+          shape.PenStyle := ClearPenStyle;
 
 
-        if vsfPenWidth in SelectedShape.Fields then SelectedShape.PenWidth := Manager.PenWidth*zoom;
-        if vsfJoinStyle in SelectedShape.Fields then SelectedShape.JoinStyle := Manager.JoinStyle;
-        if SelectedShape is TCustomPolypointShape then
+        if doDraw and (vsfPenWidth in f) then shape.PenWidth := Manager.PenWidth*zoom;
+        if doDraw and (vsfJoinStyle in f) then shape.JoinStyle := Manager.JoinStyle;
+        if shape is TCustomPolypointShape then
         begin
         begin
-          TCustomPolypointShape(SelectedShape).Closed := toCloseShape in Manager.ShapeOptions;
-          if not TCustomPolypointShape(SelectedShape).Closed then
+          TCustomPolypointShape(shape).Closed := toCloseShape in Manager.ShapeOptions;
+          if not TCustomPolypointShape(shape).Closed then
           begin
           begin
-            TCustomPolypointShape(SelectedShape).LineCap:= Manager.LineCap;
-            TCustomPolypointShape(SelectedShape).ArrowSize:= Manager.ArrowSize;
-            TCustomPolypointShape(SelectedShape).ArrowStartKind:= Manager.ArrowStart;
-            TCustomPolypointShape(SelectedShape).ArrowEndKind:= Manager.ArrowEnd;
+            TCustomPolypointShape(shape).LineCap:= Manager.LineCap;
+            TCustomPolypointShape(shape).ArrowSize:= Manager.ArrowSize;
+            TCustomPolypointShape(shape).ArrowStartKind:= Manager.ArrowStart;
+            TCustomPolypointShape(shape).ArrowEndKind:= Manager.ArrowEnd;
           end;
           end;
         end;
         end;
-        if SelectedShape is TCurveShape then
-          TCurveShape(SelectedShape).SplineStyle:= Manager.SplineStyle;
+        if shape is TCurveShape then
+          TCurveShape(shape).SplineStyle:= Manager.SplineStyle;
       end else
       end else
       begin
       begin
-        doDraw := vsfPenFill in SelectedShape.Fields;
-        doFill := vsfBackFill in SelectedShape.Fields;
+        doDraw := vsfPenFill in f;
+        doFill := vsfBackFill in f;
+      end;
+      if doFill then AssignFill(shape.BackFill, Manager.BackFill, gradBox, BackFitMode)
+      else if vsfBackFill in f then
+          shape.BackFill.Clear;
+      if doDraw then AssignFill(shape.PenFill, Manager.ForeFill, gradBox, ForeFitMode);
+      if (vsfOutlineWidth in f) and Manager.TextOutline then shape.OutlineWidth := Manager.TextOutlineWidth*zoom;
+      if vsfOutlineFill in f then
+      begin
+        if Manager.TextOutline then
+          AssignFill(shape.OutLineFill, Manager.OutLineFill, gradBox, OutlineFitMode)
+          else shape.OutlineFill.Clear;
       end;
       end;
-      if doFill then AssignFill(SelectedShape.BackFill, Manager.BackFill, gradBox, BackFitMode)
-      else if vsfBackFill in SelectedShape.Fields then
-          SelectedShape.BackFill.Clear;
-      if doDraw then AssignFill(SelectedShape.PenFill, Manager.ForeFill, gradBox, ForeFitMode);
 
 
-      if SelectedShape is TTextShape then
-      with TTextShape(SelectedShape) do
+      if shape is TTextShape then
+      with TTextShape(shape) do
       begin
       begin
         PenPhong := Manager.TextPhong;
         PenPhong := Manager.TextPhong;
         LightPosition := m*Manager.LightPosition;
         LightPosition := m*Manager.LightPosition;
@@ -657,15 +698,10 @@ begin
         FontName:= Manager.TextFontName;
         FontName:= Manager.TextFontName;
         FontEmHeight:= Manager.TextFontSize*zoom*Manager.Image.DPI/72;
         FontEmHeight:= Manager.TextFontSize*zoom*Manager.Image.DPI/72;
         FontStyle := Manager.TextFontStyle;
         FontStyle := Manager.TextFontStyle;
-        if Manager.TextOutline then
-        begin
-          OutlineWidth := Manager.TextOutlineWidth;
-          AssignFill(OutLineFill, Manager.BackFill, gradBox, BackFitMode);
-        end else
-          OutlineFill.Clear;
+        Aliased := Manager.ShapeOptionAliasing;
       end;
       end;
-      if SelectedShape is TPhongShape then
-      with TPhongShape(SelectedShape) do
+      if shape is TPhongShape then
+      with TPhongShape(shape) do
       begin
       begin
         ShapeKind := Manager.PhongShapeKind;
         ShapeKind := Manager.PhongShapeKind;
         LightPosition := Manager.LightPosition;
         LightPosition := Manager.LightPosition;
@@ -673,6 +709,7 @@ begin
         BorderSizePercent := Manager.PhongShapeBorderSize;
         BorderSizePercent := Manager.PhongShapeBorderSize;
       end;
       end;
     finally
     finally
+      if Assigned(shape) then shape.EndUpdate;
       BindOriginalEvent(false);
       BindOriginalEvent(false);
     end;
     end;
   esmGradient:
   esmGradient:
@@ -721,7 +758,7 @@ begin
     Manager.Image.LayerMayChange(GetToolDrawingLayer,r);
     Manager.Image.LayerMayChange(GetToolDrawingLayer,r);
   end;
   end;
   case GetEditMode of
   case GetEditMode of
-  esmShape: GetVectorOriginal.DeselectShape;
+  esmShape: GetVectorOriginal.DeselectShapes;
   esmGradient: FIsEditingGradient:= false;
   esmGradient: FIsEditingGradient:= false;
   esmOtherOriginal: FreeAndNil(FOriginalRect);
   esmOtherOriginal: FreeAndNil(FOriginalRect);
   esmSelection: FreeAndNil(FSelectionRect);
   esmSelection: FreeAndNil(FSelectionRect);
@@ -862,7 +899,10 @@ end;
 
 
 destructor TEditShapeTool.Destroy;
 destructor TEditShapeTool.Destroy;
 begin
 begin
-  StopEdit(False, False);
+  FreeAndNil(FOriginalRect);
+  FreeAndNil(FSelectionRect);
+  Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
+  FreeAndNil(FRectEditor);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -870,23 +910,15 @@ function TEditShapeTool.GetContextualToolbars: TContextualToolbars;
 var
 var
   shape: TVectorShape;
   shape: TVectorShape;
 begin
 begin
-  Result:= [ctPenFill, ctBackFill];
   case GetEditMode of
   case GetEditMode of
   esmShape:
   esmShape:
     begin
     begin
       shape := GetVectorOriginal.SelectedShape;
       shape := GetVectorOriginal.SelectedShape;
-      if shape is TRectShape then result := result + [ctShape,ctPenWidth,ctPenStyle,ctJoinStyle]
-      else if shape is TEllipseShape then result := result + [ctShape,ctPenWidth,ctPenStyle]
-      else if shape is TCurveShape then result := result + [ctShape,ctCloseShape,ctPenWidth,ctPenStyle,ctLineCap,ctSplineStyle]
-      else if shape is TPolylineShape then result := result + [ctShape,ctCloseShape,ctPenWidth,ctPenStyle,ctJoinStyle,ctLineCap]
-      else if shape is TPhongShape then result := result + [ctPhong,ctAltitude]
-      else if shape is TTextShape then
-      begin
-        result := result + [ctText];
-        if TTextShape(shape).PenPhong then include(result, ctAltitude);
-      end;
+      result := ContextualToolbarsFromShape(TVectorShapeAny(shape.ClassType), shape);
     end;
     end;
   esmGradient: result := [ctBackFill];
   esmGradient: result := [ctBackFill];
+  else
+    Result:= [ctPenFill, ctBackFill];
   end;
   end;
 end;
 end;
 
 
@@ -1006,7 +1038,7 @@ begin
     shapeAfter := TCurveShape.CreateFrom(orig, shapeBefore);
     shapeAfter := TCurveShape.CreateFrom(orig, shapeBefore);
     shapeAfter.JoinStyle := pjsRound;
     shapeAfter.JoinStyle := pjsRound;
     orig.ReplaceShape(orig.IndexOfShape(shapeBefore), shapeAfter);
     orig.ReplaceShape(orig.IndexOfShape(shapeBefore), shapeAfter);
-    orig.SelectShape(shapeAfter);
+    orig.SelectShape(shapeAfter, False);
     result := true;
     result := true;
   end else
   end else
     result := false;
     result := false;
@@ -1046,28 +1078,12 @@ end;
 
 
 function TEditShapeTool.BackGradTexMode: TVectorShapeUsermode;
 function TEditShapeTool.BackGradTexMode: TVectorShapeUsermode;
 begin
 begin
-  if (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape is TTextShape) then
-    result := vsuEditOutlineFill
-  else
-    result := vsuEditBackFill;
+  result := vsuEditBackFill;
 end;
 end;
 
 
-function TEditShapeTool.ShapeForeFill: TVectorialFill;
+function TEditShapeTool.OutlineGradTexMode: TVectorShapeUsermode;
 begin
 begin
-  if GetEditMode = esmShape then result := GetVectorOriginal.SelectedShape.PenFill
-  else result := nil;
-end;
-
-function TEditShapeTool.ShapeBackFill: TVectorialFill;
-begin
-  if GetEditMode = esmShape then
-  begin
-    if GetVectorOriginal.SelectedShape is TTextShape then
-      result := GetVectorOriginal.SelectedShape.OutlineFill
-    else
-      result := GetVectorOriginal.SelectedShape.BackFill;
-  end
-  else result := nil;
+  result := vsuEditOutlineFill;
 end;
 end;
 
 
 function TEditShapeTool.ForeFitMode: TFitMode;
 function TEditShapeTool.ForeFitMode: TFitMode;
@@ -1082,6 +1098,12 @@ begin
   else result := fmIfChange;
   else result := fmIfChange;
 end;
 end;
 
 
+function TEditShapeTool.OutlineFitMode: TFitMode;
+begin
+  if IsOutlineEditGradTexPoints then result := fmNever
+  else result := fmIfChange;
+end;
+
 function TEditShapeTool.GetIsForeEditGradTexPoints: boolean;
 function TEditShapeTool.GetIsForeEditGradTexPoints: boolean;
 begin
 begin
   result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = ForeGradTexMode);
   result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = ForeGradTexMode);
@@ -1092,6 +1114,11 @@ begin
   result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode);
   result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode);
 end;
 end;
 
 
+function TEditShapeTool.GetIsOutlineEditGradTexPoints: boolean;
+begin
+  result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = OutlineGradTexMode);
+end;
+
 function TEditShapeTool.GetAllowedBackFillTypes: TVectorialFillTypes;
 function TEditShapeTool.GetAllowedBackFillTypes: TVectorialFillTypes;
 begin
 begin
   if GetEditMode = esmGradient then
   if GetEditMode = esmGradient then
@@ -1130,7 +1157,7 @@ begin
   if not Manager.Image.SelectionMaskEmpty then
   if not Manager.Image.SelectionMaskEmpty then
   begin
   begin
     if (GetCurrentLayerKind = lkVectorial) and Assigned(GetVectorOriginal.SelectedShape) then
     if (GetCurrentLayerKind = lkVectorial) and Assigned(GetVectorOriginal.SelectedShape) then
-      GetVectorOriginal.DeselectShape;
+      GetVectorOriginal.DeselectShapes;
     DoEditSelection;
     DoEditSelection;
   end else
   end else
   if (GetCurrentLayerKind = lkVectorial) and Assigned(GetVectorOriginal.SelectedShape) then
   if (GetCurrentLayerKind = lkVectorial) and Assigned(GetVectorOriginal.SelectedShape) then
@@ -1161,6 +1188,14 @@ begin
           begin
           begin
             GetVectorOriginal.RemoveShape(GetVectorOriginal.SelectedShape);
             GetVectorOriginal.RemoveShape(GetVectorOriginal.SelectedShape);
             key := 0;
             key := 0;
+          end else
+          if (key = VK_ESCAPE) and Assigned(GetVectorOriginal.SelectedShape) then
+          begin
+            if GetVectorOriginal.SelectedShape.Usermode = vsuEditText then
+              GetVectorOriginal.SelectedShape.Usermode := vsuEdit
+            else
+              GetVectorOriginal.DeselectShapes;
+            key := 0;
           end;
           end;
         end;
         end;
       finally
       finally
@@ -1305,7 +1340,7 @@ begin
           zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2/Manager.Image.ZoomFactor;
           zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2/Manager.Image.ZoomFactor;
           BindOriginalEvent(true);
           BindOriginalEvent(true);
           try
           try
-            if GetVectorOriginal.MouseClick(m*FLastPos, DoScaleX(PointSize, OriginalDPI)*zoom) then
+            if GetVectorOriginal.MouseClick(m*FLastPos, DoScaleX(PointSize, OriginalDPI)*zoom, ssCtrl in ShiftState) then
             begin
             begin
               handled := true;
               handled := true;
               result := OnlyRenderChange;
               result := OnlyRenderChange;
@@ -1419,8 +1454,12 @@ begin
           tcBackEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode then
           tcBackEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode then
                                     GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
                                     GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
                                     GetVectorOriginal.SelectedShape.Usermode := BackGradTexMode;
                                     GetVectorOriginal.SelectedShape.Usermode := BackGradTexMode;
-          tcForeAdjustToShape: ShapeForeFill.FitGeometry(SuggestGradientBox);
-          tcBackAdjustToShape: ShapeBackFill.FitGeometry(SuggestGradientBox);
+          tcOutlineEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = OutlineGradTexMode then
+                                    GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
+                                    GetVectorOriginal.SelectedShape.Usermode := OutlineGradTexMode;
+          tcForeAdjustToShape: GetVectorOriginal.SelectedShape.PenFill.FitGeometry(SuggestGradientBox);
+          tcBackAdjustToShape: GetVectorOriginal.SelectedShape.BackFill.FitGeometry(SuggestGradientBox);
+          tcOutlineAdjustToShape: GetVectorOriginal.SelectedShape.OutlineFill.FitGeometry(SuggestGradientBox);
           tcShapeToSpline: result := ConvertToSpline;
           tcShapeToSpline: result := ConvertToSpline;
           else result := false;
           else result := false;
         end;
         end;
@@ -1508,12 +1547,14 @@ function TEditShapeTool.ToolProvideCommand(ACommand: TToolCommand): boolean;
 begin
 begin
   case ACommand of
   case ACommand of
   tcCut,tcCopy,tcDelete: result:= GetEditMode in [esmShape,esmOtherOriginal,esmGradient];
   tcCut,tcCopy,tcDelete: result:= GetEditMode in [esmShape,esmOtherOriginal,esmGradient];
-  tcForeAdjustToShape: result := GetEditMode = esmShape;
+  tcForeAdjustToShape,tcOutlineAdjustToShape: result := GetEditMode = esmShape;
   tcBackAdjustToShape: result := GetEditMode in [esmShape,esmGradient];
   tcBackAdjustToShape: result := GetEditMode in [esmShape,esmGradient];
   tcForeEditGradTexPoints: result := (GetEditMode = esmShape) and
   tcForeEditGradTexPoints: result := (GetEditMode = esmShape) and
-                     (ForeGradTexMode in GetVectorOriginal.SelectedShape.Usermodes);
+                     (ForeGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
   tcBackEditGradTexPoints: result := (GetEditMode = esmShape) and
   tcBackEditGradTexPoints: result := (GetEditMode = esmShape) and
-                     (BackGradTexMode in GetVectorOriginal.SelectedShape.Usermodes);
+                     (BackGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
+  tcOutlineEditGradTexPoints: result := (GetEditMode = esmShape) and
+                     (OutlineGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
   tcShapeToSpline: result:= (GetEditMode = esmShape)
   tcShapeToSpline: result:= (GetEditMode = esmShape)
                             and TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape);
                             and TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape);
   tcAlignLeft..tcAlignBottom: result:= GetEditMode in [esmShape, esmOtherOriginal, esmSelection];
   tcAlignLeft..tcAlignBottom: result:= GetEditMode in [esmShape, esmOtherOriginal, esmSelection];
@@ -1564,10 +1605,7 @@ begin
     newEditorBounds := Editor.GetRenderBounds(rect(0,0,ceil(x),ceil(y)));
     newEditorBounds := Editor.GetRenderBounds(rect(0,0,ceil(x),ceil(y)));
   r := RectUnion(FPreviousEditorBounds,newEditorBounds);
   r := RectUnion(FPreviousEditorBounds,newEditorBounds);
   if not r.IsEmpty then
   if not r.IsEmpty then
-  begin
     Manager.Image.RenderMayChange(r,false);
     Manager.Image.RenderMayChange(r,false);
-    Manager.Image.OnImageChanged.NotifyObservers;
-  end;
   FPreviousEditorBounds := newEditorBounds;
   FPreviousEditorBounds := newEditorBounds;
 end;
 end;
 
 
@@ -1648,34 +1686,32 @@ end;
 
 
 function TVectorialTool.ForeGradTexMode: TVectorShapeUsermode;
 function TVectorialTool.ForeGradTexMode: TVectorShapeUsermode;
 begin
 begin
-  if FSwapColor then result := vsuEditBackFill else
+  if Assigned(FShape) and FSwapColor then
+  begin
+    if vsfBackFill in FShape.Fields then
+      result := vsuEditBackFill
+    else if vsfOutlineFill in FShape.Fields then
+      result := vsuEditOutlineFill
+    else
+      result := vsuEditPenFill;
+  end else
     result := vsuEditPenFill;
     result := vsuEditPenFill;
 end;
 end;
 
 
 function TVectorialTool.BackGradTexMode: TVectorShapeUsermode;
 function TVectorialTool.BackGradTexMode: TVectorShapeUsermode;
 begin
 begin
-  if FSwapColor then result := vsuEditPenFill else
+  if Assigned(FShape) and FSwapColor and (vsfPenFill in FShape.Fields) then
+    result := vsuEditPenFill
+  else
     result := vsuEditBackFill;
     result := vsuEditBackFill;
 end;
 end;
 
 
-function TVectorialTool.ShapeForeFill: TVectorialFill;
-begin
-  if Assigned(FShape) then
-  begin
-    if FSwapColor then result := FShape.BackFill else
-      result := FShape.PenFill;
-  end else
-    result := nil;
-end;
-
-function TVectorialTool.ShapeBackFill: TVectorialFill;
+function TVectorialTool.OutlineGradTexMode: TVectorShapeUsermode;
 begin
 begin
-  if Assigned(FShape) then
-  begin
-    if FSwapColor then result := FShape.PenFill else
-      result := FShape.BackFill;
-  end else
-    result := nil;
+  if Assigned(FShape) and FSwapColor and ([vsfPenFill,vsfBackFill]*FShape.Fields = [vsfPenFill]) then
+    result := vsuEditPenFill
+  else
+    result := vsuEditOutlineFill;
 end;
 end;
 
 
 function TVectorialTool.ForeFitMode: TFitMode;
 function TVectorialTool.ForeFitMode: TFitMode;
@@ -1689,6 +1725,42 @@ begin
   if IsBackEditGradTexPoints then result := fmNever
   if IsBackEditGradTexPoints then result := fmNever
   else result := fmIfChange;
   else result := fmIfChange;
 end;
 end;
+
+function TVectorialTool.OutlineFitMode: TFitMode;
+begin
+  if IsOutlineEditGradTexPoints then result := fmNever
+  else result := fmIfChange;
+end;
+
+function TVectorialTool.ManagerForeFill: TVectorialFill;
+begin
+  if Assigned(FShape) and FSwapColor then
+  begin
+    if vsfBackFill in FShape.Fields then
+      result := Manager.BackFill
+    else if vsfOutlineFill in FShape.Fields then
+      result := Manager.OutlineFill
+    else
+      result := Manager.ForeFill;
+  end else
+    result := Manager.ForeFill;
+end;
+
+function TVectorialTool.ManagerBackFill: TVectorialFill;
+begin
+  if Assigned(FShape) and FSwapColor and (vsfPenFill in FShape.Fields) then
+    result := Manager.ForeFill
+  else
+    result := Manager.BackFill;
+end;
+
+function TVectorialTool.ManagerOutlineFill: TVectorialFill;
+begin
+  if Assigned(FShape) and FSwapColor and ([vsfPenFill,vsfBackFill]*FShape.Fields = [vsfPenFill]) then
+    result := Manager.ForeFill
+  else
+    result := Manager.OutlineFill;
+end;
    
    
 function TVectorialTool.GetIsForeEditGradTexPoints: boolean;
 function TVectorialTool.GetIsForeEditGradTexPoints: boolean;
 begin
 begin
@@ -1700,6 +1772,11 @@ begin
   result := Assigned(FShape) and (FShape.Usermode = BackGradTexMode);
   result := Assigned(FShape) and (FShape.Usermode = BackGradTexMode);
 end;
 end;
 
 
+function TVectorialTool.GetIsOutlineEditGradTexPoints: boolean;
+begin
+  result := Assigned(FShape) and (FShape.Usermode = OutlineGradTexMode);
+end;
+
 function TVectorialTool.GetGridMatrix: TAffineMatrix;
 function TVectorialTool.GetGridMatrix: TAffineMatrix;
 begin
 begin
   if Manager.Image.ZoomFactor > DoScaleX(35, OriginalDPI)/10 then
   if Manager.Image.ZoomFactor > DoScaleX(35, OriginalDPI)/10 then
@@ -1707,7 +1784,7 @@ begin
   else
   else
   begin
   begin
     if Assigned(FShape) and
     if Assigned(FShape) and
-         (not (vsfPenFill in FShape.Fields) or
+         (not (vsfPenFill in FShape.MultiFields) or
            (FShape.PenFill.IsFullyTransparent)) then
            (FShape.PenFill.IsFullyTransparent)) then
       result := AffineMatrixTranslation(0.5, 0.5)
       result := AffineMatrixTranslation(0.5, 0.5)
     else
     else
@@ -1792,6 +1869,11 @@ begin
   result := false;
   result := false;
 end;
 end;
 
 
+function TVectorialTool.CreateShape: TVectorShape;
+begin
+  result := ShapeClass.Create(nil);
+end;
+
 function TVectorialTool.UseOriginal: boolean;
 function TVectorialTool.UseOriginal: boolean;
 begin
 begin
   result := FUseOriginal;
   result := FUseOriginal;
@@ -1821,17 +1903,14 @@ var
   fitMode: TFitMode;
   fitMode: TFitMode;
 begin
 begin
   zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
   zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
-  f:= FShape.Fields;
+  f := FShape.MultiFields;
   gradBox := FShape.SuggestGradientBox(AffineMatrixIdentity);
   gradBox := FShape.SuggestGradientBox(AffineMatrixIdentity);
   if vsfPenFill in f then
   if vsfPenFill in f then
   begin
   begin
     if HasPen then
     if HasPen then
     begin
     begin
       if AAlwaysFit then fitMode := fmAlways else fitMode := ForeFitMode;
       if AAlwaysFit then fitMode := fmAlways else fitMode := ForeFitMode;
-      if FSwapColor then
-        AssignFill(FShape.PenFill, Manager.BackFill, gradBox, fitMode)
-      else
-        AssignFill(FShape.PenFill, Manager.ForeFill, gradBox, fitMode);
+      AssignFill(FShape.PenFill, ManagerForeFill, gradBox, fitMode)
     end else
     end else
       FShape.PenFill.Clear;
       FShape.PenFill.Clear;
   end;
   end;
@@ -1843,13 +1922,21 @@ begin
     if HasBrush then
     if HasBrush then
     begin
     begin
       if AAlwaysFit then fitMode := fmAlways else fitMode := BackFitMode;
       if AAlwaysFit then fitMode := fmAlways else fitMode := BackFitMode;
-      if FSwapColor then
-        AssignFill(FShape.BackFill, Manager.ForeFill, gradBox, fitMode)
-      else
-        AssignFill(FShape.BackFill, Manager.BackFill, gradBox, fitMode);
+      AssignFill(FShape.BackFill, ManagerBackFill, gradBox, fitMode)
     end else
     end else
       FShape.BackFill.Clear;
       FShape.BackFill.Clear;
   end;
   end;
+  if vsfOutlineFill in f then
+  begin
+    if Manager.TextOutline then
+    begin
+      if AAlwaysFit then fitMode := fmAlways else fitMode := OutlineFitMode;
+      AssignFill(FShape.OutlineFill, ManagerOutlineFill, gradBox, fitMode);
+    end else
+      FShape.OutlineFill.Clear;
+  end;
+  if (vsfOutlineWidth in f) and Manager.TextOutline then
+    FShape.OutlineWidth := zoom*Manager.TextOutlineWidth;
 end;
 end;
 
 
 function TVectorialTool.GetManagerShapeOptions: TShapeOptions;
 function TVectorialTool.GetManagerShapeOptions: TShapeOptions;
@@ -1865,7 +1952,7 @@ end;
 function TVectorialTool.RoundCoordinate(constref ptF: TPointF): TPointF;
 function TVectorialTool.RoundCoordinate(constref ptF: TPointF): TPointF;
 begin
 begin
   if not (toDrawShape in GetManagerShapeOptions) or
   if not (toDrawShape in GetManagerShapeOptions) or
-    (Assigned(FShape) and not (vsfPenFill in FShape.Fields)) then
+    (Assigned(FShape) and not (vsfPenFill in FShape.MultiFields)) then
     result := PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5)
     result := PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5)
   else
   else
     result := PointF(round(ptF.x),round(ptF.y));
     result := PointF(round(ptF.x),round(ptF.y));
@@ -2154,8 +2241,9 @@ begin
         Action.NotifyChange(toolDest, r);
         Action.NotifyChange(toolDest, r);
         result := true;
         result := true;
       end;
       end;
-  tcForeAdjustToShape: if Assigned(FShape) then ShapeForeFill.FitGeometry(SuggestGradientBox);
-  tcBackAdjustToShape: if Assigned(FShape) then ShapeBackFill.FitGeometry(SuggestGradientBox);
+  tcForeAdjustToShape: if Assigned(FShape) then FShape.PenFill.FitGeometry(SuggestGradientBox);
+  tcBackAdjustToShape: if Assigned(FShape) then FShape.BackFill.FitGeometry(SuggestGradientBox);
+  tcOutlineAdjustToShape: if Assigned(FShape) then FShape.OutlineFill.FitGeometry(SuggestGradientBox);
   tcForeEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
   tcForeEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
                           begin
                           begin
                             if FShape.Usermode = ForeGradTexMode then
                             if FShape.Usermode = ForeGradTexMode then
@@ -2168,6 +2256,12 @@ begin
                               FShape.Usermode := vsuEdit else
                               FShape.Usermode := vsuEdit else
                               FShape.Usermode := BackGradTexMode;
                               FShape.Usermode := BackGradTexMode;
                           end;
                           end;
+  tcOutlineEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
+                          begin
+                            if FShape.Usermode = OutlineGradTexMode then
+                              FShape.Usermode := vsuEdit else
+                              FShape.Usermode := OutlineGradTexMode;
+                          end;
   tcFinish: begin
   tcFinish: begin
               toolDest := GetToolDrawingLayer;
               toolDest := GetToolDrawingLayer;
               r := ValidateShape;
               r := ValidateShape;
@@ -2192,11 +2286,14 @@ begin
   case ACommand of
   case ACommand of
   tcCopy,tcCut: Result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape);
   tcCopy,tcCut: Result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape);
   tcFinish: result := not IsIdle;
   tcFinish: result := not IsIdle;
-  tcForeAdjustToShape, tcBackAdjustToShape: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine;
+  tcForeAdjustToShape, tcBackAdjustToShape, tcOutlineAdjustToShape:
+      result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine;
   tcForeEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
   tcForeEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
-                            (vsuEditPenFill in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
+                            (ForeGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
   tcBackEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
   tcBackEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
-                            (vsuEditPenFill in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
+                            (BackGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
+  tcOutlineEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
+                            (OutlineGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
   tcShapeToSpline: result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape)
   tcShapeToSpline: result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape)
                             and TCurveShape.CanCreateFrom(FShape);
                             and TCurveShape.CanCreateFrom(FShape);
   tcAlignLeft..tcAlignBottom: Result:= not FQuickDefine and Assigned(FShape);
   tcAlignLeft..tcAlignBottom: Result:= not FQuickDefine and Assigned(FShape);
@@ -2214,6 +2311,11 @@ begin
     result:= inherited SuggestGradientBox;
     result:= inherited SuggestGradientBox;
 end;
 end;
 
 
+function TVectorialTool.GetContextualToolbars: TContextualToolbars;
+begin
+  result := ContextualToolbarsFromShape(ShapeClass, FShape);
+end;
+
 function TVectorialTool.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
 function TVectorialTool.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
   VirtualScreenHeight: integer;
   VirtualScreenHeight: integer;
   BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
   BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;

+ 1 - 4
lazpaint/ucommandline.pas

@@ -278,11 +278,8 @@ end;
 
 
 procedure ProcessCommands(instance: TLazPaintCustomInstance; commandsUTF8: TStringList;
 procedure ProcessCommands(instance: TLazPaintCustomInstance; commandsUTF8: TStringList;
   out errorEncountered, fileSaved, quitQuery: boolean);
   out errorEncountered, fileSaved, quitQuery: boolean);
-var imageActions: TImageActions;
 begin
 begin
-  imageActions := TImageActions.Create(instance);
-  InternalProcessCommands(instance, commandsUTF8, errorEncountered, fileSaved, quitQuery, imageActions);
-  imageActions.Free;
+  InternalProcessCommands(instance, commandsUTF8, errorEncountered, fileSaved, quitQuery, TImageActions(instance.ImageAction));
 end;
 end;
 
 
 end.
 end.

+ 25 - 1
lazpaint/uconfig.pas

@@ -196,12 +196,16 @@ type
     //tools
     //tools
     function DefaultToolForeColor: TBGRAPixel;
     function DefaultToolForeColor: TBGRAPixel;
     function DefaultToolBackColor: TBGRAPixel;
     function DefaultToolBackColor: TBGRAPixel;
+    function DefaultToolOutlineColor: TBGRAPixel;
     procedure SetDefaultToolForeColor(value: TBGRAPixel);
     procedure SetDefaultToolForeColor(value: TBGRAPixel);
     procedure SetDefaultToolBackColor(value: TBGRAPixel);
     procedure SetDefaultToolBackColor(value: TBGRAPixel);
+    procedure SetDefaultToolOutlineColor(value: TBGRAPixel);
     function DefaultToolForeGradient: string;
     function DefaultToolForeGradient: string;
     function DefaultToolBackGradient: string;
     function DefaultToolBackGradient: string;
+    function DefaultToolOutlineGradient: string;
     procedure SetDefaultToolForeGradient(value: string);
     procedure SetDefaultToolForeGradient(value: string);
     procedure SetDefaultToolBackGradient(value: string);
     procedure SetDefaultToolBackGradient(value: string);
+    procedure SetDefaultToolOutlineGradient(value: string);
     function DefaultToolPenWidth: single;
     function DefaultToolPenWidth: single;
     procedure SetDefaultToolPenWidth(value: single);
     procedure SetDefaultToolPenWidth(value: single);
     function DefaultToolEraserWidth: single;
     function DefaultToolEraserWidth: single;
@@ -799,6 +803,11 @@ begin
   result := StrToBGRA(iniOptions.ReadString('Tool','BackColor','0080FFC0'));
   result := StrToBGRA(iniOptions.ReadString('Tool','BackColor','0080FFC0'));
 end;
 end;
 
 
+function TLazPaintConfig.DefaultToolOutlineColor: TBGRAPixel;
+begin
+  result := StrToBGRA(iniOptions.ReadString('Tool','OutlineColor','FF0000C0'));
+end;
+
 procedure TLazPaintConfig.SetDefaultToolForeColor(value: TBGRAPixel);
 procedure TLazPaintConfig.SetDefaultToolForeColor(value: TBGRAPixel);
 begin
 begin
   iniOptions.WriteString('Tool','ForeColor',BGRAToStr(value));
   iniOptions.WriteString('Tool','ForeColor',BGRAToStr(value));
@@ -809,6 +818,11 @@ begin
   iniOptions.WriteString('Tool','BackColor',BGRAToStr(value));
   iniOptions.WriteString('Tool','BackColor',BGRAToStr(value));
 end;
 end;
 
 
+procedure TLazPaintConfig.SetDefaultToolOutlineColor(value: TBGRAPixel);
+begin
+  iniOptions.WriteString('Tool','OutlineColor',BGRAToStr(value));
+end;
+
 function TLazPaintConfig.DefaultToolForeGradient: string;
 function TLazPaintConfig.DefaultToolForeGradient: string;
 begin
 begin
   result := iniOptions.ReadString('Tool','ForeGradient','');
   result := iniOptions.ReadString('Tool','ForeGradient','');
@@ -819,6 +833,11 @@ begin
   result := iniOptions.ReadString('Tool','BackGradient','');
   result := iniOptions.ReadString('Tool','BackGradient','');
 end;
 end;
 
 
+function TLazPaintConfig.DefaultToolOutlineGradient: string;
+begin
+  result := iniOptions.ReadString('Tool','OutlineGradient','');
+end;
+
 procedure TLazPaintConfig.SetDefaultToolForeGradient(value: string);
 procedure TLazPaintConfig.SetDefaultToolForeGradient(value: string);
 begin
 begin
   iniOptions.WriteString('Tool','ForeGradient',value);
   iniOptions.WriteString('Tool','ForeGradient',value);
@@ -829,6 +848,11 @@ begin
   iniOptions.WriteString('Tool','BackGradient',value);
   iniOptions.WriteString('Tool','BackGradient',value);
 end;
 end;
 
 
+procedure TLazPaintConfig.SetDefaultToolOutlineGradient(value: string);
+begin
+  iniOptions.WriteString('Tool','OutlineGradient',value);
+end;
+
 function TLazPaintConfig.DefaultToolPenWidth: single;
 function TLazPaintConfig.DefaultToolPenWidth: single;
 begin
 begin
   result := iniOptions.ReadFloat('Tool','PenWidth',5);
   result := iniOptions.ReadFloat('Tool','PenWidth',5);
@@ -922,7 +946,7 @@ end;
 function TLazPaintConfig.DefaultToolTextFont: TFont;
 function TLazPaintConfig.DefaultToolTextFont: TFont;
 var fontStyle: TFontStyles;
 var fontStyle: TFontStyles;
 begin
 begin
-  tempFont.Name := iniOptions.ReadString('Tool','TextFontName','Arial');
+  tempFont.Name := iniOptions.ReadString('Tool','TextFontName','');
   tempFont.Size := iniOptions.ReadInteger('Tool','TextFontSize',10);
   tempFont.Size := iniOptions.ReadInteger('Tool','TextFontSize',10);
   fontStyle := [];
   fontStyle := [];
   if iniOptions.ReadBool('Tool','TextFontBold',False) then fontStyle += [fsBold];
   if iniOptions.ReadBool('Tool','TextFontBold',False) then fontStyle += [fsBold];

+ 31 - 0
lazpaint/ufileextensions.pas

@@ -29,6 +29,8 @@ function GetSelectedFilterExtensions(const Filter: string; FilterIndex: integer;
 function ApplySelectedFilterExtension(const FileName: string; const Filter: string; FilterIndex: integer): string;
 function ApplySelectedFilterExtension(const FileName: string; const Filter: string; FilterIndex: integer): string;
 
 
 function GetExtensionFilter(AOption: TExtensionOptions; ADisplayPrefix: string = '*.'): string;
 function GetExtensionFilter(AOption: TExtensionOptions; ADisplayPrefix: string = '*.'): string;
+function GetExtensionFilterIndex(AOption: TExtensionOptions; AExtensions: string): integer;
+function GetExtensionFilterByIndex(AOption: TExtensionOptions; AIndex: integer): string;
 
 
 procedure RegisterPicExt(AName: string; AExtensionsWithoutDot: string; AOptions: TExtensionOptions);
 procedure RegisterPicExt(AName: string; AExtensionsWithoutDot: string; AOptions: TExtensionOptions);
 
 
@@ -139,6 +141,35 @@ begin
     result := rsAllSupportedFiletypes + ' (' + allExtWithoutDot + ')|' + allExtFilter + result;
     result := rsAllSupportedFiletypes + ' (' + allExtWithoutDot + ')|' + allExtFilter + result;
 end;
 end;
 
 
+function GetExtensionFilterIndex(AOption: TExtensionOptions; AExtensions: string): integer;
+var
+  i: Integer;
+begin
+  result := 2;
+  for i := 0 to high(PictureFileExtensions) do
+    if (PictureFileExtensions[i].options * AOption = AOption) and
+     (PictureFileExtensions[i].filterForAllCases <> '') then
+    begin
+      if PictureFileExtensions[i].filterForAllCases = AExtensions then exit;
+      inc(result);
+    end;
+  result := 1;
+end;
+
+function GetExtensionFilterByIndex(AOption: TExtensionOptions; AIndex: integer): string;
+var curIndex, i: integer;
+begin
+  curIndex := 2;
+  for i := 0 to high(PictureFileExtensions) do
+    if (PictureFileExtensions[i].options * AOption = AOption) and
+     (PictureFileExtensions[i].filterForAllCases <> '') then
+    begin
+      if curIndex = AIndex then exit(PictureFileExtensions[i].filterForAllCases);
+      inc(curIndex);
+    end;
+  result := '*.*';
+end;
+
 function GetBit(Value: QWord; Index: Byte): Boolean;
 function GetBit(Value: QWord; Index: Byte): Boolean;
 begin
 begin
   Result := ((Value shr Index) and 1) = 1;
   Result := ((Value shr Index) and 1) = 1;

+ 39 - 21
lazpaint/uimageview.pas

@@ -16,6 +16,7 @@ type
   TImageView = class
   TImageView = class
   protected
   protected
     FVirtualScreen : TBGRABitmap;
     FVirtualScreen : TBGRABitmap;
+    FUpdatingPopup: boolean;
     FPenCursorVisible: boolean;
     FPenCursorVisible: boolean;
     FPenCursorPos,FPenCursorPosBefore: TVSCursorPosition;
     FPenCursorPos,FPenCursorPosBefore: TVSCursorPosition;
     FQueryPaintVirtualScreen: boolean;
     FQueryPaintVirtualScreen: boolean;
@@ -35,7 +36,7 @@ type
     FZoom: TZoom;
     FZoom: TZoom;
     FPictureCanvas: TCanvas;
     FPictureCanvas: TCanvas;
     function GetImage: TLazPaintImage;
     function GetImage: TLazPaintImage;
-    function GetRenderUpdateRectVS(AIncludeLastToolState: boolean): TRect;
+    function GetRenderUpdateRectVS(AIncludeCurrentToolEditor: boolean): TRect;
     function GetFillSelectionHighlight: boolean;
     function GetFillSelectionHighlight: boolean;
     function GetPenCursorPosition: TVSCursorPosition;
     function GetPenCursorPosition: TVSCursorPosition;
     function GetWorkspaceColor: TColor;
     function GetWorkspaceColor: TColor;
@@ -47,6 +48,7 @@ type
     procedure SetFillSelectionHighlight(AValue: boolean);
     procedure SetFillSelectionHighlight(AValue: boolean);
     procedure SetShowSelection(AValue: boolean);
     procedure SetShowSelection(AValue: boolean);
     procedure PictureSelectionChanged({%H-}sender: TLazPaintImage; const ARect: TRect);
     procedure PictureSelectionChanged({%H-}sender: TLazPaintImage; const ARect: TRect);
+    procedure ToolManagerRenderChanged(Sender: TObject);
     procedure PaintVirtualScreenCursor({%H-}ACanvasOfs: TPoint; {%H-}AWorkArea: TRect; {%H-}AWinControlOfs: TPoint; {%H-}AWinControl: TWinControl);
     procedure PaintVirtualScreenCursor({%H-}ACanvasOfs: TPoint; {%H-}AWorkArea: TRect; {%H-}AWinControlOfs: TPoint; {%H-}AWinControl: TWinControl);
     function GetRectToInvalidate(AInvalidateAll: boolean; AWorkArea: TRect): TRect;
     function GetRectToInvalidate(AInvalidateAll: boolean; AWorkArea: TRect): TRect;
     function GetPictureCoordsDefined: boolean;
     function GetPictureCoordsDefined: boolean;
@@ -73,6 +75,7 @@ type
     property ShowSelection: boolean read FShowSelection write SetShowSelection;
     property ShowSelection: boolean read FShowSelection write SetShowSelection;
     property WorkspaceColor: TColor read GetWorkspaceColor;
     property WorkspaceColor: TColor read GetWorkspaceColor;
     property PictureCoordsDefined: boolean read GetPictureCoordsDefined;
     property PictureCoordsDefined: boolean read GetPictureCoordsDefined;
+    property UpdatingPopup: boolean read FUpdatingPopup write FUpdatingPopup;
   end;
   end;
 
 
 implementation
 implementation
@@ -108,6 +111,13 @@ begin
   result := FLastPictureParameters.defined;
   result := FLastPictureParameters.defined;
 end;
 end;
 
 
+procedure TImageView.ToolManagerRenderChanged(Sender: TObject);
+begin
+  if Assigned(FVirtualScreen) then
+    Image.RenderMayChange(LazPaintInstance.ToolManager.GetRenderBounds(
+                            FVirtualScreen.Width, FVirtualScreen.Height));
+end;
+
 function TImageView.GetImage: TLazPaintImage;
 function TImageView.GetImage: TLazPaintImage;
 begin
 begin
   result := FInstance.Image;
   result := FInstance.Image;
@@ -159,32 +169,39 @@ begin
     FreeAndNil(FVirtualScreen);
     FreeAndNil(FVirtualScreen);
 
 
   if not Assigned(FVirtualScreen) then
   if not Assigned(FVirtualScreen) then
+  begin
     FVirtualScreen := TBGRABitmap.Create(FLastPictureParameters.virtualScreenArea.Right-FLastPictureParameters.virtualScreenArea.Left,
     FVirtualScreen := TBGRABitmap.Create(FLastPictureParameters.virtualScreenArea.Right-FLastPictureParameters.virtualScreenArea.Left,
                                         FLastPictureParameters.virtualScreenArea.Bottom-FLastPictureParameters.virtualScreenArea.Top, WorkspaceColor);
                                         FLastPictureParameters.virtualScreenArea.Bottom-FLastPictureParameters.virtualScreenArea.Top, WorkspaceColor);
+  end else
+  begin
+    if picParamWereDefined then FVirtualScreen.ClipRect := GetRenderUpdateRectVS(False);
+  end;
 
 
-  if picParamWereDefined then FVirtualScreen.ClipRect := GetRenderUpdateRectVS(False);
-  Image.ResetRenderUpdateRect;
-
-  if not FVirtualScreen.ClipRect.IsEmpty then
+  if not FUpdatingPopup then
   begin
   begin
-    renderRect := FLastPictureParameters.scaledArea;
-    OffsetRect(renderRect, -FLastPictureParameters.virtualScreenArea.Left,
-                           -FLastPictureParameters.virtualScreenArea.Top);
+    Image.ResetRenderUpdateRect;
 
 
-    DrawThumbnailCheckers(FVirtualScreen,renderRect,Image.IsIconCursor);
+    if not FVirtualScreen.ClipRect.IsEmpty then
+    begin
+      renderRect := FLastPictureParameters.scaledArea;
+      OffsetRect(renderRect, -FLastPictureParameters.virtualScreenArea.Left,
+                             -FLastPictureParameters.virtualScreenArea.Top);
 
 
-    //draw image (with merged selection)
-    FVirtualScreen.StretchPutImage(renderRect,Image.RenderedImage,dmDrawWithTransparency);
-    if (Zoom.Factor > DoScaleX(MinZoomForGrid, OriginalDPI)) and LazPaintInstance.GridVisible then
-      DrawGrid(FVirtualScreen,FLastPictureParameters.zoomFactorX,FLastPictureParameters.zoomFactorY,
-         FLastPictureParameters.originInVS.X,FLastPictureParameters.originInVS.Y);
+      DrawThumbnailCheckers(FVirtualScreen,renderRect,Image.IsIconCursor);
 
 
-    DrawSelectionHighlight(renderRect);
-  end;
-  FVirtualScreen.NoClip;
+      //draw image (with merged selection)
+      FVirtualScreen.StretchPutImage(renderRect,Image.RenderedImage,dmDrawWithTransparency);
+      if (Zoom.Factor > DoScaleX(MinZoomForGrid, OriginalDPI)) and LazPaintInstance.GridVisible then
+        DrawGrid(FVirtualScreen,FLastPictureParameters.zoomFactorX,FLastPictureParameters.zoomFactorY,
+           FLastPictureParameters.originInVS.X,FLastPictureParameters.originInVS.Y);
 
 
-  //show tools info
-  LazPaintInstance.ToolManager.RenderTool(FVirtualScreen);
+      DrawSelectionHighlight(renderRect);
+    end;
+    FVirtualScreen.NoClip;
+
+    //show tools info
+    Image.RenderMayChange(LazPaintInstance.ToolManager.RenderTool(FVirtualScreen), false, false);
+  end;
 
 
   PaintVirtualScreenImplementation(ACanvasOfs, AWorkArea, AVSPart);
   PaintVirtualScreenImplementation(ACanvasOfs, AWorkArea, AVSPart);
   Image.VisibleArea := TRectF.Intersect(rectF(FormToBitmap(AWorkArea.Left, AWorkArea.Top),
   Image.VisibleArea := TRectF.Intersect(rectF(FormToBitmap(AWorkArea.Left, AWorkArea.Top),
@@ -299,6 +316,7 @@ begin
   FSelectionHighlight := TSelectionHighlight.Create(Image);
   FSelectionHighlight := TSelectionHighlight.Create(Image);
   FShowSelection:= true;
   FShowSelection:= true;
   Image.OnSelectionChanged := @PictureSelectionChanged;
   Image.OnSelectionChanged := @PictureSelectionChanged;
+  LazPaintInstance.ToolManager.OnToolRenderChanged:=@ToolManagerRenderChanged;
   LazPaintInstance.ToolManager.BitmapToVirtualScreen := @BitmapToVirtualScreen;
   LazPaintInstance.ToolManager.BitmapToVirtualScreen := @BitmapToVirtualScreen;
 end;
 end;
 
 
@@ -382,7 +400,7 @@ begin
   FLastPictureParameters.defined := false;
   FLastPictureParameters.defined := false;
 end;
 end;
 
 
-function TImageView.GetRenderUpdateRectVS(AIncludeLastToolState: boolean): TRect;
+function TImageView.GetRenderUpdateRectVS(AIncludeCurrentToolEditor: boolean): TRect;
 const displayMargin = 1;
 const displayMargin = 1;
 begin
 begin
   result := Image.RenderUpdateRectInPicCoord;
   result := Image.RenderUpdateRectInPicCoord;
@@ -400,7 +418,7 @@ begin
     end;
     end;
   end;
   end;
   result := RectUnion(result, Image.RenderUpdateRectInVSCoord);
   result := RectUnion(result, Image.RenderUpdateRectInVSCoord);
-  if AIncludeLastToolState and Assigned(FVirtualScreen) then
+  if AIncludeCurrentToolEditor and Assigned(FVirtualScreen) then
     result := RectUnion(result, LazPaintInstance.ToolManager.GetRenderBounds(FVirtualScreen.Width,FVirtualScreen.Height));
     result := RectUnion(result, LazPaintInstance.ToolManager.GetRenderBounds(FVirtualScreen.Width,FVirtualScreen.Height));
 end;
 end;
 
 

+ 72 - 49
lazpaint/umainformlayout.pas

@@ -29,8 +29,9 @@ type
     FDockedToolBoxToolBar: TToolBar;
     FDockedToolBoxToolBar: TToolBar;
     FPaletteToolbar: TPaletteToolbar;
     FPaletteToolbar: TPaletteToolbar;
     FStatusBarVisible: boolean;
     FStatusBarVisible: boolean;
-    FStatusBar: TStatusBar;
+    FStatusBar: TPanel;
     FStatusText: string;
     FStatusText: string;
+    FStatusTextSplit: TStringList;
     FDarkTheme: boolean;
     FDarkTheme: boolean;
     FDockedControlsPanel: TPanel;
     FDockedControlsPanel: TPanel;
     FDockedChooseColorSplitter: TSplitter;
     FDockedChooseColorSplitter: TSplitter;
@@ -39,6 +40,7 @@ type
     function GetStatusBarVisible: boolean;
     function GetStatusBarVisible: boolean;
     function GetStatusText: string;
     function GetStatusText: string;
     function GetToolBoxVisible: boolean;
     function GetToolBoxVisible: boolean;
+    procedure StatusBar_Paint(Sender: TObject);
     procedure ToolboxGroupMainButton_MouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
     procedure ToolboxGroupMainButton_MouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
       {%H-}Y: Integer);
       {%H-}Y: Integer);
     procedure SetDarkTheme(AValue: boolean);
     procedure SetDarkTheme(AValue: boolean);
@@ -165,12 +167,19 @@ begin
 
 
   FDockedControlsPanel := TPanel.Create(nil);
   FDockedControlsPanel := TPanel.Create(nil);
   FDockedControlsPanel.Visible := false;
   FDockedControlsPanel.Visible := false;
+  FDockedControlsPanel.Anchors:= [akRight,akTop,akBottom];
   FForm.InsertControl(FDockedControlsPanel);
   FForm.InsertControl(FDockedControlsPanel);
 
 
-  FStatusBar := TStatusBar.Create(nil);
-  FStatusBar.SizeGrip := false;
+  FStatusBar := TPanel.Create(nil);
   FStatusBar.Align := alNone;
   FStatusBar.Align := alNone;
   FStatusBar.Visible := false;
   FStatusBar.Visible := false;
+  FStatusBar.Anchors := [akLeft,akRight,akBottom];
+  FStatusBar.BevelOuter:= bvNone;
+  FStatusBar.BevelInner:= bvNone;
+  FStatusBar.Height := DoScaleY(15, OriginalDPI);
+  FStatusBar.Font.Height := -DoScaleY(12, OriginalDPI);
+  FStatusBar.OnPaint:=@StatusBar_Paint;
+  FStatusTextSplit := TStringList.Create;
   FForm.InsertControl(FStatusBar);
   FForm.InsertControl(FStatusBar);
 
 
   ApplyTheme;
   ApplyTheme;
@@ -180,6 +189,7 @@ destructor TMainFormLayout.Destroy;
 begin
 begin
   FreeAndNil(FDockedControlsPanel);
   FreeAndNil(FDockedControlsPanel);
   FreeAndNil(FStatusBar);
   FreeAndNil(FStatusBar);
+  FreeAndNil(FStatusTextSplit);
   FreeAndNil(FPaletteToolbar);
   FreeAndNil(FPaletteToolbar);
   FreeAndNil(FPanelToolBox);
   FreeAndNil(FPanelToolBox);
   FreeAndNil(FMenu);
   FreeAndNil(FMenu);
@@ -207,6 +217,49 @@ begin
   result := LazPaintInstance.ToolboxVisible;
   result := LazPaintInstance.ToolboxVisible;
 end;
 end;
 
 
+procedure TMainFormLayout.StatusBar_Paint(Sender: TObject);
+var
+  colWidth, spacing, i, x: Integer;
+begin
+  if FStatusTextSplit.Count > 0 then
+  begin
+    spacing := DoScaleX(6, OriginalDPI);
+    colWidth := (FStatusBar.ClientWidth - spacing*2) div FStatusTextSplit.Count;
+    if colWidth > spacing*2 then
+    begin
+      if DarkTheme then
+        FStatusBar.Canvas.Pen.Color := clDarkPanelHighlight
+        else FStatusBar.Canvas.Pen.Color := clBtnHighlight;
+      FStatusBar.Canvas.Line(0,0, FStatusBar.Width,0);
+      x := 0;
+      for i := 0 to FStatusTextSplit.Count-1 do
+      begin
+        FStatusBar.Canvas.Font := FStatusBar.Font;
+        if DarkTheme then
+          FStatusBar.Canvas.Font.Color := clLightText
+          else FStatusBar.Canvas.Font.Color := clBtnText;
+        FStatusBar.Canvas.TextOut(x + spacing,
+          (FStatusBar.ClientHeight - FStatusBar.Canvas.TextHeight('Hg')) div 2,
+          FStatusTextSplit[i]);
+
+        if i > 0 then
+        begin
+          if DarkTheme then
+            FStatusBar.Canvas.Pen.Color := clDarkPanelShadow
+            else FStatusBar.Canvas.Pen.Color := clBtnShadow;
+          FStatusBar.Canvas.Line(x-1,0, x-1,FStatusBar.Height);
+          if DarkTheme then
+            FStatusBar.Canvas.Pen.Color := clDarkPanelHighlight
+            else FStatusBar.Canvas.Pen.Color := clBtnHighlight;
+          FStatusBar.Canvas.Line(x,0, x,FStatusBar.Height);
+        end;
+
+        inc(x, max(colWidth, FStatusBar.Canvas.TextWidth(FStatusTextSplit[i]) + 2*spacing));
+      end;
+    end;
+  end;
+end;
+
 procedure TMainFormLayout.ToolboxGroupMainButton_MouseMove(Sender: TObject;
 procedure TMainFormLayout.ToolboxGroupMainButton_MouseMove(Sender: TObject;
   Shift: TShiftState; X, Y: Integer);
   Shift: TShiftState; X, Y: Integer);
 var
 var
@@ -254,7 +307,7 @@ end;
 
 
 function TMainFormLayout.GetStatusText: string;
 function TMainFormLayout.GetStatusText: string;
 begin
 begin
-  result := FStatusBar.SimpleText;
+  result := FStatusText;
 end;
 end;
 
 
 procedure TMainFormLayout.PaletteVisibilityChangedByUser(Sender: TObject);
 procedure TMainFormLayout.PaletteVisibilityChangedByUser(Sender: TObject);
@@ -282,46 +335,13 @@ begin
 end;
 end;
 
 
 procedure TMainFormLayout.SetStatusText(AValue: string);
 procedure TMainFormLayout.SetStatusText(AValue: string);
-var elems: TStringList;
-  i,w: Integer;
-  idxDelim: integer;
 begin
 begin
   if AValue = FStatusText then exit;
   if AValue = FStatusText then exit;
   FStatusText := AValue;
   FStatusText := AValue;
-  if pos('|',AValue) = 0 then
-  begin
-    if FStatusBar.SimplePanel <> true then
-      FStatusBar.SimplePanel := true;
-    FStatusBar.SimpleText := AValue;
-  end else
-  begin
-    elems := TStringList.Create;
-    repeat
-      idxDelim := pos('|',AValue);
-      if idxDelim = 0 then
-      begin
-        elems.Add(AValue);
-        break;
-      end;
-      elems.Add(copy(AValue,1,idxDelim-1));
-      AValue := copy(AValue,idxDelim+1,length(AValue)-idxDelim);
-    until false;
-    if FStatusBar.SimplePanel <> false then
-      FStatusBar.SimplePanel := false;
-    while FStatusBar.Panels.Count > elems.Count do
-      FStatusBar.Panels.Delete(FStatusBar.Panels.Count-1);
-    while FStatusBar.Panels.Count < elems.Count do
-      with FStatusBar.Panels.Add do
-        Width := FStatusBar.Height*10;
-    w := FStatusBar.ClientWidth div elems.Count;
-    for i := 0 to elems.Count-1 do
-      with FStatusBar.Panels[i] do
-      begin
-        Text := elems[i];
-        Width := w;
-      end;
-    elems.Free;
-  end;
+  FStatusTextSplit.Delimiter:= '|';
+  FStatusTextSplit.StrictDelimiter:= true;
+  FStatusTextSplit.DelimitedText := FStatusText;
+  FStatusBar.Invalidate;
 end;
 end;
 
 
 procedure TMainFormLayout.SetToolBoxVisible(AValue: boolean);
 procedure TMainFormLayout.SetToolBoxVisible(AValue: boolean);
@@ -446,8 +466,15 @@ begin
       w := FDockedToolBoxToolBar.ButtonWidth * nbX+2;
       w := FDockedToolBoxToolBar.ButtonWidth * nbX+2;
       FDockedToolBoxToolBar.Width := w;
       FDockedToolBoxToolBar.Width := w;
       FPanelToolBox.Width := w;
       FPanelToolBox.Width := w;
-      if FToolBoxDocking = twLeft then FPanelToolBox.Left:= Left
-      else FPanelToolBox.Left:= Right-FPanelToolBox.Width;
+      if FToolBoxDocking = twLeft then
+      begin
+        FPanelToolBox.Left:= Left;
+        FPanelToolBox.Anchors:= [akLeft,akTop,akBottom];
+      end else
+      begin
+        FPanelToolBox.Left:= Right-FPanelToolBox.Width;
+        FPanelToolBox.Anchors:= [akRight,akTop,akBottom];
+      end;
       for i := 0 to FDockedToolBoxToolBar.ButtonCount-1 do
       for i := 0 to FDockedToolBoxToolBar.ButtonCount-1 do
         FDockedToolBoxToolBar.Buttons[i].Top := i*FDockedToolBoxToolBar.ButtonHeight;
         FDockedToolBoxToolBar.Buttons[i].Top := i*FDockedToolBoxToolBar.ButtonHeight;
     end;
     end;
@@ -487,12 +514,6 @@ begin
   begin
   begin
     with GetWorkAreaAt(lsAfterDockedControlsPanel) do
     with GetWorkAreaAt(lsAfterDockedControlsPanel) do
       FStatusBar.SetBounds(Left,Bottom-FStatusBar.Height,Right-Left,FStatusBar.Height);
       FStatusBar.SetBounds(Left,Bottom-FStatusBar.Height,Right-Left,FStatusBar.Height);
-    if not FStatusBar.SimplePanel then
-    begin
-      w := FStatusBar.ClientWidth div FStatusBar.Panels.Count;
-      for i := 0 to FStatusBar.Panels.Count-1 do
-        FStatusBar.Panels[i].Width := w;
-    end;
     if not FStatusBar.Visible then
     if not FStatusBar.Visible then
     begin
     begin
       FStatusBar.Visible := true;
       FStatusBar.Visible := true;
@@ -513,6 +534,7 @@ begin
     FDockedToolBoxToolBar.EdgeOuter := esNone;
     FDockedToolBoxToolBar.EdgeOuter := esNone;
     FDockedToolBoxToolBar.OnPaint := @DarkThemeInstance.ToolBarPaint;
     FDockedToolBoxToolBar.OnPaint := @DarkThemeInstance.ToolBarPaint;
     FDockedToolBoxToolBar.OnPaintButton:= @DarkThemeInstance.ToolBarPaintButton;
     FDockedToolBoxToolBar.OnPaintButton:= @DarkThemeInstance.ToolBarPaintButton;
+    FStatusBar.Color:= clDarkBtnFace;
   end
   end
   else
   else
   begin
   begin
@@ -521,6 +543,7 @@ begin
     FDockedToolBoxToolBar.EdgeOuter := esNone;
     FDockedToolBoxToolBar.EdgeOuter := esNone;
     FDockedToolBoxToolBar.OnPaint := nil;
     FDockedToolBoxToolBar.OnPaint := nil;
     FDockedToolBoxToolBar.OnPaintButton:= nil;
     FDockedToolBoxToolBar.OnPaintButton:= nil;
+    FStatusBar.Color:= clBtnFace;
   end;
   end;
   DarkThemeInstance.Apply(FDockedControlsPanel, DarkTheme, false);
   DarkThemeInstance.Apply(FDockedControlsPanel, DarkTheme, false);
   bevelOfs := integer(FDockedControlsPanel.BevelOuter <> bvNone)*FDockedControlsPanel.BevelWidth;
   bevelOfs := integer(FDockedControlsPanel.BevelOuter <> bvNone)*FDockedControlsPanel.BevelWidth;

+ 45 - 9
lazpaint/umenu.pas

@@ -240,6 +240,47 @@ begin
 end;
 end;
 
 
 procedure TMainFormMenu.AddInstalledScripts(AMenu: TMenuItem; AIndex: integer);
 procedure TMainFormMenu.AddInstalledScripts(AMenu: TMenuItem; AIndex: integer);
+
+  procedure AddScriptRec(AMenu: TMenuItem; var AIndex: integer; AItem: TMenuItem);
+  var
+    posSub, j, subIndex: integer;
+    sectionName: String;
+    sectionItem: TMenuItem;
+  begin
+    posSub := pos('>', AItem.Caption);
+    if posSub > 0 then
+    begin
+      sectionName := copy(AItem.Caption, 1, posSub-1);
+      AItem.Caption := copy(AItem.Caption, posSub+1, length(AItem.Caption) - posSub);
+      subIndex := -1;
+      for j := 0 to AMenu.Count-1 do
+        if AMenu.Items[j].Caption = sectionName then
+        begin
+          AddScriptRec(AMenu.Items[j], subIndex, AItem);
+          exit;
+        end;
+      sectionItem := TMenuItem.Create(AMenu);
+      sectionItem.Caption := sectionName;
+      if AIndex = -1 then
+        AMenu.Add(sectionItem)
+      else
+      begin
+        AMenu.Insert(AIndex, sectionItem);
+        inc(AIndex);
+      end;
+      AddScriptRec(sectionItem, subIndex, AItem);
+      exit;
+    end;
+
+    if AIndex = -1 then
+      AMenu.Add(AItem)
+    else
+    begin
+      AMenu.Insert(AIndex, AItem);
+      inc(AIndex);
+    end;
+  end;
+
 var
 var
   path, fullname, header, title: String;
   path, fullname, header, title: String;
   searchRec: TSearchRec;
   searchRec: TSearchRec;
@@ -266,6 +307,8 @@ begin
           if header.StartsWith('#') then
           if header.StartsWith('#') then
           begin
           begin
             title := header.Substring(1).Trim;
             title := header.Substring(1).Trim;
+            title := StringReplace(title, ' >', '>', [rfReplaceAll]);
+            title := StringReplace(title, '> ', '>', [rfReplaceAll]);
             item := TMenuItem.Create(AMenu);
             item := TMenuItem.Create(AMenu);
             item.Caption := title;
             item.Caption := title;
             item.Tag := FInstalledScripts.Add(fullname);
             item.Tag := FInstalledScripts.Add(fullname);
@@ -277,15 +320,7 @@ begin
     finally
     finally
       FindCloseUTF8(searchRec);
       FindCloseUTF8(searchRec);
       for i := 0 to items.Count-1 do
       for i := 0 to items.Count-1 do
-      begin
-        if AIndex = -1 then
-          AMenu.Add(TMenuItem(items.Objects[i]))
-        else
-        begin
-          AMenu.Insert(AIndex, TMenuItem(items.Objects[i]));
-          inc(AIndex);
-        end;
-      end;
+        AddScriptRec(AMenu, AIndex, TMenuItem(items.Objects[i]));
       items.Free;
       items.Free;
     end;
     end;
   end;
   end;
@@ -557,6 +592,7 @@ begin
      FToolbarBackground.Left := 0;
      FToolbarBackground.Left := 0;
      FToolbarBackground.width := ClientWidth;
      FToolbarBackground.width := ClientWidth;
      FToolbarBackground.Height := FToolbarsHeight;
      FToolbarBackground.Height := FToolbarsHeight;
+     FToolbarBackground.Anchors:= [akLeft,akTop,akRight];
      FToolbarBackground.Visible := true;
      FToolbarBackground.Visible := true;
    end;
    end;
 end;
 end;

+ 1 - 0
lazpaint/upalettetoolbar.pas

@@ -473,6 +473,7 @@ begin
     FPaletteAlphaWidth := FPaletteItemWidth div 3;
     FPaletteAlphaWidth := FPaletteItemWidth div 3;
 
 
     FPanelPalette := TBGRAVirtualScreen.Create(nil);
     FPanelPalette := TBGRAVirtualScreen.Create(nil);
+    FPanelPalette.Anchors:= [akTop,akRight,akBottom];
     FPanelPalette.Width := DoScaleX(FPaletteItemWidth, OriginalDPI)+VolatileScrollBarSize;
     FPanelPalette.Width := DoScaleX(FPaletteItemWidth, OriginalDPI)+VolatileScrollBarSize;
     FPanelPalette.Visible := false;
     FPanelPalette.Visible := false;
     FPanelPalette.OnRedraw := @RepaintPalette;
     FPanelPalette.OnRedraw := @RepaintPalette;

+ 1 - 1
lazpaint/upython.pas

@@ -204,7 +204,7 @@ begin
     raise exception.Create(
     raise exception.Create(
       StringReplace( StringReplace(rsPythonUnexpectedVersion,
       StringReplace( StringReplace(rsPythonUnexpectedVersion,
         '%1',inttostr(APythonVersion),[]),
         '%1',inttostr(APythonVersion),[]),
-        '%2',inttostr(PythonVersionMajor),[]) );
+        '%2',inttostr(PythonVersionMajor),[]) + #9 + rsDownload + #9 + 'https://www.python.org');
   FFirstOutput:= true;
   FFirstOutput:= true;
   AutomationEnvironment.Values['PYTHONPATH'] := DefaultScriptDirectory;
   AutomationEnvironment.Values['PYTHONPATH'] := DefaultScriptDirectory;
   try
   try

+ 2 - 1
lazpaint/uresourcestrings.pas

@@ -19,7 +19,7 @@ resourcestring
   rsLazPaint = 'LazPaint';
   rsLazPaint = 'LazPaint';
   rsScript = 'Script';
   rsScript = 'Script';
   rsFunctionNotDefined = 'The function %1 is not defined.';
   rsFunctionNotDefined = 'The function %1 is not defined.';
-  rsPythonUnexpectedVersion = 'Expected python version %1 but %2 found.';
+  rsPythonUnexpectedVersion = 'Expected Python version %1 but %2 found.';
   rsOpening='Opening';
   rsOpening='Opening';
   rsLoading='Loading';
   rsLoading='Loading';
   rsRecentDirectories='Recent directories:';
   rsRecentDirectories='Recent directories:';
@@ -180,6 +180,7 @@ resourcestring
   rsCancelledByUser='Cancelled by user';
   rsCancelledByUser='Cancelled by user';
   rsNoAndProceedToNext='Do not save and open another file';
   rsNoAndProceedToNext='Do not save and open another file';
   rsInformation='Information';
   rsInformation='Information';
+  rsDownload='Download';
   rsError='Error';
   rsError='Error';
   rsEndWithoutMatchingBegin = 'End without matching begin';
   rsEndWithoutMatchingBegin = 'End without matching begin';
   rsThereAreNoCheckedItems='There are no checked items. Check some items or add some new ones.';
   rsThereAreNoCheckedItems='There are no checked items. Check some items or add some new ones.';

+ 8 - 7
lazpaintcontrols/lazpaintcontrols.lpk

@@ -21,7 +21,7 @@
       </Linking>
       </Linking>
     </CompilerOptions>
     </CompilerOptions>
     <Version Minor="1"/>
     <Version Minor="1"/>
-    <Files Count="12">
+    <Files Count="13">
       <Item1>
       <Item1>
         <Filename Value="lctoolbars.pas"/>
         <Filename Value="lctoolbars.pas"/>
         <UnitName Value="LCToolbars"/>
         <UnitName Value="LCToolbars"/>
@@ -71,24 +71,25 @@
         <Filename Value="lcresourcestring.pas"/>
         <Filename Value="lcresourcestring.pas"/>
         <UnitName Value="LCResourceString"/>
         <UnitName Value="LCResourceString"/>
       </Item12>
       </Item12>
+      <Item13>
+        <Filename Value="lcvectormultishape.pas"/>
+        <UnitName Value="LCVectorMultishape"/>
+      </Item13>
     </Files>
     </Files>
     <i18n>
     <i18n>
       <EnableI18N Value="True"/>
       <EnableI18N Value="True"/>
       <OutDir Value="../lazpaint/release/bin/i18n"/>
       <OutDir Value="../lazpaint/release/bin/i18n"/>
     </i18n>
     </i18n>
-    <RequiredPkgs Count="4">
+    <RequiredPkgs Count="3">
       <Item1>
       <Item1>
         <PackageName Value="bgracontrols"/>
         <PackageName Value="bgracontrols"/>
       </Item1>
       </Item1>
       <Item2>
       <Item2>
-        <PackageName Value="BGRABitmapPack"/>
+        <PackageName Value="LCL"/>
       </Item2>
       </Item2>
       <Item3>
       <Item3>
-        <PackageName Value="LCL"/>
-      </Item3>
-      <Item4>
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
-      </Item4>
+      </Item3>
     </RequiredPkgs>
     </RequiredPkgs>
     <UsageOptions>
     <UsageOptions>
       <UnitPath Value="$(PkgOutDir)"/>
       <UnitPath Value="$(PkgOutDir)"/>

+ 1 - 1
lazpaintcontrols/lazpaintcontrols.pas

@@ -11,7 +11,7 @@ uses
   LCToolbars, LCVectorialFill, LCVectorialFillInterface, LCVectorOriginal, 
   LCToolbars, LCVectorialFill, LCVectorialFillInterface, LCVectorOriginal, 
   LCVectorPolyShapes, LCVectorRectShapes, LCVectorialFillControl, 
   LCVectorPolyShapes, LCVectorRectShapes, LCVectorialFillControl, 
   LCVectorShapes, LCVectorTextShapes, LCScaleDPI, LCVectorClipboard, 
   LCVectorShapes, LCVectorTextShapes, LCScaleDPI, LCVectorClipboard, 
-  LCResourceString, LazarusPackageIntf;
+  LCResourceString, LCVectorMultishape, LazarusPackageIntf;
 
 
 implementation
 implementation
 
 

+ 24 - 7
lazpaintcontrols/lcvectorclipboard.pas

@@ -22,8 +22,9 @@ function CopyShapesToClipboard(AShapes: array of TVectorShape; const AMatrix: TA
 var
 var
   tempContainer: TVectorOriginal;
   tempContainer: TVectorOriginal;
   mem: TMemoryStream;
   mem: TMemoryStream;
-  i: Integer;
+  i, j: Integer;
   s: TVectorShape;
   s: TVectorShape;
+  multiSel: IVectorMultishape;
 begin
 begin
   result:= false;
   result:= false;
   if length(AShapes)=0 then exit;
   if length(AShapes)=0 then exit;
@@ -32,9 +33,21 @@ begin
   try
   try
     for i := 0 to high(AShapes) do
     for i := 0 to high(AShapes) do
     begin
     begin
-      s := AShapes[i].Duplicate;
-      s.Transform(AMatrix);
-      tempContainer.AddShape(s);
+      if AShapes[i] is VectorMultiselectionFactory then
+      begin
+        multiSel := AShapes[i].GetAsMultishape;
+        for j := 0 to multiSel.ShapeCount-1 do
+        begin
+          s := multiSel.GetShape(j).Duplicate;
+          s.Transform(AMatrix);
+          tempContainer.AddShape(s);
+        end;
+      end else
+      begin
+        s := AShapes[i].Duplicate;
+        s.Transform(AMatrix);
+        tempContainer.AddShape(s);
+      end;
     end;
     end;
     tempContainer.SaveToStream(mem);
     tempContainer.SaveToStream(mem);
     Clipboard.Clear;
     Clipboard.Clear;
@@ -52,6 +65,7 @@ var
   mem: TMemoryStream;
   mem: TMemoryStream;
   i: Integer;
   i: Integer;
   pastedShape: TVectorShape;
   pastedShape: TVectorShape;
+  pastedShapes: TVectorShapes;
   invMatrix, m: TAffineMatrix;
   invMatrix, m: TAffineMatrix;
   pastedBounds: TRectF;
   pastedBounds: TRectF;
   ofs: TPointF;
   ofs: TPointF;
@@ -84,14 +98,17 @@ begin
             ofs.y := floor(ABounds.Bottom - pastedBounds.Bottom);
             ofs.y := floor(ABounds.Bottom - pastedBounds.Bottom);
         end;
         end;
         m := invMatrix*AffineMatrixTranslation(ofs.x,ofs.y);
         m := invMatrix*AffineMatrixTranslation(ofs.x,ofs.y);
+        ATargetContainer.DeselectShapes;
+        pastedShapes := TVectorShapes.Create;
         for i := 0 to tempContainer.ShapeCount-1 do
         for i := 0 to tempContainer.ShapeCount-1 do
         begin
         begin
           pastedShape := tempContainer.Shape[i].Duplicate;
           pastedShape := tempContainer.Shape[i].Duplicate;
           pastedShape.Transform(m);
           pastedShape.Transform(m);
-          ATargetContainer.AddShape(pastedShape);
-          if i = tempContainer.ShapeCount-1 then
-            ATargetContainer.SelectShape(pastedShape);
+          pastedShapes.Add(pastedShape);
         end;
         end;
+        ATargetContainer.AddShapes(pastedShapes);
+        ATargetContainer.SelectShapes(pastedShapes);
+        pastedShapes.Free;
       end;
       end;
     finally
     finally
       tempContainer.Free;
       tempContainer.Free;

+ 35 - 5
lazpaintcontrols/lcvectorialfill.pas

@@ -10,6 +10,7 @@ uses
 
 
 type
 type
   TTextureRepetition = (trNone, trRepeatX, trRepeatY, trRepeatBoth);
   TTextureRepetition = (trNone, trRepeatX, trRepeatY, trRepeatBoth);
+  TTransparentMode = (tmEnforeAllChannelsZero, tmAlphaZeroOnly, tmNoFill);
   TVectorialFillType = (vftNone, vftSolid, vftGradient, vftTexture);
   TVectorialFillType = (vftNone, vftSolid, vftGradient, vftTexture);
   TVectorialFillTypes = set of TVectorialFillType;
   TVectorialFillTypes = set of TVectorialFillType;
   TVectorialFill = class;
   TVectorialFill = class;
@@ -44,6 +45,7 @@ type
   TVectorialFillDiff = class(TCustomVectorialFillDiff)
   TVectorialFillDiff = class(TCustomVectorialFillDiff)
   protected
   protected
     FStart,FEnd: TVectorialFill;
     FStart,FEnd: TVectorialFill;
+    FTransparentMode: TTransparentMode;
   public
   public
     constructor Create(AFrom: TVectorialFill);
     constructor Create(AFrom: TVectorialFill);
     procedure ComputeDiff(ATo: TVectorialFill);
     procedure ComputeDiff(ATo: TVectorialFill);
@@ -68,6 +70,7 @@ type
     FTextureRepetition: TTextureRepetition;
     FTextureRepetition: TTextureRepetition;
     FTextureAverageColor: TBGRAPixel;
     FTextureAverageColor: TBGRAPixel;
     FTextureAverageColorComputed: boolean;
     FTextureAverageColorComputed: boolean;
+    FTransparentMode: TTransparentMode;
     FGradient: TBGRALayerGradientOriginal;
     FGradient: TBGRALayerGradientOriginal;
     FOnChange: TVectorialFillChangeEvent;
     FOnChange: TVectorialFillChangeEvent;
     FOnBeforeChange: TNotifyEvent;
     FOnBeforeChange: TNotifyEvent;
@@ -81,6 +84,7 @@ type
     procedure SetTextureMatrix(AValue: TAffineMatrix);
     procedure SetTextureMatrix(AValue: TAffineMatrix);
     procedure SetTextureOpacity(AValue: byte);
     procedure SetTextureOpacity(AValue: byte);
     procedure SetTextureRepetition(AValue: TTextureRepetition);
     procedure SetTextureRepetition(AValue: TTextureRepetition);
+    procedure SetTransparentMode(AValue: TTransparentMode);
     procedure InternalClear;
     procedure InternalClear;
     procedure BeginUpdate;
     procedure BeginUpdate;
     procedure EndUpdate;
     procedure EndUpdate;
@@ -129,6 +133,7 @@ type
     property TextureRepetition: TTextureRepetition read FTextureRepetition write SetTextureRepetition;
     property TextureRepetition: TTextureRepetition read FTextureRepetition write SetTextureRepetition;
     property OnChange: TVectorialFillChangeEvent read FOnChange write SetOnChange;
     property OnChange: TVectorialFillChangeEvent read FOnChange write SetOnChange;
     property OnBeforeChange: TNotifyEvent read FOnBeforeChange write FOnBeforeChange;
     property OnBeforeChange: TNotifyEvent read FOnBeforeChange write FOnBeforeChange;
+    property TransparentMode: TTransparentMode read FTransparentMode write SetTransparentMode;
   end;
   end;
 
 
 implementation
 implementation
@@ -140,12 +145,14 @@ uses BGRAGradientScanner, BGRABlend, LCResourceString;
 constructor TVectorialFillDiff.Create(AFrom: TVectorialFill);
 constructor TVectorialFillDiff.Create(AFrom: TVectorialFill);
 begin
 begin
   FStart := TVectorialFill.Create;
   FStart := TVectorialFill.Create;
+  FStart.TransparentMode:= AFrom.TransparentMode;
   FStart.Assign(AFrom);
   FStart.Assign(AFrom);
 end;
 end;
 
 
 procedure TVectorialFillDiff.ComputeDiff(ATo: TVectorialFill);
 procedure TVectorialFillDiff.ComputeDiff(ATo: TVectorialFill);
 begin
 begin
   FEnd := TVectorialFill.Create;
   FEnd := TVectorialFill.Create;
+  FEnd.TransparentMode := ATo.TransparentMode;
   FEnd.Assign(ATo);
   FEnd.Assign(ATo);
 end;
 end;
 
 
@@ -401,6 +408,7 @@ begin
   FTextureAverageColorComputed:= false;
   FTextureAverageColorComputed:= false;
   FGradient := nil;
   FGradient := nil;
   FIsSolid := false;
   FIsSolid := false;
+  FTransparentMode := tmEnforeAllChannelsZero;
 end;
 end;
 
 
 function TVectorialFill.GetIsEditable: boolean;
 function TVectorialFill.GetIsEditable: boolean;
@@ -446,13 +454,31 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TVectorialFill.SetTransparentMode(AValue: TTransparentMode);
+begin
+  if FTransparentMode=AValue then Exit;
+  if (FillType = vftSolid) and (SolidColor.alpha = 0) then
+  begin
+    case FTransparentMode of
+    tmNoFill: Clear;
+    tmEnforeAllChannelsZero: SolidColor := BGRAPixelTransparent;
+    end;
+  end;
+  FTransparentMode:=AValue;
+end;
+
 procedure TVectorialFill.GradientChange(ASender: TObject; ABounds: PRectF; var ADiff: TBGRAOriginalDiff);
 procedure TVectorialFill.GradientChange(ASender: TObject; ABounds: PRectF; var ADiff: TBGRAOriginalDiff);
 var
 var
   fillDiff: TVectorialFillGradientDiff;
   fillDiff: TVectorialFillGradientDiff;
 begin
 begin
+  if Assigned(FDiff) then
+  begin
+    FreeAndNil(ADiff);
+    exit;
+  end;
   if Assigned(OnChange) then
   if Assigned(OnChange) then
   begin
   begin
-    if Assigned(FDiff) then
+    if Assigned(ADiff) then
     begin
     begin
       fillDiff := TVectorialFillGradientDiff.Create(ADiff as TBGRAGradientOriginalDiff);
       fillDiff := TVectorialFillGradientDiff.Create(ADiff as TBGRAGradientOriginalDiff);
       ADiff := nil;
       ADiff := nil;
@@ -501,10 +527,14 @@ end;
 
 
 procedure TVectorialFill.SetSolid(AColor: TBGRAPixel);
 procedure TVectorialFill.SetSolid(AColor: TBGRAPixel);
 begin
 begin
-  if (FillType = vftSolid) and (SolidColor = AColor) then exit;
+  if AColor.alpha = 0 then
+  case TransparentMode of
+  tmNoFill: begin Clear; exit; end;
+  tmEnforeAllChannelsZero: AColor := BGRAPixelTransparent;
+  end;
+  if (FillType = vftSolid) and SolidColor.EqualsExactly(AColor) then exit;
   BeginUpdate;
   BeginUpdate;
   InternalClear;
   InternalClear;
-  if AColor.alpha = 0 then AColor := BGRAPixelTransparent;
   FColor := AColor;
   FColor := AColor;
   FIsSolid:= true;
   FIsSolid:= true;
   EndUpdate;
   EndUpdate;
@@ -635,7 +665,7 @@ begin
     else
     else
     begin
     begin
       case other.FillType of
       case other.FillType of
-      vftSolid: result := (FillType = vftSolid) and (other.SolidColor = SolidColor);
+      vftSolid: result := (FillType = vftSolid) and other.SolidColor.EqualsExactly(SolidColor);
       vftGradient: result := (FillType = vftGradient) and (other.Gradient.Equals(Gradient));
       vftGradient: result := (FillType = vftGradient) and (other.Gradient.Equals(Gradient));
       vftTexture: result := (FillType = vftTexture) and (other.Texture = Texture) and
       vftTexture: result := (FillType = vftTexture) and (other.Texture = Texture) and
                        (other.TextureMatrix = TextureMatrix) and (other.TextureOpacity = TextureOpacity)
                        (other.TextureMatrix = TextureMatrix) and (other.TextureOpacity = TextureOpacity)
@@ -727,7 +757,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TVectorialFill.ApplyOpacity(AOpacity: byte);
+procedure TVectorialFill.ApplyOpacity(AOpacity: Byte);
 var
 var
   c: TBGRAPixel;
   c: TBGRAPixel;
 begin
 begin

+ 3 - 3
lazpaintcontrols/lcvectorialfillinterface.pas

@@ -904,7 +904,7 @@ end;
 
 
 procedure TVectorialFillInterface.SetSolidColor(AValue: TBGRAPixel);
 procedure TVectorialFillInterface.SetSolidColor(AValue: TBGRAPixel);
 begin
 begin
-  if FSolidColor=AValue then Exit;
+  if FSolidColor.EqualsExactly(AValue) then Exit;
   FSolidColor:=AValue;
   FSolidColor:=AValue;
   UpdateShapeSolidColor;
   UpdateShapeSolidColor;
   If FillType = vftSolid then Changed;
   If FillType = vftSolid then Changed;
@@ -957,7 +957,7 @@ end;
 
 
 procedure TVectorialFillInterface.SetGradEndColor(AValue: TBGRAPixel);
 procedure TVectorialFillInterface.SetGradEndColor(AValue: TBGRAPixel);
 begin
 begin
-  if CompareMem(@FGradEndColor,@AValue,sizeof(TBGRAPixel)) then Exit;
+  if FGradEndColor.EqualsExactly(AValue) then Exit;
   FGradEndColor:=AValue;
   FGradEndColor:=AValue;
   UpdateGradientParams;
   UpdateGradientParams;
   if FillType = vftGradient then Changed;
   if FillType = vftGradient then Changed;
@@ -965,7 +965,7 @@ end;
 
 
 procedure TVectorialFillInterface.SetGradStartColor(AValue: TBGRAPixel);
 procedure TVectorialFillInterface.SetGradStartColor(AValue: TBGRAPixel);
 begin
 begin
-  if CompareMem(@FGradStartColor,@AValue,sizeof(TBGRAPixel)) then Exit;
+  if FGradStartColor.EqualsExactly(AValue) then Exit;
   FGradStartColor:=AValue;
   FGradStartColor:=AValue;
   UpdateGradientParams;
   UpdateGradientParams;
   if FillType = vftGradient then Changed;
   if FillType = vftGradient then Changed;

+ 1018 - 0
lazpaintcontrols/lcvectormultishape.pas

@@ -0,0 +1,1018 @@
+unit LCVectorMultishape;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LCVectorRectShapes, LCVectorOriginal, BGRALayerOriginal,
+  BGRATransform, BGRABitmap, BGRABitmapTypes, BGRAPen, fgl, LCVectorialFill;
+
+type
+  TShapeChangeHandlerMap = specialize TFPGMap<Pointer, TShapeChangeEvent>;
+  TShapeDiffMap = specialize TFPGMap<integer, TVectorShapeDiff>;
+  TIntegerList = specialize TFPGList<integer>;
+
+  { TMultiSelectionShapesDiff }
+
+  TMultiSelectionShapesDiff = class(TCustomMultiSelectionDiff)
+  protected
+    FDiffs: TShapeDiffMap;
+    FSelectedIds: TIntegerList;
+    function GetShapeById(AContainer: TVectorShape; AId: integer): TVectorShape;
+    function GetShapeCount: integer; override;
+    function GetShapeId(AIndex: integer): integer; override;
+  public
+    constructor Create(AStartShape: TVectorShape); override;
+    procedure ComputeDiff(AEndShape: TVectorShape); override;
+    procedure Apply(AStartShape: TVectorShape); override;
+    procedure Unapply(AEndShape: TVectorShape); override;
+    function CanAppend(ADiff: TVectorShapeDiff): boolean; override;
+    procedure Append(ADiff: TVectorShapeDiff); override; //does not preserve ADiff
+    procedure AppendForShape(AShape: TVectorShape; var ADiff: TVectorShapeDiff); //does not preserve ADiff
+    function IsIdentity: boolean; override;
+    destructor Destroy; override;
+    property ShapeCount: integer read GetShapeCount;
+    property ShapeId[AIndex: integer]: integer read GetShapeId;
+  end;
+
+  { TVectorMultiselection }
+
+  TVectorMultiselection = class(TCustomRectShape, IVectorMultishape)
+  protected
+    function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND};
+    function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND};
+    function _Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND};
+  protected
+    FShapes: TVectorShapes;
+    FOldChangeHandler: TShapeChangeHandlerMap;
+    FOnSelectionChange: TNotifyEvent;
+    FUpdatingFromShape, FInMultiTranformFill: Boolean;
+    function GetCornerPositition: single; override;
+    procedure RestoreChangeHandler(AShape: TVectorShape);
+    procedure AttachChangeHandler(AShape: TVectorShape);
+    procedure ContainedShape_Change(ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff);
+    procedure UpdateFromShapes;
+    procedure UpdateFrameFromShapes;
+    procedure FillChange({%H-}ASender: TObject; var ADiff: TCustomVectorialFillDiff); override;
+    procedure FillBeforeChange({%H-}ASender: TObject); override;
+    procedure SetPenStyle(AValue: TBGRAPenStyle); override;
+    procedure SetPenWidth(AValue: single); override;
+    procedure SetJoinStyle(AValue: TPenJoinStyle); override;
+    procedure SetOutlineWidth(AValue: single); override;
+    function GetIsFront: boolean; override;
+    function GetIsBack: boolean; override;
+    function GetPenVisible(AAssumePenFill: boolean = False): boolean; override;
+    function GetBackVisible: boolean; override;
+    function GetOutlineVisible: boolean; override;
+    procedure NotifySelectionChanged;
+    procedure InternalMoveToIndex(AFirst: integer);
+  public
+    constructor Create(AContainer: TVectorOriginal); override;
+    class function StorageClassName: RawByteString; override;
+    destructor Destroy; override;
+    procedure BeginUpdate(ADiffHandler: TVectorShapeDiffAny=nil); override;
+    procedure EndUpdate; override;
+    procedure BringToFront; override;
+    procedure SendToBack; override;
+    procedure MoveUp(APassNonIntersectingShapes: boolean); override;
+    procedure MoveDown(APassNonIntersectingShapes: boolean); override;
+    procedure ClearShapes;
+    procedure AddShape(AShape: TVectorShape);
+    procedure RemoveShape(AShape: TVectorShape);
+    function ContainsShape(AShape: TVectorShape): boolean;
+    function ShapeCount: integer;
+    function GetShape(AIndex: integer): TVectorShape;
+    function SetShapes(AShapes: TVectorShapes): boolean;
+    function FrontShape: TVectorShape;
+    function BackShape: TVectorShape;
+    function GetShapeById(AId: integer): TVectorShape;
+    function MultiFields: TVectorShapeFields; override;
+    procedure TransformFrame(const AMatrix: TAffineMatrix); override;
+    procedure TransformFill(const AMatrix: TAffineMatrix; ABackOnly: boolean); override;
+    function AllowShearTransform: boolean; override;
+    procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
+    procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
+    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
+    procedure Render(ADest: TBGRABitmap; ARenderOffset: TPoint; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
+    function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; {%H-}AOptions: TRenderBoundsOptions = []): TRectF; override;
+    function GetAlignBounds(const ALayoutRect: TRect; const AMatrix: TAffineMatrix): TRectF; override;
+    function SuggestGradientBox(AMatrix: TAffineMatrix): TAffineBox; override;
+    procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
+    function PointInShape(APoint: TPointF): boolean; overload; override;
+    function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
+    function PointInBack(APoint: TPointF): boolean; overload; override;
+    function PointInPen(APoint: TPointF): boolean; overload; override;
+    function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
+    function GetAsMultishape: IVectorMultishape; override;
+    procedure SetOnSelectionChange(AHandler: TNotifyEvent);
+    function GetOnSelectionChange: TNotifyEvent;
+    property OnSelectionChange: TNotifyEvent read GetOnSelectionChange write SetOnSelectionChange;
+  end;
+
+implementation
+
+function Shapes_CompareDepth(const Item1, Item2: TVectorShape): Integer;
+var
+  idx1, idx2: Integer;
+begin
+  if Assigned(Item1.Container) and Assigned(Item2.Container) then
+  begin
+    idx1 := Item1.Container.IndexOfShape(Item1);
+    idx2 := Item2.Container.IndexOfShape(Item2);
+    result := idx1 - idx2;
+  end;
+end;
+
+{ TMultiSelectionShapesDiff }
+
+function TMultiSelectionShapesDiff.GetShapeCount: integer;
+begin
+  result := FSelectedIds.Count;
+end;
+
+function TMultiSelectionShapesDiff.GetShapeId(AIndex: integer): integer;
+begin
+  result := FSelectedIds.Items[AIndex];
+end;
+
+function TMultiSelectionShapesDiff.GetShapeById(AContainer: TVectorShape; AId: integer): TVectorShape;
+begin
+  result := AContainer.Container.FindShapeById(AId);
+end;
+
+constructor TMultiSelectionShapesDiff.Create(AStartShape: TVectorShape);
+var
+  i: Integer;
+begin
+  if not (AStartShape is TVectorMultiselection) then
+    raise exception.Create('Expecting TVectorMultishape');
+  FDiffs := TShapeDiffMap.Create;
+  FSelectedIds := TIntegerList.Create;
+  with AStartShape.GetAsMultishape do
+  begin
+    for i := 0 to ShapeCount-1 do
+      FSelectedIds.Add(GetShape(i).Id);
+  end;
+end;
+
+procedure TMultiSelectionShapesDiff.ComputeDiff(AEndShape: TVectorShape);
+begin
+  //nothing
+end;
+
+procedure TMultiSelectionShapesDiff.Apply(AStartShape: TVectorShape);
+var
+  s: TVectorShape;
+  i: Integer;
+begin
+  for i := 0 to FDiffs.Count-1 do
+  begin
+    s := GetShapeById(AStartShape, FDiffs.Keys[i]);
+    if Assigned(s) then
+      FDiffs.Data[i].Apply(s);
+  end;
+end;
+
+procedure TMultiSelectionShapesDiff.Unapply(AEndShape: TVectorShape);
+var
+  s: TVectorShape;
+  i: Integer;
+begin
+  for i := FDiffs.Count-1 downto 0 do
+  begin
+    s := GetShapeById(AEndShape, FDiffs.Keys[i]);
+    if Assigned(s) then
+      FDiffs.Data[i].Unapply(s);
+  end;
+end;
+
+function TMultiSelectionShapesDiff.CanAppend(ADiff: TVectorShapeDiff): boolean;
+var
+  other: TMultiSelectionShapesDiff;
+  i, j: Integer;
+begin
+  if not (ADiff is TMultiSelectionShapesDiff) then exit(false);
+  other := TMultiSelectionShapesDiff(ADiff);
+  for i := 0 to other.FDiffs.Count-1 do
+    for j := 0 to FDiffs.Count-1 do
+      if FDiffs.Keys[j] = other.FDiffs.Keys[i] then
+      begin
+        if not FDiffs.Data[j].CanAppend(other.FDiffs.Data[i]) then
+          exit(false);
+      end;
+  result := true;
+end;
+
+procedure TMultiSelectionShapesDiff.Append(ADiff: TVectorShapeDiff);
+var found: boolean;
+  other: TMultiSelectionShapesDiff;
+  otherKey, i, j: integer;
+  otherData: TVectorShapeDiff;
+  toCopy: TShapeDiffMap;
+begin
+  if not (ADiff is TMultiSelectionShapesDiff) then raise exception.Create('Unexpected diff type');
+  other := TMultiSelectionShapesDiff(ADiff);
+  toCopy := TShapeDiffMap.Create;
+  for i := 0 to other.FDiffs.Count-1 do
+  begin
+    found := false;
+    otherKey := other.FDiffs.Keys[i];
+    otherData := other.FDiffs.Data[i];
+    for j := 0 to FDiffs.Count-1 do
+      if FDiffs.Keys[j] = otherKey then
+      begin
+        FDiffs.Data[j].Append(otherData);
+        found := true;
+        break;
+      end;
+    if not found then toCopy.Add(otherKey, otherData);
+  end;
+  for i := 0 to toCopy.Count-1 do
+  begin
+    FDiffs.Add(toCopy.Keys[i], toCopy.Data[i]);
+    other.FDiffs.Remove(toCopy.Keys[i]);
+  end;
+  toCopy.Free;
+end;
+
+procedure TMultiSelectionShapesDiff.AppendForShape(AShape: TVectorShape;
+  var ADiff: TVectorShapeDiff);
+var
+  idx: Integer;
+begin
+  idx := FDiffs.IndexOf(AShape.Id);
+  if idx <> -1 then
+    FDiffs.Data[idx].Append(ADiff)
+  else
+  begin
+    FDiffs.Add(AShape.Id, ADiff);
+    ADiff := nil;
+  end;
+end;
+
+function TMultiSelectionShapesDiff.IsIdentity: boolean;
+var
+  i: Integer;
+begin
+  for i := 0 to FDiffs.Count-1 do
+    if not FDiffs.Data[i].IsIdentity then exit(false);
+  result := true;
+end;
+
+destructor TMultiSelectionShapesDiff.Destroy;
+var
+  i: Integer;
+begin
+  for i := 0 to FDiffs.Count-1 do
+    FDiffs.Data[i].Free;
+  FDiffs.Free;
+  FSelectedIds.Free;
+  inherited Destroy;
+end;
+
+{ TVectorMultiselection }
+
+function TVectorMultiselection.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND};
+begin
+  if GetInterface(iid, obj) then
+    Result := S_OK
+  else
+    Result := longint(E_NOINTERFACE);
+end;
+
+function TVectorMultiselection._AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND};
+begin
+  result := 0;
+end;
+
+function TVectorMultiselection._Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND};
+begin
+  result := 0;
+end;
+
+procedure TVectorMultiselection.TransformFill(const AMatrix: TAffineMatrix;
+  ABackOnly: boolean);
+var
+  i: Integer;
+begin
+  FInMultiTranformFill := true;
+  BeginUpdate(TMultiSelectionShapesDiff);
+  for i := 0 to FShapes.Count-1 do
+  begin
+    FShapes[i].BeginUpdate;
+    FShapes[i].TransformFrame(AMatrix);
+    FShapes[i].TransformFill(AMatrix, ABackOnly);
+    FShapes[i].EndUpdate;
+  end;
+  inherited TransformFill(AMatrix, ABackOnly);
+  EndUpdate;
+  FInMultiTranformFill := false;
+end;
+
+procedure TVectorMultiselection.ContainedShape_Change(ASender: TObject;
+  ABounds: TRectF; ADiff: TVectorShapeDiff);
+var
+  contained: TMultiSelectionShapesDiff;
+begin
+  if Assigned(ADiff) then
+  begin
+    contained := TMultiSelectionShapesDiff(AddDiffHandler(TMultiSelectionShapesDiff));
+    contained.AppendForShape(ASender as TVectorShape, ADiff);
+    ADiff.Free;
+  end else
+  begin
+    if not IsUpdating and Assigned(OnChange) then
+      OnChange(self, ABounds, nil);
+  end;
+end;
+
+procedure TVectorMultiselection.UpdateFromShapes;
+var
+  i: Integer;
+  found: boolean;
+begin
+  if FShapes.Count > 0 then
+  begin
+    FUpdatingFromShape := true;
+    BeginEditingUpdate;
+    UpdateFrameFromShapes;
+
+    found := false;
+    for i := 0 to FShapes.Count-1 do
+      if (vsfPenFill in FShapes[i].Fields) and
+         FShapes[i].PenVisible then
+      begin
+        PenFill.Assign(FShapes[i].PenFill);
+        found := true;
+        break;
+      end;
+    if not found then PenFill.Clear;
+
+    found := false;
+    for i := 0 to FShapes.Count-1 do
+      if (vsfPenStyle in FShapes[i].Fields) and
+         FShapes[i].PenVisible then
+      begin
+        Stroker.CustomPenStyle := FShapes[i].PenStyle;
+        found := true;
+        break;
+      end;
+    if not found then Stroker.CustomPenStyle := ClearPenStyle;
+
+    for i := 0 to FShapes.Count-1 do
+      if (vsfPenWidth in FShapes[i].Fields) and
+         FShapes[i].PenVisible then
+      begin
+        FPenWidth := FShapes[i].PenWidth;
+        break;
+      end;
+
+    for i := 0 to FShapes.Count-1 do
+      if vsfJoinStyle in FShapes[i].Fields then
+      begin
+        Stroker.JoinStyle := FShapes[i].JoinStyle;
+        break;
+      end;
+
+    found := false;
+    for i := 0 to FShapes.Count-1 do
+      if (vsfBackFill in FShapes[i].Fields) and
+         FShapes[i].BackVisible then
+      begin
+        BackFill.Assign(FShapes[i].BackFill);
+        found := true;
+        break;
+      end;
+    if not found then BackFill.Clear;
+
+    found := false;
+    for i := 0 to FShapes.Count-1 do
+      if (vsfOutlineFill in FShapes[i].Fields) and
+         FShapes[i].OutlineVisible then
+      begin
+        OutlineFill.Assign(FShapes[i].OutlineFill);
+        found := true;
+        break;
+      end;
+    if not found then OutlineFill.Clear;
+
+    for i := 0 to FShapes.Count-1 do
+      if (vsfOutlineWidth in FShapes[i].Fields) and
+         FShapes[i].OutlineVisible then
+      begin
+        FOutlineWidth:= FShapes[i].OutlineWidth;
+        break;
+      end;
+
+    EndEditingUpdate;
+    FUpdatingFromShape := false;
+  end;
+end;
+
+procedure TVectorMultiselection.UpdateFrameFromShapes;
+var
+  rF: TRectF;
+  i: Integer;
+begin
+  BeginEditingUpdate;
+  rF := EmptyRectF;
+  for i := 0 to FShapes.Count-1 do
+    rF := rF.Union(FShapes[i].GetAlignBounds(InfiniteRect, AffineMatrixIdentity), true);
+  FOrigin := (rF.TopLeft + rf.BottomRight)*0.5;
+  FXAxis := FOrigin + PointF(rF.Width/2, 0);
+  FYAxis := FOrigin + PointF(0, rF.Height/2);
+  EndEditingUpdate;
+end;
+
+procedure TVectorMultiselection.FillChange(ASender: TObject;
+  var ADiff: TCustomVectorialFillDiff);
+var
+  i: Integer;
+begin
+  if FUpdatingFromShape or FInMultiTranformFill then exit;
+  BeginUpdate;
+  AddFillDiffHandler(ASender as TVectorialFill, ADiff);
+  if ASender = PenFill then
+  begin
+    for i := 0 to FShapes.Count-1 do
+      if vsfPenFill in FShapes[i].Fields then
+      begin
+        if not PenFill.IsFullyTransparent or FShapes[i].BackVisible or FShapes[i].OutlineVisible then
+        FShapes[i].PenFill.Assign(PenFill);
+      end;
+  end else
+  if ASender = BackFill then
+  begin
+    for i := 0 to FShapes.Count-1 do
+      if vsfBackFill in FShapes[i].Fields then
+      begin
+        if not BackFill.IsFullyTransparent or FShapes[i].PenVisible or FShapes[i].OutlineVisible then
+          FShapes[i].BackFill.Assign(BackFill);
+      end;
+  end else
+  if ASender = OutlineFill then
+  begin
+    for i := 0 to FShapes.Count-1 do
+      if vsfOutlineFill in FShapes[i].Fields then
+      begin
+        if not OutlineFill.IsFullyTransparent or FShapes[i].PenVisible or FShapes[i].BackVisible then
+          FShapes[i].OutlineFill.Assign(OutlineFill);
+      end;
+  end;
+  EndUpdate;
+end;
+
+procedure TVectorMultiselection.FillBeforeChange(ASender: TObject);
+begin
+  //nothing
+end;
+
+procedure TVectorMultiselection.SetPenStyle(AValue: TBGRAPenStyle);
+var
+  i: Integer;
+begin
+  if PenStyleEqual(AValue, PenStyle) then exit;
+  BeginUpdate;
+  inherited SetPenStyle(AValue);
+  for i := 0 to FShapes.Count-1 do
+    if vsfPenStyle in FShapes[i].Fields then
+    begin
+      if not IsClearPenStyle(AValue) or FShapes[i].BackVisible then
+        FShapes[i].PenStyle := AValue;
+    end;
+  EndUpdate;
+end;
+
+procedure TVectorMultiselection.SetPenWidth(AValue: single);
+var
+  i: Integer;
+begin
+  if AValue < 0 then AValue := 0;
+  if AValue = PenWidth then exit;
+  BeginUpdate;
+  inherited SetPenWidth(AValue);
+  for i := 0 to FShapes.Count-1 do
+    if vsfPenWidth in FShapes[i].Fields then
+    begin
+      if (AValue > 0) or FShapes[i].BackVisible then
+        FShapes[i].PenWidth := AValue;
+    end;
+  EndUpdate;
+end;
+
+procedure TVectorMultiselection.SetJoinStyle(AValue: TPenJoinStyle);
+var
+  i: Integer;
+begin
+  if AValue = JoinStyle then exit;
+  BeginUpdate;
+  inherited SetJoinStyle(AValue);
+  for i := 0 to FShapes.Count-1 do
+    if vsfJoinStyle in FShapes[i].Fields then
+      FShapes[i].JoinStyle := AValue;
+  EndUpdate;
+end;
+
+procedure TVectorMultiselection.SetOutlineWidth(AValue: single);
+var
+  i: Integer;
+begin
+  if AValue < 0 then AValue := 0;
+  if AValue = OutlineWidth then exit;
+  BeginUpdate;
+  inherited SetOutlineWidth(AValue);
+  for i := 0 to FShapes.Count-1 do
+    if vsfOutlineWidth in FShapes[i].Fields then
+      FShapes[i].OutlineWidth := AValue;
+  EndUpdate;
+end;
+
+function TVectorMultiselection.GetIsFront: boolean;
+var
+  i, containerIdx: Integer;
+  s: TVectorShape;
+begin
+  s := FrontShape;
+  if not Assigned(s) or not s.IsFront then exit(false);
+  containerIdx := Container.IndexOfShape(s);
+  for i := FShapes.Count-2 downto 0 do
+  begin
+    dec(containerIdx);
+    if Container.IndexOfShape(FShapes[i]) <> containerIdx then
+      exit(false);
+  end;
+  result := true;
+end;
+
+function TVectorMultiselection.GetIsBack: boolean;
+var
+  i, containerIdx: Integer;
+  s: TVectorShape;
+begin
+  s := BackShape;
+  if not Assigned(s) or not s.IsBack then exit(false);
+  containerIdx := Container.IndexOfShape(s);
+  for i := 1 to FShapes.Count-1 do
+  begin
+    inc(containerIdx);
+    if Container.IndexOfShape(FShapes[i]) <> containerIdx then
+      exit(false);
+  end;
+  result := true;
+end;
+
+function TVectorMultiselection.GetPenVisible(AAssumePenFill: boolean): boolean;
+var
+  i: Integer;
+begin
+  for i := 0 to ShapeCount-1 do
+    if FShapes[i].PenVisible then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.GetBackVisible: boolean;
+var
+  i: Integer;
+begin
+  for i := 0 to ShapeCount-1 do
+    if FShapes[i].BackVisible then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.GetOutlineVisible: boolean;
+var
+  i: Integer;
+begin
+  for i := 0 to ShapeCount-1 do
+    if FShapes[i].OutlineVisible then exit(true);
+  Result:= false;
+end;
+
+procedure TVectorMultiselection.NotifySelectionChanged;
+begin
+  if OnSelectionChange <> nil then
+    OnSelectionChange(self);
+end;
+
+procedure TVectorMultiselection.InternalMoveToIndex(AFirst: integer);
+var fromIndex, toIndex: array of integer;
+  i: Integer;
+begin
+  if Container = nil then exit;
+  setlength(fromIndex, ShapeCount);
+  setlength(toIndex, ShapeCount);
+  for i := 0 to ShapeCount-1 do
+  begin
+    fromIndex[i] := Container.IndexOfShape(FShapes[i]);
+    toIndex[i] := AFirst + i;
+  end;
+  Container.MoveShapeToIndex(fromIndex, toIndex);
+end;
+
+function TVectorMultiselection.GetCornerPositition: single;
+begin
+  result := 1;
+end;
+
+procedure TVectorMultiselection.RestoreChangeHandler(AShape: TVectorShape);
+var
+  handlerIndex: Integer;
+begin
+  if AShape.OnChange <> @ContainedShape_Change then exit;
+  handlerIndex := FOldChangeHandler.IndexOf(AShape);
+  if handlerIndex <> -1 then
+  begin
+    AShape.OnChange:= FOldChangeHandler.Data[handlerIndex];
+    FOldChangeHandler.Delete(handlerIndex);
+  end
+  else
+    AShape.OnChange:= nil;
+end;
+
+procedure TVectorMultiselection.AttachChangeHandler(AShape: TVectorShape);
+begin
+  if AShape.OnChange <> @ContainedShape_Change then
+  begin
+    FOldChangeHandler.Add(AShape, AShape.OnChange);
+    AShape.OnChange:= @ContainedShape_Change;
+  end;
+end;
+
+function TVectorMultiselection.AllowShearTransform: boolean;
+var
+  i: Integer;
+begin
+  for i := 0 to FShapes.Count-1 do
+    if not FShapes[i].AllowShearTransform then exit(false);
+  result := true;
+end;
+
+procedure TVectorMultiselection.LoadFromStorage(AStorage: TBGRACustomOriginalStorage);
+begin
+  raise exception.Create('Cannot be deserialized');
+end;
+
+procedure TVectorMultiselection.SaveToStorage(AStorage: TBGRACustomOriginalStorage);
+begin
+  raise exception.Create('Cannot be serialized');
+end;
+
+procedure TVectorMultiselection.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
+  ADraft: boolean);
+var
+  i: Integer;
+begin
+  for i := 0 to FShapes.Count-1 do
+    FShapes[i].Render(ADest, AMatrix, ADraft);
+end;
+
+procedure TVectorMultiselection.Render(ADest: TBGRABitmap; ARenderOffset: TPoint;
+  AMatrix: TAffineMatrix; ADraft: boolean);
+var
+  i: Integer;
+begin
+  for i := 0 to FShapes.Count-1 do
+    FShapes[i].Render(ADest, ARenderOffset, AMatrix, ADraft);
+end;
+
+function TVectorMultiselection.GetRenderBounds(ADestRect: TRect;
+  AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions): TRectF;
+var
+  i: Integer;
+begin
+  result := EmptyRectF;
+  for i := 0 to FShapes.Count-1 do
+    result := result.Union(FShapes[i].GetRenderBounds(ADestRect, AMatrix, AOptions), true);
+end;
+
+function TVectorMultiselection.GetAlignBounds(const ALayoutRect: TRect;
+  const AMatrix: TAffineMatrix): TRectF;
+var
+  i: Integer;
+begin
+  result := EmptyRectF;
+  for i := 0 to FShapes.Count-1 do
+    result := result.Union(FShapes[i].GetAlignBounds(ALayoutRect, AMatrix), true);
+end;
+
+function TVectorMultiselection.SuggestGradientBox(AMatrix: TAffineMatrix): TAffineBox;
+var
+  i: Integer;
+  r: TRectF;
+begin
+  if FShapes.Count = 1 then
+    result := FShapes[i].SuggestGradientBox(AMatrix)
+  else
+  begin
+    r := EmptyRectF;
+    for i := 0 to FShapes.Count-1 do
+      r := r.Union(FShapes[i].SuggestGradientBox(AMatrix).RectBoundsF, true);
+    result := TAffineBox.AffineBox(r);
+  end;
+end;
+
+procedure TVectorMultiselection.ConfigureCustomEditor(AEditor: TBGRAOriginalEditor);
+var
+  i: Integer;
+  ab: TAffineBox;
+begin
+  for i := 0 to FShapes.Count-1 do
+  begin
+    ab := FShapes[i].SuggestGradientBox(AffineMatrixIdentity);
+    AEditor.AddPolyline(ab.AsPolygon, true, opsDash);
+  end;
+  inherited ConfigureCustomEditor(AEditor);
+end;
+
+function TVectorMultiselection.PointInShape(APoint: TPointF): boolean;
+var
+  i: LongInt;
+begin
+  for i := FShapes.Count-1 downto 0 do
+    if FShapes[i].PointInShape(APoint) then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.PointInShape(APoint: TPointF; ARadius: single): boolean;
+var
+  i: LongInt;
+begin
+  for i := FShapes.Count-1 downto 0 do
+    if FShapes[i].PointInShape(APoint, ARadius) then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.PointInBack(APoint: TPointF): boolean;
+var
+  i: LongInt;
+begin
+  for i := FShapes.Count-1 downto 0 do
+    if FShapes[i].PointInBack(APoint) then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.PointInPen(APoint: TPointF): boolean;
+var
+  i: LongInt;
+begin
+  for i := FShapes.Count-1 downto 0 do
+    if FShapes[i].PointInPen(APoint) then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
+var
+  i: LongInt;
+begin
+  if FShapes.Count >= 5 then exit(true);
+  for i := 0 to FShapes.Count-1 do
+    if FShapes[i].GetIsSlow(AMatrix) then exit(true);
+  result := false;
+end;
+
+function TVectorMultiselection.GetAsMultishape: IVectorMultishape;
+begin
+  Result:= self;
+end;
+
+procedure TVectorMultiselection.SetOnSelectionChange(AHandler: TNotifyEvent);
+begin
+  FOnSelectionChange := AHandler;
+end;
+
+function TVectorMultiselection.GetOnSelectionChange: TNotifyEvent;
+begin
+  result := FOnSelectionChange;
+end;
+
+class function TVectorMultiselection.StorageClassName: RawByteString;
+begin
+  result := 'multishape';
+end;
+
+procedure TVectorMultiselection.ClearShapes;
+var
+  i: Integer;
+begin
+  if FShapes.Count = 0 then exit;
+  for i := 0 to FShapes.Count-1 do
+    RestoreChangeHandler(FShapes[i]);
+  FShapes.Clear;
+  UpdateFromShapes;
+  NotifySelectionChanged;
+end;
+
+procedure TVectorMultiselection.AddShape(AShape: TVectorShape);
+begin
+  if ContainsShape(AShape) then exit;
+  FShapes.Add(AShape);
+  FShapes.Sort(@Shapes_CompareDepth);
+  AttachChangeHandler(AShape);
+  UpdateFromShapes;
+  NotifySelectionChanged;
+end;
+
+procedure TVectorMultiselection.RemoveShape(AShape: TVectorShape);
+begin
+  RestoreChangeHandler(AShape);
+  FShapes.Remove(AShape);
+  UpdateFromShapes;
+  NotifySelectionChanged;
+end;
+
+function TVectorMultiselection.ContainsShape(AShape: TVectorShape): boolean;
+begin
+  result := FShapes.IndexOf(AShape) <> -1;
+end;
+
+function TVectorMultiselection.ShapeCount: integer;
+begin
+  result := FShapes.Count;
+end;
+
+function TVectorMultiselection.GetShape(AIndex: integer): TVectorShape;
+begin
+  if (AIndex < 0) or (AIndex >= FShapes.Count) then
+    raise exception.Create('Index out of bounds');
+  result := FShapes[AIndex];
+end;
+
+function TVectorMultiselection.SetShapes(AShapes: TVectorShapes): boolean;
+var
+  i: Integer;
+  different: Boolean;
+begin
+  different := false;
+  for i := 0 to FShapes.Count-1 do
+    if AShapes.IndexOf(FShapes[i]) = -1 then
+    begin
+      different := true;
+      break;
+    end;
+  for i := 0 to AShapes.Count-1 do
+    if FShapes.IndexOf(AShapes[i]) = -1 then
+    begin
+      different := true;
+      break;
+    end;
+  if not different then exit(false);
+
+  for i := 0 to FShapes.Count-1 do
+    RestoreChangeHandler(FShapes[i]);
+  FShapes.Clear;
+
+  for i := 0 to AShapes.Count-1 do
+  begin
+    FShapes.Add(AShapes[i]);
+    AttachChangeHandler(AShapes[i]);
+  end;
+  FShapes.Sort(@Shapes_CompareDepth);
+  UpdateFromShapes;
+  NotifySelectionChanged;
+  exit(true);
+end;
+
+function TVectorMultiselection.FrontShape: TVectorShape;
+begin
+  if FShapes.Count > 0 then
+    result := FShapes[FShapes.Count-1]
+    else result := nil;
+end;
+
+function TVectorMultiselection.BackShape: TVectorShape;
+begin
+  if FShapes.Count > 0 then
+    result := FShapes[0]
+    else result := nil;
+end;
+
+function TVectorMultiselection.GetShapeById(AId: integer): TVectorShape;
+var
+  i: Integer;
+begin
+  for i := 0 to FShapes.Count-1 do
+    if FShapes[i].Id = AId then exit(FShapes[i]);
+  result := nil;
+end;
+
+function TVectorMultiselection.MultiFields: TVectorShapeFields;
+var
+  i: Integer;
+begin
+  result := [];
+  for i := 0 to FShapes.Count-1 do
+    result += FShapes[i].Fields;
+end;
+
+constructor TVectorMultiselection.Create(AContainer: TVectorOriginal);
+begin
+  inherited Create(AContainer);
+  FShapes := TVectorShapes.Create;
+  FOldChangeHandler := TShapeChangeHandlerMap.Create;
+end;
+
+procedure TVectorMultiselection.TransformFrame(const AMatrix: TAffineMatrix);
+var
+  i: Integer;
+begin
+  BeginUpdate(TMultiSelectionShapesDiff);
+  for i := 0 to FShapes.Count-1 do
+    FShapes[i].TransformFrame(AMatrix);
+  inherited TransformFrame(AMatrix);
+  EndUpdate;
+end;
+
+destructor TVectorMultiselection.Destroy;
+begin
+  ClearShapes;
+  FShapes.Free;
+  FOldChangeHandler.Free;
+  inherited Destroy;
+end;
+
+procedure TVectorMultiselection.BeginUpdate(ADiffHandler: TVectorShapeDiffAny);
+var
+  i: Integer;
+begin
+  inherited BeginUpdate(ADiffHandler);
+  for i := 0 to FShapes.Count-1 do
+    FShapes[i].BeginUpdate;
+end;
+
+procedure TVectorMultiselection.EndUpdate;
+var
+  i: Integer;
+begin
+  for i := 0 to FShapes.Count-1 do
+    FShapes[i].EndUpdate;
+  inherited EndUpdate;
+end;
+
+procedure TVectorMultiselection.BringToFront;
+begin
+  if Assigned(Container) then
+    InternalMoveToIndex(Container.ShapeCount - ShapeCount);
+end;
+
+procedure TVectorMultiselection.SendToBack;
+begin
+  InternalMoveToIndex(0);
+end;
+
+procedure TVectorMultiselection.MoveUp(APassNonIntersectingShapes: boolean);
+var
+  topIndex, i: Integer;
+  curBounds: TRectF;
+  touch: Boolean;
+begin
+  if Container = nil then exit;
+  topIndex := Container.IndexOfShape(FrontShape);
+  while topIndex < Container.ShapeCount-1 do
+  begin
+    inc(topIndex);
+    curBounds := Container.Shape[topIndex].GetAlignBounds(InfiniteRect, AffineMatrixIdentity);
+    if not APassNonIntersectingShapes then break;
+    touch := false;
+    for i := 0 to ShapeCount-1 do
+      if FShapes[i].GetAlignBounds(InfiniteRect, AffineMatrixIdentity).IntersectsWith(curBounds) then
+      begin
+        touch := true;
+        break;
+      end;
+    if touch then break;
+  end;
+  InternalMoveToIndex(topIndex + 1 - ShapeCount);
+end;
+
+procedure TVectorMultiselection.MoveDown(APassNonIntersectingShapes: boolean);
+var
+  bottomIndex, i: Integer;
+  curBounds: TRectF;
+  touch: Boolean;
+begin
+  if Container = nil then exit;
+  bottomIndex := Container.IndexOfShape(FrontShape);
+  while bottomIndex > 0 do
+  begin
+    dec(bottomIndex);
+    curBounds := Container.Shape[bottomIndex].GetAlignBounds(InfiniteRect, AffineMatrixIdentity);
+    if not APassNonIntersectingShapes then break;
+    touch := false;
+    for i := 0 to ShapeCount-1 do
+      if FShapes[i].GetAlignBounds(InfiniteRect, AffineMatrixIdentity).IntersectsWith(curBounds) then
+      begin
+        touch := true;
+        break;
+      end;
+    if touch then break;
+  end;
+  InternalMoveToIndex(bottomIndex);
+end;
+
+initialization
+
+  VectorMultiselectionFactory := TVectorMultiselection;
+
+end.
+

Разница между файлами не показана из-за своего большого размера
+ 423 - 112
lazpaintcontrols/lcvectororiginal.pas


+ 51 - 31
lazpaintcontrols/lcvectorpolyshapes.pas

@@ -118,7 +118,7 @@ type
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
     procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
-    procedure Transform(const AMatrix: TAffineMatrix); override;
+    procedure TransformFrame(const AMatrix: TAffineMatrix); override;
     class function Usermodes: TVectorShapeUsermodes; override;
     class function Usermodes: TVectorShapeUsermodes; override;
     class function DefaultArrowSize: TPointF;
     class function DefaultArrowSize: TPointF;
     property Points[AIndex:integer]: TPointF read GetPoint write SetPoint;
     property Points[AIndex:integer]: TPointF read GetPoint write SetPoint;
@@ -136,15 +136,14 @@ type
   { TPolylineShape }
   { TPolylineShape }
 
 
   TPolylineShape = class(TCustomPolypointShape)
   TPolylineShape = class(TCustomPolypointShape)
-  protected
-    function PenVisible(AAssumePenFill: boolean = false): boolean;
-    function BackVisible: boolean;
   public
   public
     class function Fields: TVectorShapeFields; override;
     class function Fields: TVectorShapeFields; override;
-    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
+    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
+    function PointInBack(APoint: TPointF): boolean; overload; override;
+    function PointInPen(APoint: TPointF): boolean; overload; override;
     function GetIsSlow(const {%H-}AMatrix: TAffineMatrix): boolean; override;
     function GetIsSlow(const {%H-}AMatrix: TAffineMatrix): boolean; override;
     class function StorageClassName: RawByteString; override;
     class function StorageClassName: RawByteString; override;
   end;
   end;
@@ -1145,7 +1144,7 @@ begin
     FCenterPointEditorIndex := -1;
     FCenterPointEditorIndex := -1;
 end;
 end;
 
 
-procedure TCustomPolypointShape.Transform(const AMatrix: TAffineMatrix);
+procedure TCustomPolypointShape.TransformFrame(const AMatrix: TAffineMatrix);
 var
 var
   i: Integer;
   i: Integer;
   m: TAffineMatrix;
   m: TAffineMatrix;
@@ -1154,22 +1153,11 @@ begin
   m := MatrixForPixelCentered(AMatrix);
   m := MatrixForPixelCentered(AMatrix);
   for i := 0 to PointCount-1 do
   for i := 0 to PointCount-1 do
     FPoints[i].coord := m*FPoints[i].coord;
     FPoints[i].coord := m*FPoints[i].coord;
-  inherited Transform(AMatrix);
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
 { TPolylineShape }
 { TPolylineShape }
 
 
-function TPolylineShape.PenVisible(AAssumePenFill: boolean): boolean;
-begin
-  result := (PenWidth>0) and not IsClearPenStyle(PenStyle) and (not PenFill.IsFullyTransparent or AAssumePenFill);
-end;
-
-function TPolylineShape.BackVisible: boolean;
-begin
-  result := not BackFill.IsFullyTransparent;
-end;
-
 class function TPolylineShape.Fields: TVectorShapeFields;
 class function TPolylineShape.Fields: TVectorShapeFields;
 begin
 begin
   Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill];
   Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill];
@@ -1181,9 +1169,9 @@ var
   pts: array of TPointF;
   pts: array of TPointF;
   backScan, penScan: TBGRACustomScanner;
   backScan, penScan: TBGRACustomScanner;
 begin
 begin
-  if not BackVisible and not PenVisible then exit;
+  if not GetBackVisible and not GetPenVisible then exit;
   pts := GetCurve(AMatrix);
   pts := GetCurve(AMatrix);
-  if BackVisible then
+  if GetBackVisible then
   begin
   begin
     if BackFill.FillType = vftSolid then backScan := nil
     if BackFill.FillType = vftSolid then backScan := nil
     else backScan := BackFill.CreateScanner(AMatrix, ADraft);
     else backScan := BackFill.CreateScanner(AMatrix, ADraft);
@@ -1203,7 +1191,7 @@ begin
 
 
     backScan.Free;
     backScan.Free;
   end;
   end;
-  if PenVisible then
+  if GetPenVisible then
   begin
   begin
     if PenFill.FillType = vftSolid then penScan := nil
     if PenFill.FillType = vftSolid then penScan := nil
     else penScan := PenFill.CreateScanner(AMatrix, ADraft);
     else penScan := PenFill.CreateScanner(AMatrix, ADraft);
@@ -1232,12 +1220,12 @@ var
   xMargin, yMargin: single;
   xMargin, yMargin: single;
   fillBounds, penBounds: TRectF;
   fillBounds, penBounds: TRectF;
 begin
 begin
-  if not (BackVisible or (rboAssumeBackFill in AOptions)) and not PenVisible(rboAssumePenFill in AOptions) then
+  if not (GetBackVisible or (rboAssumeBackFill in AOptions)) and not GetPenVisible(rboAssumePenFill in AOptions) then
     result:= EmptyRectF
     result:= EmptyRectF
   else
   else
   begin
   begin
     pts := GetCurve(AMatrix);
     pts := GetCurve(AMatrix);
-    if PenVisible(rboAssumePenFill in AOptions) then
+    if GetPenVisible(rboAssumePenFill in AOptions) then
     begin
     begin
       if (JoinStyle = pjsRound) and (ArrowStartKind = akNone) and (ArrowEndKind = akNone) then
       if (JoinStyle = pjsRound) and (ArrowStartKind = akNone) and (ArrowEndKind = akNone) then
       begin
       begin
@@ -1250,7 +1238,7 @@ begin
         result.Bottom += yMargin;
         result.Bottom += yMargin;
       end else
       end else
       begin
       begin
-        if BackVisible or (rboAssumeBackFill in AOptions) then fillBounds := GetPointsBoundsF(pts)
+        if GetBackVisible or (rboAssumeBackFill in AOptions) then fillBounds := GetPointsBoundsF(pts)
         else fillBounds := EmptyRectF;
         else fillBounds := EmptyRectF;
         pts := ComputeStroke(pts, Closed, AMatrix);
         pts := ComputeStroke(pts, Closed, AMatrix);
         penBounds := GetPointsBoundsF(pts);
         penBounds := GetPointsBoundsF(pts);
@@ -1267,10 +1255,10 @@ function TPolylineShape.PointInShape(APoint: TPointF): boolean;
 var
 var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
 begin
 begin
-  if not BackVisible and not PenVisible then exit(false);
+  if not GetBackVisible and not GetPenVisible then exit(false);
   pts := GetCurve(AffineMatrixIdentity);
   pts := GetCurve(AffineMatrixIdentity);
-  if BackVisible and IsPointInPolygon(pts, APoint, true) then exit(true);
-  if PenVisible then
+  if GetBackVisible and IsPointInPolygon(pts, APoint, true) then exit(true);
+  if GetPenVisible then
   begin
   begin
     pts := ComputeStroke(pts, Closed, AffineMatrixIdentity);
     pts := ComputeStroke(pts, Closed, AffineMatrixIdentity);
     if IsPointInPolygon(pts, APoint, true) then exit(true);
     if IsPointInPolygon(pts, APoint, true) then exit(true);
@@ -1282,12 +1270,44 @@ function TPolylineShape.PointInShape(APoint: TPointF; ARadius: single): boolean;
 var
 var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
 begin
 begin
-  if not BackVisible and not PenVisible then exit(false);
+  if not GetBackVisible and not GetPenVisible then exit(false);
   pts := GetCurve(AffineMatrixIdentity);
   pts := GetCurve(AffineMatrixIdentity);
   pts := ComputeStrokeEnvelope(pts, Closed, ARadius*2);
   pts := ComputeStrokeEnvelope(pts, Closed, ARadius*2);
   result := IsPointInPolygon(pts, APoint, true);
   result := IsPointInPolygon(pts, APoint, true);
 end;
 end;
 
 
+function TPolylineShape.PointInBack(APoint: TPointF): boolean;
+var
+  pts: ArrayOfTPointF;
+  scan: TBGRACustomScanner;
+begin
+  if GetBackVisible then
+  begin
+    pts := GetCurve(AffineMatrixIdentity);
+    result := IsPointInPolygon(pts, APoint, true);
+    if result and (BackFill.FillType = vftTexture) then
+    begin
+      scan := BackFill.CreateScanner(AffineMatrixIdentity, false);
+      if scan.ScanAt(APoint.X,APoint.Y).alpha = 0 then result := false;
+      scan.Free;
+    end;
+  end else
+    result := false;
+end;
+
+function TPolylineShape.PointInPen(APoint: TPointF): boolean;
+var
+  pts: ArrayOfTPointF;
+begin
+  if GetBackVisible then
+  begin
+    pts := GetCurve(AffineMatrixIdentity);
+    pts := ComputeStroke(pts, Closed, AffineMatrixIdentity);
+    result := IsPointInPolygon(pts, APoint, true);
+  end else
+    result := false;
+end;
+
 function TPolylineShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 function TPolylineShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 var pts: ArrayOfTPointF;
 var pts: ArrayOfTPointF;
   i: Integer;
   i: Integer;
@@ -1295,13 +1315,13 @@ var pts: ArrayOfTPointF;
   backSurface: Single;
   backSurface: Single;
   penLength, zoomFactor, penSurface, totalSurface: single;
   penLength, zoomFactor, penSurface, totalSurface: single;
 begin
 begin
-  if not PenVisible and not BackVisible or (PointCount = 0) then exit(false);
+  if not GetPenVisible and not GetBackVisible or (PointCount = 0) then exit(false);
 
 
   setlength(pts, PointCount);
   setlength(pts, PointCount);
   for i := 0 to high(pts) do
   for i := 0 to high(pts) do
     pts[i] := AMatrix * Points[i];
     pts[i] := AMatrix * Points[i];
 
 
-  if PenVisible then
+  if GetPenVisible then
   begin
   begin
     penLength := 0;
     penLength := 0;
     zoomFactor := max(VectLen(AMatrix[1,1],AMatrix[2,1]), VectLen(AMatrix[1,2],AMatrix[2,2]));
     zoomFactor := max(VectLen(AMatrix[1,1],AMatrix[2,1]), VectLen(AMatrix[1,2],AMatrix[2,2]));
@@ -1321,14 +1341,14 @@ begin
     penSurface := penLength*PenWidth*zoomFactor;
     penSurface := penLength*PenWidth*zoomFactor;
   end else penSurface := 0;
   end else penSurface := 0;
 
 
-  if BackVisible then
+  if GetBackVisible then
   begin
   begin
     ptsBounds := GetPointsBoundsF(pts);
     ptsBounds := GetPointsBoundsF(pts);
     backSurface := ptsBounds.Width*ptsBounds.Height;
     backSurface := ptsBounds.Width*ptsBounds.Height;
   end else
   end else
     backSurface := 0;
     backSurface := 0;
 
 
-  if PenVisible and BackVisible then totalSurface := backSurface+penSurface/2
+  if GetPenVisible and GetBackVisible then totalSurface := backSurface+penSurface/2
   else totalSurface := backSurface+penSurface;
   else totalSurface := backSurface+penSurface;
 
 
   Result:= (PointCount > 40) or
   Result:= (PointCount > 40) or

+ 126 - 86
lazpaintcontrols/lcvectorrectshapes.pas

@@ -62,10 +62,9 @@ type
     procedure OnMoveXYNegCornerAlt({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF; AShift: TShiftState);
     procedure OnMoveXYNegCornerAlt({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF; AShift: TShiftState);
     procedure OnMoveXNegYNegCornerAlt({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF; AShift: TShiftState);
     procedure OnMoveXNegYNegCornerAlt({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF; AShift: TShiftState);
     procedure OnStartMove({%H-}ASender: TObject; {%H-}APointIndex: integer; {%H-}AShift: TShiftState);
     procedure OnStartMove({%H-}ASender: TObject; {%H-}APointIndex: integer; {%H-}AShift: TShiftState);
-    procedure UpdateFillMatrixFromRect;
+    procedure UpdateFillFromRectDiff;
     function GetCornerPositition: single; virtual; abstract;
     function GetCornerPositition: single; virtual; abstract;
     function GetOrthoRect(AMatrix: TAffineMatrix; out ARect: TRectF): boolean;
     function GetOrthoRect(AMatrix: TAffineMatrix; out ARect: TRectF): boolean;
-    function AllowShearTransform: boolean; virtual;
     function ShowArrows: boolean; virtual;
     function ShowArrows: boolean; virtual;
     procedure SetOrigin(AValue: TPointF);
     procedure SetOrigin(AValue: TPointF);
     function GetHeight: single;
     function GetHeight: single;
@@ -82,7 +81,7 @@ type
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; {%H-}AOptions: TRenderBoundsOptions = []): TRectF; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; {%H-}AOptions: TRenderBoundsOptions = []): TRectF; override;
     procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
     procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
     function GetAffineBox(const AMatrix: TAffineMatrix; APixelCentered: boolean): TAffineBox;
     function GetAffineBox(const AMatrix: TAffineMatrix; APixelCentered: boolean): TAffineBox;
-    procedure Transform(const AMatrix: TAffineMatrix); override;
+    procedure TransformFrame(const AMatrix: TAffineMatrix); override;
     procedure AlignTransform(const AMatrix: TAffineMatrix); override;
     procedure AlignTransform(const AMatrix: TAffineMatrix); override;
     property Origin: TPointF read FOrigin write SetOrigin;
     property Origin: TPointF read FOrigin write SetOrigin;
     property XAxis: TPointF read FXAxis write SetXAxis;
     property XAxis: TPointF read FXAxis write SetXAxis;
@@ -96,15 +95,15 @@ type
 
 
   TRectShape = class(TCustomRectShape)
   TRectShape = class(TCustomRectShape)
   protected
   protected
-    function PenVisible(AAssumePenFill: boolean = false): boolean;
-    function BackVisible: boolean;
     function GetCornerPositition: single; override;
     function GetCornerPositition: single; override;
   public
   public
     class function Fields: TVectorShapeFields; override;
     class function Fields: TVectorShapeFields; override;
-    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
+    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
+    function PointInBack(APoint: TPointF): boolean; overload; override;
+    function PointInPen(APoint: TPointF): boolean; overload; override;
     function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
     function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
     class function StorageClassName: RawByteString; override;
     class function StorageClassName: RawByteString; override;
   end;
   end;
@@ -113,17 +112,17 @@ type
 
 
   TEllipseShape = class(TCustomRectShape)
   TEllipseShape = class(TCustomRectShape)
   protected
   protected
-    function PenVisible(AAssumePenFill: boolean = false): boolean;
-    function BackVisible: boolean;
     function GetCornerPositition: single; override;
     function GetCornerPositition: single; override;
   public
   public
     constructor Create(AContainer: TVectorOriginal); override;
     constructor Create(AContainer: TVectorOriginal); override;
     class function Fields: TVectorShapeFields; override;
     class function Fields: TVectorShapeFields; override;
     function GetAlignBounds(const {%H-}ALayoutRect: TRect; const AMatrix: TAffineMatrix): TRectF; override;
     function GetAlignBounds(const {%H-}ALayoutRect: TRect; const AMatrix: TAffineMatrix): TRectF; override;
-    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
+    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
+    function PointInBack(APoint: TPointF): boolean; overload; override;
+    function PointInPen(APoint: TPointF): boolean; overload; override;
     function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
     function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
     class function StorageClassName: RawByteString; override;
     class function StorageClassName: RawByteString; override;
   end;
   end;
@@ -171,10 +170,7 @@ type
     procedure SetLightPosition(AValue: TPointF);
     procedure SetLightPosition(AValue: TPointF);
     procedure SetShapeAltitudePercent(AValue: single);
     procedure SetShapeAltitudePercent(AValue: single);
     procedure SetShapeKind(AValue: TPhongShapeKind);
     procedure SetShapeKind(AValue: TPhongShapeKind);
-    function BackVisible: boolean;
     function GetEnvelope: ArrayOfTPointF;
     function GetEnvelope: ArrayOfTPointF;
-  protected
-    function AllowShearTransform: boolean; override;
   public
   public
     constructor Create(AContainer: TVectorOriginal); override;
     constructor Create(AContainer: TVectorOriginal); override;
     destructor Destroy; override;
     destructor Destroy; override;
@@ -186,13 +182,15 @@ type
     procedure MouseDown(RightButton: boolean; Shift: TShiftState; X, Y: single; var ACursor: TOriginalEditorCursor; var AHandled: boolean); override;
     procedure MouseDown(RightButton: boolean; Shift: TShiftState; X, Y: single; var ACursor: TOriginalEditorCursor; var AHandled: boolean); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
-    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
+    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
     function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; override;
+    function PointInBack(APoint: TPointF): boolean; overload; override;
     function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
     function GetIsSlow(const AMatrix: TAffineMatrix): boolean; override;
     function GetGenericCost: integer; override;
     function GetGenericCost: integer; override;
     procedure Transform(const AMatrix: TAffineMatrix); override;
     procedure Transform(const AMatrix: TAffineMatrix); override;
+    function AllowShearTransform: boolean; override;
     class function StorageClassName: RawByteString; override;
     class function StorageClassName: RawByteString; override;
     property ShapeKind: TPhongShapeKind read FShapeKind write SetShapeKind;
     property ShapeKind: TPhongShapeKind read FShapeKind write SetShapeKind;
     property LightPosition: TPointF read FLightPosition write SetLightPosition;
     property LightPosition: TPointF read FLightPosition write SetLightPosition;
@@ -354,8 +352,7 @@ begin
   FOrigin := AValue;
   FOrigin := AValue;
   FXAxis := t*FXAxis;
   FXAxis := t*FXAxis;
   FYAxis := t*FYAxis;
   FYAxis := t*FYAxis;
-  if vsfBackFill in Fields then BackFill.Transform(t);
-  if vsfPenFill in Fields then PenFill.Transform(t);
+  TransformFill(t, False);
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
@@ -499,7 +496,7 @@ begin
     end;
     end;
   end;
   end;
   EnsureRatio(-AFactor,0);
   EnsureRatio(-AFactor,0);
-  UpdateFillMatrixFromRect;
+  UpdateFillFromRectDiff;
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
@@ -538,7 +535,7 @@ begin
     end;
     end;
   end;
   end;
   EnsureRatio(0,-AFactor);
   EnsureRatio(0,-AFactor);
-  UpdateFillMatrixFromRect;
+  UpdateFillFromRectDiff;
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
@@ -598,7 +595,7 @@ begin
     end;
     end;
   end;
   end;
   EnsureRatio(-AFactorX,-AFactorY);
   EnsureRatio(-AFactorX,-AFactorY);
-  UpdateFillMatrixFromRect;
+  UpdateFillFromRectDiff;
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
@@ -719,18 +716,15 @@ begin
   FMatrixBackup := AffineMatrix(FXAxis-FOrigin, FYAxis-FOrigin, FOrigin);
   FMatrixBackup := AffineMatrix(FXAxis-FOrigin, FYAxis-FOrigin, FOrigin);
 end;
 end;
 
 
-procedure TCustomRectShape.UpdateFillMatrixFromRect;
+procedure TCustomRectShape.UpdateFillFromRectDiff;
 var
 var
   newMatrix, matrixDiff: TAffineMatrix;
   newMatrix, matrixDiff: TAffineMatrix;
 begin
 begin
   newMatrix := AffineMatrix(FXAxis-FOrigin, FYAxis-FOrigin, FOrigin);
   newMatrix := AffineMatrix(FXAxis-FOrigin, FYAxis-FOrigin, FOrigin);
   if IsAffineMatrixInversible(newMatrix) and IsAffineMatrixInversible(FMatrixBackup) then
   if IsAffineMatrixInversible(newMatrix) and IsAffineMatrixInversible(FMatrixBackup) then
   begin
   begin
-    if vsfBackFill in Fields then
-    begin
-      matrixDiff := newMatrix*AffineMatrixInverse(FMatrixBackup);
-      BackFill.Transform(matrixDiff);
-    end;
+    matrixDiff := newMatrix*AffineMatrixInverse(FMatrixBackup);
+    TransformFill(matrixDiff, True);
     FMatrixBackup := newMatrix;
     FMatrixBackup := newMatrix;
   end;
   end;
 end;
 end;
@@ -747,7 +741,7 @@ begin
       FXAxis - (FYAxis - FOrigin), FYAxis - (FXAxis - FOrigin));
       FXAxis - (FYAxis - FOrigin), FYAxis - (FXAxis - FOrigin));
 end;
 end;
 
 
-procedure TCustomRectShape.Transform(const AMatrix: TAffineMatrix);
+procedure TCustomRectShape.TransformFrame(const AMatrix: TAffineMatrix);
 var
 var
   m: TAffineMatrix;
   m: TAffineMatrix;
 begin
 begin
@@ -756,7 +750,6 @@ begin
   FOrigin := m*FOrigin;
   FOrigin := m*FOrigin;
   FXAxis := m*FXAxis;
   FXAxis := m*FXAxis;
   FYAxis := m*FYAxis;
   FYAxis := m*FYAxis;
-  inherited Transform(AMatrix);
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
@@ -788,11 +781,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TCustomRectShape.AllowShearTransform: boolean;
-begin
-  result := true;
-end;
-
 function TCustomRectShape.ShowArrows: boolean;
 function TCustomRectShape.ShowArrows: boolean;
 begin
 begin
   result := true;
   result := true;
@@ -899,16 +887,6 @@ end;
 
 
 { TRectShape }
 { TRectShape }
 
 
-function TRectShape.PenVisible(AAssumePenFill: boolean): boolean;
-begin
-  result := (PenWidth>0) and not IsClearPenStyle(PenStyle) and (not PenFill.IsFullyTransparent or AAssumePenFill);
-end;
-
-function TRectShape.BackVisible: boolean;
-begin
-  result := not BackFill.IsFullyTransparent;
-end;
-
 function TRectShape.GetCornerPositition: single;
 function TRectShape.GetCornerPositition: single;
 begin
 begin
   result := 1;
   result := 1;
@@ -919,24 +897,24 @@ var
   ab: TAffineBox;
   ab: TAffineBox;
   backSurface, totalSurface, penSurface: Single;
   backSurface, totalSurface, penSurface: Single;
 begin
 begin
-  if not PenVisible and not BackVisible then
+  if not GetPenVisible and not GetBackVisible then
     result := false
     result := false
   else
   else
   begin
   begin
     ab := GetAffineBox(AMatrix, true);
     ab := GetAffineBox(AMatrix, true);
     backSurface := ab.Surface;
     backSurface := ab.Surface;
-    if PenVisible then
+    if GetPenVisible then
     begin
     begin
       penSurface := (ab.Width+ab.Height)*2*PenWidth;
       penSurface := (ab.Width+ab.Height)*2*PenWidth;
-      if BackVisible then
+      if GetBackVisible then
         totalSurface:= backSurface+penSurface/2
         totalSurface:= backSurface+penSurface/2
       else
       else
         totalSurface := penSurface;
         totalSurface := penSurface;
     end else
     end else
       totalSurface := backSurface;
       totalSurface := backSurface;
     result := (totalSurface > 800*600) or
     result := (totalSurface > 800*600) or
-              ((backSurface > 320*240) and BackVisible and BackFill.IsSlow(AMatrix)) or
-              ((penSurface > 320*240) and PenVisible and PenFill.IsSlow(AMatrix));
+              ((backSurface > 320*240) and GetBackVisible and BackFill.IsSlow(AMatrix)) or
+              ((penSurface > 320*240) and GetPenVisible and PenFill.IsSlow(AMatrix));
   end;
   end;
 end;
 end;
 
 
@@ -957,7 +935,7 @@ var
   i: Integer;
   i: Integer;
 begin
 begin
   pts := GetAffineBox(AMatrix, true).AsPolygon;
   pts := GetAffineBox(AMatrix, true).AsPolygon;
-  If BackVisible then
+  If GetBackVisible then
   begin
   begin
     if (BackFill.FillType = vftSolid) then backScan := nil
     if (BackFill.FillType = vftSolid) then backScan := nil
     else backScan := BackFill.CreateScanner(AMatrix, ADraft);
     else backScan := BackFill.CreateScanner(AMatrix, ADraft);
@@ -1022,7 +1000,7 @@ begin
 
 
     backScan.Free;
     backScan.Free;
   end;
   end;
-  if PenVisible then
+  if GetPenVisible then
   begin
   begin
     if (PenFill.FillType = vftSolid) then penScan := nil
     if (PenFill.FillType = vftSolid) then penScan := nil
     else penScan := PenFill.CreateScanner(AMatrix, ADraft);
     else penScan := PenFill.CreateScanner(AMatrix, ADraft);
@@ -1051,12 +1029,12 @@ var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
   xMargin, yMargin: single;
   xMargin, yMargin: single;
 begin
 begin
-  if not (BackVisible or (rboAssumeBackFill in AOptions)) and not PenVisible(rboAssumePenFill in AOptions) then
+  if not (GetBackVisible or (rboAssumeBackFill in AOptions)) and not GetPenVisible(rboAssumePenFill in AOptions) then
     result:= EmptyRectF
     result:= EmptyRectF
   else
   else
   begin
   begin
     result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
     result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
-    if PenVisible(rboAssumePenFill in AOptions) then
+    if GetPenVisible(rboAssumePenFill in AOptions) then
     begin
     begin
       if (JoinStyle <> pjsMiter) or (Stroker.MiterLimit <= 1) then
       if (JoinStyle <> pjsMiter) or (Stroker.MiterLimit <= 1) then
       begin
       begin
@@ -1087,9 +1065,9 @@ var
   box: TAffineBox;
   box: TAffineBox;
 begin
 begin
   box := GetAffineBox(AffineMatrixIdentity, true);
   box := GetAffineBox(AffineMatrixIdentity, true);
-  if BackVisible and box.Contains(APoint) then
+  if GetBackVisible and box.Contains(APoint) then
     result := true else
     result := true else
-  if PenVisible then
+  if GetPenVisible then
   begin
   begin
     pts := ComputeStroke(box.AsPolygon, true, AffineMatrixIdentity);
     pts := ComputeStroke(box.AsPolygon, true, AffineMatrixIdentity);
     result:= IsPointInPolygon(pts, APoint, true);
     result:= IsPointInPolygon(pts, APoint, true);
@@ -1102,7 +1080,7 @@ var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
   box: TAffineBox;
   box: TAffineBox;
 begin
 begin
-  if PenVisible or BackVisible then
+  if GetPenVisible or GetBackVisible then
   begin
   begin
     box := GetAffineBox(AffineMatrixIdentity, true);
     box := GetAffineBox(AffineMatrixIdentity, true);
     pts := ComputeStrokeEnvelope(box.AsPolygon, true, ARadius*2);
     pts := ComputeStrokeEnvelope(box.AsPolygon, true, ARadius*2);
@@ -1111,23 +1089,45 @@ begin
   else result := false;
   else result := false;
 end;
 end;
 
 
-class function TRectShape.StorageClassName: RawByteString;
+function TRectShape.PointInBack(APoint: TPointF): boolean;
+var
+  box: TAffineBox;
+  scan: TBGRACustomScanner;
 begin
 begin
-  result := 'rect';
+  if GetBackVisible then
+  begin
+    box := GetAffineBox(AffineMatrixIdentity, true);
+    result := box.Contains(APoint);
+    if result and (BackFill.FillType = vftTexture) then
+    begin
+      scan := BackFill.CreateScanner(AffineMatrixIdentity, false);
+      if scan.ScanAt(APoint.X,APoint.Y).alpha = 0 then result := false;
+      scan.Free;
+    end;
+  end else
+    result := false;
 end;
 end;
 
 
-{ TEllipseShape }
-
-function TEllipseShape.PenVisible(AAssumePenFill: boolean): boolean;
+function TRectShape.PointInPen(APoint: TPointF): boolean;
+var
+  pts: ArrayOfTPointF;
 begin
 begin
-  result := (PenWidth>0) and not IsClearPenStyle(PenStyle) and (not PenFill.IsFullyTransparent or AAssumePenFill);
+  if GetPenVisible then
+  begin
+    pts := GetAffineBox(AffineMatrixIdentity, true).AsPolygon;
+    pts := ComputeStroke(pts,true, AffineMatrixIdentity);
+    result:= IsPointInPolygon(pts, APoint, true);
+  end else
+    result := false;
 end;
 end;
 
 
-function TEllipseShape.BackVisible: boolean;
+class function TRectShape.StorageClassName: RawByteString;
 begin
 begin
-  result := not BackFill.IsFullyTransparent;
+  result := 'rect';
 end;
 end;
 
 
+{ TEllipseShape }
+
 function TEllipseShape.GetCornerPositition: single;
 function TEllipseShape.GetCornerPositition: single;
 begin
 begin
   result := sqrt(2)/2;
   result := sqrt(2)/2;
@@ -1171,7 +1171,7 @@ begin
   IncludePoint(m*YAxis);
   IncludePoint(m*YAxis);
   IncludePoint(m*(Origin-(XAxis-Origin)));
   IncludePoint(m*(Origin-(XAxis-Origin)));
   IncludePoint(m*(Origin-(YAxis-Origin)));
   IncludePoint(m*(Origin-(YAxis-Origin)));
-  if PenVisible then
+  if GetPenVisible then
   begin
   begin
     zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
     zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
     result.Left -= zoom*PenWidth/2;
     result.Left -= zoom*PenWidth/2;
@@ -1198,7 +1198,7 @@ begin
   begin
   begin
     center := (orthoRect.TopLeft+orthoRect.BottomRight)*0.5;
     center := (orthoRect.TopLeft+orthoRect.BottomRight)*0.5;
     radius := (orthoRect.BottomRight-orthoRect.TopLeft)*0.5;
     radius := (orthoRect.BottomRight-orthoRect.TopLeft)*0.5;
-    If BackVisible then
+    If GetBackVisible then
     begin
     begin
       if BackFill.FillType = vftSolid then backScan := nil
       if BackFill.FillType = vftSolid then backScan := nil
       else backScan := BackFill.CreateScanner(AMatrix, ADraft);
       else backScan := BackFill.CreateScanner(AMatrix, ADraft);
@@ -1219,7 +1219,7 @@ begin
 
 
       backScan.Free;
       backScan.Free;
     end;
     end;
-    if PenVisible then
+    if GetPenVisible then
     begin
     begin
       if PenFill.FillType = vftSolid then penScan := nil
       if PenFill.FillType = vftSolid then penScan := nil
       else penScan := PenFill.CreateScanner(AMatrix, ADraft);
       else penScan := PenFill.CreateScanner(AMatrix, ADraft);
@@ -1263,7 +1263,7 @@ begin
   begin
   begin
     m:= MatrixForPixelCentered(AMatrix);
     m:= MatrixForPixelCentered(AMatrix);
     pts := ComputeEllipse(m*FOrigin, m*FXAxis, m*FYAxis);
     pts := ComputeEllipse(m*FOrigin, m*FXAxis, m*FYAxis);
-    If BackVisible then
+    If GetBackVisible then
     begin
     begin
       if BackFill.FillType = vftSolid then backScan := nil
       if BackFill.FillType = vftSolid then backScan := nil
       else backScan := BackFill.CreateScanner(AMatrix, ADraft);
       else backScan := BackFill.CreateScanner(AMatrix, ADraft);
@@ -1283,7 +1283,7 @@ begin
 
 
       backScan.Free;
       backScan.Free;
     end;
     end;
-    if PenVisible then
+    if GetPenVisible then
     begin
     begin
       if PenFill.FillType = vftSolid then penScan := nil
       if PenFill.FillType = vftSolid then penScan := nil
       else penScan := PenFill.CreateScanner(AMatrix, ADraft);
       else penScan := PenFill.CreateScanner(AMatrix, ADraft);
@@ -1311,12 +1311,12 @@ function TEllipseShape.GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMa
 var
 var
   xMargin, yMargin: single;
   xMargin, yMargin: single;
 begin
 begin
-  if not (BackVisible or (rboAssumeBackFill in AOptions)) and not PenVisible(rboAssumePenFill in AOptions) then
+  if not (GetBackVisible or (rboAssumeBackFill in AOptions)) and not GetPenVisible(rboAssumePenFill in AOptions) then
     result:= EmptyRectF
     result:= EmptyRectF
   else
   else
   begin
   begin
     result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
     result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
-    if PenVisible(rboAssumePenFill in AOptions) then
+    if GetPenVisible(rboAssumePenFill in AOptions) then
     begin
     begin
       xMargin := (abs(AMatrix[1,1])+abs(AMatrix[1,2]))*PenWidth*0.5;
       xMargin := (abs(AMatrix[1,1])+abs(AMatrix[1,2]))*PenWidth*0.5;
       yMargin := (abs(AMatrix[2,1])+abs(AMatrix[2,2]))*PenWidth*0.5;
       yMargin := (abs(AMatrix[2,1])+abs(AMatrix[2,2]))*PenWidth*0.5;
@@ -1333,9 +1333,9 @@ var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
 begin
 begin
   pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
   pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
-  if BackVisible and IsPointInPolygon(pts, APoint, true) then
+  if GetBackVisible and IsPointInPolygon(pts, APoint, true) then
     result := true else
     result := true else
-  if PenVisible then
+  if GetPenVisible then
   begin
   begin
     pts := ComputeStroke(pts, true, AffineMatrixIdentity);
     pts := ComputeStroke(pts, true, AffineMatrixIdentity);
     result:= IsPointInPolygon(pts, APoint, true);
     result:= IsPointInPolygon(pts, APoint, true);
@@ -1347,7 +1347,7 @@ function TEllipseShape.PointInShape(APoint: TPointF; ARadius: single): boolean;
 var
 var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
 begin
 begin
-  if PenVisible or BackVisible then
+  if GetPenVisible or GetBackVisible then
   begin
   begin
     pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
     pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
     pts := ComputeStrokeEnvelope(pts, true, ARadius*2);
     pts := ComputeStrokeEnvelope(pts, true, ARadius*2);
@@ -1356,29 +1356,61 @@ begin
     result := false;
     result := false;
 end;
 end;
 
 
+function TEllipseShape.PointInBack(APoint: TPointF): boolean;
+var
+  pts: ArrayOfTPointF;
+  scan: TBGRACustomScanner;
+begin
+  if GetBackVisible then
+  begin
+    pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
+    result:= IsPointInPolygon(pts, APoint, true);
+    if result and (BackFill.FillType = vftTexture) then
+    begin
+      scan := BackFill.CreateScanner(AffineMatrixIdentity, false);
+      if scan.ScanAt(APoint.X,APoint.Y).alpha = 0 then result := false;
+      scan.Free;
+    end;
+  end else
+    result := false;
+end;
+
+function TEllipseShape.PointInPen(APoint: TPointF): boolean;
+var
+  pts: ArrayOfTPointF;
+begin
+  if GetPenVisible then
+  begin
+    pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
+    pts := ComputeStroke(pts,true, AffineMatrixIdentity);
+    result:= IsPointInPolygon(pts, APoint, true);
+  end else
+    result := false;
+end;
+
 function TEllipseShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 function TEllipseShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 var
 var
   ab: TAffineBox;
   ab: TAffineBox;
   backSurface, totalSurface, penSurface: Single;
   backSurface, totalSurface, penSurface: Single;
 begin
 begin
-  if not PenVisible and not BackVisible then
+  if not GetPenVisible and not GetBackVisible then
     result := false
     result := false
   else
   else
   begin
   begin
     ab := GetAffineBox(AMatrix, true);
     ab := GetAffineBox(AMatrix, true);
     backSurface := ab.Surface*Pi/4;
     backSurface := ab.Surface*Pi/4;
-    if PenVisible then
+    if GetPenVisible then
     begin
     begin
       penSurface := (ab.Width+ab.Height)*(Pi/2)*PenWidth;
       penSurface := (ab.Width+ab.Height)*(Pi/2)*PenWidth;
-      if BackVisible then
+      if GetBackVisible then
         totalSurface:= backSurface+penSurface/2
         totalSurface:= backSurface+penSurface/2
       else
       else
         totalSurface := penSurface;
         totalSurface := penSurface;
     end else
     end else
       totalSurface := backSurface;
       totalSurface := backSurface;
     result := (totalSurface > 640*480) or
     result := (totalSurface > 640*480) or
-              ((backSurface > 320*240) and BackVisible and BackFill.IsSlow(AMatrix)) or
-              ((penSurface > 320*240) and PenVisible and PenFill.IsSlow(AMatrix));
+              ((backSurface > 320*240) and GetBackVisible and BackFill.IsSlow(AMatrix)) or
+              ((penSurface > 320*240) and GetPenVisible and PenFill.IsSlow(AMatrix));
   end;
   end;
 end;
 end;
 
 
@@ -1427,11 +1459,6 @@ begin
   EndUpdate;
   EndUpdate;
 end;
 end;
 
 
-function TPhongShape.BackVisible: boolean;
-begin
-  result := not BackFill.IsFullyTransparent;
-end;
-
 function TPhongShape.GetEnvelope: ArrayOfTPointF;
 function TPhongShape.GetEnvelope: ArrayOfTPointF;
 var
 var
   box: TAffineBox;
   box: TAffineBox;
@@ -1605,7 +1632,7 @@ var
   rectRenderF,rectRasterF: TRectF;
   rectRenderF,rectRasterF: TRectF;
   rectRender,rectRaster, prevClip: TRect;
   rectRender,rectRaster, prevClip: TRect;
 begin
 begin
-  if not BackVisible then exit;
+  if not GetBackVisible then exit;
 
 
   //determine final render bounds
   //determine final render bounds
   rectRenderF := GetRenderBounds(InfiniteRect,AMatrix);
   rectRenderF := GetRenderBounds(InfiniteRect,AMatrix);
@@ -1733,7 +1760,7 @@ end;
 function TPhongShape.GetRenderBounds(ADestRect: TRect; AMatrix: TAffineMatrix;
 function TPhongShape.GetRenderBounds(ADestRect: TRect; AMatrix: TAffineMatrix;
   AOptions: TRenderBoundsOptions): TRectF;
   AOptions: TRenderBoundsOptions): TRectF;
 begin
 begin
-  if not (BackVisible or (rboAssumeBackFill in AOptions)) then
+  if not (GetBackVisible or (rboAssumeBackFill in AOptions)) then
     result:= EmptyRectF
     result:= EmptyRectF
   else
   else
     result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
     result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
@@ -1743,7 +1770,7 @@ function TPhongShape.PointInShape(APoint: TPointF): boolean;
 var
 var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
 begin
 begin
-  if not BackVisible then exit(false);
+  if not GetBackVisible then exit(false);
   pts := GetEnvelope;
   pts := GetEnvelope;
   result := IsPointInPolygon(pts, APoint, true);
   result := IsPointInPolygon(pts, APoint, true);
 end;
 end;
@@ -1752,7 +1779,7 @@ function TPhongShape.PointInShape(APoint: TPointF; ARadius: single): boolean;
 var
 var
   pts: ArrayOfTPointF;
   pts: ArrayOfTPointF;
 begin
 begin
-  if BackVisible then
+  if GetBackVisible then
   begin
   begin
     pts := ComputeStrokeEnvelope(GetEnvelope, true, ARadius*2);
     pts := ComputeStrokeEnvelope(GetEnvelope, true, ARadius*2);
     result:= IsPointInPolygon(pts, APoint, true);
     result:= IsPointInPolygon(pts, APoint, true);
@@ -1760,11 +1787,24 @@ begin
     else result := false;
     else result := false;
 end;
 end;
 
 
+function TPhongShape.PointInBack(APoint: TPointF): boolean;
+var
+  scan: TBGRACustomScanner;
+begin
+  result := PointInShape(APoint);
+  if result and (BackFill.FillType = vftTexture) then
+  begin
+    scan := BackFill.CreateScanner(AffineMatrixIdentity, false);
+    if scan.ScanAt(APoint.X,APoint.Y).alpha = 0 then result := false;
+    scan.Free;
+  end;
+end;
+
 function TPhongShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 function TPhongShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 var
 var
   ab: TAffineBox;
   ab: TAffineBox;
 begin
 begin
-  if not BackVisible then exit(false);
+  if not GetBackVisible then exit(false);
   ab := GetAffineBox(AMatrix, true);
   ab := GetAffineBox(AMatrix, true);
   result := ab.Surface > 320*240;
   result := ab.Surface > 320*240;
 end;
 end;

+ 50 - 16
lazpaintcontrols/lcvectortextshapes.pas

@@ -22,10 +22,12 @@ type
     FFontEmHeightBefore: single;
     FFontEmHeightBefore: single;
     FFontNameBefore: string;
     FFontNameBefore: string;
     FFontStyleBefore: TFontStyles;
     FFontStyleBefore: TFontStyles;
+    FAliasedBefore: boolean;
     FFontBidiModeAfter: TFontBidiMode;
     FFontBidiModeAfter: TFontBidiMode;
     FFontEmHeightAfter: single;
     FFontEmHeightAfter: single;
     FFontNameAfter: string;
     FFontNameAfter: string;
     FFontStyleAfter: TFontStyles;
     FFontStyleAfter: TFontStyles;
+    FAliasedAfter: boolean;
   public
   public
     constructor Create(AStartShape: TVectorShape); override;
     constructor Create(AStartShape: TVectorShape); override;
     procedure ComputeDiff(AEndShape: TVectorShape); override;
     procedure ComputeDiff(AEndShape: TVectorShape); override;
@@ -79,6 +81,7 @@ type
 
 
   TTextShape = class(TCustomRectShape)
   TTextShape = class(TCustomRectShape)
   private
   private
+    FAliased: boolean;
     FAltitudePercent: single;
     FAltitudePercent: single;
     FPenPhong: boolean;
     FPenPhong: boolean;
     FLightPosition: TPointF;
     FLightPosition: TPointF;
@@ -99,6 +102,7 @@ type
     function GetParagraphAlignment: TAlignment;
     function GetParagraphAlignment: TAlignment;
     procedure OnMoveLightPos({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF;
     procedure OnMoveLightPos({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF;
       {%H-}AShift: TShiftState);
       {%H-}AShift: TShiftState);
+    procedure SetAliased(AValue: boolean);
     procedure SetAltitudePercent(AValue: single);
     procedure SetAltitudePercent(AValue: single);
     procedure SetPenPhong(AValue: boolean);
     procedure SetPenPhong(AValue: boolean);
     procedure SetFontBidiMode(AValue: TFontBidiMode);
     procedure SetFontBidiMode(AValue: TFontBidiMode);
@@ -116,8 +120,6 @@ type
     FGlobalMatrix: TAffineMatrix;
     FGlobalMatrix: TAffineMatrix;
     procedure DoOnChange(ABoundsBefore: TRectF; ADiff: TVectorShapeDiff); override;
     procedure DoOnChange(ABoundsBefore: TRectF; ADiff: TVectorShapeDiff); override;
     procedure SetGlobalMatrix(AMatrix: TAffineMatrix);
     procedure SetGlobalMatrix(AMatrix: TAffineMatrix);
-    function PenVisible(AAssumePenFill: boolean = false): boolean;
-    function AllowShearTransform: boolean; override;
     function ShowArrows: boolean; override;
     function ShowArrows: boolean; override;
     function GetTextLayout: TBidiTextLayout;
     function GetTextLayout: TBidiTextLayout;
     function GetFontRenderer: TBGRACustomFontRenderer;
     function GetFontRenderer: TBGRACustomFontRenderer;
@@ -149,10 +151,11 @@ type
     class function StorageClassName: RawByteString; override;
     class function StorageClassName: RawByteString; override;
     class function Usermodes: TVectorShapeUsermodes; override;
     class function Usermodes: TVectorShapeUsermodes; override;
     procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
     procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); override;
-    procedure Render(ADest: TBGRABitmap; ARenderOffset: TPoint; AMatrix: TAffineMatrix; ADraft: boolean); override;
+    procedure Render(ADest: TBGRABitmap; ARenderOffset: TPoint; AMatrix: TAffineMatrix; ADraft: boolean); overload; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape(APoint: TPointF): boolean; overload; override;
     function PointInShape({%H-}APoint: TPointF; {%H-}ARadius: single): boolean; overload; override;
     function PointInShape({%H-}APoint: TPointF; {%H-}ARadius: single): boolean; overload; override;
+    function PointInPen(APoint: TPointF): boolean; overload; override;
     function GetIsSlow(const {%H-}AMatrix: TAffineMatrix): boolean; override;
     function GetIsSlow(const {%H-}AMatrix: TAffineMatrix): boolean; override;
     function GetGenericCost: integer; override;
     function GetGenericCost: integer; override;
     procedure MouseMove({%H-}Shift: TShiftState; {%H-}X, {%H-}Y: single; var {%H-}ACursor: TOriginalEditorCursor; var {%H-}AHandled: boolean); override;
     procedure MouseMove({%H-}Shift: TShiftState; {%H-}X, {%H-}Y: single; var {%H-}ACursor: TOriginalEditorCursor; var {%H-}AHandled: boolean); override;
@@ -168,6 +171,7 @@ type
     function DeleteSelection: boolean;
     function DeleteSelection: boolean;
     function GetAlignBounds(const {%H-}ALayoutRect: TRect; const AMatrix: TAffineMatrix): TRectF; override;
     function GetAlignBounds(const {%H-}ALayoutRect: TRect; const AMatrix: TAffineMatrix): TRectF; override;
     procedure Transform(const AMatrix: TAffineMatrix); override;
     procedure Transform(const AMatrix: TAffineMatrix); override;
+    function AllowShearTransform: boolean; override;
     property HasSelection: boolean read GetHasSelection;
     property HasSelection: boolean read GetHasSelection;
     property CanPasteSelection: boolean read GetCanPasteSelection;
     property CanPasteSelection: boolean read GetCanPasteSelection;
     property Text: string read FText write SetText;
     property Text: string read FText write SetText;
@@ -181,6 +185,7 @@ type
     property PenPhong: boolean read FPenPhong write SetPenPhong;
     property PenPhong: boolean read FPenPhong write SetPenPhong;
     property LightPosition: TPointF read FLightPosition write SetLightPosition;
     property LightPosition: TPointF read FLightPosition write SetLightPosition;
     property AltitudePercent: single read FAltitudePercent write SetAltitudePercent;
     property AltitudePercent: single read FAltitudePercent write SetAltitudePercent;
+    property Aliased: boolean read FAliased write SetAliased;
   end;
   end;
 
 
 function FontStyleToStr(AStyle: TFontStyles): string;
 function FontStyleToStr(AStyle: TFontStyles): string;
@@ -193,7 +198,7 @@ implementation
 
 
 uses BGRATransform, BGRAText, BGRAVectorize, LCVectorialFill, math,
 uses BGRATransform, BGRAText, BGRAVectorize, LCVectorialFill, math,
   BGRAUTF8, BGRAUnicode, Graphics, Clipbrd, LCLType, LCLIntf,
   BGRAUTF8, BGRAUnicode, Graphics, Clipbrd, LCLType, LCLIntf,
-  BGRAGradients, BGRACustomTextFX, LCResourceString;
+  BGRAGradients, BGRACustomTextFX, LCResourceString, BGRAFillInfo;
 
 
 function FontStyleToStr(AStyle: TFontStyles): string;
 function FontStyleToStr(AStyle: TFontStyles): string;
 begin
 begin
@@ -420,6 +425,7 @@ begin
     FFontEmHeightBefore:= FFontEmHeight;
     FFontEmHeightBefore:= FFontEmHeight;
     FFontNameBefore:= FFontName;
     FFontNameBefore:= FFontName;
     FFontStyleBefore:= FFontStyle;
     FFontStyleBefore:= FFontStyle;
+    FAliasedBefore := FAliased;
   end;
   end;
 end;
 end;
 
 
@@ -431,6 +437,7 @@ begin
     FFontEmHeightAfter:= FFontEmHeight;
     FFontEmHeightAfter:= FFontEmHeight;
     FFontNameAfter:= FFontName;
     FFontNameAfter:= FFontName;
     FFontStyleAfter:= FFontStyle;
     FFontStyleAfter:= FFontStyle;
+    FAliasedAfter := FAliased;
   end;
   end;
 end;
 end;
 
 
@@ -443,6 +450,7 @@ begin
     FFontEmHeight := FFontEmHeightAfter;
     FFontEmHeight := FFontEmHeightAfter;
     FFontName := FFontNameAfter;
     FFontName := FFontNameAfter;
     FFontStyle := FFontStyleAfter;
     FFontStyle := FFontStyleAfter;
+    FAliased := FAliasedAfter;
     if Assigned(FTextLayout) then FTextLayout.InvalidateLayout;
     if Assigned(FTextLayout) then FTextLayout.InvalidateLayout;
     EndUpdate;
     EndUpdate;
   end;
   end;
@@ -457,6 +465,7 @@ begin
     FFontEmHeight := FFontEmHeightBefore;
     FFontEmHeight := FFontEmHeightBefore;
     FFontName := FFontNameBefore;
     FFontName := FFontNameBefore;
     FFontStyle := FFontStyleBefore;
     FFontStyle := FFontStyleBefore;
+    FAliased := FAliasedBefore;
     if Assigned(FTextLayout) then FTextLayout.InvalidateLayout;
     if Assigned(FTextLayout) then FTextLayout.InvalidateLayout;
     EndUpdate;
     EndUpdate;
   end;
   end;
@@ -471,6 +480,7 @@ begin
   FFontEmHeightAfter := next.FFontEmHeightAfter;
   FFontEmHeightAfter := next.FFontEmHeightAfter;
   FFontNameAfter := next.FFontNameAfter;
   FFontNameAfter := next.FFontNameAfter;
   FFontStyleAfter := next.FFontStyleAfter;
   FFontStyleAfter := next.FFontStyleAfter;
+  FAliasedAfter := next.FAliasedAfter;
 end;
 end;
 
 
 function TTextShapeFontDiff.IsIdentity: boolean;
 function TTextShapeFontDiff.IsIdentity: boolean;
@@ -478,7 +488,8 @@ begin
   result := (FFontBidiModeBefore = FFontBidiModeAfter) and
   result := (FFontBidiModeBefore = FFontBidiModeAfter) and
     (FFontEmHeightBefore = FFontEmHeightAfter) and
     (FFontEmHeightBefore = FFontEmHeightAfter) and
     (FFontNameBefore = FFontNameAfter) and
     (FFontNameBefore = FFontNameAfter) and
-    (FFontStyleBefore = FFontStyleAfter);
+    (FFontStyleBefore = FFontStyleAfter) and
+    (FAliasedBefore = FAliasedAfter);
 end;
 end;
 
 
 { TTextShape }
 { TTextShape }
@@ -547,6 +558,14 @@ begin
   LightPosition := ANewCoord;
   LightPosition := ANewCoord;
 end;
 end;
 
 
+procedure TTextShape.SetAliased(AValue: boolean);
+begin
+  if FAliased=AValue then Exit;
+  BeginUpdate(TTextShapeFontDiff);
+  FAliased:=AValue;
+  EndUpdate;
+end;
+
 procedure TTextShape.SetAltitudePercent(AValue: single);
 procedure TTextShape.SetAltitudePercent(AValue: single);
 begin
 begin
   if AValue < 0 then AValue := 0;
   if AValue < 0 then AValue := 0;
@@ -711,11 +730,6 @@ begin
   FGlobalMatrix := AMatrix;
   FGlobalMatrix := AMatrix;
 end;
 end;
 
 
-function TTextShape.PenVisible(AAssumePenFill: boolean): boolean;
-begin
-  result := not PenFill.IsFullyTransparent or AAssumePenFill;
-end;
-
 function TTextShape.AllowShearTransform: boolean;
 function TTextShape.AllowShearTransform: boolean;
 begin
 begin
   Result:= true;
   Result:= true;
@@ -960,6 +974,7 @@ begin
   FPenPhong:= false;
   FPenPhong:= false;
   FAltitudePercent:= DefaultAltitudePercent;
   FAltitudePercent:= DefaultAltitudePercent;
   FLightPosition := PointF(0,0);
   FLightPosition := PointF(0,0);
+  FAliased := false;
 end;
 end;
 
 
 procedure TTextShape.QuickDefine(constref APoint1, APoint2: TPointF);
 procedure TTextShape.QuickDefine(constref APoint1, APoint2: TPointF);
@@ -1019,6 +1034,8 @@ begin
   end else
   end else
     SetDefaultFont;
     SetDefaultFont;
 
 
+  Aliased := AStorage.Bool['aliased'];
+
   phongObj := AStorage.OpenObject('pen-phong');
   phongObj := AStorage.OpenObject('pen-phong');
   PenPhong := Assigned(phongObj);
   PenPhong := Assigned(phongObj);
   if PenPhong then
   if PenPhong then
@@ -1064,6 +1081,7 @@ begin
   font.RawString['bidi'] := FontBidiModeToStr(FontBidiMode);
   font.RawString['bidi'] := FontBidiModeToStr(FontBidiMode);
   font.RawString['style'] := FontStyleToStr(FontStyle);
   font.RawString['style'] := FontStyleToStr(FontStyle);
   font.Free;
   font.Free;
+  AStorage.Bool['aliased'] := Aliased;
 
 
   if PenPhong then
   if PenPhong then
   begin
   begin
@@ -1099,7 +1117,7 @@ end;
 
 
 class function TTextShape.Fields: TVectorShapeFields;
 class function TTextShape.Fields: TVectorShapeFields;
 begin
 begin
-  Result:= [vsfPenFill,vsfOutlineFill];
+  Result:= [vsfPenFill,vsfOutlineFill,vsfOutlineWidth];
 end;
 end;
 
 
 class function TTextShape.PreferPixelCentered: boolean;
 class function TTextShape.PreferPixelCentered: boolean;
@@ -1109,7 +1127,7 @@ end;
 
 
 class function TTextShape.DefaultFontName: string;
 class function TTextShape.DefaultFontName: string;
 begin
 begin
-  result := {$IFDEF WINDOWS}'Arial'{$ELSE}{$IFDEF DARWIN}'Helvetica'{$ELSE}'FreeSans'{$ENDIF}{$ENDIF};
+  result := {$IFDEF WINDOWS}'Arial'{$ELSE}{$IFDEF DARWIN}'Helvetica'{$ELSE}'Liberation Sans'{$ENDIF}{$ENDIF};
 end;
 end;
 
 
 class function TTextShape.DefaultFontEmHeight: single;
 class function TTextShape.DefaultFontEmHeight: single;
@@ -1283,7 +1301,7 @@ begin
     ctx := tmpTransf.Canvas2D;
     ctx := tmpTransf.Canvas2D;
     ctx.transform(AffineMatrixTranslation(-transfRect.Left,-transfRect.Top)*m);
     ctx.transform(AffineMatrixTranslation(-transfRect.Left,-transfRect.Top)*m);
     ctx.fillMode := fmWinding;
     ctx.fillMode := fmWinding;
-    ctx.antialiasing:= not ADraft;
+    ctx.antialiasing:= not ADraft and not Aliased;
     ctx.beginPath;
     ctx.beginPath;
     tl.PathText(ctx);
     tl.PathText(ctx);
     ctx.resetTransform;
     ctx.resetTransform;
@@ -1309,7 +1327,7 @@ begin
     if HasOutline then
     if HasOutline then
     begin
     begin
       ctx := tmpTransf.Canvas2D;
       ctx := tmpTransf.Canvas2D;
-      ctx.lineWidth := OutlineWidth;
+      ctx.lineWidth := zoom*OutlineWidth;
       ctx.lineJoinLCL:= pjsRound;
       ctx.lineJoinLCL:= pjsRound;
       ctx.lineStyle(psSolid);
       ctx.lineStyle(psSolid);
       if OutlineFill.FillType = vftSolid then
       if OutlineFill.FillType = vftSolid then
@@ -1366,7 +1384,7 @@ begin
     ADest.PutImage(transfRect.Left, transfRect.Top, tmpTransf, dmDrawWithTransparency);
     ADest.PutImage(transfRect.Left, transfRect.Top, tmpTransf, dmDrawWithTransparency);
   end else
   end else
   begin
   begin
-    if ADraft then rf := rfBox else rf := rfHalfCosine;
+    if ADraft or Aliased then rf := rfBox else rf := rfHalfCosine;
     if storeImage then
     if storeImage then
       tmpTransf := TBGRABitmap.Create(transfRect.Width,transfRect.Height)
       tmpTransf := TBGRABitmap.Create(transfRect.Width,transfRect.Height)
     else
     else
@@ -1445,7 +1463,7 @@ var
   u: TPointF;
   u: TPointF;
   lenU, margin: Single;
   lenU, margin: Single;
 begin
 begin
-  if (PenVisible(rboAssumePenFill in AOptions) or HasOutline) and
+  if (GetPenVisible(rboAssumePenFill in AOptions) or HasOutline) and
     (Text <> '') then
     (Text <> '') then
   begin
   begin
     ab := GetAffineBox(AMatrix, false);
     ab := GetAffineBox(AMatrix, false);
@@ -1474,6 +1492,22 @@ begin
   result := false;
   result := false;
 end;
 end;
 
 
+function TTextShape.PointInPen(APoint: TPointF): boolean;
+var
+  tl: TBidiTextLayout;
+  pt: TPointF;
+  i: Integer;
+begin
+  if not GetAffineBox(AffineMatrixIdentity,true).Contains(APoint) then
+    exit(false);
+  SetGlobalMatrix(AffineMatrixIdentity);
+  tl := GetTextLayout;
+  pt := AffineMatrixInverse(GetUntransformedMatrix)*APoint;
+  for i := 0 to tl.PartCount-1 do
+    if tl.PartAffineBox[i].Contains(pt) then exit(true);
+  result := false;
+end;
+
 function TTextShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 function TTextShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
 begin
 begin
   Result:= true;
   Result:= true;

+ 1 - 1
scripts/merge_channels.py → scripts/channels_merge.py

@@ -1,4 +1,4 @@
-# Merge channels
+# Channels > Merge
 from lazpaint import image, dialog, layer
 from lazpaint import image, dialog, layer
 
 
 channels_id = None
 channels_id = None

+ 1 - 1
scripts/split_hsl_native.py → scripts/channels_split_hsl.py

@@ -1,4 +1,4 @@
-# Split HSL channels
+# Channels > Split HSL
 from lazpaint import image, dialog, layer, filters
 from lazpaint import image, dialog, layer, filters
 
 
 # check if it is a channel
 # check if it is a channel

+ 1 - 1
scripts/split_rgb_native.py → scripts/channels_split_rgb.py

@@ -1,4 +1,4 @@
-# Split RGB channels
+# Channels > Split RGB
 from lazpaint import image, dialog, layer, filters
 from lazpaint import image, dialog, layer, filters
 
 
 # check if it is a channel
 # check if it is a channel

+ 10 - 0
scripts/display_version.py

@@ -0,0 +1,10 @@
+# Version
+
+from lazpaint import command, dialog
+import sys
+
+lazpaint_version = command.get_version()
+python_version = sys.version_info
+
+dialog.show_message("Python version " + str(python_version[0]) + "." + str(python_version[1]) + "." + str(python_version[2]) + ", " + "LazPaint version " + str(lazpaint_version[0]) + "." + str(lazpaint_version[1]) + "." + str(lazpaint_version[2]) )
+

+ 1 - 1
scripts/color_overlay.py → scripts/layerfx_color_overlay.py

@@ -1,4 +1,4 @@
-# Color overlay
+# Layer effect > Color overlay
 from lazpaint import image, colors, layer, filters
 from lazpaint import image, colors, layer, filters
 
 
 color = colors.show_dialog(layer.get_registry("overlay-color"))
 color = colors.show_dialog(layer.get_registry("overlay-color"))

+ 261 - 0
scripts/layerfx_innerlight.py

@@ -0,0 +1,261 @@
+# Layer effect > Inner light
+from lazpaint import dialog
+
+try:
+    from tkinter import *
+except ImportError:
+    dialog.show_message("Please install tkinter.")
+    exit()
+        
+from lazpaint import colors, image, layer, filters, tools, selection
+import math
+
+if layer.is_empty():
+    dialog.show_message("Layer is empty")
+    exit()
+
+############ image processing
+
+FRIENDLY_NAME = "Inner light"
+REGISTRY_NAME = "innerlight"
+OPPOSITE_REGISTRY_NAME = "innershadow"
+DEFAULT_ANGLE = 315
+DEFAULT_COLOR = colors.WHITE
+
+MAX_RADIUS = 200
+MAX_OPACITY = 255
+MAX_ANGLE = 360
+
+source_layer_id = layer.get_registry(REGISTRY_NAME+"-source-layer-id")
+if source_layer_id is not None:
+  layer.select_id(source_layer_id)
+else:
+  source_layer_id = layer.get_id()
+source_layer_name = layer.get_name()
+
+chosen_radius = layer.get_registry(REGISTRY_NAME+"-radius")
+if chosen_radius == None: 
+    chosen_radius = layer.get_registry(OPPOSITE_REGISTRY_NAME+"-radius")
+if chosen_radius == None: 
+    chosen_radius = image.get_registry(REGISTRY_NAME+"-radius")
+if chosen_radius == None: 
+    chosen_radius = image.get_registry(OPPOSITE_REGISTRY_NAME+"-radius")
+if chosen_radius == None:
+    chosen_radius = 20
+
+chosen_angle = layer.get_registry(REGISTRY_NAME+"-angle")
+if chosen_angle == None: 
+    chosen_angle = layer.get_registry(OPPOSITE_REGISTRY_NAME+"-angle")
+    if chosen_angle is not None:
+        chosen_angle = (chosen_angle+180) % 360
+if chosen_angle == None: 
+    chosen_angle = image.get_registry(REGISTRY_NAME+"-angle")
+if chosen_angle == None: 
+    chosen_angle = image.get_registry(OPPOSITE_REGISTRY_NAME+"-angle")
+    if chosen_angle is not None:
+        chosen_angle = (chosen_angle+180) % 360
+if chosen_angle == None:
+    chosen_angle = DEFAULT_ANGLE
+
+shadow_layer_id = layer.get_registry(REGISTRY_NAME+"-layer-id")
+if image.get_layer_index(shadow_layer_id) == None:
+    shadow_layer_id = None
+
+if shadow_layer_id is not None:
+    layer.select_id(shadow_layer_id)
+    chosen_opacity = layer.get_opacity()
+    overlay_color = colors.str_to_RGBA(layer.get_registry("overlay-color"))
+    layer.select_id(source_layer_id)
+else:
+    chosen_opacity = layer.get_opacity()*2/3 
+    overlay_color = None
+
+if overlay_color is None:
+  overlay_color = DEFAULT_COLOR
+
+def create_shadow_layer():
+    global shadow_layer_id
+    image.do_begin()
+    if shadow_layer_id != None:
+        layer.select_id(shadow_layer_id)
+        layer.remove()
+    layer.select_id(source_layer_id)
+    layer.duplicate()
+    layer.rasterize()
+    layer.set_name(FRIENDLY_NAME+" of "+source_layer_name)
+    layer.set_registry(REGISTRY_NAME+"-source-layer-id", source_layer_id)
+    shadow_layer_id = layer.get_id()
+    layer.set_registry("overlay-color", overlay_color)
+    layer.set_opacity(chosen_opacity)    
+    image.do_end()
+
+blur_done = False
+opacity_done = False
+
+def apply_blur():
+    global blur_done, opacity_done
+    if opacity_done:
+        image.undo()
+        opacity_done = False
+    if blur_done:
+        image.undo()
+        blur_done = False
+    image.do_begin()
+    if chosen_radius == 0:
+        filters.filter_function(alpha=0, gamma_correction=False)
+    else:
+        layer.duplicate()
+        layer.set_opacity(255)
+        filters.filter_function(red="alpha", green="alpha", blue="alpha", alpha=1, gamma_correction=False)
+        mask_layer_id = layer.get_id()    
+
+        layer.select_id(shadow_layer_id)
+        filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, gamma_correction=False)
+        tools.choose(tools.MOVE_LAYER)
+        offset = (math.sin(chosen_angle*math.pi/180)*chosen_radius, -math.cos(chosen_angle*math.pi/180)*chosen_radius)
+        tools.mouse([(0,0), (offset[0],offset[1])])
+
+        layer.select_id(mask_layer_id)
+        layer.duplicate()
+        mask_layer_id2 = layer.get_id()
+        layer.select_id(mask_layer_id)
+        tools.choose(tools.MOVE_LAYER)
+        tools.mouse([(offset[0]/2,offset[1]/2), (0,0)])
+        colors.linear_negative()
+        layer.set_blend_op(layer.BLEND_MASK)
+        layer.merge_over()
+        mask_layer_id = mask_layer_id2
+
+        filters.blur(radius=chosen_radius)
+
+        layer.select_id(mask_layer_id)
+        layer.set_blend_op(layer.BLEND_MASK)
+        layer.merge_over()  
+   
+    blur_done = image.do_end()
+    apply_opacity()
+
+def apply_opacity():
+    global opacity_done
+    if opacity_done:
+        image.undo()
+        opacity_done = False
+    image.do_begin()
+    layer.set_opacity(chosen_opacity)
+    opacity_done = image.do_end()
+
+######## interface
+
+def button_ok_click():
+    global source_layer_id, chosen_radius, chosen_angle
+    layer.select_id(source_layer_id)
+    layer.set_registry(REGISTRY_NAME+"-radius", chosen_radius)
+    layer.set_registry(REGISTRY_NAME+"-angle", chosen_angle)
+    layer.set_registry(REGISTRY_NAME+"-layer-id", shadow_layer_id)
+    image.set_registry(REGISTRY_NAME+"-radius", chosen_radius)
+    image.set_registry(REGISTRY_NAME+"-angle", chosen_angle)
+    image.do_end()
+    exit()
+
+def button_cancel_click():    
+    if image.do_end():
+        image.undo()
+    layer.select_id(source_layer_id)
+    exit()
+
+scale_radius_update_job = None
+
+def scale_radius_update_do():
+    global scale_radius_update_job, chosen_radius, scale_radius
+    new_radius = scale_radius.get() 
+    if new_radius != chosen_radius:
+        chosen_radius = new_radius
+        apply_blur()
+    scale_radius_update_job = None    
+
+def scale_radius_update(event):
+    global window, scale_radius_update_job
+    if scale_radius_update_job:
+        window.after_cancel(scale_radius_update_job)
+    scale_radius_update_job = window.after(800, scale_radius_update_do)
+
+scale_angle_update_job = None
+
+def scale_angle_update_do():
+    global scale_angle_update_job, chosen_angle, scale_angle
+    new_angle = scale_angle.get() 
+    if new_angle != chosen_angle:
+        chosen_angle = new_angle
+        apply_blur()
+    scale_angle_update_job = None    
+
+def scale_angle_update(event):
+    global window, scale_angle_update_job
+    if scale_angle_update_job:
+        window.after_cancel(scale_angle_update_job)
+    scale_angle_update_job = window.after(800, scale_angle_update_do)
+
+scale_opacity_update_job = None
+
+def scale_opacity_update_do():
+    global chosen_opacity 
+    new_opacity = scale_opacity.get()
+    if new_opacity != chosen_opacity:
+        chosen_opacity = new_opacity
+        apply_opacity()
+    scale_opacity_update_job = None
+
+def scale_opacity_update(event):   
+    global window, scale_opacity_update_job
+    if scale_opacity_update_job:
+        window.after_cancel(scale_opacity_update_job)
+    scale_opacity_update_job = window.after(100, scale_opacity_update_do)
+
+window = Tk()
+window.title(FRIENDLY_NAME)
+window.resizable(False, False)
+
+frame = Frame(window)
+frame.pack()
+
+label_radius = Label(frame, text="Radius:")
+label_radius.grid(column=0, row=0)
+scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
+scale_radius.grid(column=1, row=0, sticky=W+E, padx=10)
+scale_radius.set(chosen_radius)
+
+label_angle = Label(frame, text="Angle:")
+label_angle.grid(column=0, row=1)
+scale_angle = Scale(frame, from_=0, to=MAX_ANGLE, orient=HORIZONTAL, command=scale_angle_update)
+scale_angle.grid(column=1, row=1, sticky=W+E, padx=10)
+scale_angle.set(chosen_angle)
+
+label_opacity = Label(frame, text="Opacity:")
+label_opacity.grid(column=0, row=2)
+scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update)
+scale_opacity.grid(column=1, row=2, sticky=W+E, padx=10)
+scale_opacity.set(chosen_opacity)
+
+frame.columnconfigure(0, pad=20)
+frame.columnconfigure(1, minsize=250)
+frame.rowconfigure(0, pad=20)
+frame.rowconfigure(1, pad=20)
+frame.rowconfigure(2, pad=20)
+
+button_ok = Button(window, text="Ok", command=button_ok_click)
+button_ok.pack(side=RIGHT, padx=10, pady=10)
+button_cancel = Button(window, text="Cancel", command=button_cancel_click)
+button_cancel.pack(side=RIGHT, pady=10)
+
+image.do_begin()
+selection.deselect()
+create_shadow_layer()
+apply_blur()
+
+window.update()
+window_width = window.winfo_width()
+screen_width = window.winfo_screenwidth()
+window.geometry('+%d+0' % (int((screen_width - window_width) / 2)))
+
+window.mainloop()
+button_cancel_click()

+ 261 - 0
scripts/layerfx_innershadow.py

@@ -0,0 +1,261 @@
+# Layer effect > Inner shadow
+from lazpaint import dialog
+
+try:
+    from tkinter import *
+except ImportError:
+    dialog.show_message("Please install tkinter.")
+    exit()
+        
+from lazpaint import colors, image, layer, filters, tools, selection
+import math
+
+if layer.is_empty():
+    dialog.show_message("Layer is empty")
+    exit()
+
+############ image processing
+
+FRIENDLY_NAME = "Inner shadow"
+REGISTRY_NAME = "innershadow"
+OPPOSITE_REGISTRY_NAME = "innerlight"
+DEFAULT_ANGLE = 135
+DEFAULT_COLOR = colors.BLACK
+
+MAX_RADIUS = 200
+MAX_OPACITY = 255
+MAX_ANGLE = 360
+
+source_layer_id = layer.get_registry(REGISTRY_NAME+"-source-layer-id")
+if source_layer_id is not None:
+  layer.select_id(source_layer_id)
+else:
+  source_layer_id = layer.get_id()
+source_layer_name = layer.get_name()
+
+chosen_radius = layer.get_registry(REGISTRY_NAME+"-radius")
+if chosen_radius == None: 
+    chosen_radius = layer.get_registry(OPPOSITE_REGISTRY_NAME+"-radius")
+if chosen_radius == None: 
+    chosen_radius = image.get_registry(REGISTRY_NAME+"-radius")
+if chosen_radius == None: 
+    chosen_radius = image.get_registry(OPPOSITE_REGISTRY_NAME+"-radius")
+if chosen_radius == None:
+    chosen_radius = 20
+
+chosen_angle = layer.get_registry(REGISTRY_NAME+"-angle")
+if chosen_angle == None: 
+    chosen_angle = layer.get_registry(OPPOSITE_REGISTRY_NAME+"-angle")
+    if chosen_angle is not None:
+        chosen_angle = (chosen_angle+180) % 360
+if chosen_angle == None: 
+    chosen_angle = image.get_registry(REGISTRY_NAME+"-angle")
+if chosen_angle == None: 
+    chosen_angle = image.get_registry(OPPOSITE_REGISTRY_NAME+"-angle")
+    if chosen_angle is not None:
+        chosen_angle = (chosen_angle+180) % 360
+if chosen_angle == None:
+    chosen_angle = DEFAULT_ANGLE
+
+shadow_layer_id = layer.get_registry(REGISTRY_NAME+"-layer-id")
+if image.get_layer_index(shadow_layer_id) == None:
+    shadow_layer_id = None
+
+if shadow_layer_id is not None:
+    layer.select_id(shadow_layer_id)
+    chosen_opacity = layer.get_opacity()
+    overlay_color = colors.str_to_RGBA(layer.get_registry("overlay-color"))
+    layer.select_id(source_layer_id)
+else:
+    chosen_opacity = layer.get_opacity()*2/3 
+    overlay_color = None
+
+if overlay_color is None:
+  overlay_color = DEFAULT_COLOR
+
+def create_shadow_layer():
+    global shadow_layer_id
+    image.do_begin()
+    if shadow_layer_id != None:
+        layer.select_id(shadow_layer_id)
+        layer.remove()
+    layer.select_id(source_layer_id)
+    layer.duplicate()
+    layer.rasterize()
+    layer.set_name(FRIENDLY_NAME+" of "+source_layer_name)
+    layer.set_registry(REGISTRY_NAME+"-source-layer-id", source_layer_id)
+    shadow_layer_id = layer.get_id()
+    layer.set_registry("overlay-color", overlay_color)
+    layer.set_opacity(chosen_opacity)    
+    image.do_end()
+
+blur_done = False
+opacity_done = False
+
+def apply_blur():
+    global blur_done, opacity_done
+    if opacity_done:
+        image.undo()
+        opacity_done = False
+    if blur_done:
+        image.undo()
+        blur_done = False
+    image.do_begin()
+    if chosen_radius == 0:
+        filters.filter_function(alpha=0, gamma_correction=False)
+    else:
+        layer.duplicate()
+        layer.set_opacity(255)
+        filters.filter_function(red="alpha", green="alpha", blue="alpha", alpha=1, gamma_correction=False)
+        mask_layer_id = layer.get_id()    
+
+        layer.select_id(shadow_layer_id)
+        filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, gamma_correction=False)
+        tools.choose(tools.MOVE_LAYER)
+        offset = (math.sin(chosen_angle*math.pi/180)*chosen_radius, -math.cos(chosen_angle*math.pi/180)*chosen_radius)
+        tools.mouse([(0,0), (offset[0],offset[1])])
+
+        layer.select_id(mask_layer_id)
+        layer.duplicate()
+        mask_layer_id2 = layer.get_id()
+        layer.select_id(mask_layer_id)
+        tools.choose(tools.MOVE_LAYER)
+        tools.mouse([(offset[0]/2,offset[1]/2), (0,0)])
+        colors.linear_negative()
+        layer.set_blend_op(layer.BLEND_MASK)
+        layer.merge_over()
+        mask_layer_id = mask_layer_id2
+
+        filters.blur(radius=chosen_radius)
+
+        layer.select_id(mask_layer_id)
+        layer.set_blend_op(layer.BLEND_MASK)
+        layer.merge_over()  
+   
+    blur_done = image.do_end()
+    apply_opacity()
+
+def apply_opacity():
+    global opacity_done
+    if opacity_done:
+        image.undo()
+        opacity_done = False
+    image.do_begin()
+    layer.set_opacity(chosen_opacity)
+    opacity_done = image.do_end()
+
+######## interface
+
+def button_ok_click():
+    global source_layer_id, chosen_radius, chosen_angle
+    layer.select_id(source_layer_id)
+    layer.set_registry(REGISTRY_NAME+"-radius", chosen_radius)
+    layer.set_registry(REGISTRY_NAME+"-angle", chosen_angle)
+    layer.set_registry(REGISTRY_NAME+"-layer-id", shadow_layer_id)
+    image.set_registry(REGISTRY_NAME+"-radius", chosen_radius)
+    image.set_registry(REGISTRY_NAME+"-angle", chosen_angle)
+    image.do_end()
+    exit()
+
+def button_cancel_click():    
+    if image.do_end():
+        image.undo()
+    layer.select_id(source_layer_id)
+    exit()
+
+scale_radius_update_job = None
+
+def scale_radius_update_do():
+    global scale_radius_update_job, chosen_radius, scale_radius
+    new_radius = scale_radius.get() 
+    if new_radius != chosen_radius:
+        chosen_radius = new_radius
+        apply_blur()
+    scale_radius_update_job = None    
+
+def scale_radius_update(event):
+    global window, scale_radius_update_job
+    if scale_radius_update_job:
+        window.after_cancel(scale_radius_update_job)
+    scale_radius_update_job = window.after(800, scale_radius_update_do)
+
+scale_angle_update_job = None
+
+def scale_angle_update_do():
+    global scale_angle_update_job, chosen_angle, scale_angle
+    new_angle = scale_angle.get() 
+    if new_angle != chosen_angle:
+        chosen_angle = new_angle
+        apply_blur()
+    scale_angle_update_job = None    
+
+def scale_angle_update(event):
+    global window, scale_angle_update_job
+    if scale_angle_update_job:
+        window.after_cancel(scale_angle_update_job)
+    scale_angle_update_job = window.after(800, scale_angle_update_do)
+
+scale_opacity_update_job = None
+
+def scale_opacity_update_do():
+    global chosen_opacity 
+    new_opacity = scale_opacity.get()
+    if new_opacity != chosen_opacity:
+        chosen_opacity = new_opacity
+        apply_opacity()
+    scale_opacity_update_job = None
+
+def scale_opacity_update(event):   
+    global window, scale_opacity_update_job
+    if scale_opacity_update_job:
+        window.after_cancel(scale_opacity_update_job)
+    scale_opacity_update_job = window.after(100, scale_opacity_update_do)
+
+window = Tk()
+window.title(FRIENDLY_NAME)
+window.resizable(False, False)
+
+frame = Frame(window)
+frame.pack()
+
+label_radius = Label(frame, text="Radius:")
+label_radius.grid(column=0, row=0)
+scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
+scale_radius.grid(column=1, row=0, sticky=W+E, padx=10)
+scale_radius.set(chosen_radius)
+
+label_angle = Label(frame, text="Angle:")
+label_angle.grid(column=0, row=1)
+scale_angle = Scale(frame, from_=0, to=MAX_ANGLE, orient=HORIZONTAL, command=scale_angle_update)
+scale_angle.grid(column=1, row=1, sticky=W+E, padx=10)
+scale_angle.set(chosen_angle)
+
+label_opacity = Label(frame, text="Opacity:")
+label_opacity.grid(column=0, row=2)
+scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update)
+scale_opacity.grid(column=1, row=2, sticky=W+E, padx=10)
+scale_opacity.set(chosen_opacity)
+
+frame.columnconfigure(0, pad=20)
+frame.columnconfigure(1, minsize=250)
+frame.rowconfigure(0, pad=20)
+frame.rowconfigure(1, pad=20)
+frame.rowconfigure(2, pad=20)
+
+button_ok = Button(window, text="Ok", command=button_ok_click)
+button_ok.pack(side=RIGHT, padx=10, pady=10)
+button_cancel = Button(window, text="Cancel", command=button_cancel_click)
+button_cancel.pack(side=RIGHT, pady=10)
+
+image.do_begin()
+selection.deselect()
+create_shadow_layer()
+apply_blur()
+
+window.update()
+window_width = window.winfo_width()
+screen_width = window.winfo_screenwidth()
+window.geometry('+%d+0' % (int((screen_width - window_width) / 2)))
+
+window.mainloop()
+button_cancel_click()

+ 7 - 7
scripts/layer_shadow.py → scripts/layerfx_shadow.py

@@ -1,4 +1,4 @@
-# Layer shadow
+# Layer effect > Drop shadow
 from lazpaint import dialog
 from lazpaint import dialog
 
 
 try:
 try:
@@ -176,7 +176,7 @@ frame.pack()
 label_radius = Label(frame, text="Radius:")
 label_radius = Label(frame, text="Radius:")
 label_radius.grid(column=0, row=0)
 label_radius.grid(column=0, row=0)
 scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
 scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
-scale_radius.grid(column=1, row=0, columnspan=2, sticky=W+E, padx=10)
+scale_radius.grid(column=1, row=0, sticky=W+E, padx=10)
 scale_radius.set(chosen_radius)
 scale_radius.set(chosen_radius)
 
 
 label_offset = Label(frame, text="Offset:")
 label_offset = Label(frame, text="Offset:")
@@ -185,21 +185,21 @@ scale_offset_x = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTA
 scale_offset_x.grid(column=1, row=1, sticky=W+E, padx=10)
 scale_offset_x.grid(column=1, row=1, sticky=W+E, padx=10)
 scale_offset_x.set(chosen_offset[0])
 scale_offset_x.set(chosen_offset[0])
 scale_offset_y = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTAL, command=scale_offset_update)
 scale_offset_y = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTAL, command=scale_offset_update)
-scale_offset_y.grid(column=2, row=1, sticky=W+E, padx=10)
+scale_offset_y.grid(column=1, row=2, sticky=W+E, padx=10)
 scale_offset_y.set(chosen_offset[1])
 scale_offset_y.set(chosen_offset[1])
 
 
 label_opacity = Label(frame, text="Opacity:")
 label_opacity = Label(frame, text="Opacity:")
-label_opacity.grid(column=0, row=2)
+label_opacity.grid(column=0, row=3)
 scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update)
 scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update)
-scale_opacity.grid(column=1, row=2, columnspan=2, sticky=W+E, padx=10)
+scale_opacity.grid(column=1, row=3, sticky=W+E, padx=10)
 scale_opacity.set(chosen_opacity)
 scale_opacity.set(chosen_opacity)
 
 
 frame.columnconfigure(0, pad=20)
 frame.columnconfigure(0, pad=20)
-frame.columnconfigure(1, weight=1)
-frame.columnconfigure(2, weight=1)
+frame.columnconfigure(1, minsize=250)
 frame.rowconfigure(0, pad=20)
 frame.rowconfigure(0, pad=20)
 frame.rowconfigure(1, pad=20)
 frame.rowconfigure(1, pad=20)
 frame.rowconfigure(2, pad=20)
 frame.rowconfigure(2, pad=20)
+frame.rowconfigure(3, pad=20)
 
 
 button_ok = Button(window, text="Ok", command=button_ok_click)
 button_ok = Button(window, text="Ok", command=button_ok_click)
 button_ok.pack(side=RIGHT, padx=10, pady=10)
 button_ok.pack(side=RIGHT, padx=10, pady=10)

+ 215 - 0
scripts/layerfx_stroke.py

@@ -0,0 +1,215 @@
+# Layer effect > Stroke
+from lazpaint import dialog
+
+try:
+    from tkinter import *
+except ImportError:
+    dialog.show_message("Please install tkinter.")
+    exit()
+        
+from lazpaint import colors, image, layer, filters, tools, selection
+
+if layer.is_empty():
+    dialog.show_message("Layer is empty")
+    exit()
+
+############ image processing
+
+MAX_RADIUS = 100
+MAX_OPACITY = 255
+
+source_layer_id = layer.get_id()
+source_layer_name = layer.get_name()
+
+chosen_radius = layer.get_registry("stroke-radius")
+if chosen_radius == None: 
+    chosen_radius = image.get_registry("stroke-radius")
+if chosen_radius == None:
+    chosen_radius = 10
+
+stroke_layer_id = layer.get_registry("stroke-layer-id")
+if image.get_layer_index(stroke_layer_id) == None:
+    stroke_layer_id = None
+
+if stroke_layer_id is not None:
+    layer.select_id(stroke_layer_id)
+    chosen_opacity = layer.get_opacity()
+    overlay_color = colors.str_to_RGBA(layer.get_registry("overlay-color"))
+    layer.select_id(source_layer_id)
+else:
+    chosen_opacity = layer.get_opacity() 
+    overlay_color = None
+
+if overlay_color is None:
+  overlay_color = colors.BLACK
+
+def create_stroke_layer():
+    global stroke_layer_id
+    image.do_begin()
+    if stroke_layer_id != None:
+        layer.select_id(stroke_layer_id)
+        stroke_index = image.get_layer_index()
+        selection.select_all()
+        selection.delete()
+        layer.select_id(source_layer_id)
+        layer.duplicate()
+        image.move_layer_index(image.get_layer_index(), stroke_index+1)
+        layer.merge_over()        
+    else:
+        layer.select_id(source_layer_id)
+        layer.duplicate()
+        layer.set_name("Stroke of "+source_layer_name)
+        layer.set_registry("stroke-source-layer-id", source_layer_id)
+        stroke_layer_id = layer.get_id()
+        stroke_index = image.get_layer_index()
+        image.move_layer_index(stroke_index, stroke_index-1)
+    image.do_end()
+
+stroke_done = False
+opacity_done = False
+stroke_initial_color = None
+
+def apply_stroke():
+    global stroke_done, opacity_done, stroke_initial_color
+    if opacity_done:
+        image.undo()
+        opacity_done = False
+    if stroke_done:
+        image.undo()
+        stroke_done = False
+    image.do_begin() 
+    if chosen_radius > 0.5:
+        layer.duplicate()
+        disk_id = layer.get_id()
+        filters.blur(name=filters.BLUR_DISK, radius=chosen_radius-0.5)
+        filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, alpha="min(alpha*"+str(chosen_radius*5)+",(1-alpha)*"+str(chosen_radius*5)+")", gamma_correction=False)
+        layer.select_id(stroke_layer_id) 
+    else:
+        disk_id = None   
+    filters.blur(name=filters.BLUR_CORONA, radius=chosen_radius+0.5)
+    filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, alpha="min(alpha*"+str(chosen_radius)+",(1-alpha)*"+str(chosen_radius)+")", gamma_correction=False)
+    if disk_id is not None:
+        layer.select_id(disk_id)
+        layer.merge_over()
+    layer.set_registry("overlay-color", overlay_color)
+    stroke_initial_color = overlay_color
+    stroke_done = image.do_end()
+    apply_opacity()
+
+def apply_opacity():
+    global opacity_done, chosen_opacity, overlay_color
+    if opacity_done:
+        image.undo()
+        opacity_done = False
+    image.do_begin()
+    layer.set_opacity(chosen_opacity)
+    if overlay_color != stroke_initial_color:
+        filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, gamma_correction=False)
+        layer.set_registry("overlay-color", overlay_color)
+    opacity_done = image.do_end()
+
+######## interface
+
+def button_ok_click():
+    global source_layer_id, chosen_radius, chosen_offset
+    layer.select_id(source_layer_id)
+    layer.set_registry("stroke-radius", chosen_radius)
+    layer.set_registry("stroke-layer-id", stroke_layer_id)
+    image.set_registry("stroke-radius", chosen_radius)
+    image.do_end()
+    exit()
+
+def button_cancel_click():    
+    if image.do_end():
+        image.undo()
+    layer.select_id(source_layer_id)
+    exit()
+
+scale_radius_update_job = None
+
+def scale_radius_update_do():
+    global scale_radius_update_job, chosen_radius, scale_radius
+    new_radius = scale_radius.get() 
+    if new_radius != chosen_radius:
+        chosen_radius = new_radius
+        apply_stroke()
+    scale_radius_update_job = None    
+
+def scale_radius_update(event):
+    global window, scale_radius_update_job
+    if scale_radius_update_job:
+        window.after_cancel(scale_radius_update_job)
+    scale_radius_update_job = window.after(500, scale_radius_update_do)
+
+scale_opacity_update_job = None
+
+def scale_opacity_update_do():
+    global chosen_opacity 
+    new_opacity = scale_opacity.get()
+    if new_opacity != chosen_opacity:
+        chosen_opacity = new_opacity
+        apply_opacity()
+    scale_opacity_update_job = None
+
+def scale_opacity_update(event):   
+    global window, scale_opacity_update_job
+    if scale_opacity_update_job:
+        window.after_cancel(scale_opacity_update_job)
+    scale_opacity_update_job = window.after(100, scale_opacity_update_do)
+
+def button_color_click():
+    global overlay_color, window
+    new_color = colors.show_dialog(overlay_color)
+    window.attributes('-topmost', True)
+    window.attributes('-topmost', False)
+    if new_color is not None and new_color != overlay_color:
+        overlay_color = new_color
+        apply_opacity()
+
+window = Tk()
+window.title("Layer stroke")
+window.resizable(False, False)
+
+frame = Frame(window)
+frame.pack()
+
+label_radius = Label(frame, text="Radius:")
+label_radius.grid(column=0, row=0)
+scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
+scale_radius.grid(column=1, row=0, sticky=W+E, padx=10)
+scale_radius.set(chosen_radius)
+
+label_opacity = Label(frame, text="Opacity:")
+label_opacity.grid(column=0, row=1)
+scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update)
+scale_opacity.grid(column=1, row=1, sticky=W+E, padx=10)
+scale_opacity.set(chosen_opacity)
+
+label_color = Label(frame, text="Color:")
+label_color.grid(column=0, row=2)
+button_color = Button(frame, text="Color...", command=button_color_click)
+button_color.grid(column=1, row=2)
+
+frame.columnconfigure(0, pad=20)
+frame.columnconfigure(1, minsize=250)
+frame.rowconfigure(0, pad=20)
+frame.rowconfigure(1, pad=20)
+frame.rowconfigure(2, pad=20)
+
+button_ok = Button(window, text="Ok", command=button_ok_click)
+button_ok.pack(side=RIGHT, padx=10, pady=10)
+button_cancel = Button(window, text="Cancel", command=button_cancel_click)
+button_cancel.pack(side=RIGHT, pady=10)
+
+image.do_begin()
+selection.deselect()
+create_stroke_layer()
+apply_stroke()
+
+window.update()
+window_width = window.winfo_width()
+screen_width = window.winfo_screenwidth()
+window.geometry('+%d+0' % (int((screen_width - window_width) / 2)))
+
+window.mainloop()
+button_cancel_click()

+ 2 - 0
scripts/lazpaint/command.py

@@ -24,3 +24,5 @@ def send(command: str, **keywords):
   else:
   else:
     return
     return
 
 
+def get_version(): # (major, minor, revision)
+  return send("LazPaintGetVersion?")

+ 45 - 0
scripts/lazpaint/tools.py

@@ -240,12 +240,18 @@ def set_fore_color(color):
 def set_back_color(color):
 def set_back_color(color):
   command.send("ToolSetBackColor", Color=color)
   command.send("ToolSetBackColor", Color=color)
 
 
+def set_outline_color(color):
+  command.send("ToolSetOutlineColor", Color=color)
+
 def get_fore_color():
 def get_fore_color():
   return colors.str_to_RGBA(command.send("ToolGetForeColor?"))
   return colors.str_to_RGBA(command.send("ToolGetForeColor?"))
 
 
 def get_back_color():
 def get_back_color():
   return colors.str_to_RGBA(command.send("ToolGetBackColor?"))
   return colors.str_to_RGBA(command.send("ToolGetBackColor?"))
 
 
+def get_outline_color():
+  return colors.str_to_RGBA(command.send("ToolGetOutlineColor?"))
+
 def set_eraser_mode(mode):
 def set_eraser_mode(mode):
   command.send('ToolSetEraserMode', Mode=mode)
   command.send('ToolSetEraserMode', Mode=mode)
 
 
@@ -429,6 +435,30 @@ def set_back_gradient_repetition(repetition):
 def get_back_gradient_repetition():
 def get_back_gradient_repetition():
   return command.send('ToolGetBackGradientRepetition?')
   return command.send('ToolGetBackGradientRepetition?')
 
 
+def set_outline_gradient_type(gradient_type):
+  command.send('ToolSetOutlineGradientType', GradientType=gradient_type)
+
+def get_outline_gradient_type():
+  return command.send('ToolGetOutlineGradientType?')
+
+def set_outline_gradient_colors(colors: list):
+  command.send('ToolSetOutlineGradientColors', Colors=colors)
+
+def get_outline_gradient_colors() -> list:
+  return colors.str_to_RGBA(command.send('ToolGetOutlineGradientColors?'))
+
+def set_outline_gradient_interpolation(interpolation):
+  command.send('ToolSetOutlineGradientInterpolation', Interpolation=interpolation)
+
+def get_outline_gradient_interpolation():
+  return command.send('ToolGetOutlineGradientInterpolation?')
+
+def set_outline_gradient_repetition(repetition):
+  command.send('ToolSetOutlineGradientRepetition', Repetition=repetition)
+
+def get_outline_gradient_repetition():
+  return command.send('ToolGetOutlineGradientRepetition?')
+
 def set_fore_texture(file_name):
 def set_fore_texture(file_name):
   command.send('ToolSetForeTexture', FileName=file_name)
   command.send('ToolSetForeTexture', FileName=file_name)
 
 
@@ -459,6 +489,21 @@ def set_back_texture_opacity(opacity: int):
 def get_back_texture_opacity(): #-> int 0..255
 def get_back_texture_opacity(): #-> int 0..255
   return command.send('ToolGetBackTextureOpacity?')
   return command.send('ToolGetBackTextureOpacity?')
 
 
+def set_outline_texture(file_name):
+  command.send('ToolSetOutlineTexture', FileName=file_name)
+
+def set_outline_texture_repetition(repetition):
+  command.send('ToolSetOutlineTextureRepetition', Repetition=repetition)
+
+def get_outline_texture_repetition():
+  return command.send('ToolGetOutlineTextureRepetition?')
+
+def set_outline_texture_opacity(opacity: int):
+  command.send('ToolSetOutlineTextureOpacity', Opacity=opacity)
+
+def get_outline_texture_opacity(): #-> int 0..255
+  return command.send('ToolGetOutlineTextureOpacity?')
+
 def set_phong_shape_kind(kind):
 def set_phong_shape_kind(kind):
   command.send('ToolSetPhongShapeKind', Kind=kind)
   command.send('ToolSetPhongShapeKind', Kind=kind)
 
 

+ 12 - 0
scripts/mask_from_alpha.py

@@ -0,0 +1,12 @@
+# Mask > Mask from alpha channel
+from lazpaint import image, layer, filters, selection
+
+image.do_begin()
+
+selection.deselect()
+layer.duplicate()
+layer.set_name("Mask")
+filters.filter_function(red="alpha", green="alpha", blue="alpha", alpha=255, gamma_correction=False)
+layer.set_blend_op(layer.BLEND_MASK)
+
+image.do_end()

+ 1 - 1
scripts/new_mask.py → scripts/mask_new.py

@@ -1,4 +1,4 @@
-# New mask
+# Mask > New mask
 from lazpaint import image, layer, tools, colors, selection
 from lazpaint import image, layer, tools, colors, selection
 
 
 image.do_begin()
 image.do_begin()

+ 1 - 1
scripts/fractal_tree.py → scripts/render_fractal_tree.py

@@ -1,4 +1,4 @@
-# Render fractal tree
+# Render > Fractal tree
 from lazpaint import tools, image, layer, dialog
 from lazpaint import tools, image, layer, dialog
 import math, random
 import math, random
 
 

+ 1 - 1
scripts/render_lava.py

@@ -1,4 +1,4 @@
-# Render Lava
+# Render > Lava
 from lazpaint import image, layer, filters, colors
 from lazpaint import image, layer, filters, colors
 
 
 image.do_begin()
 image.do_begin()

Некоторые файлы не были показаны из-за большого количества измененных файлов