Bläddra i källkod

Merge branch 'master' of https://github.com/bgrabitmap/lazpaint

circular17 6 år sedan
förälder
incheckning
c80afaf945
51 ändrade filer med 1579 tillägg och 806 borttagningar
  1. 1 0
      .gitignore
  2. 2 1
      lazpaint.logic
  3. 33 19
      lazpaint/dialog/ubrowseimages.pas
  4. 2 2
      lazpaint/dialog/usaveoption.pas
  5. 14 8
      lazpaint/lazpaint.lpi
  6. 25 0
      lazpaint/lazpaint.lpr
  7. 1 1
      lazpaint/lazpaintembeddedpack.lpk
  8. 4 4
      lazpaint/lazpaintinstance.pas
  9. 7 1
      lazpaint/lazpaintmainform.lfm
  10. 60 5
      lazpaint/lazpaintmainform.pas
  11. 2 11
      lazpaint/lazpainttype.pas
  12. 20 15
      lazpaint/release/bin/i18n/lazpaint.ar.po
  13. 20 15
      lazpaint/release/bin/i18n/lazpaint.cs.po
  14. 36 15
      lazpaint/release/bin/i18n/lazpaint.de.po
  15. 21 15
      lazpaint/release/bin/i18n/lazpaint.es.po
  16. 16 11
      lazpaint/release/bin/i18n/lazpaint.fi.po
  17. 36 15
      lazpaint/release/bin/i18n/lazpaint.fr.po
  18. 16 11
      lazpaint/release/bin/i18n/lazpaint.ja.po
  19. 19 15
      lazpaint/release/bin/i18n/lazpaint.lv.po
  20. 159 145
      lazpaint/release/bin/i18n/lazpaint.nl.po
  21. 14 10
      lazpaint/release/bin/i18n/lazpaint.po
  22. 20 15
      lazpaint/release/bin/i18n/lazpaint.pt_BR.po
  23. 20 15
      lazpaint/release/bin/i18n/lazpaint.ru.po
  24. 16 11
      lazpaint/release/bin/i18n/lazpaint.sv.po
  25. 16 1
      lazpaint/release/changelog
  26. 16 1
      lazpaint/release/debian/linux32/DEBIAN/changelog
  27. 1 1
      lazpaint/release/debian/linux32/DEBIAN/control
  28. 16 1
      lazpaint/release/debian/linux64/DEBIAN/changelog
  29. 1 1
      lazpaint/release/debian/linux64/DEBIAN/control
  30. 47 0
      lazpaint/release/macOS/LazPaint.app/Contents/Info.plist
  31. 0 0
      lazpaint/release/macOS/LazPaint.app/Contents/MacOS/delete.me
  32. 1 0
      lazpaint/release/macOS/LazPaint.app/Contents/PkgInfo
  33. BIN
      lazpaint/release/macOS/LazPaint.app/Contents/Resources/lazpaint.icns
  34. 5 0
      lazpaint/release/macOS/instructions.txt
  35. 1 1
      lazpaint/release/macOS/makedmg.sh
  36. 1 1
      lazpaint/release/windows/lazpaint.iss
  37. 59 56
      lazpaint/tools/utool.pas
  38. 33 21
      lazpaint/tools/utoolbasic.pas
  39. 3 3
      lazpaint/tools/utooldeformationgrid.pas
  40. 96 43
      lazpaint/tools/utoollayer.pas
  41. 41 2
      lazpaint/tools/utoolpolygon.pas
  42. 59 19
      lazpaint/tools/utoolselect.pas
  43. 367 262
      lazpaint/tools/utoolvectorial.pas
  44. 143 17
      lazpaint/ufilesystem.pas
  45. 4 2
      lazpaint/uimagepreview.pas
  46. 2 1
      lazpaint/uimageview.pas
  47. 3 3
      lazpaint/umenu.pas
  48. 8 4
      lazpaint/uresourcestrings.pas
  49. 7 3
      lazpaint/utiff.pas
  50. 11 1
      lazpaintcontrols/lazpaintcontrols.lpk
  51. 74 2
      lazpaintcontrols/lcvectorpolyshapes.pas

+ 1 - 0
.gitignore

@@ -32,3 +32,4 @@ lazpaint/tools/backup/
 lazpaint/image/backup/
 
 lazpaint/dialog/backup/
+.DS_Store

+ 2 - 1
lazpaint.logic

@@ -9,4 +9,5 @@ echo "Don't forget to UPDATE changelog file"
 copy release/changelog release/debian/linux32/DEBIAN/changelog
 copy release/changelog release/debian/linux64/DEBIAN/changelog
 text release/macOS/makedmg.sh "appversion=$(Version)"
-
+plist release/macOS/LazPaint.app/Contents/Info.plist
+copy ../resources/icon/lazpaint.icns release/macOS/LazPaint.app/Contents/Resources/lazpaint.icns

+ 33 - 19
lazpaint/dialog/ubrowseimages.pas

@@ -67,6 +67,9 @@ type
     procedure ToolButton_ViewBigIconClick(Sender: TObject);
     procedure Tool_SelectDriveClick(Sender: TObject);
     function OnDeleteConfirmation({%H-}AForm:TForm; const AFiles: array of string; AContained: boolean): boolean;
+  private
+    function GetCurrentDirectory: string;
+    procedure SetCurrentDirectory(AValue: string);
   private
     FLazPaintInstance: TLazPaintCustomInstance;
     FDefaultExtension: string;
@@ -124,6 +127,7 @@ type
     procedure DeleteSelectedFiles;
     procedure SelectFile(AName: string);
     procedure PreviewValidate({%H-}ASender: TObject);
+    property CurrentDirectory: string read GetCurrentDirectory write SetCurrentDirectory;
   public
     { public declarations }
     ShowRememberStartupDirectory: boolean;
@@ -295,8 +299,7 @@ begin
   BGRAPaintNet.RegisterPaintNetFormat;
   BGRAOpenRaster.RegisterOpenRasterFormat;
 
-  FFileSystems := FileManager.GetFileSystems;
-  if length(FFileSystems)>0 then
+  if FileManager.CanGetFileSystems then
   begin
     Tool_SelectDrive.Visible := true;
   end else
@@ -335,8 +338,8 @@ begin
   if not IsSaveDialog then FFilename:= FPreviewFilename;
   Timer1.Enabled := false;
   vsList.Anchors := [akLeft,akTop,akRight,akBottom];
-  FLastDirectory := DirectoryEdit1.Text;
-  DirectoryEdit1.Text := '';
+  FLastDirectory := CurrentDirectory;
+  CurrentDirectory := '';
   UpdatePreview('');
 end;
 
@@ -403,9 +406,9 @@ begin
   end;
   if FLastBigIcon then ViewBigIcons;
   if (FLastDirectory = '') or not FileManager.IsDirectory(FLastDirectory) then
-    DirectoryEdit1.Text := DefaultPicturesDirectory
+    CurrentDirectory := DefaultPicturesDirectory
   else
-    DirectoryEdit1.Text := FLastDirectory;
+    CurrentDirectory := FLastDirectory;
   Timer1.Enabled := true;
   vsList.Anchors := [akLeft,akTop];
   ShellListView1.SetFocus;
@@ -449,8 +452,8 @@ procedure TFBrowseImages.ListBox_RecentDirsClick(Sender: TObject);
 begin
   if ListBox_RecentDirs.ItemIndex <> -1 then
   begin
-    if ChompPathDelim(DirectoryEdit1.Text) <> ChompPathDelim(ListBox_RecentDirs.Items[ListBox_RecentDirs.ItemIndex]) then
-      DirectoryEdit1.Text := AppendPathDelim(ListBox_RecentDirs.Items[ListBox_RecentDirs.ItemIndex]);
+    if ChompPathDelim(CurrentDirectory) <> ChompPathDelim(ListBox_RecentDirs.Items[ListBox_RecentDirs.ItemIndex]) then
+      CurrentDirectory := AppendPathDelim(ListBox_RecentDirs.Items[ListBox_RecentDirs.ItemIndex]);
   end;
 end;
 
@@ -604,13 +607,13 @@ var
   newName: String;
   newFullname: string;
 begin
-  if pos(PathDelim, DirectoryEdit1.Text) = 0 then exit;
+  if pos(PathDelim, CurrentDirectory) = 0 then exit;
   newName := InputBox(FCreateFolderOrContainerCaption, rsEnterFolderOrContainerName, '');
   if newName = '' then exit;
   if (pos(':',newName) <> 0) or (pos('\',newName) <> 0) then
     MessageDlg(rsInvalidName, mtError, [mbOK], 0) else
   begin
-    newFullname := ChompPathDelim(DirectoryEdit1.Text)+PathDelim+newName;
+    newFullname := ChompPathDelim(CurrentDirectory)+PathDelim+newName;
     if FileManager.IsDirectory(newFullname) then
       MessageDlg(rsFolderOrContainerAlreadyExists, mtInformation, [mbOK], 0)
     else
@@ -667,7 +670,7 @@ end;
 
 procedure TFBrowseImages.Tool_SelectDriveClick(Sender: TObject);
 begin
-  DirectoryEdit1.Text := ':';
+  CurrentDirectory := ':';
 end;
 
 function TFBrowseImages.OnDeleteConfirmation(AForm: TForm;
@@ -688,6 +691,17 @@ begin
     result := true;
 end;
 
+function TFBrowseImages.GetCurrentDirectory: string;
+begin
+  result := DirectoryEdit1.Text;
+end;
+
+procedure TFBrowseImages.SetCurrentDirectory(AValue: string);
+begin
+  DirectoryEdit1.Text := AValue;
+  ResetDirectory(False);
+end;
+
 procedure TFBrowseImages.UpdateToolButtonOpen;
 var chosenFilename: string;
 begin
@@ -838,7 +852,7 @@ var I: integer;
 begin
   ListBox_RecentDirs.ItemIndex := -1;
   for I := 0 to ListBox_RecentDirs.Count-1 do
-    if ChompPathDelim(ListBox_RecentDirs.Items[i]) = ChompPathDelim(DirectoryEdit1.Text) then
+    if ChompPathDelim(ListBox_RecentDirs.Items[i]) = ChompPathDelim(CurrentDirectory) then
     begin
       ListBox_RecentDirs.ItemIndex:= I;
       break;
@@ -936,7 +950,7 @@ begin
     fullName := ShellListView1.ItemFullName[ShellListView1.SelectedIndex];
     if ShellListView1.ItemIsFolder[ShellListView1.SelectedIndex] then
     begin
-      DirectoryEdit1.Text := fullName;
+      CurrentDirectory := fullName;
       InFilenameChange := true;
       Edit_Filename.text := '';
       InFilenameChange := false;
@@ -977,10 +991,10 @@ begin
       ModalResult:= mrOk;
     end;
   end else
-    if IsSaveDialog and (Trim(Edit_Filename.Text)<>'') and (DirectoryEdit1.Text <> ':') and
-      FileManager.IsDirectory(trim(DirectoryEdit1.Text)) then
+    if IsSaveDialog and (Trim(Edit_Filename.Text)<>'') and (CurrentDirectory <> ':') and
+      FileManager.IsDirectory(trim(CurrentDirectory)) then
     begin
-      FFilename:= IncludeTrailingPathDelimiter(trim(DirectoryEdit1.Text))+Edit_Filename.Text;
+      FFilename:= IncludeTrailingPathDelimiter(trim(CurrentDirectory))+Edit_Filename.Text;
       if (ExtractFileExt(FFilename)='') then
       begin
         if (ComboBox_FileExtension.ItemIndex > 0) then
@@ -1004,15 +1018,15 @@ procedure TFBrowseImages.GoDirUp;
 var dir: string;
   itemToSelect: string;
 begin
-  dir := DirectoryEdit1.Text;
+  dir := CurrentDirectory;
   FileManager.RemoveLastPathElement(dir, itemToSelect);
   if dir = '' then
   begin
     FFileSystems:= FileManager.GetFileSystems;
-    if length(FFileSystems)>0 then DirectoryEdit1.Text := ':';
+    if length(FFileSystems)>0 then CurrentDirectory := ':';
     itemToSelect := '';
   end else
-    DirectoryEdit1.Text := dir;
+    CurrentDirectory := dir;
   ShellListView1.SetFocus;
   UpdatePreview('');
   InFilenameChange := true;

+ 2 - 2
lazpaint/dialog/usaveoption.pas

@@ -845,9 +845,9 @@ begin
   UpdateFileSize;
   DrawHourglass(BGRAPreview.Bitmap);
   BGRAPreview.Repaint;
-  {$IFDEF LINUX}
+  { $IFDEF LINUX}
   Application.ProcessMessages;
-  {$ENDIF}
+  { $ENDIF}
   BGRAPreview.DiscardBitmap;
 end;
 

+ 14 - 8
lazpaint/lazpaint.lpi

@@ -21,7 +21,7 @@
     <VersionInfo>
       <UseVersionInfo Value="True"/>
       <MajorVersionNr Value="7"/>
-      <RevisionNr Value="4"/>
+      <RevisionNr Value="5"/>
       <CharSet Value="04B0"/>
       <StringTable CompanyName="http://sourceforge.net/projects/lazpaint/" ProductName="LazPaint" InternalName="lazpaint" OriginalFilename="lazpaint.exe"/>
     </VersionInfo>
@@ -36,7 +36,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="buttons;tablet;dialog;dialog\color;dialog\filter;tools;image"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="release\lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -74,7 +74,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="buttons;tablet"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="release\lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -114,7 +114,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="buttons;tablet"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="release\lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -157,7 +157,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="buttons;tablet"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="release\lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -197,7 +197,7 @@
           <PathDelim Value="\"/>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="tablet"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="debug\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <CodeGeneration>
@@ -223,6 +223,9 @@
               </Win32>
             </Options>
           </Linking>
+          <Other>
+            <CustomOptions Value="-dDEBUG"/>
+          </Other>
         </CompilerOptions>
       </Item6>
       <Item7 Name="Release Linux32">
@@ -234,7 +237,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="buttons;tablet"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="release\lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -274,7 +277,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="buttons;tablet"/>
+            <OtherUnitFiles Value="tablet;tools;dialog;dialog\color;dialog\filter;image"/>
             <UnitOutputDirectory Value="release\lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -954,6 +957,9 @@
         </Win32>
       </Options>
     </Linking>
+    <Other>
+      <CustomOptions Value="-dDEBUG"/>
+    </Other>
   </CompilerOptions>
   <Debugging>
     <Exceptions Count="10">

+ 25 - 0
lazpaint/lazpaint.lpr

@@ -93,7 +93,30 @@ end;
 
 {$R *.res}
 
+{$IFDEF DARWIN}{$IFDEF DEBUG}
+var
+  OldOutput: TextFile;
+
+  procedure InitOutput;
+  begin
+    OldOutput := Output;
+    AssignFile(Output, '/dev/ttys000');
+    Append(Output);
+    Writeln;
+    Writeln('Debug started');
+  end;
+
+  procedure DoneOutput;
+  begin
+    Writeln('Debug ended');
+    CloseFile(Output);
+    Output := OldOutput;
+  end;
+{$ENDIF}{$ENDIF}
+
 begin
+  {$IFDEF DARWIN}{$IFDEF DEBUG}InitOutput;{$ENDIF}{$ENDIF}
+
   ActualConfig := GetActualConfig;
   TranslateLazPaint(ActualConfig);
 
@@ -121,5 +144,7 @@ begin
   RestartQuery := LazpaintApplication.RestartQuery;
   LazpaintApplication.Free;
   if RestartQuery then RestartApplication;
+
+  {$IFDEF DARWIN}{$IFDEF DEBUG}DoneOutput;{$ENDIF}{$ENDIF}
 end.
 

+ 1 - 1
lazpaint/lazpaintembeddedpack.lpk

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

+ 4 - 4
lazpaint/lazpaintinstance.pas

@@ -17,7 +17,7 @@ uses
   ULoading, UImage, UTool, uconfig, IniFiles, uresourcestrings, uscripting;
 
 const
-  MaxToolPopupShowCount = 2;
+  MaxToolPopupShowCount = 3;
 
 type
   TImageListList = specialize TFPGObjectList<TImageList>;
@@ -113,7 +113,7 @@ type
     procedure Init(AEmbedded: boolean);
     procedure SetBlackAndWhite(AValue: boolean); override;
     procedure OnStackChanged({%H-}sender: TLazPaintImage; AScrollIntoView: boolean);
-    procedure OnToolPopup({%H-}sender: TToolManager; AMessage: TToolPopupMessage);
+    procedure OnToolPopup({%H-}sender: TToolManager; AMessage: TToolPopupMessage; AKey: Word);
 
     function GetImageListWindowHeight: integer; override;
     function GetImageListWindowWidth: integer; override;
@@ -484,7 +484,7 @@ begin
     FLayerStack.InvalidateStack(AScrollIntoView);
 end;
 
-procedure TLazPaintInstance.OnToolPopup(sender: TToolManager; AMessage: TToolPopupMessage);
+procedure TLazPaintInstance.OnToolPopup(sender: TToolManager; AMessage: TToolPopupMessage; AKey: Word);
 var messageStr: string;
     idx: integer;
 begin
@@ -496,7 +496,7 @@ begin
     else
       exit;
   end;
-  messageStr := ToolPopupMessageToStr(AMessage);
+  messageStr := ToolPopupMessageToStr(AMessage, AKey);
   if messageStr <> '' then
     MessagePopup(messageStr,4000);
 end;

+ 7 - 1
lazpaint/lazpaintmainform.lfm

@@ -8562,7 +8562,7 @@ object FMain: TFMain
     object ToolSpline: TAction
       Category = 'Tool'
       Caption = 'Curve'
-      Hint = 'Spline'
+      Hint = 'Curve'
       ImageIndex = 22
       OnExecute = ToolAnyExecute
     end
@@ -8710,6 +8710,12 @@ object FMain: TFMain
       OnExecute = EditShapeAlignBottomExecute
       OnUpdate = EditShapeAlignBottomUpdate
     end
+    object EditShapeToCurve: TAction
+      Category = 'Edit'
+      Hint = 'Convert shape to curve'
+      OnExecute = EditShapeToCurveExecute
+      OnUpdate = EditShapeToCurveUpdate
+    end
   end
   object ColorDialog1: TColorDialog
     Title = 'Choose color'

+ 60 - 5
lazpaint/lazpaintmainform.pas

@@ -28,6 +28,7 @@ type
   { TFMain }
 
   TFMain = class(TForm)
+    EditShapeToCurve: TAction;
     EditShapeAlignBottom: TAction;
     EditShapeCenterVertically: TAction;
     EditShapeAlignTop: TAction;
@@ -463,6 +464,8 @@ type
     procedure EditShapeCenterHorizontallyUpdate(Sender: TObject);
     procedure EditShapeCenterVerticallyExecute(Sender: TObject);
     procedure EditShapeCenterVerticallyUpdate(Sender: TObject);
+    procedure EditShapeToCurveExecute(Sender: TObject);
+    procedure EditShapeToCurveUpdate(Sender: TObject);
     procedure FileChooseEntryExecute(Sender: TObject);
     procedure FileChooseEntryUpdate(Sender: TObject);
     procedure FileImport3DUpdate(Sender: TObject);
@@ -712,7 +715,7 @@ type
     initialized: boolean;
     shouldArrangeOnResize: boolean;
     btnLeftDown, btnRightDown, btnMiddleDown: boolean;
-    spacePressed: boolean;
+    spacePressed, altPressed, snapPressed, shiftPressed: boolean;
     FormMouseMovePos: TPoint;
     InFormMouseMove: boolean;
     InFormPaint: boolean;
@@ -793,6 +796,7 @@ type
     procedure LabelAutosize(ALabel: TLabel);
     procedure AskMergeSelection(ACaption: string);
     procedure ReleaseMouseButtons(Shift: TShiftState);
+    procedure UpdateSpecialKeys({%H-}Shift: TShiftState);
     procedure UpdateCurveModeToolbar;
     function ShowOpenTextureDialog: boolean;
     procedure ShowNoPicture;
@@ -907,6 +911,10 @@ begin
   btnRightDown := false;
   btnMiddleDown:= false;
   FTablet := TLazTablet.Create(self);
+  spacePressed:= false;
+  altPressed:= false;
+  snapPressed:= false;
+  shiftPressed:= false;
 
   //recursive calls
   InFormMouseMove:= false;
@@ -1150,9 +1158,11 @@ begin
   if Button = mbMiddle then
   begin
     btnMiddleDown:= true;
-    if not ToolManager.ToolSleeping then ToolManager.ToolSleep;
+    if not ToolManager.ToolSleeping and not (ssAlt in Shift) then ToolManager.ToolSleep;
   end;
-  if ToolManager.ToolDown(FImageView.FormToBitmap(X,Y),btnRightDown,CurrentPressure) then
+  if ToolManager.ToolDown(FImageView.FormToBitmap(X,Y),
+      btnRightDown{$IFDEF DARWIN} or (ssCtrl in Shift){$ENDIF},
+      CurrentPressure) then
       PaintPictureNow;
   UpdateToolbar;
 end;
@@ -1168,6 +1178,7 @@ begin
   if not Assigned(FImageView) then exit;
 
   ReleaseMouseButtons(Shift);
+  UpdateSpecialKeys(Shift);
   HidePenPreview;
   if LazPaintInstance.TopMostHasFocus then
   begin
@@ -1198,7 +1209,6 @@ begin
   if ToolManager.ToolMove(BmpPos,CurrentPressure) then
   begin
     FImageView.UpdatePicture(PictureCanvasOfs, FLayout.WorkArea, self);
-    ToolManager.ToolMoveAfter(FImageView.FormToBitmap(FormMouseMovePos)); //new BmpPos after repaint
   end else
     updateForVSCursor := true;
   UpdateToolbar;
@@ -1222,10 +1232,11 @@ var redraw: boolean;
 begin
   if not Assigned(FImageView) then exit;
 
-  redraw := ToolManager.ToolMove(FImageView.FormToBitmap(X,Y),CurrentPressure);
+  redraw := false;
   if (btnLeftDown and (Button = mbLeft)) or (btnRightDown and (Button=mbRight))
     or (btnMiddleDown and (Button = mbMiddle)) then
   begin
+    redraw := ToolManager.ToolMove(FImageView.FormToBitmap(X,Y),CurrentPressure);
     if ToolManager.ToolUp then redraw := true;
     btnLeftDown := false;
     btnRightDown := false;
@@ -1634,6 +1645,9 @@ procedure TFMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
   );
 begin
   try
+    if Key = VK_MENU then altPressed:= true
+    else if (Key = VK_SNAP) or (Key = VK_SNAP2) then snapPressed:= true
+    else if Key = VK_SHIFT then shiftPressed:= true;
     if Zoom.EditingZoom then exit;
     if not ((CurrentTool = ptText) and TextSpinEditFocused and (Key = VK_BACK)) and ToolManager.ToolKeyDown(Key) then
     begin
@@ -2019,6 +2033,9 @@ end;
 
 procedure TFMain.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
 begin
+  if Key = VK_MENU then altPressed:= false
+  else if (Key = VK_SNAP) or (Key = VK_SNAP2) then snapPressed:= false
+  else if Key = VK_SHIFT then shiftPressed:= false;
   if ToolManager.ToolKeyUp(Key) then
   begin
     DelayedPaintPicture := True;
@@ -2052,6 +2069,7 @@ begin
     if toolProcessKey and ToolManager.ToolKeyPress(UTF8Key) then
     begin
       DelayedPaintPicture := true;
+      UpdateToolbar;
     end else
     if UTF8Key <> '' then
     begin
@@ -2980,6 +2998,17 @@ begin
   EditShapeCenterVertically.Enabled := ToolManager.ToolProvideCommand(tcCenterVertically);
 end;
 
+procedure TFMain.EditShapeToCurveExecute(Sender: TObject);
+begin
+  if ToolManager.CurrentTool is TVectorialTool then ChooseTool(ptEditShape);
+  ToolManager.ToolCommand(tcShapeToSpline);
+end;
+
+procedure TFMain.EditShapeToCurveUpdate(Sender: TObject);
+begin
+  EditShapeToCurve.Enabled := ToolManager.ToolProvideCommand(tcShapeToSpline);
+end;
+
 procedure TFMain.FileChooseEntryExecute(Sender: TObject);
 var
   openParams: TVariableSet;
@@ -3116,9 +3145,13 @@ begin
 end;
 
 procedure TFMain.ForgetDialogAnswersExecute(Sender: TObject);
+var
+  m: TToolPopupMessage;
 begin
   Config.SetDefaultTransformSelectionAnswer(0);
   Config.SetDefaultRetrieveSelectionAnswer(0);
+  for m := low(TToolPopupMessage) to high(TToolPopupMessage) do
+    Config.SetToolPopupMessageShownCount(ord(m), 0);
 end;
 
 procedure TFMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
@@ -3291,6 +3324,28 @@ begin
   end;
 end;
 
+procedure TFMain.UpdateSpecialKeys(Shift: TShiftState);
+  procedure UpdateKey(AShift: TShiftStateEnum; ACode: Word; var APressed: boolean);
+  begin
+    if (AShift in Shift) and not APressed then
+    begin
+      if ToolManager.ToolKeyDown(ACode) then PaintPictureNow;
+      APressed:= true;
+    end else
+    if not (AShift in Shift) and APressed then
+    begin
+      if ToolManager.ToolKeyUp(ACode) then PaintPictureNow;
+      APressed:= false;
+    end;
+  end;
+begin
+  {$IFDEF DARWIN}
+  UpdateKey(ssSnap, VK_SNAP, snapPressed);
+  UpdateKey(ssAlt, VK_MENU, altPressed);
+  UpdateKey(ssShift, VK_SHIFT, shiftPressed);
+  {$ENDIF}
+end;
+
 function TFMain.ShowOpenTextureDialog: boolean;
 var newTex: TBGRABitmap;
   texFilename: string;

+ 2 - 11
lazpaint/lazpainttype.pas

@@ -10,7 +10,7 @@ uses
   {$IFDEF LINUX}, InterfaceBase{$ENDIF};
 
 const
-  LazPaintVersion = 7000400;
+  LazPaintVersion = 7000500;
 
   function LazPaintVersionStr: string;
 
@@ -19,22 +19,14 @@ const
   Improvements accepted:
   ----------------------
   Mac:
-  - Combobox ownerdrawn (brush, arrow)
-  - update image preview when saving
-  - filename fix
-  - ctrl shortcut to change
+  - combobox dropdown rect without scrollbar
   Scripting
   Color picker
   - From final image
   - With radius
   Translation of curve modes (in dropdown)
   Lasso
-  Raccourcis clavier pour utiliser le bouton droit
   Utiliser les touches de direction
-  Indiquer l'outil actif
-  Rotation des objets des outils
-  Afficher les coordonnees des points (snap de la valeur en haut?)
-  Ajout barre d'outils pour les coordonnees de la selection 
   Mettre a jour le curseur quand on change d'outil (notamment avec Espace)
 
   Possible improvements:
@@ -49,7 +41,6 @@ const
   - load/save RAW
 
   Filters:
-  - filtre de vagues concentriques
   - filtre de vagues en translation
   - filtre pontillisme
   - G'MIC filters

+ 20 - 15
lazpaint/release/bin/i18n/lazpaint.ar.po

@@ -217,6 +217,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "تراجع"
@@ -1218,9 +1222,10 @@ msgid "Curve"
 msgstr "منحنى"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "رتب"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "منحنى"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1553,9 +1558,9 @@ msgstr "الكل"
 msgid "All supported filetypes"
 msgstr "كل الملفات المدعمة"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "إضغط ALT او SHIFT للتحريف"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "إضغط %1 او %2 للتحريف"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1670,9 +1675,9 @@ msgstr "جيب التمام"
 msgid "Crop"
 msgstr "محصول"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "إضغط CTRL لتقييد زاوية الدوران"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "إضغط %1 لتقييد زاوية الدوران"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1835,13 +1840,13 @@ msgstr ""
 msgid "Half-cosine"
 msgstr "نصف - جيب التمام"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "إضغط CTRL لالتقاط إلى بكسل"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "إضغط %1 لالتقاط إلى بكسل"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "إضغط على SHIFT لرسم مربع او دائرة"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "إضغط على %1 لرسم مربع او دائرة"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

+ 20 - 15
lazpaint/release/bin/i18n/lazpaint.cs.po

@@ -213,6 +213,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Vrátit zpět"
@@ -1215,9 +1219,10 @@ msgid "Curve"
 msgstr "Křivka"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Spline"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Křivka"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1550,9 +1555,9 @@ msgstr "všechny"
 msgid "All supported filetypes"
 msgstr "Všechny podporované formáty souborů"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Držte ALT nebo SHIFT pro měřítko "
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Držte %1 nebo %2 pro měřítko "
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1667,9 +1672,9 @@ msgstr "Kosinus"
 msgid "Crop"
 msgstr "Oříznout"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Přidržte CTRL pro omezení úhlu otočení"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Přidržte %1 pro omezení úhlu otočení"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1832,13 +1837,13 @@ msgstr ""
 msgid "Half-cosine"
 msgstr "Poloviční-kosinus"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Přidržte CTRL pro přichycení k bodům"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Přidržte %1 pro přichycení k bodům"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Přidržte SHIFT pro kreslení čtverce nebo kruhu"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Přidržte %1 pro kreslení čtverce nebo kruhu"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

+ 36 - 15
lazpaint/release/bin/i18n/lazpaint.de.po

@@ -228,6 +228,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Rückgängig"
@@ -1230,9 +1234,10 @@ msgid "Curve"
 msgstr "Kurve"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Polynomzug (Spline)"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Kurve"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1566,9 +1571,13 @@ msgstr "alle"
 msgid "All supported filetypes"
 msgstr "Alle unterstützten Dateitypen"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Halten Sie ALT oder UMSCHALT zum Skalieren"
+#: uresourcestrings.rsalt
+msgid "ALT"
+msgstr "ALT"
+
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Halten Sie %1 oder %2 zum Skalieren"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1683,9 +1692,17 @@ msgstr "Kosinus"
 msgid "Crop"
 msgstr "Beschneiden"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Halten Sie STRG für stufenweise Drehung"
+#: uresourcestrings.rsctrl
+msgid "CTRL"
+msgstr "STRG"
+
+#: uresourcestrings.rscmd
+msgid "CMD"
+msgstr "CMD"
+
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Halten Sie %1 für stufenweise Drehung"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1848,13 +1865,17 @@ msgstr "Grün"
 msgid "Half-cosine"
 msgstr "Halber Kosinus"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Halten Sie STRG zum Ausrichten am raster"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Halten Sie %1 zum Ausrichten am raster"
+
+#: uresourcestrings.rsshift
+msgid "SHIFT"
+msgstr "UMSCHALT"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Halten Sie UMSCHALT für ein Quadrat / einen Kreis"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Halten Sie %2 für ein Quadrat / einen Kreis"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

+ 21 - 15
lazpaint/release/bin/i18n/lazpaint.es.po

@@ -210,6 +210,10 @@ msgstr "Centrar la forma horizontalmente"
 msgid "Center shape vertically"
 msgstr "Centrar la forma verticalmente"
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr "Convertir forma a curva"
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Deshacer"
@@ -1209,9 +1213,10 @@ msgid "Curve"
 msgstr "Curva"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Ranura"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Curva"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1544,9 +1549,9 @@ msgstr "todo"
 msgid "All supported filetypes"
 msgstr "Todos los tipos soportados"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Manten ALT o SHIFT para escalar"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Manten %1 o %2 para escalar"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1664,9 +1669,9 @@ msgstr "Coseno"
 msgid "Crop"
 msgstr "Cortar"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Manten CTRL para restringir el ángulo de rotación"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Manten %1 para restringir el ángulo de rotación"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1835,13 +1840,13 @@ msgctxt "uresourcestrings.rshalfcosine"
 msgid "Half-cosine"
 msgstr "Medio-coseno"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Manten CTRL para ajustar a los pixeles"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Manten %1 para ajustar a los pixeles"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Manten SHIFT para dibujar un cuadrado o un circulo"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Manten %1 para dibujar un cuadrado o un circulo"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"
@@ -2314,3 +2319,4 @@ msgstr "Capa vectorial"
 #: uresourcestrings.rsyes
 msgid "Yes"
 msgstr "Sí"
+

+ 16 - 11
lazpaint/release/bin/i18n/lazpaint.fi.po

@@ -202,6 +202,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Kumoa"
@@ -1205,9 +1209,10 @@ msgid "Curve"
 msgstr "Muodokas"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr ""
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Muodokas"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1541,8 +1546,8 @@ msgstr "kaikki"
 msgid "All supported filetypes"
 msgstr "Kaikki tuetut tiedostotyypit"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %A to scale"
 msgstr ""
 
 #: uresourcestrings.rsanimatedgif
@@ -1658,8 +1663,8 @@ msgstr ""
 msgid "Crop"
 msgstr ""
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
 msgstr ""
 
 #: uresourcestrings.rscurvemodehint
@@ -1823,12 +1828,12 @@ msgstr "Vihreä"
 msgid "Half-cosine"
 msgstr ""
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
 msgstr ""
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
 msgstr ""
 
 #: uresourcestrings.rshotspot

+ 36 - 15
lazpaint/release/bin/i18n/lazpaint.fr.po

@@ -217,6 +217,10 @@ msgstr "Centrer la forme horizontalement"
 msgid "Center shape vertically"
 msgstr "Centrer la forme verticalement"
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr "Convertir la forme en courbe"
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Annuler"
@@ -1219,9 +1223,10 @@ msgid "Curve"
 msgstr "Courbe"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Éclisse"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Courbe"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1554,9 +1559,13 @@ msgstr "tout"
 msgid "All supported filetypes"
 msgstr "Tous les formats connus"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Appuyez sur ALT et MAJ pour étirer"
+#: uresourcestrings.rsalt
+msgid "ALT"
+msgstr "ALT"
+
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Appuyez sur %1 et %2 pour étirer"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1674,9 +1683,17 @@ msgstr "Cosinus"
 msgid "Crop"
 msgstr "Recadrer"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Maintenir CTRL pour restreindre l'angle de rotation"
+#: uresourcestrings.rsctrl
+msgid "CTRL"
+msgstr "CTRL"
+
+#: uresourcestrings.rscmd
+msgid "CMD"
+msgstr "CMD"
+
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Maintenir %1 pour restreindre l'angle de rotation"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1845,13 +1862,17 @@ msgctxt "uresourcestrings.rshalfcosine"
 msgid "Half-cosine"
 msgstr "Semi-cosinus"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Maintenir CTRL pour aligner aux pixels"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Maintenir %1 pour aligner aux pixels"
+
+#: uresourcestrings.rsshift
+msgid "SHIFT"
+msgstr "MAJ"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Maintenir MAJ pour dessiner un carré ou un cercle"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Maintenir %1 pour dessiner un carré ou un cercle"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

+ 16 - 11
lazpaint/release/bin/i18n/lazpaint.ja.po

@@ -217,6 +217,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "アンドゥ"
@@ -1218,9 +1222,10 @@ msgid "Curve"
 msgstr "カーブ"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "スプライン曲線"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "カーブ"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1553,8 +1558,8 @@ msgstr ""
 msgid "All supported filetypes"
 msgstr ""
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
 msgstr ""
 
 #: uresourcestrings.rsanimatedgif
@@ -1670,8 +1675,8 @@ msgstr "コサイン"
 msgid "Crop"
 msgstr "切り抜く"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
 msgstr ""
 
 #: uresourcestrings.rscurvemodehint
@@ -1835,12 +1840,12 @@ msgstr ""
 msgid "Half-cosine"
 msgstr "Half-cosine"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
 msgstr ""
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
 msgstr ""
 
 #: uresourcestrings.rshotspot

+ 19 - 15
lazpaint/release/bin/i18n/lazpaint.lv.po

@@ -215,6 +215,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Atsaukt"
@@ -1216,9 +1220,9 @@ msgstr "Līknes"
 
 #: tfmain.toolspline.hint
 #, fuzzy
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Pielāgots"
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Līknes"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1552,9 +1556,9 @@ msgstr "visi"
 msgid "All supported filetypes"
 msgstr "Visi atbalstītie failu formāti"
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Turi [ALT] vai [SHIFT] lai mērogotu"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Turi %1 vai %2 lai mērogotu"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1669,9 +1673,9 @@ msgstr ""
 msgid "Crop"
 msgstr "Apcirpt"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Turi [CTRL] lai izmantotu noteiktus leņķus"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Turi %1 lai izmantotu noteiktus leņķus"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1834,13 +1838,13 @@ msgstr "Zaļš"
 msgid "Half-cosine"
 msgstr ""
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Turi [CTRL], lai pieliptu pikseļiem"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Turi %1, lai pieliptu pikseļiem"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Turi [SHIFT} lai zīmētu kvadrātu vai apli"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Turi %1 lai zīmētu kvadrātu vai apli"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 159 - 145
lazpaint/release/bin/i18n/lazpaint.nl.po


+ 14 - 10
lazpaint/release/bin/i18n/lazpaint.po

@@ -200,6 +200,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr ""
@@ -1199,8 +1203,8 @@ msgid "Curve"
 msgstr ""
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
 msgstr ""
 
 #: tfmain.tooltext.hint
@@ -1534,8 +1538,8 @@ msgstr ""
 msgid "All supported filetypes"
 msgstr ""
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
 msgstr ""
 
 #: uresourcestrings.rsanimatedgif
@@ -1651,8 +1655,8 @@ msgstr ""
 msgid "Crop"
 msgstr ""
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
 msgstr ""
 
 #: uresourcestrings.rscurvemodehint
@@ -1816,12 +1820,12 @@ msgstr ""
 msgid "Half-cosine"
 msgstr ""
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
 msgstr ""
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
 msgstr ""
 
 #: uresourcestrings.rshotspot

+ 20 - 15
lazpaint/release/bin/i18n/lazpaint.pt_BR.po

@@ -221,6 +221,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Desfazer"
@@ -1220,9 +1224,10 @@ msgid "Curve"
 msgstr "Curva"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Ranhura"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Curva"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1555,9 +1560,9 @@ msgstr "todos"
 msgid "All supported filetypes"
 msgstr ""
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Pressione ALT ou SHIFT para alongar"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Pressione %1 ou %2 para alongar"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1672,9 +1677,9 @@ msgstr "Co-seno"
 msgid "Crop"
 msgstr "Cortar"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Segurar Ctrl para restringir o ângulo de rotação"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Segurar %1 para restringir o ângulo de rotação"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1837,13 +1842,13 @@ msgstr ""
 msgid "Half-cosine"
 msgstr "Meio-cosseno"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Segurar CTRL para tirar pixels"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Segurar %1 para tirar pixels"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Segurar SHIFT para desenhar um quadrado ou um círculo"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Segurar %1 para desenhar um quadrado ou um círculo"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

+ 20 - 15
lazpaint/release/bin/i18n/lazpaint.ru.po

@@ -217,6 +217,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Отменить"
@@ -1218,9 +1222,10 @@ msgid "Curve"
 msgstr "Кривая"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Сплайн"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Кривая"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1551,9 +1556,9 @@ msgstr "все"
 msgid "All supported filetypes"
 msgstr ""
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
-msgstr "Удерживайте ALT или SHIFT для масштабирования"
+#: uresourcestrings.rsohldkeysscalemode
+msgid "Hold %1 or %2 to scale"
+msgstr "Удерживайте %1 или %2 для масштабирования"
 
 #: uresourcestrings.rsanimatedgif
 msgid "Animated GIF"
@@ -1668,9 +1673,9 @@ msgstr "Косинус"
 msgid "Crop"
 msgstr "Обрезать"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
-msgstr "Удерживайте CTRL для ограничения угла поворота"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
+msgstr "Удерживайте %1 для ограничения угла поворота"
 
 #: uresourcestrings.rscurvemodehint
 msgid "Press S or X to set the curve mode of the last point"
@@ -1833,13 +1838,13 @@ msgstr ""
 msgid "Half-cosine"
 msgstr "Полу-косинус"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
-msgstr "Удерживайте CTRL для привязки к пикселям"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
+msgstr "Удерживайте %1 для привязки к пикселям"
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
-msgstr "Удерживайте SHIFT для рисования квадрата или круга"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
+msgstr "Удерживайте %1 для рисования квадрата или круга"
 
 #: uresourcestrings.rshotspot
 msgctxt "uresourcestrings.rshotspot"

+ 16 - 11
lazpaint/release/bin/i18n/lazpaint.sv.po

@@ -201,6 +201,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Ångra"
@@ -1202,9 +1206,10 @@ msgid "Curve"
 msgstr "Kurva"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Spline"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Kurva"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -1537,8 +1542,8 @@ msgstr ""
 msgid "All supported filetypes"
 msgstr ""
 
-#: uresourcestrings.rsaltshiftscalemode
-msgid "Hold ALT or SHIFT to scale"
+#: uresourcestrings.rsholdkeysscalemode
+msgid "Hold %1 or %2 to scale"
 msgstr ""
 
 #: uresourcestrings.rsanimatedgif
@@ -1654,8 +1659,8 @@ msgstr "Cosine"
 msgid "Crop"
 msgstr "Beskär"
 
-#: uresourcestrings.rsctrlrestrictrotation
-msgid "Hold CTRL to restrict rotation angle"
+#: uresourcestrings.rsholdkeyrestrictrotation
+msgid "Hold %1 to restrict rotation angle"
 msgstr ""
 
 #: uresourcestrings.rscurvemodehint
@@ -1819,12 +1824,12 @@ msgstr ""
 msgid "Half-cosine"
 msgstr "Halv-cosine"
 
-#: uresourcestrings.rsholdctrlsnaptopixel
-msgid "Hold CTRL to snap to pixels"
+#: uresourcestrings.rsholdkeysnaptopixel
+msgid "Hold %1 to snap to pixels"
 msgstr ""
 
-#: uresourcestrings.rsholdshiftforsquare
-msgid "Hold SHIFT to draw a square or a circle"
+#: uresourcestrings.rsholdkeyforsquare
+msgid "Hold %1 to draw a square or a circle"
 msgstr ""
 
 #: uresourcestrings.rshotspot

+ 16 - 1
lazpaint/release/changelog

@@ -52,7 +52,7 @@ lazpaint (7.0.3) unstable; urgency=low
 
 -- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
 
-lazpaint (7.0.4) stable; urgency=low
+lazpaint (7.0.4) unstable; urgency=low
 
   * adjusting font size for windows
   * fix screen update on move image
@@ -60,3 +60,18 @@ lazpaint (7.0.4) stable; urgency=low
 
 -- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
 
+lazpaint (7.0.5) stable; urgency=low
+
+  * added convert shape to curve
+  * adjust pixel-centered coordinates
+  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
+  * dutch translation
+  * filling of workarea with maximum zoom
+  * paste vector shape on empty layer
+  * alignment of vector shapes to pixels with CTRL
+  * return key to finish polygon shape
+  * reset counter of popups on "forget dialogs"
+  * fix TIFF loading error on some systems
+
+-- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
+

+ 16 - 1
lazpaint/release/debian/linux32/DEBIAN/changelog

@@ -52,7 +52,7 @@ lazpaint (7.0.3) unstable; urgency=low
 
 -- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
 
-lazpaint (7.0.4) stable; urgency=low
+lazpaint (7.0.4) unstable; urgency=low
 
   * adjusting font size for windows
   * fix screen update on move image
@@ -60,3 +60,18 @@ lazpaint (7.0.4) stable; urgency=low
 
 -- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
 
+lazpaint (7.0.5) stable; urgency=low
+
+  * added convert shape to curve
+  * adjust pixel-centered coordinates
+  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
+  * dutch translation
+  * filling of workarea with maximum zoom
+  * paste vector shape on empty layer
+  * alignment of vector shapes to pixels with CTRL
+  * return key to finish polygon shape
+  * reset counter of popups on "forget dialogs"
+  * fix TIFF loading error on some systems
+
+-- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
+

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

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

+ 16 - 1
lazpaint/release/debian/linux64/DEBIAN/changelog

@@ -52,7 +52,7 @@ lazpaint (7.0.3) unstable; urgency=low
 
 -- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
 
-lazpaint (7.0.4) stable; urgency=low
+lazpaint (7.0.4) unstable; urgency=low
 
   * adjusting font size for windows
   * fix screen update on move image
@@ -60,3 +60,18 @@ lazpaint (7.0.4) stable; urgency=low
 
 -- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
 
+lazpaint (7.0.5) stable; urgency=low
+
+  * added convert shape to curve
+  * adjust pixel-centered coordinates
+  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
+  * dutch translation
+  * filling of workarea with maximum zoom
+  * paste vector shape on empty layer
+  * alignment of vector shapes to pixels with CTRL
+  * return key to finish polygon shape
+  * reset counter of popups on "forget dialogs"
+  * fix TIFF loading error on some systems
+
+-- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
+

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

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

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

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleIconFile</key>
+	<string>lazpaint</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>lazpaint</string>
+	<key>CFBundleName</key>
+	<string>LazPaint</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.company.lazpaint</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>lazp</string>
+	<key>CFBundleShortVersionString</key>
+	<string>7.0.5</string>
+	<key>CFBundleVersion</key>
+	<string>7.0.5</string>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Viewer</string>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>*</string>
+			</array>
+			<key>CFBundleTypeOSTypes</key>
+			<array>
+				<string>fold</string>
+				<string>disk</string>
+				<string>****</string>
+			</array>
+		</dict>
+	</array>
+	<key>NSHighResolutionCapable</key>
+	<true/>
+</dict>
+</plist>

+ 0 - 0
lazpaint/release/macOS/LazPaint.app/Contents/MacOS/delete.me


+ 1 - 0
lazpaint/release/macOS/LazPaint.app/Contents/PkgInfo

@@ -0,0 +1 @@
+APPL????

BIN
lazpaint/release/macOS/LazPaint.app/Contents/Resources/lazpaint.icns


+ 5 - 0
lazpaint/release/macOS/instructions.txt

@@ -0,0 +1,5 @@
+To make application bundle:
+- make copy the LazPaint.app folder
+- copy "lazpaint" executable file into subfolder /Contents/MacOS
+- copy additionnal files into subfolder /Contents/Resources
+(including i18n and models folders, but not the application bundle)

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

@@ -12,7 +12,7 @@ fi
 
 
 appname=LazPaint
-appversion=7.0.4
+appversion=7.0.5
 pkgversion=0
 
 appnamenospaces=LazPaint

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

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

+ 59 - 56
lazpaint/tools/utool.pas

@@ -5,9 +5,14 @@ unit UTool;
 interface
 
 uses
-  Classes, SysUtils, Graphics, BGRABitmap, BGRABitmapTypes, uimage,
-  UImageType, ULayerAction, LCLType, Controls, UBrushType, UConfig,
-  LCVectorPolyShapes, BGRAGradientScanner, LCVectorRectShapes;
+  Classes, SysUtils, Graphics, BGRABitmap, BGRABitmapTypes, uimage, UImageType,
+  ULayerAction, LCLType, Controls, UBrushType, UConfig, LCVectorPolyShapes,
+  BGRAGradientScanner, BGRALayerOriginal, LCVectorRectShapes;
+
+const
+  VK_SNAP = {$IFDEF DARWIN}VK_LWIN{$ELSE}VK_CONTROL{$ENDIF};
+  VK_SNAP2 = {$IFDEF DARWIN}VK_RWIN{$ELSE}VK_CONTROL{$ENDIF};
+  ssSnap = {$IFDEF DARWIN}ssMeta{$ELSE}ssCtrl{$ENDIF};
 
 type TPaintToolType = (ptHand,ptHotSpot, ptMoveLayer,ptRotateLayer,ptZoomLayer,
                    ptPen, ptBrush, ptClone, ptColorPicker, ptEraser,
@@ -40,12 +45,15 @@ type
 
   TEraserMode = (emEraseAlpha, emSoften);
   TToolCommand = (tcCut, tcCopy, tcPaste, tcDelete, tcMoveUp, tcMoveDown, tcMoveToFront, tcMoveToBack,
-    tcAlignLeft, tcCenterHorizontally, tcAlignRight, tcAlignTop, tcCenterVertically, tcAlignBottom);
+    tcAlignLeft, tcCenterHorizontally, tcAlignRight, tcAlignTop, tcCenterVertically, tcAlignBottom,
+    tcShapeToSpline);
 
 function GradientColorSpaceToDisplay(AValue: TBGRAColorInterpolation): string;
 function DisplayToGradientColorSpace(AValue: string): TBGRAColorInterpolation;
 
 type
+  TLayerKind = (lkUnknown, lkEmpty, lkBitmap, lkTransformedBitmap, lkGradient, lkVectorial, lkSVG, lkOther);
+
   { TGenericTool }
 
   TGenericTool = class
@@ -63,12 +71,12 @@ type
     function FixLayerOffset: boolean; virtual;
     function DoToolDown(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF; rightBtn: boolean): TRect; virtual;
     function DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect; virtual;
-    procedure DoToolMoveAfter(pt: TPoint; ptF: TPointF); virtual;
     function DoToolUpdate(toolDest: TBGRABitmap): TRect; virtual;
     procedure OnTryStop(sender: TCustomLayerAction); virtual;
     function SelectionMaxPointDistance: single;
     function GetStatusText: string; virtual;
     function DoGetToolDrawingLayer: TBGRABitmap; virtual;
+    function GetCurrentLayerKind: TLayerKind;
   public
     ToolUpdateNeeded: boolean;
     Cursor: TCursor;
@@ -83,7 +91,6 @@ type
     function ToolUpdate: TRect;
     function ToolDown(X,Y: single; rightBtn: boolean): TRect;
     function ToolMove(X,Y: single): TRect;
-    procedure ToolMoveAfter(X,Y: single);
     function ToolKeyDown(var key: Word): TRect; virtual;
     function ToolKeyUp(var key: Word): TRect; virtual;
     function ToolKeyPress(var key: TUTF8Char): TRect; virtual;
@@ -116,13 +123,13 @@ type
 
   TToolClass = class of TGenericTool;
 
-  TToolPopupMessage= (tpmNone,tpmHoldShiftForSquare, tpmHoldCtrlSnapToPixel,
-    tpmReturnValides, tpmBackspaceRemoveLastPoint, tpmCtrlRestrictRotation,
-    tpmAltShiftScaleMode, tpmCurveModeHint, tpmBlendOpBackground,
+  TToolPopupMessage= (tpmNone,tpmHoldKeyForSquare, tpmHoldKeySnapToPixel,
+    tpmReturnValides, tpmBackspaceRemoveLastPoint, tpmHoldKeyRestrictRotation,
+    tpmHoldKeysScaleMode, tpmCurveModeHint, tpmBlendOpBackground,
     tpmRightClickForSource);
 
   TOnToolChangedHandler = procedure(sender: TToolManager; ANewToolType: TPaintToolType) of object;
-  TOnPopupToolHandler = procedure(sender: TToolManager; APopupMessage: TToolPopupMessage) of object;
+  TOnPopupToolHandler = procedure(sender: TToolManager; APopupMessage: TToolPopupMessage; AKey: Word) of object;
 
   TShapeOption = (toAliasing, toDrawShape, toFillShape, toCloseShape);
   TShapeOptions = set of TShapeOption;
@@ -271,10 +278,8 @@ type
 
     function ToolDown(X,Y: single; ARightBtn: boolean; APressure: single): boolean; overload;
     function ToolMove(X,Y: single; APressure: single): boolean; overload;
-    procedure ToolMoveAfter(X,Y: single); overload;
     function ToolDown(ACoord: TPointF; ARightBtn: boolean; APressure: single): boolean; overload;
     function ToolMove(ACoord: TPointF; APressure: single): boolean; overload;
-    procedure ToolMoveAfter(coord: TPointF); overload;
     function ToolKeyDown(var key: Word): boolean;
     function ToolKeyUp(var key: Word): boolean;
     function ToolKeyPress(var key: TUTF8Char): boolean;
@@ -285,7 +290,7 @@ type
     procedure ToolOpen;
     function ToolUpdate: boolean;
     function ToolUpdateNeeded: boolean;
-    procedure ToolPopup(AMessage: TToolPopupMessage);
+    procedure ToolPopup(AMessage: TToolPopupMessage; AKey: Word = 0);
     procedure HintReturnValidates;
 
     function IsSelectingTool: boolean;
@@ -367,12 +372,12 @@ type
    end;
 
 procedure RegisterTool(ATool: TPaintToolType; AClass: TToolClass);
-function ToolPopupMessageToStr(AMessage :TToolPopupMessage): string;
+function ToolPopupMessageToStr(AMessage :TToolPopupMessage; AKey: Word = 0): string;
 
 implementation
 
 uses Types, ugraph, LCScaleDPI, LazPaintType, UCursors, BGRATextFX, ULoading, uresourcestrings,
-  BGRATransform;
+  BGRATransform, LCVectorOriginal, BGRAGradientOriginal, BGRASVGOriginal;
 
 function StrToPaintToolType(const s: ansistring): TPaintToolType;
 var pt: TPaintToolType;
@@ -420,15 +425,25 @@ begin
   PaintTools[ATool] := AClass;
 end;
 
-function ToolPopupMessageToStr(AMessage: TToolPopupMessage): string;
+function ReplaceKey(AText: string; AKey: Word; AParam: integer = 1): string;
+begin
+  if AKey = VK_SHIFT then result := StringReplace(AText, '%'+inttostr(AParam), rsShift, []) else
+  if AKey = VK_CONTROL then result := StringReplace(AText, '%'+inttostr(AParam), rsCtrl, []) else
+  if AKey = VK_MENU then result := StringReplace(AText, '%'+inttostr(AParam), rsAlt, []) else
+  if AKey = VK_LWIN then result := StringReplace(AText, '%'+inttostr(AParam), rsCmd, []) else
+    result := AText;
+
+end;
+
+function ToolPopupMessageToStr(AMessage: TToolPopupMessage; AKey: Word = 0): string;
 begin
   case AMessage of
-  tpmHoldShiftForSquare: result := rsHoldShiftForSquare;
-  tpmHoldCtrlSnapToPixel: result := rsHoldCtrlSnapToPixel;
+  tpmHoldKeyForSquare: result := ReplaceKey(rsHoldKeyForSquare, AKey);
+  tpmHoldKeySnapToPixel: result := ReplaceKey(rsHoldKeySnapToPixel, AKey);
   tpmReturnValides: result := rsReturnValides;
   tpmBackspaceRemoveLastPoint: result := rsBackspaceRemoveLastPoint;
-  tpmCtrlRestrictRotation: result := rsCtrlRestrictRotation;
-  tpmAltShiftScaleMode: result := rsAltShiftScaleMode;
+  tpmHoldKeyRestrictRotation: result := ReplaceKey(rsHoldKeyRestrictRotation, AKey);
+  tpmHoldKeysScaleMode: result := ReplaceKey(ReplaceKey(rsHoldKeysScaleMode, AKey, 2), VK_MENU);
   tpmCurveModeHint: result := rsCurveModeHint;
   tpmBlendOpBackground: result := rsBlendOpNotUsedForBackground;
   tpmRightClickForSource: result := rsRightClickForSource;
@@ -501,6 +516,28 @@ begin
     result := Action.DrawingLayer;
 end;
 
+function TGenericTool.GetCurrentLayerKind: TLayerKind;
+var
+  c: TBGRALayerOriginalAny;
+begin
+  if not Manager.Image.LayerOriginalDefined[Manager.Image.CurrentLayerIndex] then
+  begin
+    if Manager.Image.CurrentLayerEmpty then exit(lkEmpty)
+    else exit(lkBitmap);
+  end else
+  if not Manager.Image.LayerOriginalKnown[Manager.Image.CurrentLayerIndex] then
+   exit(lkUnknown)
+  else
+  begin
+    c := Manager.Image.LayerOriginalClass[Manager.Image.CurrentLayerIndex];
+    if c = TVectorOriginal then exit(lkVectorial) else
+    if c = TBGRALayerImageOriginal then exit(lkTransformedBitmap) else
+    if c = TBGRALayerGradientOriginal then exit(lkGradient) else
+    if c = TBGRALayerSVGOriginal then exit(lkSVG) else
+      exit(lkOther);
+  end;
+end;
+
 function TGenericTool.GetAction: TLayerAction;
 begin
   if not Assigned(FAction) then
@@ -548,14 +585,6 @@ begin
 end;
 {$hints on}
 
-{$hints off}
-procedure TGenericTool.DoToolMoveAfter(pt: TPoint; ptF: TPointF);
-begin
-  //nothing
-end;
-
-{$hints on}
-
 constructor TGenericTool.Create(AManager: TToolManager);
 begin
   inherited Create;
@@ -711,21 +740,6 @@ begin
   result := DoToolMove(toolDest,ptF.Round,ptF);
 end;
 
-procedure TGenericTool.ToolMoveAfter(X, Y: single);
-var
-  pt: TPoint;
-  ptF: TPointF;
-begin
-  if FixLayerOffset then
-  begin
-    x -= LayerOffset.x;
-    y -= LayerOffset.y;
-  end;
-  pt := Point(round(x),round(y));
-  ptF := PointF(x,y);
-  DoToolMoveAfter(pt,ptF);
-end;
-
 {$hints off}
 function TGenericTool.ToolKeyDown(var key: Word): TRect;
 begin
@@ -1673,12 +1687,6 @@ begin
   if result then NotifyImageOrSelectionChanged(currentTool.LastToolDrawingLayer, changed);
 end;
 
-procedure TToolManager.ToolMoveAfter(X, Y: single); overload;
-begin
-  if ToolCanBeUsed then
-    currentTool.ToolMoveAfter(X,Y);
-end;
-
 function TToolManager.ToolKeyDown(var key: Word): boolean;
 var changed: TRect;
 begin
@@ -1796,10 +1804,10 @@ begin
     result := true;
 end;
 
-procedure TToolManager.ToolPopup(AMessage: TToolPopupMessage);
+procedure TToolManager.ToolPopup(AMessage: TToolPopupMessage; AKey: Word = 0);
 begin
   if Assigned(FOnPopupToolHandler) then
-    FOnPopupToolHandler(self, AMessage);
+    FOnPopupToolHandler(self, AMessage, AKey);
 end;
 
 function TToolManager.IsSelectingTool: boolean;
@@ -1845,11 +1853,6 @@ begin
   result := ToolMove(ACoord.x,ACoord.y,APressure)
 end;
 
-procedure TToolManager.ToolMoveAfter(coord: TPointF); overload;
-begin
-  ToolMoveAfter(coord.x,coord.y);
-end;
-
 initialization
   fillchar({%H-}PaintTools,sizeof(PaintTools),0);
 

+ 33 - 21
lazpaint/tools/utoolbasic.pas

@@ -15,14 +15,15 @@ type
   TToolHand = class(TReadonlyTool)
   protected
     handMoving: boolean;
-    handOrigin: TPoint;
+    handOriginF: TPointF;
     function FixSelectionTransform: boolean; override;
+    function FixLayerOffset: boolean; override;
     function DoToolDown({%H-}toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF;
       {%H-}rightBtn: boolean): TRect; override;
     function DoToolMove({%H-}toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF): TRect; override;
-    procedure DoToolMoveAfter(pt: TPoint; {%H-}ptF: TPointF); override;
     function GetStatusText: string; override;
   public
+    constructor Create(AManager: TToolManager); override;
     function ToolUp: TRect; override;
   end;
 
@@ -305,12 +306,11 @@ begin
     result := EmptyRect;
 end;
 
-function TToolPen.DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF
-  ): TRect;
+function TToolPen.DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect;
 begin
   if (manager.PenWidth <= 3) and not HintShowed then
   begin
-    Manager.ToolPopup(tpmHoldCtrlSnapToPixel);
+    Manager.ToolPopup(tpmHoldKeySnapToPixel, VK_SNAP);
     HintShowed:= true;
   end;
   if snapToPixel then ptF := PointF(pt.X,pt.Y);
@@ -326,11 +326,12 @@ end;
 constructor TToolPen.Create(AManager: TToolManager);
 begin
   inherited Create(AManager);
+  snapToPixel:= false;
 end;
 
 function TToolPen.ToolKeyDown(var key: Word): TRect;
 begin
-  if key = VK_CONTROL then
+  if key = VK_SNAP then
   begin
     snapToPixel := true;
     Key := 0;
@@ -340,7 +341,7 @@ end;
 
 function TToolPen.ToolKeyUp(var key: Word): TRect;
 begin
-  if key = VK_CONTROL then
+  if key = VK_SNAP then
   begin
     snapToPixel := false;
     key := 0;
@@ -415,6 +416,11 @@ begin
   Result:= false;
 end;
 
+function TToolHand.FixLayerOffset: boolean;
+begin
+  Result:= false;
+end;
+
 function TToolHand.DoToolDown(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF;
   rightBtn: boolean): TRect;
 begin
@@ -422,25 +428,25 @@ begin
   if not handMoving then
   begin
     handMoving := true;
-    handOrigin := pt;
+    handOriginF := ptF;
   end;
 end;
 
-function TToolHand.DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF
-  ): TRect;
+function TToolHand.DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect;
+var
+  newOfs: TPoint;
 begin
-  if handMoving and ((handOrigin.X <> pt.X) or (handOrigin.Y <> pt.Y)) then
+  result := EmptyRect;
+  if handMoving then
   begin
-    Manager.Image.ImageOffset := Point(Manager.Image.ImageOffset.X+pt.X-HandOrigin.X,
-                                       Manager.Image.ImageOffset.Y+pt.Y-HandOrigin.Y);
-    result := OnlyRenderChange;
-  end else
-    result := EmptyRect;
-end;
-
-procedure TToolHand.DoToolMoveAfter(pt: TPoint; ptF: TPointF);
-begin
-  if handMoving then handOrigin := pt;
+    newOfs := Point(Manager.Image.ImageOffset.X+round(ptF.X-HandOriginF.X),
+                    Manager.Image.ImageOffset.Y+round(ptF.Y-HandOriginF.Y));
+    if newOfs <> Manager.Image.ImageOffset then
+    begin
+      Manager.Image.ImageOffset := newOfs;
+      result := OnlyRenderChange;
+    end;
+  end;
 end;
 
 function TToolHand.GetStatusText: string;
@@ -479,6 +485,12 @@ begin
   end;
 end;
 
+constructor TToolHand.Create(AManager: TToolManager);
+begin
+  inherited Create(AManager);
+  handMoving := false;
+end;
+
 function TToolHand.ToolUp: TRect;
 begin
   handMoving := false;

+ 3 - 3
lazpaint/tools/utooldeformationgrid.pas

@@ -398,7 +398,7 @@ var n: integer;
 begin
   if not FHintShowed then
   begin
-    Manager.ToolPopup(tpmAltShiftScaleMode);
+    Manager.ToolPopup(tpmHoldKeysScaleMode, VK_SHIFT);
     FHintShowed:= true;
   end;
   result := EmptyRect;
@@ -576,7 +576,7 @@ begin
     key := 0;
   end
   else
-  if Key = VK_CONTROL then
+  if Key = VK_SNAP then
   begin
     snapToPixel:= true;
     key := 0;
@@ -614,7 +614,7 @@ end;
 function TToolTextureMapping.ToolKeyUp(var key: Word): TRect;
 begin
   result := EmptyRect;
-  if Key = VK_CONTROL then
+  if Key = VK_SNAP then
   begin
     snapToPixel:= false;
     key := 0;

+ 96 - 43
lazpaint/tools/utoollayer.pas

@@ -15,7 +15,10 @@ type
   TToolMoveLayer = class(TGenericTool)
   protected
     handMoving: boolean;
-    handOrigin: TPoint;
+    handOriginF: TPointF;
+    originalTransformBefore: TAffineMatrix;
+    layerOffsetBefore: TPoint;
+    snapToPixel: boolean;
     FStartLayerOffset: TPoint;
     FStartLayerMatrix: TAffineMatrix;
     FStartLayerOffsetDefined: boolean;
@@ -25,15 +28,17 @@ type
     function DoToolDown({%H-}toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF;
       {%H-}rightBtn: boolean): TRect; override;
     function DoToolMove({%H-}toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF): TRect; override;
-    procedure DoToolMoveAfter(pt: TPoint; {%H-}ptF: TPointF); override;
     function UseOriginal: boolean;
     procedure NeedLayerBounds;
     function GetAction: TLayerAction; override;
     function DoGetToolDrawingLayer: TBGRABitmap; override;
     procedure OnTryStop({%H-}sender: TCustomLayerAction); override;
+    function FixLayerOffset: boolean; override;
   public
+    constructor Create(AManager: TToolManager); override;
     function ToolUp: TRect; override;
     function ToolKeyDown(var key: Word): TRect; override;
+    function ToolKeyUp(var key: Word): TRect; override;
     function GetContextualToolbars: TContextualToolbars; override;
     function ToolCommand(ACommand: TToolCommand): boolean; override;
     function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
@@ -63,7 +68,7 @@ type
     FPreviousFilter: TResampleFilter;
     FTransforming: boolean;
     FPreviousMousePos: TPointF;
-    FCtrlDown: boolean;
+    FSnapDown: boolean;
     FLastUpdateRect: TRect;
     FLastUpdateRectDefined: boolean;
     FOriginalBounds: TRect;
@@ -152,46 +157,62 @@ begin
   if not handMoving then
   begin
     handMoving := true;
-    handOrigin := pt;
+    handOriginF := ptF;
+    idx := Manager.Image.CurrentLayerIndex;
     if not FStartLayerOffsetDefined then
     begin
       FStartLayerOffsetDefined := true;
-      idx := Manager.Image.CurrentLayerIndex;
       NeedLayerBounds;
       FStartLayerOffset := Manager.Image.LayerOffset[idx];
       FStartLayerMatrix := Manager.Image.LayerOriginalMatrix[idx];
     end;
-    if UseOriginal then Manager.Image.DraftOriginal := true;
+    if UseOriginal then
+    begin
+      Manager.Image.DraftOriginal := true;
+      originalTransformBefore := Manager.Image.LayerOriginalMatrix[idx];
+    end else
+      originalTransformBefore := AffineMatrixIdentity;
+    layerOffsetBefore := Manager.Image.LayerOffset[idx];
   end;
 end;
 
 function TToolMoveLayer.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF): TRect;
 var idx: integer;
-  prev: TPoint;
+  dx, dy: Single;
+  newTransform: TAffineMatrix;
+  newOfs: TPoint;
 begin
-  if handMoving and ((handOrigin.X <> pt.X) or (handOrigin.Y <> pt.Y)) then
+  result := EmptyRect;
+  if handMoving then
   begin
     idx := Manager.Image.CurrentLayerIndex;
+    dx := ptF.X-HandOriginF.X;
+    dy := ptF.Y-HandOriginF.Y;
+    if snapToPixel then
+    begin
+      dx := round(dx);
+      dy := round(dy);
+    end;
     if UseOriginal then
     begin
-      Manager.Image.LayerOriginalMatrix[idx] :=
-          AffineMatrixTranslation(pt.X-HandOrigin.X,pt.Y-HandOrigin.Y)*Manager.Image.LayerOriginalMatrix[idx];
-      result := OnlyRenderChange;
+      newTransform := AffineMatrixTranslation(dx,dy)*originalTransformBefore;
+      if Manager.Image.LayerOriginalMatrix[idx] <> newTransform then
+      begin
+        Manager.Image.LayerOriginalMatrix[idx] := newTransform;
+        result := OnlyRenderChange;
+      end;
     end else
     begin
-      prev := Manager.Image.LayerOffset[idx];
-      Manager.Image.SetLayerOffset(idx, Point(prev.X+pt.X-HandOrigin.X,
-                                         prev.Y+pt.Y-HandOrigin.Y), FLayerBounds);
-      result := OnlyRenderChange;
+      newOfs := Point(layerOffsetBefore.X+round(dx),
+                      layerOffsetBefore.Y+round(dy));
+      if Manager.Image.LayerOffset[idx]<>newOfs then
+      begin
+        Manager.Image.SetLayerOffset(idx, newOfs, FLayerBounds);
+        result := OnlyRenderChange;
+      end;
     end;
-  end else
-    result := EmptyRect;
-end;
-
-procedure TToolMoveLayer.DoToolMoveAfter(pt: TPoint; ptF: TPointF);
-begin
-  if handMoving then handOrigin := pt;
+  end;
 end;
 
 function TToolMoveLayer.UseOriginal: boolean;
@@ -240,6 +261,19 @@ begin
   //nothing
 end;
 
+function TToolMoveLayer.FixLayerOffset: boolean;
+begin
+  Result:= false;
+end;
+
+constructor TToolMoveLayer.Create(AManager: TToolManager);
+begin
+  inherited Create(AManager);
+  handMoving := false;
+  FStartLayerOffsetDefined:= false;
+  snapToPixel:= false;
+end;
+
 function TToolMoveLayer.ToolUp: TRect;
 begin
   handMoving := false;
@@ -256,6 +290,12 @@ begin
     result := EmptyRect;
     Key := 0;
   end
+  else if (key = VK_SNAP) or (key = VK_SNAP2) then
+  begin
+    snapToPixel:= true;
+    result := EmptyRect;
+    key := 0;
+  end
   else if key = VK_ESCAPE then
   begin
     if FStartLayerOffsetDefined then
@@ -274,6 +314,17 @@ begin
     Result:=inherited ToolKeyDown(key);
 end;
 
+function TToolMoveLayer.ToolKeyUp(var key: Word): TRect;
+begin
+  if (key = VK_SNAP) or (key = VK_SNAP2) then
+  begin
+    snapToPixel:= false;
+    result := EmptyRect;
+    key := 0;
+  end
+  else Result:=inherited ToolKeyUp(key);
+end;
+
 function TToolMoveLayer.GetContextualToolbars: TContextualToolbars;
 begin
   Result:= [];
@@ -320,9 +371,10 @@ begin
       m := AffineMatrixTranslation(-x,-y)*m;
   end else m := AffineMatrixIdentity;
 
-  ab := TAffineBox.AffineBox(BitmapToVirtualScreen(m*PointF(FLayerBounds.Left-0.499,FLayerBounds.Top-0.499)),
-            BitmapToVirtualScreen(m*PointF(FLayerBounds.Right-0.501,FLayerBounds.Top-0.499)),
-            BitmapToVirtualScreen(m*PointF(FLayerBounds.Left-0.499,FLayerBounds.Bottom-0.501)));
+  m := AffineMatrixTranslation(-0.5,-0.5)*m;
+  ab := TAffineBox.AffineBox(BitmapToVirtualScreen(m*PointF(FLayerBounds.Left+0.001,FLayerBounds.Top+0.001)),
+            BitmapToVirtualScreen(m*PointF(FLayerBounds.Right-0.001,FLayerBounds.Top+0.001)),
+            BitmapToVirtualScreen(m*PointF(FLayerBounds.Left+0.001,FLayerBounds.Bottom-0.001)));
   ptsF := ab.AsPolygon;
   setlength(pts, length(ptsF));
   for i := 0 to high(pts) do
@@ -401,7 +453,7 @@ begin
   begin
     FTransforming := true;
     FPreviousMousePos := ptF;
-    if FCtrlDown then
+    if FSnapDown then
     begin
       result := UpdateTransform;
       if IsRectEmpty(result) then result := OnlyRenderChange;
@@ -490,7 +542,7 @@ end;
 constructor TToolTransformLayer.Create(AManager: TToolManager);
 begin
   inherited Create(AManager);
-  FCtrlDown:= false;
+  FSnapDown:= false;
   FTransformCenterDefined := false;
   FLastUpdateRectDefined:= false;
 end;
@@ -530,9 +582,9 @@ end;
 
 function TToolTransformLayer.ToolKeyDown(var key: Word): TRect;
 begin
-  if key = VK_CONTROL then
+  if (key = VK_SNAP) or (KEY = VK_SNAP2) then
   begin
-    FCtrlDown:= true;
+    FSnapDown:= true;
     if FTransforming and CtrlChangesTransform then
     begin
       result := UpdateTransform;
@@ -559,9 +611,9 @@ end;
 
 function TToolTransformLayer.ToolKeyUp(var key: Word): TRect;
 begin
-  if key = VK_CONTROL then
+  if (key = VK_SNAP) or (KEY = VK_SNAP2) then
   begin
-    FCtrlDown := false;
+    FSnapDown := false;
     if FTransforming and CtrlChangesTransform then
     begin
       result := UpdateTransform;
@@ -597,9 +649,6 @@ var
   ptsRect: TRect;
 begin
   idx := Manager.Image.CurrentLayerIndex;
-  with Manager.Image.LayerOffset[idx] do
-    Result:= NicePoint(VirtualScreen,BitmapToVirtualScreen(TransformCenter-PointF(X,Y)));
-
   if not FOriginalBoundsDefined then
   begin
     if Manager.Image.LayerOriginalDefined[idx] then
@@ -618,10 +667,14 @@ begin
   m := Manager.Image.LayerOriginalMatrix[idx];
   with Manager.Image.LayerOffset[idx] do
     m := AffineMatrixTranslation(-x,-y)*m;
+  m := AffineMatrixTranslation(-0.5,-0.5)*m;
+
+  with Manager.Image.LayerOffset[idx] do
+    Result:= NicePoint(VirtualScreen,BitmapToVirtualScreen(TransformCenter-PointF(X,Y)));
 
-  ab := TAffineBox.AffineBox(BitmapToVirtualScreen(m*PointF(FOriginalBounds.Left-0.499,FOriginalBounds.Top-0.499)),
-            BitmapToVirtualScreen(m*PointF(FOriginalBounds.Right-0.501,FOriginalBounds.Top-0.499)),
-            BitmapToVirtualScreen(m*PointF(FOriginalBounds.Left-0.499,FOriginalBounds.Bottom-0.501)));
+  ab := TAffineBox.AffineBox(BitmapToVirtualScreen(m*PointF(FOriginalBounds.Left+0.001,FOriginalBounds.Top+0.001)),
+            BitmapToVirtualScreen(m*PointF(FOriginalBounds.Right-0.001,FOriginalBounds.Top+0.001)),
+            BitmapToVirtualScreen(m*PointF(FOriginalBounds.Left+0.001,FOriginalBounds.Bottom-0.001)));
   ptsF := ab.AsPolygon;
   setlength(pts, length(ptsF));
   for i := 0 to high(pts) do
@@ -650,7 +703,7 @@ var
   baseZoom: single;
   invZoom: boolean;
 begin
-  if FCtrlDown then
+  if FSnapDown then
   begin
     logZoom := ln(FZoom)/ln(2);
     if logZoom < 0 then
@@ -689,9 +742,9 @@ begin
   result := EmptyRect;
   NeedOriginal;
   Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] :=
-    AffineMatrixTranslation(TransformCenter.X,TransformCenter.Y)*
+    AffineMatrixTranslation(TransformCenter.X+0.5,TransformCenter.Y+0.5)*
     AffineMatrixScale(FActualZoom,FActualZoom)*
-    AffineMatrixTranslation(-TransformCenter.X,-TransformCenter.Y)*
+    AffineMatrixTranslation(-TransformCenter.X-0.5,-TransformCenter.Y-0.5)*
     FInitialOriginalMatrix;
 end;
 
@@ -740,7 +793,7 @@ end;
 
 function TToolRotateLayer.GetActualAngle: single;
 begin
-  if FCtrlDown then
+  if FSnapDown then
     result := round(FAngle/15)*15
   else
     result := FAngle;
@@ -798,9 +851,9 @@ begin
   result := EmptyRect;
   NeedOriginal;
   Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] :=
-    AffineMatrixTranslation(TransformCenter.X,TransformCenter.Y)*
+    AffineMatrixTranslation(TransformCenter.X+0.5,TransformCenter.Y+0.5)*
     AffineMatrixRotationDeg(FActualAngle)*
-    AffineMatrixTranslation(-TransformCenter.X,-TransformCenter.Y)*
+    AffineMatrixTranslation(-TransformCenter.X-0.5,-TransformCenter.Y-0.5)*
     FInitialOriginalMatrix;
 end;
 

+ 41 - 2
lazpaint/tools/utoolpolygon.pas

@@ -38,6 +38,8 @@ type
     procedure AssignShapeStyle(AMatrix: TAffineMatrix); override;
     procedure UpdateUserMode; virtual;
   public
+    function ToolKeyPress(var key: TUTF8Char): TRect; override;
+    function ToolKeyDown(var key: Word): TRect; override;
     function GetContextualToolbars: TContextualToolbars; override;
   end;
 
@@ -153,8 +155,16 @@ end;
 
 function TToolSpline.ToolKeyPress(var key: TUTF8Char): TRect;
 begin
-  Result:=inherited ToolKeyPress(key);
-  if Key='x' then Key := #0;
+  if (Key='z') or (Key = 'Z') then
+  begin
+    CurrentMode:= tsmMovePoint;
+    result := OnlyRenderChange;
+    Key := #0;
+  end else
+  begin
+    Result:=inherited ToolKeyPress(key);
+    if Key='x' then Key := #0;
+  end;
 end;
 
 function TToolSpline.GetContextualToolbars: TContextualToolbars;
@@ -186,6 +196,35 @@ begin
   if FQuickDefine then FShape.Usermode := vsuCreate;
 end;
 
+function TToolPolygon.ToolKeyPress(var key: TUTF8Char): TRect;
+var
+  keyCode: Word;
+begin
+  if (Key='i') or (Key='I') then
+  begin
+    keyCode := VK_INSERT;
+    ToolKeyDown(keyCode);
+    if keyCode = 0 then key := #0;
+    keyCode := VK_INSERT;
+    ToolKeyUp(keyCode);
+    result := EmptyRect;
+  end else
+    Result:=inherited ToolKeyPress(key);
+end;
+
+function TToolPolygon.ToolKeyDown(var key: Word): TRect;
+begin
+  if (key = VK_RETURN) and Assigned(FShape)
+   and (FShape.Usermode = vsuCreate) then
+  begin
+    FShape.Usermode:= vsuEdit;
+    result := OnlyRenderChange;
+    key := 0;
+    exit;
+  end else
+    Result:=inherited ToolKeyDown(key);
+end;
+
 function TToolPolygon.GetContextualToolbars: TContextualToolbars;
 begin
   Result:= [ctColor,ctTexture,ctShape,ctPenWidth,ctPenStyle,ctJoinStyle,ctLineCap];

+ 59 - 19
lazpaint/tools/utoolselect.pas

@@ -100,14 +100,17 @@ type
 
   TToolMoveSelection = class(TTransformSelectionTool)
   protected
-    handMoving: boolean;
-    handOrigin: TPoint;
+    handMoving, snapToPixel: boolean;
+    handOriginF: TPointF;
+    selectionTransformBefore: TAffineMatrix;
     function DoToolDown({%H-}toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF;
       {%H-}rightBtn: boolean): TRect; override;
     function DoToolMove({%H-}toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF): TRect; override;
-    procedure DoToolMoveAfter(pt: TPoint; {%H-}ptF: TPointF); override;
   public
+    constructor Create(AManager: TToolManager); override;
     function ToolUp: TRect; override;
+    function ToolKeyDown(var key: Word): TRect; override;
+    function ToolKeyUp(var key: Word): TRect; override;
     destructor Destroy; override;
   end;
 
@@ -272,7 +275,8 @@ begin
 
   if BigImage and FQuickDefine then
   begin
-    ab := TCustomRectShape(FShape).GetAffineBox(FEditor.Matrix, true);
+    ab := TCustomRectShape(FShape).GetAffineBox(
+      AffineMatrixTranslation(0.5,0.5)*FEditor.Matrix*AffineMatrixTranslation(-0.5,-0.5), false);
     abBounds := ab.RectBounds;
     abBounds.Inflate(1,1);
     result := RectUnion(result, abBounds);
@@ -281,7 +285,7 @@ begin
       ptsF := ab.AsPolygon;
       setlength(pts, length(ptsF));
       for i := 0 to high(ptsF) do
-        pts[i] := ptsF[i].Round;
+        pts[i] := (ptsF[i]+PointF(0.5,0.5)).Round;
       VirtualScreen.DrawPolygonAntialias(pts,BGRAWhite,BGRABlack,FrameDashLength);
     end;
   end;
@@ -314,7 +318,8 @@ begin
 
   if BigImage and FQuickDefine then
   begin
-    ab := TCustomRectShape(FShape).GetAffineBox(FEditor.Matrix, true);
+    ab := TCustomRectShape(FShape).GetAffineBox(
+      AffineMatrixTranslation(0.5,0.5)*FEditor.Matrix*AffineMatrixTranslation(-0.5,-0.5), false);
     abBounds := ab.RectBounds;
     abBounds.Inflate(1,1);
     result := RectUnion(result, abBounds);
@@ -393,7 +398,7 @@ var angleDiff: single;
 begin
   if not HintShowed then
   begin
-    Manager.ToolPopup(tpmCtrlRestrictRotation);
+    Manager.ToolPopup(tpmHoldKeyRestrictRotation, VK_SNAP);
     HintShowed:= true;
   end;
   if handMoving and ((handOrigin.X <> ptF.X) or (handOrigin.Y <> ptF.Y)) then
@@ -437,7 +442,7 @@ end;
 function TToolRotateSelection.ToolKeyDown(var key: Word): TRect;
 begin
   result := EmptyRect;
-  if key = VK_CONTROL then
+  if key = VK_SNAP then
   begin
     if not snapRotate then
     begin
@@ -467,7 +472,7 @@ end;
 
 function TToolRotateSelection.ToolKeyUp(var key: Word): TRect;
 begin
-  if key = VK_CONTROL then
+  if key = VK_SNAP then
   begin
     snapRotate := false;
     Key := 0;
@@ -500,31 +505,44 @@ end;
 function TToolMoveSelection.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF; rightBtn: boolean): TRect;
 begin
-  if not handMoving then
+  if not handMoving and not Manager.Image.SelectionMaskEmpty then
   begin
     handMoving := true;
-    handOrigin := pt;
+    handOriginF := ptF;
+    selectionTransformBefore := Manager.Image.SelectionTransform;
   end;
   result := EmptyRect;
 end;
 
 function TToolMoveSelection.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF): TRect;
-var dx,dy: integer;
+var dx,dy: single;
+  newSelTransform: TAffineMatrix;
 begin
   result := EmptyRect;
-  if handMoving and ((handOrigin.X <> pt.X) or (handOrigin.Y <> pt.Y)) then
+  if handMoving then
   begin
-    dx := pt.X-HandOrigin.X;
-    dy := pt.Y-HandOrigin.Y;
-    Manager.Image.SelectionTransform := AffineMatrixTranslation(dx,dy) * Manager.Image.SelectionTransform;
-    result := OnlyRenderChange;
+    dx := ptF.X-HandOriginF.X;
+    dy := ptF.Y-HandOriginF.Y;
+    if snapToPixel then
+    begin
+      dx := round(dx);
+      dy := round(dy);
+    end;
+    newSelTransform := AffineMatrixTranslation(dx,dy) * selectionTransformBefore;
+    if Manager.Image.SelectionTransform <> newSelTransform then
+    begin
+      Manager.Image.SelectionTransform := newSelTransform;
+      result := OnlyRenderChange;
+    end;
   end;
 end;
 
-procedure TToolMoveSelection.DoToolMoveAfter(pt: TPoint; ptF: TPointF);
+constructor TToolMoveSelection.Create(AManager: TToolManager);
 begin
-  if handMoving then handOrigin := pt;
+  inherited Create(AManager);
+  handMoving := false;
+  snapToPixel:= false;
 end;
 
 function TToolMoveSelection.ToolUp: TRect;
@@ -533,6 +551,28 @@ begin
   result := EmptyRect;
 end;
 
+function TToolMoveSelection.ToolKeyDown(var key: Word): TRect;
+begin
+  if (Key = VK_SNAP) or (Key = VK_SNAP2) then
+  begin
+    result := EmptyRect;
+    snapToPixel:= true;
+    key := 0;
+  end else
+    Result:=inherited ToolKeyDown(key);
+end;
+
+function TToolMoveSelection.ToolKeyUp(var key: Word): TRect;
+begin
+  if (Key = VK_SNAP) or (Key = VK_SNAP2) then
+  begin
+    result := EmptyRect;
+    snapToPixel:= false;
+    key := 0;
+  end else
+    Result:=inherited ToolKeyUp(key);
+end;
+
 destructor TToolMoveSelection.Destroy;
 begin
   if handMoving then handMoving := false;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 367 - 262
lazpaint/tools/utoolvectorial.pas


+ 143 - 17
lazpaint/ufilesystem.pas

@@ -28,11 +28,15 @@ const
 
   //more Linux file systems
   fsSysV = 'sysv';     // Unix System V
-  rsXFS = 'XFS';       //IRIX
-  rsJFS = 'JFS';       //AIX journaled file system
-  rsXiaFS = 'xiafs';   //extension of Minix file system
+  fsXFS = 'XFS';       //IRIX
+  fsJFS = 'JFS';       //AIX journaled file system
+  fsXiaFS = 'xiafs';   //extension of Minix file system
   fsReiserFS = 'Reiserfs';  //ReiserFS
 
+  //Apple file systems
+  fsAPFS = 'APFS';
+  fsHFS = 'HFS';
+
   //Misc
   fsHPFS = 'HPFS';     // OS/2 'High Performance File System'
   fsNWFS = 'NWFS';     // Novel NetWare File System
@@ -73,6 +77,7 @@ type
     function RemovePathTrail(ADir: string): string;
     procedure RemoveLastPathElement(var ADir: string; out ALastElement: string);
     function GetFileSystems: TFileSystemArray;
+    function CanGetFileSystems: boolean;
     function MoveToTrash(AForm: TForm; const AFilenamesUTF8: array of string; AConfirmationCallback: TDeleteConfirmationFunction): boolean;
     function CreateFileStream(AFilenameUTF8: string; AMode: Word): TStream; overload;
     procedure CancelStreamAndFree(AStream: TStream);
@@ -96,7 +101,7 @@ implementation
 uses BGRAUTF8, BGRAWinResource, BGRALazResource, LazFileUtils, Dialogs
 {$IFDEF WINDOWS}, Windows{$ENDIF}
 {$IFDEF LINUX}, Process{$ENDIF}
-;
+{$IFDEF DARWIN}, Process{$ENDIF};
 
 type
   TExtendedFilename = record
@@ -104,11 +109,29 @@ type
     SubFilename: string;
   end;
 
+procedure LinuxBundleToFileSystem(ABundle: string; out AFilesystem: string;
+      out ALongFilenames: boolean; out ACaseSensitive: boolean);
+begin
+  if (ABundle = 'ntfs') or (ABundle = 'fuseblk') then AFilesystem := fsNTFS else
+  if (ABundle = 'msdos') or (ABundle = 'umsdos') or (ABundle='vfat') then AFilesystem := fsFAT else
+  if ABundle = 'iso9660' then AFilesystem:= fsCDFS else
+  if ABundle = 'hpfs' then AFilesystem := fsHPFS else
+  if ABundle = 'udf' then AFilesystem := fsUDF else
+  if ABundle = 'ncp' then AFilesystem := fsNWFS else
+  if ABundle = 'apfs' then AFilesystem := fsAPFS else
+  if ABundle = 'hfs' then AFilesystem := fsHFS else
+  if ABundle = 'exfat' then AFilesystem := fsExFAT else
+    AFilesystem := ABundle;
+  ALongFilenames := (ABundle <> 'minix') and (ABundle <> 'msdos');
+  ACaseSensitive := (ABundle <> 'msdos') and (ABundle <> 'umsdos') and (ABundle <> 'vfat')
+                and (ABundle <> 'exfat');
+end;
+
 {$IFDEF LINUX}
-const LinuxFileSystems: array[0..20] of string =
+const LinuxFileSystems: array[0..21] of string =
  ('minix', 'ext2', 'ext3', 'ext4',
   'sysv', 'XFS', 'JFS', 'xiafs', 'Reiserfs',
-  {FAT} 'msdos', 'umsdos', 'vfat', {NTFS} 'ntfs', 'fuseblk',
+  {FAT} 'msdos', 'umsdos', 'vfat', 'exfat', {NTFS} 'ntfs', 'fuseblk',
   {CDFS} 'iso9660', {UDF} 'udf',
   {HPFS} 'hpfs', {NWFS} 'ncp',
   'nfs', 'smb', 'ncpfs');
@@ -179,10 +202,6 @@ begin
               fileSystem := lFileSystem;
               path := UnespacePath(parsedDesc[1]);
               device := parsedDesc[0];
-              longFilenames := (fileSystem <> 'minix') and
-                (fileSystem <> 'msdos');
-              caseSensitive := (fileSystem <> 'msdos') and
-                (fileSystem <> 'umsdos') and (fileSystem <> 'vfat');
               readonly:= (copy(parsedDesc[3],1,3) <> 'rw,') and (parsedDesc[3]<>'rw');
 
               //detecting device type
@@ -221,12 +240,7 @@ begin
                 name := ExtractFileName(path);
 
               //formatting file system
-              if (fileSystem = 'ntfs') or (fileSystem = 'fuseblk') then fileSystem := fsNTFS else
-              if (fileSystem = 'msdos') or (fileSystem = 'umsdos') or (fileSystem='vfat') then fileSystem := fsFAT else
-              if fileSystem = 'iso9660' then fileSystem:= fsCDFS else
-              if fileSystem = 'hpfs' then fileSystem := fsHPFS else
-              if fileSystem = 'udf' then fileSystem := fsUDF else
-              if fileSystem = 'ncp' then fileSystem := fsNWFS;
+              LinuxBundleToFileSystem(fileSystem, fileSystem, longFilenames, caseSensitive);
             end;
           end;
         end;
@@ -294,6 +308,105 @@ begin
 end;
 {$ENDIF}
 
+{$IFDEF DARWIN}
+var
+  darwinFilesystemsDate: TDateTime;
+  darwinFilesystemsCached: TFileSystemArray;
+
+function GetDarwinFileSystems: TFileSystemArray;
+  procedure FindDevices;
+  var
+    runResult, headers, curLine, fs, mountPath: string;
+    lines: TStringList;
+    blocksPos, mountedPos, i, endFS: integer;
+    count: integer;
+  begin
+    if not RunCommand('df',['-P'],runResult) then exit;
+    lines := TStringList.Create;
+    lines.Text:= runResult;
+    headers := lines[0];
+    blocksPos := pos('-blocks', headers);
+    mountedPos := pos('Mounted on', headers);
+    if (blocksPos <> 0) and (mountedPos <> 0) then
+    begin
+      inc(blocksPos, 5);
+      count := 0;
+      setlength(result, lines.Count-1);
+      for i := 1 to lines.Count-1 do
+      begin
+        curLine := lines[i];
+        endFS := blocksPos;
+        if endFS > length(curLine) then continue;
+        while (endFS > 1) and (curLine[endFS] in['0'..'9']) do dec(endFS);
+        while (endFS > 1) and (curLine[endFS] in[#0..#32]) do dec(endFS);
+        fs := copy(curLine,1,endFS);
+        if fs.StartsWith('/dev/') then
+        begin
+          mountPath := copy(curLine, mountedPos, length(curLine)-mountedPos+1);
+          if (mountPath <> '/var/vm') and (mountPath <> '/private/var/vm') then
+          begin
+            result[count].path := mountPath;
+            inc(count);
+          end;
+        end;
+      end;
+      setlength(result, count);
+    end;
+    lines.Free;
+  end;
+
+  procedure FetchDiskInfo(var fsi: TFileSystemInfo);
+  var
+    runResult, curLine, key, value: string;
+    lines: TStringList;
+    posColon: SizeInt;
+    i: Integer;
+  begin
+    if not RunCommand('diskutil',['info',fsi.path],runResult) then exit;
+    lines := TStringList.Create;
+    lines.Text:= runResult;
+    fsi.name:= '';
+    fsi.device := '?';
+    fsi.fileSystem := '?';
+    fsi.longFilenames:= true;
+    for i := 0 to lines.Count-1 do
+    begin
+      curLine := lines[i];
+      posColon := pos(':',curLine);
+      if posColon <> 0 then
+      begin
+        key := copy(curLine,1,posColon-1).TrimLeft;
+        value := copy(curLine,posColon+1,length(curLine)-posColon).Trim;
+        if key = 'Optical Drive Type' then fsi.device := rsCdRom else
+        if (key = 'Removable Media') and (fsi.device = '?') then
+        begin
+          if value = 'Fixed' then fsi.device := rsFixedDrive
+          else fsi.device := rsRemovableDrive;
+        end else
+        if key = 'Type (Bundle)' then
+        begin
+          LinuxBundleToFileSystem(value, fsi.fileSystem, fsi.longFilenames, fsi.caseSensitive);
+        end else
+        if key = 'Volume Name' then fsi.name:= value else
+        if key = 'Read-Only Volume' then fsi.readonly:= value='Yes';
+      end;
+    end;
+    lines.Free;
+  end;
+
+var i: integer;
+begin
+  if (darwinFilesystemsDate <> 0) and (Now < darwinFilesystemsDate + (10/(60*60*24))) then
+    exit(darwinFilesystemsCached);
+  result := nil;
+  FindDevices;
+  for i := 0 to high(result) do
+    FetchDiskInfo(result[i]);
+  darwinFilesystemsCached := result;
+  darwinFilesystemsDate:= Now;
+end;
+{$ENDIF}
+
 function TFileManager.RemovePathTrail(ADir: string): string;
 begin
   if (length(ADir)>=1) and (ADir[length(ADir)]=PathDelim) then
@@ -328,11 +441,24 @@ begin
     {$IFDEF WINDOWS}
     result := GetWindowsFileSystems;
     {$ELSE}
-    result := nil;
+      {$IFDEF DARWIN}
+      result := GetDarwinFileSystems;
+      {$ELSE}
+      result := nil;
+      {$ENDIF}
     {$ENDIF}
   {$ENDIF}
 end;
 
+function TFileManager.CanGetFileSystems: boolean;
+begin
+  {$IFDEF DARWIN}
+  result := true;
+  {$ELSE}
+  result := length(GetFileSystems)>0;
+  {$ENDIF}
+end;
+
 {$IFDEF WINDOWS}
 type
   {$PUSH}{$PACKRECORDS C}

+ 4 - 2
lazpaint/uimagepreview.pas

@@ -749,6 +749,7 @@ var reader: TFPCustomImageReader;
   jpegReader: TBGRAReaderJpeg;
   source: TStream;
   svg: TBGRASVG;
+  tr: TTiffError;
 begin
   if FInUpdatePreview then
   begin
@@ -775,8 +776,9 @@ begin
         begin
           try
             FTiff := TTiff.Create;
-            if FTiff.LoadFromStream(source) <> teNone then
-              raise exception.Create(rsCannotOpenFile);
+            tr := FTiff.LoadFromStream(source);
+            if tr <> teNone then
+              raise exception.Create(rsCannotOpenFile+' (TIFF '+inttostr(ord(tr))+')');
 
             FImageNbLayers := 1;
             if FTiff.Count = 0 then

+ 2 - 1
lazpaint/uimageview.pas

@@ -249,6 +249,7 @@ begin
     workArea := FLastPictureParameters.workArea;
     if (workArea.Right <= workArea.Left) or (workArea.Bottom <= workArea.Top) then exit;
     scaledArea := FLastPictureParameters.scaledArea;
+    IntersectRect(scaledArea, scaledArea,workArea);
     with PictureCanvas do
     begin
       Brush.Color := WorkspaceColor;
@@ -530,7 +531,7 @@ var virtualScreenPenCursorBefore: boolean;
       PtInRect(FLastPictureParameters.scaledArea, Point(X,Y)) then
     begin
       FPenCursorVisible := True;
-      wantedCursor := crNone;
+      {$IFNDEF DARWIN}wantedCursor := crNone;{$ENDIF}
       result := true;
     end else
       result := false;

+ 3 - 3
lazpaint/umenu.pas

@@ -372,7 +372,7 @@ begin
 end;
 
 procedure TMainFormMenu.Apply;
-const ImageBrowser = {$IFNDEF DARWIN}'FileUseImageBrowser,'{$ELSE}''{$ENDIF};
+const ImageBrowser = 'FileUseImageBrowser,';
 var i,j,tbHeight,tbHeightOrig: NativeInt;
 begin
   for i := 0 to FActionList.ActionCount-1 do
@@ -380,7 +380,7 @@ begin
     if (Caption = '') and (Hint <> '') then Caption := Hint;
 
   AddMenus('MenuFile',   'FileNew,FileOpen,LayerFromFile,FileChooseEntry,FileReload,MenuRecentFiles,-,FileSave,FileSaveAsInSameFolder,FileSaveAs,-,FileImport3D,-,FilePrint,-,'+ImageBrowser+'FileRememberSaveFormat,ForgetDialogAnswers,MenuLanguage,*');
-  AddMenus('MenuEdit',   'EditUndo,EditRedo,-,EditCut,EditCopy,EditPaste,EditPasteAsNew,EditPasteAsNewLayer,EditDeleteSelection,-,EditMoveUp,EditMoveToFront,EditMoveDown,EditMoveToBack,EditShapeAlign,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect');
+  AddMenus('MenuEdit',   'EditUndo,EditRedo,-,EditCut,EditCopy,EditPaste,EditPasteAsNew,EditPasteAsNewLayer,EditDeleteSelection,-,EditMoveUp,EditMoveToFront,EditMoveDown,EditMoveToBack,EditShapeAlign,EditShapeToCurve,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect');
   AddMenus('MenuSelect', 'EditSelection,FileLoadSelection,FileSaveSelectionAs,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect,-,ToolSelectRect,ToolSelectEllipse,ToolSelectPoly,ToolSelectSpline,-,ToolMoveSelection,ToolRotateSelection,SelectionHorizontalFlip,SelectionVerticalFlip,-,ToolSelectPen,ToolMagicWand');
   AddMenus('MenuView',   'ViewGrid,ViewZoomOriginal,ViewZoomIn,ViewZoomOut,ViewZoomFit,-,ViewToolBox,ViewColors,ViewPalette,ViewLayerStack,ViewImageList,ViewStatusBar,-,*,-,ViewDarkTheme,ViewWorkspaceColor,MenuIconSize');
   AddMenus('MenuImage',  'ImageCrop,ImageCropLayer,ImageFlatten,MenuRemoveTransparency,-,ImageNegative,ImageLinearNegative,ImageSwapRedBlue,-,ImageChangeCanvasSize,ImageRepeat,-,ImageResample,ImageSmartZoom3,-,ImageRotateCW,ImageRotateCCW,ImageHorizontalFlip,ImageVerticalFlip');
@@ -512,7 +512,7 @@ begin
   ActionShortcut('ToolHotSpot','H');
   ActionShortcut('ToolPen','P');
   ActionShortcut('ToolBrush','B');
-  ActionShortcut('ToolColorPicker','I');
+  ActionShortcut('ToolColorPicker','C');
   ActionShortcut('ToolEraser','E');
   ActionShortcut('ToolEditShape','J');
   ActionShortcut('ToolRect','U');

+ 8 - 4
lazpaint/uresourcestrings.pas

@@ -73,12 +73,16 @@ resourcestring
   rsLatestVersion = 'The latest version of LazPaint available online is';
   rsMustReleaseSelection = 'You must first release the selection';
   rsMustShowLayer = 'You must first make the layer visible';
-  rsHoldShiftForSquare = 'Hold SHIFT to draw a square or a circle';
-  rsHoldCtrlSnapToPixel = 'Hold CTRL to snap to pixels';
+  rsCtrl = 'CTRL';
+  rsAlt = 'ALT';
+  rsShift = 'SHIFT';
+  rsCmd = 'CMD';
+  rsHoldKeyForSquare = 'Hold %1 to draw a square or a circle';
+  rsHoldKeySnapToPixel = 'Hold %1 to snap to pixels';
   rsReturnValides = 'Press ENTER to validate';
   rsBackspaceRemoveLastPoint = 'Press BACKSPACE to remove last point';
-  rsCtrlRestrictRotation = 'Hold CTRL to restrict rotation angle';
-  rsAltShiftScaleMode = 'Hold ALT or SHIFT to scale';
+  rsHoldKeyRestrictRotation = 'Hold %1 to restrict rotation angle';
+  rsHoldKeysScaleMode = 'Hold %1 or %2 to scale';
   rsCurveModeHint = 'Press S or X to set the curve mode of the last point';
   rsBlendOpNotUsedForBackground = 'The blend operation is applied only if there is a layer underneath';
   rsRightClickForSource = 'Use RIGHT click to define source';

+ 7 - 3
lazpaint/utiff.pas

@@ -466,6 +466,8 @@ begin
 
   subError := LoadChunkList(AInput, TiffTagFreeOffsets, TiffTagFreeByteCounts, FFreeChunks);
   if subError <> teNone then Exit(subError);
+
+  result := teNone;
 end;
 
 procedure TTiffImageDirectory.SaveChunks(AOutput: TTiffIO);
@@ -1143,6 +1145,7 @@ begin
         AList.Add(mem);
     end;
   end;
+  result := teNone;
 end;
 
 procedure TTiffDirectory.SaveChunkList(AOutput: TTiffIO; ATagOffsets,
@@ -1365,15 +1368,15 @@ end;
 
 function TTiff.LoadImageEntries(var AInput: TTiffIO; AFirstImagePos: LongWord
   ): TTiffError;
-type TIntegerList = specialize TFPGList<integer>;
+type TLongwordList = specialize TFPGList<Longword>;
 var
   curImagePos, nextImagePos: LongWord;
-  previousPositions: TIntegerList;
+  previousPositions: TLongwordList;
   newEntry: TTiffImageDirectory;
   i: Integer;
   subError: TTiffError;
 begin
-  previousPositions := TIntegerList.Create;
+  previousPositions := TLongwordList.Create;
   try
     curImagePos := AFirstImagePos;
     repeat
@@ -1403,6 +1406,7 @@ begin
   finally
     previousPositions.Free;
   end;
+  result := teNone;
 end;
 
 constructor TTiff.Create;

+ 11 - 1
lazpaintcontrols/lazpaintcontrols.lpk

@@ -9,6 +9,16 @@
         <IncludeFiles Value="../resources"/>
         <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
       </SearchPaths>
+      <CodeGeneration>
+        <Optimizations>
+          <OptimizationLevel Value="3"/>
+        </Optimizations>
+      </CodeGeneration>
+      <Linking>
+        <Debugging>
+          <GenerateDebugInfo Value="False"/>
+        </Debugging>
+      </Linking>
     </CompilerOptions>
     <Version Minor="1"/>
     <Files Count="11">
@@ -55,7 +65,7 @@
       </Item10>
       <Item11>
         <Filename Value="lcvectorclipboard.pas"/>
-        <UnitName Value="lcvectorclipboard"/>
+        <UnitName Value="LCVectorClipboard"/>
       </Item11>
     </Files>
     <RequiredPkgs Count="4">

+ 74 - 2
lazpaintcontrols/lcvectorpolyshapes.pas

@@ -171,7 +171,10 @@ type
   public
     class function Usermodes: TVectorShapeUsermodes; override;
     constructor Create(AContainer: TVectorOriginal); override;
-    function AddPoint(const APoint: TPointF): integer; override;
+    constructor CreateFrom(AContainer: TVectorOriginal; AShape: TVectorShape);
+    class function CanCreateFrom(AShape: TVectorShape): boolean;
+    function AddPoint(const APoint: TPointF): integer; overload; override;
+    function AddPoint(const APoint: TPointF; AMode: TEasyBezierCurveMode): integer; overload;
     procedure KeyPress(UTF8Key: string; var AHandled: boolean); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
@@ -186,7 +189,7 @@ procedure ApplyArrowStyle(AArrow: TBGRACustomArrow; AStart: boolean; AKind: TArr
 implementation
 
 uses BGRAPen, BGRAFillInfo, BGRAPath, math, LCVectorialFill,
-  BGRAArrow;
+  BGRAArrow, LCVectorRectShapes;
 
 function StrToArrowKind(AStr: string): TArrowKind;
 var
@@ -1138,6 +1141,69 @@ begin
   FSplineStyle:= ssEasyBezier;
 end;
 
+constructor TCurveShape.CreateFrom(AContainer: TVectorOriginal;
+  AShape: TVectorShape);
+var
+  r: TCustomRectShape;
+  u, v: TPointF;
+  p: TCustomPolypointShape;
+  i: Integer;
+  f: TVectorShapeFields;
+  sq2m1: single;
+begin
+  Create(AContainer);
+  if AShape is TEllipseShape then
+  begin
+    r := AShape as TCustomRectShape;
+    u := r.XAxis-r.Origin;
+    v := r.YAxis-r.Origin;
+    sq2m1 := sqrt(2)-1;
+    AddPoint(r.Origin-v+u*sq2m1);
+    AddPoint(r.Origin-v*sq2m1+u);
+    AddPoint(r.Origin+v*sq2m1+u);
+    AddPoint(r.Origin+v+u*sq2m1);
+    AddPoint(r.Origin+v-u*sq2m1);
+    AddPoint(r.Origin+v*sq2m1-u);
+    AddPoint(r.Origin-v*sq2m1-u);
+    AddPoint(r.Origin-v-u*sq2m1);
+    Closed := true;
+  end else
+  if AShape is TRectShape then
+  begin
+    r := AShape as TCustomRectShape;
+    u := r.XAxis-r.Origin;
+    v := r.YAxis-r.Origin;
+    AddPoint(r.Origin-v-u, cmAngle);
+    AddPoint(r.Origin-v+u, cmAngle);
+    AddPoint(r.Origin+v+u, cmAngle);
+    AddPoint(r.Origin+v-u, cmAngle);
+    Closed := true;
+  end else
+  if AShape is TPolylineShape then
+  begin
+    p := AShape as TCustomPolypointShape;
+    for i := 0 to p.PointCount-1 do
+      AddPoint(p.Points[i], cmAngle);
+    Closed := p.Closed;
+  end else
+    raise exception.Create('Shape not handled');
+
+  f := AShape.Fields;
+  if vsfPenFill in f then PenFill.Assign(AShape.PenFill);
+  if vsfPenWidth in f then PenWidth := AShape.PenWidth;
+  if vsfPenStyle in f then PenStyle := AShape.PenStyle;
+  if vsfJoinStyle in f then JoinStyle := AShape.JoinStyle;
+  if vsfBackFill in f then BackFill.Assign(AShape.BackFill);
+end;
+
+class function TCurveShape.CanCreateFrom(AShape: TVectorShape): boolean;
+begin
+  result := (AShape is TEllipseShape) or
+    (AShape is TRectShape) or
+    ((AShape is TPolylineShape) and not
+     (AShape is TCurveShape));
+end;
+
 function TCurveShape.AddPoint(const APoint: TPointF): integer;
 begin
   if (PointCount > 1) and (APoint = Points[PointCount-1]) then
@@ -1150,6 +1216,12 @@ begin
   else Result:=inherited AddPoint(APoint);
 end;
 
+function TCurveShape.AddPoint(const APoint: TPointF; AMode: TEasyBezierCurveMode): integer;
+begin
+  result := inherited AddPoint(APoint);
+  CurveMode[result] := AMode;
+end;
+
 procedure TCurveShape.KeyPress(UTF8Key: string; var AHandled: boolean);
 var
   targetPoint: Integer;

Vissa filer visades inte eftersom för många filer har ändrats