소스 검색

Merge pull request #514 from bgrabitmap/dev-lazpaint

LazPaint v7.2 (testing)
circular17 3 년 전
부모
커밋
2bac451579
92개의 변경된 파일3795개의 추가작업 그리고 557개의 파일을 삭제
  1. 1 0
      lazpaint/dialog/filter/umotionblur.pas
  2. 1 1
      lazpaint/dialog/filter/utwirl.lfm
  3. 3 17
      lazpaint/dialog/ublendop.lfm
  4. 22 1
      lazpaint/dialog/ubrowseimages.pas
  5. 15 7
      lazpaint/dialog/ucanvassize.pas
  6. 4 1
      lazpaint/dialog/uchoosecolorinterface.pas
  7. 21 4
      lazpaint/dialog/ulayerstackinterface.pas
  8. 0 16
      lazpaint/dialog/unewimage.lfm
  9. 56 14
      lazpaint/dialog/unewimage.pas
  10. 42 53
      lazpaint/dialog/uprint.lfm
  11. 30 4
      lazpaint/image/uimage.pas
  12. 36 9
      lazpaint/image/uimageaction.pas
  13. 9 5
      lazpaint/lazpaint.lpi
  14. 1 1
      lazpaint/lazpaintdialogs.inc
  15. 1 1
      lazpaint/lazpaintembeddedpack.lpk
  16. 34 13
      lazpaint/lazpaintinstance.pas
  17. 835 59
      lazpaint/lazpaintmainform.lfm
  18. 14 0
      lazpaint/lazpaintmainform.lrj
  19. 132 32
      lazpaint/lazpaintmainform.pas
  20. 10 3
      lazpaint/lazpainttype.pas
  21. 124 4
      lazpaint/maintoolbar.inc
  22. 74 0
      lazpaint/release/bin/i18n/lazpaint.ar.po
  23. 74 0
      lazpaint/release/bin/i18n/lazpaint.bg.po
  24. 74 0
      lazpaint/release/bin/i18n/lazpaint.cs.po
  25. 75 1
      lazpaint/release/bin/i18n/lazpaint.de.po
  26. 74 0
      lazpaint/release/bin/i18n/lazpaint.es.po
  27. 74 0
      lazpaint/release/bin/i18n/lazpaint.fi.po
  28. 74 0
      lazpaint/release/bin/i18n/lazpaint.fr.po
  29. 74 0
      lazpaint/release/bin/i18n/lazpaint.it.po
  30. 74 0
      lazpaint/release/bin/i18n/lazpaint.ja.po
  31. 74 0
      lazpaint/release/bin/i18n/lazpaint.kab.po
  32. 74 0
      lazpaint/release/bin/i18n/lazpaint.lv.po
  33. 74 0
      lazpaint/release/bin/i18n/lazpaint.nl.po
  34. 74 0
      lazpaint/release/bin/i18n/lazpaint.pl.po
  35. 74 0
      lazpaint/release/bin/i18n/lazpaint.pot
  36. 74 0
      lazpaint/release/bin/i18n/lazpaint.pt_BR.po
  37. 172 116
      lazpaint/release/bin/i18n/lazpaint.ru.po
  38. 74 0
      lazpaint/release/bin/i18n/lazpaint.sv.po
  39. 74 0
      lazpaint/release/bin/i18n/lazpaint.zh_CN.po
  40. 1 1
      lazpaint/release/bin/i18n/lcresourcestring.ru.po
  41. 64 0
      lazpaint/release/debian/debian/changelog
  42. 1 1
      lazpaint/release/debian/debian/control
  43. 2 2
      lazpaint/release/macOS/LazPaint.app/Contents/Info.plist
  44. 1 1
      lazpaint/release/macOS/makedmg.sh
  45. 1 1
      lazpaint/release/windows/lazpaint.iss
  46. 92 14
      lazpaint/tools/utool.pas
  47. 9 3
      lazpaint/tools/utoolbasic.pas
  48. 12 1
      lazpaint/tools/utoolbrush.pas
  49. 115 40
      lazpaint/tools/utooldeformationgrid.pas
  50. 41 1
      lazpaint/tools/utoolpolygon.pas
  51. 9 3
      lazpaint/tools/utoolselect.pas
  52. 27 2
      lazpaint/tools/utooltext.pas
  53. 64 23
      lazpaint/tools/utoolvectorial.pas
  54. 1 1
      lazpaint/uchoosecolor.pas
  55. 41 13
      lazpaint/ucommandline.pas
  56. 16 11
      lazpaint/udarktheme.pas
  57. 1 0
      lazpaint/ufileextensions.pas
  58. 25 0
      lazpaint/ufilesystem.pas
  59. 34 10
      lazpaint/ugraph.pas
  60. 1 0
      lazpaint/uimagelist.pas
  61. 8 3
      lazpaint/uimageview.pas
  62. 1 0
      lazpaint/ulayerstack.pas
  63. 1 0
      lazpaint/uloading.pas
  64. 32 11
      lazpaint/umenu.pas
  65. 57 12
      lazpaint/umyslv.pas
  66. 1 0
      lazpaint/upalettetoolbar.pas
  67. 1 1
      lazpaint/upython.pas
  68. 7 1
      lazpaint/uresourcestrings.pas
  69. 1 1
      lazpaint/utoolbox.pas
  70. 11 3
      lazpaint/uzoom.pas
  71. 3 2
      lazpaintcontrols/lazpaintcontrols.lpk
  72. 9 0
      lazpaintcontrols/lcvectorialfillcontrol.pas
  73. 7 1
      lazpaintcontrols/lcvectorialfillinterface.pas
  74. 2 0
      lazpaintcontrols/lcvectororiginal.pas
  75. 78 13
      lazpaintcontrols/lcvectorpolyshapes.pas
  76. 2 1
      lazpaintcontrols/lcvectorrectshapes.pas
  77. 42 17
      lazpaintcontrols/lcvectortextshapes.pas
  78. 10 0
      resources/scripts/lazpaint/tools.py
  79. BIN
      resources/vector/textalignbottom32.lzp
  80. 27 0
      resources/vector/textalignbottom32.svg
  81. BIN
      resources/vector/textalignmiddle32.lzp
  82. 27 0
      resources/vector/textalignmiddle32.svg
  83. BIN
      resources/vector/textaligntop32.lzp
  84. 27 0
      resources/vector/textaligntop32.svg
  85. 8 0
      resources/vector/textbold32.svg
  86. 9 0
      resources/vector/textdirectionany32.svg
  87. 9 0
      resources/vector/textdirectionltr32.svg
  88. 9 0
      resources/vector/textdirectionrtl32.svg
  89. 9 0
      resources/vector/textitalic32.svg
  90. 7 0
      resources/vector/textstrikeout32.svg
  91. 9 0
      resources/vector/textunderline32.svg
  92. 1 1
      web/config.toml

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

@@ -245,6 +245,7 @@ end;
 procedure TFMotionBlur.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
   X, Y: Integer);
 begin
+  if not (ssLeft in Shift) then selectingAngle:= false;
   PaintBoxMouseMovePos := Point(X,Y);
   if InPaintBoxMouseMove then Exit;
   InPaintBoxMouseMove := True;

+ 1 - 1
lazpaint/dialog/filter/utwirl.lfm

@@ -83,7 +83,7 @@ object FTwirl: TFTwirl
       Font.Height = -15
       Increment = 30
       MaxValue = 10000
-      MinValue = 1
+      MinValue = -10000
       OnChange = SpinEdit_AngleChange
       ParentFont = False
       TabOrder = 1

+ 3 - 17
lazpaint/dialog/ublendop.lfm

@@ -12,7 +12,7 @@ object FBlendOp: TFBlendOp
   OnResize = FormResize
   OnShow = FormShow
   Position = poMainFormCenter
-  LCLVersion = '1.6.0.4'
+  LCLVersion = '2.2.0.1'
   object ListBox_PatternUnder: TListBox
     Left = 8
     Height = 248
@@ -39,7 +39,6 @@ object FBlendOp: TFBlendOp
     OnDrawItem = ListBox_DrawPatternItem
     OnMeasureItem = ListBox_MeasureItem
     OnSelectionChange = ListBox_PatternSelectionChange
-    ScrollWidth = 149
     Style = lbOwnerDrawFixed
     TabOrder = 0
   end
@@ -52,7 +51,6 @@ object FBlendOp: TFBlendOp
     Alignment = taCenter
     AutoSize = False
     Caption = 'Pattern under'
-    ParentColor = False
     ParentShowHint = False
     ShowHint = True
   end
@@ -82,7 +80,6 @@ object FBlendOp: TFBlendOp
     OnDrawItem = ListBox_DrawPatternItem
     OnMeasureItem = ListBox_MeasureItem
     OnSelectionChange = ListBox_PatternSelectionChange
-    ScrollWidth = 149
     Style = lbOwnerDrawFixed
     TabOrder = 1
   end
@@ -95,7 +92,6 @@ object FBlendOp: TFBlendOp
     Alignment = taCenter
     AutoSize = False
     Caption = 'Pattern over'
-    ParentColor = False
     ParentShowHint = False
     ShowHint = True
   end
@@ -124,7 +120,6 @@ object FBlendOp: TFBlendOp
     OnDrawItem = ListBox_DrawBlendItem
     OnMeasureItem = ListBox_MeasureItem
     OnSelectionChange = ListBox_BlendSelectionChange
-    ScrollWidth = 120
     Style = lbOwnerDrawFixed
     TabOrder = 2
   end
@@ -137,7 +132,6 @@ object FBlendOp: TFBlendOp
     Alignment = taCenter
     AutoSize = False
     Caption = 'Basic SVG'
-    ParentColor = False
     ParentShowHint = False
     ShowHint = True
   end
@@ -174,7 +168,6 @@ object FBlendOp: TFBlendOp
     OnDrawItem = ListBox_DrawBlendItem
     OnMeasureItem = ListBox_MeasureItem
     OnSelectionChange = ListBox_BlendSelectionChange
-    ScrollWidth = 156
     Style = lbOwnerDrawFixed
     TabOrder = 3
   end
@@ -187,7 +180,6 @@ object FBlendOp: TFBlendOp
     Alignment = taCenter
     AutoSize = False
     Caption = 'Krita'
-    ParentColor = False
     ParentShowHint = False
     ShowHint = True
   end
@@ -220,7 +212,6 @@ object FBlendOp: TFBlendOp
     OnDrawItem = ListBox_DrawBlendItem
     OnMeasureItem = ListBox_MeasureItem
     OnSelectionChange = ListBox_BlendSelectionChange
-    ScrollWidth = 114
     Style = lbOwnerDrawFixed
     TabOrder = 4
   end
@@ -233,7 +224,6 @@ object FBlendOp: TFBlendOp
     Alignment = taCenter
     AutoSize = False
     Caption = 'Other'
-    ParentColor = False
     ParentShowHint = False
     ShowHint = True
   end
@@ -244,7 +234,6 @@ object FBlendOp: TFBlendOp
     Width = 137
     Anchors = [akLeft, akBottom]
     Caption = 'Selected blend operation :'
-    ParentColor = False
   end
   object Label_BlendOpValue: TLabel
     Left = 152
@@ -253,7 +242,6 @@ object FBlendOp: TFBlendOp
     Width = 3
     Anchors = [akLeft, akBottom]
     Caption = '.'
-    ParentColor = False
   end
   object Button_OK: TButton
     Left = 192
@@ -286,7 +274,6 @@ object FBlendOp: TFBlendOp
     AutoSize = False
     Caption = 'Preview with'
     Font.Style = [fsBold]
-    ParentColor = False
     ParentFont = False
   end
   object Label_BlendOpCategory: TLabel
@@ -299,7 +286,6 @@ object FBlendOp: TFBlendOp
     AutoSize = False
     Caption = 'Category of blend operation'
     Font.Style = [fsBold]
-    ParentColor = False
     ParentFont = False
   end
   object ScrollBar1: TScrollBar
@@ -315,7 +301,7 @@ object FBlendOp: TFBlendOp
     Enabled = False
     Interval = 100
     OnTimer = TimerResizeTimer
-    left = 382
-    top = 288
+    Left = 382
+    Top = 288
   end
 end

+ 22 - 1
lazpaint/dialog/ubrowseimages.pas

@@ -194,10 +194,26 @@ var i: integer;
 begin
   if InFilenameChange then exit;
   InFilenameChange := true;
+  txt := trim(Edit_Filename.Text);
+  {$IFDEF WINDOWS}
+  if (length(txt) >= 3) and (upcase(txt[1]) in ['A'..'Z']) and (txt[2]=':') and (txt[3]='\') then
+  {$ELSE}
+  if (length(txt) >= 1) and (txt[1] = PathDelim) then
+  {$ENDIF}
+  begin
+    DirectoryEdit1.Text := ExtractFilePath(txt);
+    txt := ExtractFileName(txt);
+    Edit_Filename.Text := txt;
+  end else
+  if pos(PathDelim, txt) > 1 then
+  begin
+    DirectoryEdit1.Text := ConcatPaths([DirectoryEdit1.Text,ExtractFilePath(txt)]);
+    txt := ExtractFileName(txt);
+    Edit_Filename.Text := txt;
+  end;
   ShellListView1.DeselectAll;
   UpdatePreview('');
   first := true;
-  txt := trim(Edit_Filename.Text);
   for i := 0 to ShellListView1.ItemCount-1 do
     if UTF8CompareText(ShellListView1.ItemName[i],txt) = 0 then
     begin
@@ -1128,6 +1144,11 @@ begin
           if DefaultExtension <> '' then
             FFilename += DefaultExtension;
       end;
+      if not FileManager.IsValidFileName(ExtractFileName(FFilename)) and IsSaveDialog then
+      begin
+        ShowMessage(rsInvalidName);
+        exit;
+      end;
       if FileManager.FileExists(FFilename) and IsSaveDialog and OverwritePrompt then
       begin
         if QuestionDlg(rsSave, rsOverwriteFile, mtConfirmation, [mrOk, rsOkay, mrCancel, rsCancel],0) <> mrOk then exit;

+ 15 - 7
lazpaint/dialog/ucanvassize.pas

@@ -213,7 +213,7 @@ var
 begin
     case FMUnit of
     0: begin //pixels
-         tx:=SpinEdit_Width.Value;
+         tx:= SpinEdit_Width.Value;
          ty:= SpinEdit_Height.Value;
        end;
     1: begin //percent
@@ -246,18 +246,26 @@ begin
 end;
 
 procedure TFCanvasSize.ComboBox_MUnitChange(Sender: TObject);
+var
+  curWidth, curHeight: Integer;
 begin
   if FMUnit= ComboBox_MUnit.ItemIndex then exit;
   FMUnit:= ComboBox_MUnit.ItemIndex;
   FIgnoreInput:=True;
+  curWidth := SpinEdit_Width.Value;
+  curHeight := SpinEdit_Height.Value;
   case FMUnit of
-    0: begin //pixels
-         SpinEdit_Width.Value:=  round (LazPaintInstance.Image.Width*SpinEdit_Width.Value/100);
-         SpinEdit_Height.Value:= round (LazPaintInstance.Image.Height*SpinEdit_Height.Value/100);
+    0: begin //percent -> pixels
+         SpinEdit_Width.MaxValue := MaxImageWidth;
+         SpinEdit_Height.MaxValue := MaxImageHeight;
+         SpinEdit_Width.Value:=  round (LazPaintInstance.Image.Width*curWidth/100);
+         SpinEdit_Height.Value:= round (LazPaintInstance.Image.Height*curHeight/100);
        end;
-    1: begin //percent
-         SpinEdit_Width.Value:= round (SpinEdit_Width.Value/ LazPaintInstance.Image.Width*100);
-         SpinEdit_Height.Value:= round (SpinEdit_Height.Value/ LazPaintInstance.Image.Height*100);
+    1: begin //pixels -> percent
+         SpinEdit_Width.MaxValue := round(MaxImageWidth / LazPaintInstance.Image.Width * 100);
+         SpinEdit_Height.MaxValue := round(MaxImageHeight / LazPaintInstance.Image.Height * 100);
+         SpinEdit_Width.Value:= round (curWidth/ LazPaintInstance.Image.Width*100);
+         SpinEdit_Height.Value:= round (curHeight/ LazPaintInstance.Image.Height*100);
        end;
   end;
   FIgnoreInput:=False;

+ 4 - 1
lazpaint/dialog/uchoosecolorinterface.pas

@@ -579,7 +579,9 @@ end;
 
 procedure TChooseColorInterface.DoClick(X, Y: single);
 begin
-  if FColorCircle.Bounds.Contains(PointF(X,Y)) then
+  if FColorCircle.Bounds.Contains(PointF(X,Y)) and
+     (VectLen(PointF(X,Y) - FColorCircle.center) <=
+      max(FColorCircle.bounds.Width, FColorCircle.bounds.Height)/2 + DoScaleX(14, 96)) then
   begin
     FSelectZone := szColorCircle;
     DoSelect(X,Y);
@@ -1072,6 +1074,7 @@ begin
   EColor.Text:= '#FFFFFF';
   LColor.Visible := true;
   LColor.Caption := '#FFFFFF';
+  LColor.Hint := rsColorDescription;
   FCurrentColorFormatError:= false;
   vsColorView.Left := ExternalMargin;
   vsColorView.Top := 0;

+ 21 - 4
lazpaint/dialog/ulayerstackinterface.pas

@@ -200,13 +200,16 @@ procedure TLayerStackInterface.BGRALayerStack_MouseDown(Sender: TObject;
   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 var i: integer;
   str: string;
+  isRightClick: boolean;
 begin
   if Assigned(LazPaintInstance) then LazPaintInstance.ExitColorEditor;
   X := round(X*FScaling);
   Y := round(Y*FScaling);
   if PtInRect(Point(X,Y),FScrollButtonRect) then exit;
-  If (Button = mbLeft) then
+  isRightClick := (Button = mbRight) {$IFDEF DARWIN}or ((Button = mbLeft) and (ssCtrl in Shift)){$ENDIF};
+  If (Button = mbLeft) and not isRightClick then
   begin
+    FRightClickOrigin := EmptyPoint;
     if ((VolatileHorzScrollBar <> nil) and VolatileHorzScrollBar.MouseDown(X,Y)) or
       ((VolatileVertScrollBar <> nil) and VolatileVertScrollBar.MouseDown(X,Y)) then
     begin
@@ -266,7 +269,7 @@ begin
         exit;
       end;
   end else
-  if Button = mbRight then
+  if isRightClick then
     FRightClickOrigin := Point(X,Y);
 end;
 
@@ -302,6 +305,18 @@ begin
       BGRALayerStack.Hint := FLayerInfo[i].KindIconHint;
       BGRALayerStack.ShowHint:= true;
       exit;
+    end else
+    if FLayerInfo[i].VisibleCheckbox.Contains(Point(X,Y)) then
+    begin
+      BGRALayerStack.Hint := rsVisible;
+      BGRALayerStack.ShowHint:= true;
+      exit;
+    end else
+    if FLayerInfo[i].RightPart.OpacityBar.Contains(Point(X,Y)) then
+    begin
+      BGRALayerStack.Hint := rsOpacity;
+      BGRALayerStack.ShowHint:= true;
+      exit;
     end;
   BGRALayerStack.ShowHint:= false;
 end;
@@ -312,10 +327,12 @@ var destinationIndex, prevIndex, i: integer;
   indexF: single;
   res: TModalResult;
   topmostInfo: TTopMostInfo;
+  isRightClick: Boolean;
 begin
   X := round(X*FScaling);
   Y := round(Y*FScaling);
-  if Button = mbLeft then
+  isRightClick := (Button = mbRight) {$IFDEF DARWIN}or ((Button = mbLeft) and not IsEmptyPoint(FRightClickOrigin)){$ENDIF};
+  if (Button = mbLeft) and not isRightClick then
   begin
     FMovingItemStart := false;
     if FMovingItemBitmap <> nil then
@@ -362,7 +379,7 @@ begin
       FAskTransferSelectionLayerIndex := -1;
     end;
   end else
-  if (Button = mbRight) and (Abs(X - FRightClickOrigin.X) <= 2) and
+  if isRightClick and (Abs(X - FRightClickOrigin.X) <= 2) and
     (Abs(Y - FRightClickOrigin.Y) <= 2) then
   begin
     for i := 0 to high(FLayerInfo) do

+ 0 - 16
lazpaint/dialog/unewimage.lfm

@@ -116,22 +116,6 @@ object FNewImage: TFNewImage
     Top = 103
     Width = 63
     ItemHeight = 15
-    Items.Strings = (
-      ''
-      '1:1'
-      '6:5'
-      '5:4'
-      '4:3'
-      '11:8'
-      '1.414:1'
-      '1.43:1'
-      '3:2'
-      '8:5'
-      '1.618:1'
-      '5:3'
-      '16:9'
-      '2:1'
-    )
     MaxLength = 12
     OnChange = ComboBox_RatioChange
     OnEnter = ComboBox_RatioEnter

+ 56 - 14
lazpaint/dialog/unewimage.pas

@@ -14,6 +14,10 @@ const
   shadowOffsetX = 3;
   shadowOffsetY = 3;
   shadowBlur= 3;
+  defaultAspectRatios: array[0..12] of string =
+    ('1:1', '6:5', '5:4', '4:3', '11:8',
+     '1.414:1', '1.43:1', '3:2', '8:5',
+     '1.618:1', '5:3', '16:9', '2:1');
 
 type
   TLastEnteredValue = (valWidth,valHeight,valRatio);
@@ -73,6 +77,7 @@ type
     procedure ThemeChanged(Sender: TObject);
     procedure UpdatePreview;
     function GetBitDepth: integer;
+    procedure FillAspectRatios;
   public
     ForIcon: boolean;
     newImageResult: TBGRABitmap;
@@ -184,8 +189,6 @@ end;
 
 procedure TFNewImage.ToolButton_RotateClick(Sender: TObject);
 var tx,ty: integer;
-  s: string;
-  idxCol: integer;
 begin
   if FRecomputing then exit;
   FRecomputing:= true;
@@ -196,13 +199,7 @@ begin
   if FRatio <> 0 then
   begin
     FRatio := 1/FRatio;
-    s := ComboBox_Ratio.Text;
-    idxCol := pos(':',s);
-    if idxCol <> 0 then
-    begin
-      s := copy(s,idxCol+1,length(s)-idxCol)+':'+ copy(s,1,idxCol-1);
-      ComboBox_Ratio.Text := s;
-    end;
+    ComboBox_Ratio.Text := InverseRatio(ComboBox_Ratio.Text);
   end;
   FRecomputing:= false;
   if FLastEnteredValue = valWidth then
@@ -210,6 +207,7 @@ begin
   if FLastEnteredValue = valHeight then
     FLastEnteredValue:= valWidth;
   UpdatePreview;
+  FillAspectRatios;
 end;
 
 procedure TFNewImage.ComboBox_RatioChange(Sender: TObject);
@@ -268,11 +266,12 @@ begin
   end;
   FRecomputing:= false;
   UpdatePreview;
+  FillAspectRatios;
 end;
 
 procedure TFNewImage.ToolButton_ClearRatioClick(Sender: TObject);
 begin
-  ComboBox_Ratio.ItemIndex:= 0;
+  ComboBox_Ratio.Text := '';
   ComboBox_RatioChange(ComboBox_Ratio);
 end;
 
@@ -293,6 +292,10 @@ begin
 end;
 
 procedure TFNewImage.FormShow(Sender: TObject);
+var
+  currentRatio: single;
+  currentRatioStr: String;
+  currentRatioIdx, i: Integer;
 begin
   ToolBar_Rotate.Images := LazPaintInstance.Icons[DoScaleY(16,OriginalDPI)];
   ToolBar_Ratio.Images := ToolBar_Rotate.Images;
@@ -322,11 +325,34 @@ begin
     ComboBox_BitDepth.Visible := false;
     ComboBox_BitDepth.Text := '32';
   end;
-  if SpinEdit_Width.Value = SpinEdit_Height.Value then
+  FillAspectRatios;
+  FRatio := 0;
+  if SpinEdit_Height.Value <> 0 then
   begin
-    ComboBox_Ratio.Text := '1:1';
-    FRatio := ComputeRatio(ComboBox_Ratio.Text);
-    FLastEnteredValue := valRatio;
+    currentRatio := SpinEdit_Width.Value/SpinEdit_Height.Value;
+    currentRatioStr := RatioToStr(currentRatio);
+    currentRatioIdx := ComboBox_Ratio.Items.IndexOf(currentRatioStr);
+    if currentRatioIdx <> -1 then
+    begin
+      ComboBox_Ratio.Text := currentRatioStr;
+      FRatio := currentRatio;
+      FLastEnteredValue := valRatio;
+    end else
+    begin
+      for i := 0 to ComboBox_Ratio.Items.Count-1 do
+      begin
+        currentRatioStr := ComboBox_Ratio.Items[i];
+        currentRatio := ComputeRatio(currentRatioStr);
+        if (SpinEdit_Width.Value = round(SpinEdit_Height.Value*currentRatio)) or
+          (SpinEdit_Height.Value = round(SpinEdit_Width.Value/currentRatio)) then
+        begin
+          ComboBox_Ratio.Text := currentRatioStr;
+          FRatio := currentRatio;
+          FLastEnteredValue := valRatio;
+          break;
+        end;
+      end;
+    end;
   end;
   FRecomputing := false;
 
@@ -350,6 +376,7 @@ begin
   end;
   FRecomputing:= false;
   UpdatePreview;
+  FillAspectRatios;
 end;
 
 procedure TFNewImage.UpdatePreview;
@@ -381,6 +408,21 @@ begin
   result := StrToInt(ComboBox_BitDepth.Text);
 end;
 
+procedure TFNewImage.FillAspectRatios;
+var
+  aspect, rotatedAspect: String;
+begin
+  ComboBox_Ratio.Items.Clear;
+  for aspect in defaultAspectRatios do
+  begin
+    if SpinEdit_Width.Value >= SpinEdit_Height.Value then
+      rotatedAspect := aspect
+    else
+      rotatedAspect := InverseRatio(aspect);
+    ComboBox_Ratio.Items.add(rotatedAspect);
+  end;
+end;
+
 destructor TFNewImage.Destroy;
 begin
   if Assigned(FLazPaintInstance) then

+ 42 - 53
lazpaint/dialog/uprint.lfm

@@ -13,7 +13,7 @@ object FPrint: TFPrint
   OnShow = FormShow
   Position = poMainFormCenter
   ShowInTaskBar = stAlways
-  LCLVersion = '1.0.10.0'
+  LCLVersion = '2.2.0.1'
   object Label_PrinterAndPaper: TLabel
     Left = 9
     Height = 25
@@ -22,7 +22,6 @@ object FPrint: TFPrint
     AutoSize = False
     Caption = 'Printer and paper:'
     Layout = tlCenter
-    ParentColor = False
   end
   object Label_SelectedPrinterAndPaper: TLabel
     Cursor = crHandPoint
@@ -35,7 +34,6 @@ object FPrint: TFPrint
     Color = clWindow
     Font.Color = clWindowText
     Layout = tlCenter
-    ParentColor = False
     ParentFont = False
     Transparent = False
     OnClick = Label_SelectedPrinterAndPaperClick
@@ -51,39 +49,37 @@ object FPrint: TFPrint
     TabOrder = 0
   end
   object Label_Orientation: TLabel
-    Left = 12
-    Height = 16
+    Left = 9
+    Height = 15
     Top = 37
-    Width = 64
+    Width = 63
     Caption = 'Orientation:'
-    ParentColor = False
   end
   object ComboBox_Orientation: TComboBox
-    Left = 12
+    Left = 9
     Height = 23
     Top = 53
-    Width = 172
+    Width = 175
     ItemHeight = 15
     OnChange = ComboBox_OrientationChange
     Style = csDropDownList
     TabOrder = 1
   end
   object GroupBox_Margins: TGroupBox
-    Left = 12
+    Left = 8
     Height = 119
     Top = 79
-    Width = 174
+    Width = 178
     Caption = 'Margins'
-    ClientHeight = 101
-    ClientWidth = 170
+    ClientHeight = 99
+    ClientWidth = 174
     TabOrder = 2
     object Label_Left: TLabel
-      Left = 10
-      Height = 16
+      Left = 7
+      Height = 15
       Top = 27
-      Width = 24
+      Width = 23
       Caption = 'Left:'
-      ParentColor = False
     end
     object Label_Top: TLabel
       Left = 2
@@ -93,15 +89,13 @@ object FPrint: TFPrint
       Alignment = taRightJustify
       AutoSize = False
       Caption = 'Top:'
-      ParentColor = False
     end
     object Label_Right: TLabel
-      Left = 106
-      Height = 16
+      Left = 110
+      Height = 15
       Top = 27
-      Width = 32
+      Width = 31
       Caption = 'Right:'
-      ParentColor = False
     end
     object Label_Bottom: TLabel
       Left = 2
@@ -111,7 +105,6 @@ object FPrint: TFPrint
       Alignment = taRightJustify
       AutoSize = False
       Caption = 'Bottom:'
-      ParentColor = False
     end
     object SpinEdit_Top: TSpinEdit
       Left = 66
@@ -132,7 +125,7 @@ object FPrint: TFPrint
       Value = 10
     end
     object SpinEdit_Left: TSpinEdit
-      Left = 10
+      Left = 7
       Height = 23
       Top = 43
       Width = 56
@@ -141,7 +134,7 @@ object FPrint: TFPrint
       Value = 10
     end
     object SpinEdit_Right: TSpinEdit
-      Left = 106
+      Left = 110
       Height = 23
       Top = 43
       Width = 56
@@ -167,16 +160,16 @@ object FPrint: TFPrint
     OnResize = BGRAVirtualScreen1Resize
   end
   object GroupBox_ImageSize: TGroupBox
-    Left = 12
+    Left = 8
     Height = 157
     Top = 202
-    Width = 175
+    Width = 179
     Caption = 'Image size'
-    ClientHeight = 139
-    ClientWidth = 171
+    ClientHeight = 137
+    ClientWidth = 175
     TabOrder = 4
     object SpinEdit_DpiX: TSpinEdit
-      Left = 10
+      Left = 7
       Height = 23
       Top = 38
       Width = 56
@@ -188,23 +181,21 @@ object FPrint: TFPrint
       Value = 96
     end
     object Label_DpiX: TLabel
-      Left = 10
-      Height = 16
+      Left = 7
+      Height = 15
       Top = 22
-      Width = 4
+      Width = 3
       Caption = '.'
-      ParentColor = False
     end
     object Label_Width: TLabel
-      Left = 10
-      Height = 16
+      Left = 7
+      Height = 15
       Top = 63
-      Width = 36
+      Width = 35
       Caption = 'Width:'
-      ParentColor = False
     end
     object SpinEdit_Width: TSpinEdit
-      Left = 10
+      Left = 7
       Height = 23
       Top = 79
       Width = 72
@@ -215,15 +206,14 @@ object FPrint: TFPrint
       Value = 10
     end
     object Label_Height: TLabel
-      Left = 90
-      Height = 16
+      Left = 94
+      Height = 15
       Top = 63
-      Width = 40
+      Width = 39
       Caption = 'Height:'
-      ParentColor = False
     end
     object SpinEdit_Height: TSpinEdit
-      Left = 90
+      Left = 94
       Height = 23
       Top = 79
       Width = 72
@@ -234,16 +224,15 @@ object FPrint: TFPrint
       Value = 10
     end
     object Label_DpiY: TLabel
-      Left = 90
-      Height = 16
+      Left = 94
+      Height = 15
       Top = 22
-      Width = 4
+      Width = 3
       Caption = '.'
-      ParentColor = False
       Visible = False
     end
     object SpinEdit_DpiY: TSpinEdit
-      Left = 90
+      Left = 94
       Height = 23
       Top = 38
       Width = 56
@@ -256,7 +245,7 @@ object FPrint: TFPrint
       Visible = False
     end
     object CheckBox_Ratio: TCheckBox
-      Left = 10
+      Left = 7
       Height = 19
       Top = 3
       Width = 110
@@ -270,7 +259,7 @@ object FPrint: TFPrint
       Left = 7
       Height = 25
       Top = 110
-      Width = 155
+      Width = 161
       Caption = 'Zoom fit'
       OnClick = Button_ZoomFitClick
       TabOrder = 5
@@ -286,7 +275,7 @@ object FPrint: TFPrint
     TabOrder = 5
   end
   object PrinterSetupDialog1: TPrinterSetupDialog
-    left = 288
-    top = 120
+    Left = 288
+    Top = 120
   end
 end

+ 30 - 4
lazpaint/image/uimage.pas

@@ -31,6 +31,7 @@ type
   TOnStackChanged = procedure(ASender: TLazPaintImage; AScrollIntoView: boolean) of object;
   TImageExceptionHandler = procedure(AFunctionName: string; AException: Exception) of object;
   TOnCurrentFilenameChanged = procedure(ASender: TLazPaintImage) of object;
+  TOnRenderChanged = procedure(ASender: TLazPaintImage; AInvalidateAll: boolean) of object;
 
   TOnQueryExitToolHandler = procedure(sender: TLazPaintImage) of object;
 
@@ -39,6 +40,7 @@ type
   TLazPaintImage = class
   private
     FLazPaintInstance: TObject;
+    FZoom: TZoom;
     FActionInProgress: TCustomLayerAction;
     FOnActionProgress: TLayeredActionProgressEvent;
     FOnSelectedLayerIndexChanging: TOnCurrentLayerIndexChanged;
@@ -51,7 +53,7 @@ type
     FRenderedImage: TBGRABitmap;
     FRenderedImageInvalidated: TRect;
     FOnImageChanged, FOnImageSaving, FOnImageExport: TLazPaintImageObservable;
-    FOnImageRenderChanged: TNotifyEvent;
+    FOnImageRenderChanged: TOnRenderChanged;
     FUndoList: TComposedImageDifference;
     FUndoPos: integer;
     FRenderUpdateRectInPicCoord, FRenderUpdateRectInVSCoord: TRect;
@@ -126,6 +128,7 @@ type
     procedure SetOnActionProgress(AValue: TLayeredActionProgressEvent);
     procedure SetOnSizeChanged(AValue: TNotifyEvent);
     procedure SetSelectionTransform(ATransform: TAffineMatrix);
+    procedure SetZoom(AValue: TZoom);
     procedure UpdateIconFileUTF8(AFilename: string; AOutputFilename: string = ''; AExport: boolean = false);
     procedure UpdateTiffFileUTF8(AFilename: string; AOutputFilename: string = ''; AExport: boolean = false);
     procedure UpdateGifFileUTF8(AFilename: string; AOutputFilename: string = ''; AExport: boolean = false);
@@ -133,10 +136,10 @@ type
     procedure LayerActionNotifyChange({%H-}ASender: TObject; ALayer: TBGRABitmap; ARect: TRect);
     procedure LayerActionDestroy(Sender: TObject);
     procedure LayerActionNotifyUndo({%H-}ASender: TObject; AUndo: TCustomImageDifference; var Owned: boolean);
+    procedure ZoomOnCenterQuery(Sender: TObject);
   public
     OnException: TImageExceptionHandler;
     ImageOffset: TPoint;
-    Zoom: TZoom;
     CursorHotSpot: TPoint;
     BPP, FrameIndex, FrameCount: integer;
     VisibleArea: TRectF;
@@ -169,6 +172,7 @@ type
     procedure SelectionMaskMayChange(ARect: TRect);
     procedure SelectionMaskMayChangeCompletely;
     procedure RenderMayChange(ARect: TRect; APicCoords: boolean = false; ANotify: boolean = true);
+    procedure RenderMayChangeCompletely(ANotify: boolean = true);
     procedure ResetRenderUpdateRect;
 
     // selection mask
@@ -267,7 +271,7 @@ type
     property OnSelectedLayerIndexChanged: TOnCurrentLayerIndexChanged read FOnSelectedLayerIndexChanged write FOnSelectedLayerIndexChanged;
     property OnStackChanged: TOnStackChanged read FOnStackChanged write FOnStackChanged;
     property OnImageChanged: TLazPaintImageObservable read FOnImageChanged;
-    property OnImageRenderChanged: TNotifyEvent read FOnImageRenderChanged write FOnImageRenderChanged;
+    property OnImageRenderChanged: TOnRenderChanged read FOnImageRenderChanged write FOnImageRenderChanged;
     property OnImageSaving: TLazPaintImageObservable read FOnImageSaving;
     property OnImageExport: TLazPaintImageObservable read FOnImageExport;
     property OnSizeChanged: TNotifyEvent read FOnSizeChanged write SetOnSizeChanged;
@@ -298,6 +302,7 @@ type
     property RenderUpdateRectInPicCoord: TRect read FRenderUpdateRectInPicCoord;
     property RenderUpdateRectInVSCoord: TRect read FRenderUpdateRectInVSCoord;
     property SelectionTransform: TAffineMatrix read GetSelectionTransform write SetSelectionTransform;
+    property Zoom: TZoom read FZoom write SetZoom;
     property ZoomFactor: single read GetZoomFactor;
     property DraftOriginal: boolean read FDraftOriginal write SetDraftOriginal;
     property IsIconCursor: boolean read GetIsIconCursor;
@@ -352,6 +357,11 @@ begin
   OnImageChanged.NotifyObservers;
 end;
 
+procedure TLazPaintImage.ZoomOnCenterQuery(Sender: TObject);
+begin
+  ImageOffset := Point(0,0);
+end;
+
 function TLazPaintImage.MakeCroppedLayer: TBGRABitmap;
 var r: TRect;
   cropped: TBGRABitmap;
@@ -964,6 +974,14 @@ begin
   end;
 end;
 
+procedure TLazPaintImage.SetZoom(AValue: TZoom);
+begin
+  if FZoom=AValue then Exit;
+  if Assigned(FZoom) then FZoom.OnCenterQuery:= nil;
+  FZoom:=AValue;
+  if Assigned(FZoom) then FZoom.OnCenterQuery:=@ZoomOnCenterQuery;
+end;
+
 procedure TLazPaintImage.SetLayerName(AIndex: integer; AValue: string);
 begin
   AddUndo(FCurrentState.SetLayerName(AIndex,Avalue));
@@ -1253,6 +1271,7 @@ end;
 procedure TLazPaintImage.ImageMayChangeCompletely;
 begin
   ImageMayChange(rect(0,0,Width,Height));
+  RenderMayChangeCompletely;
 end;
 
 procedure TLazPaintImage.LayerMayChange(ALayer: TBGRABitmap; ARect: TRect);
@@ -1325,7 +1344,14 @@ begin
   else
      FRenderUpdateRectInVSCoord := RectUnion(FRenderUpdateRectInVSCoord,ARect);
   if ANotify and Assigned(OnImageRenderChanged) then
-    OnImageRenderChanged(self);
+    OnImageRenderChanged(self, false);
+end;
+
+procedure TLazPaintImage.RenderMayChangeCompletely(ANotify: boolean);
+begin
+  FRenderUpdateRectInPicCoord := rect(-MaxLongint div 2,-MaxLongint div 2,MaxLongint div 2,MaxLongint div 2);
+  if ANotify and Assigned(OnImageRenderChanged) then
+    OnImageRenderChanged(self, true);
 end;
 
 procedure TLazPaintImage.LayerBlendMayChange(AIndex: integer);

+ 36 - 9
lazpaint/image/uimageaction.pas

@@ -20,7 +20,7 @@ type
     function GetCurrentTool: TPaintToolType;
     function GetImage: TLazPaintImage;
     function GetToolManager: TToolManager;
-    procedure ChooseTool(ATool: TPaintToolType);
+    procedure ChooseTool(ATool: TPaintToolType; AAsFromGui: boolean = true);
     procedure RegisterScripts(ARegister: Boolean);
     function GenericScriptFunction(AVars: TVariableSet): TScriptResult;
     function ScriptGetAllLayersId(AVars: TVariableSet): TScriptResult;
@@ -131,9 +131,9 @@ begin
   result := FInstance.ToolManager;
 end;
 
-procedure TImageActions.ChooseTool(ATool: TPaintToolType);
+procedure TImageActions.ChooseTool(ATool: TPaintToolType; AAsFromGui: boolean);
 begin
-  FInstance.ChooseTool(ATool);
+  FInstance.ChooseTool(ATool, AAsFromGui);
 end;
 
 procedure TImageActions.RegisterScripts(ARegister: Boolean);
@@ -805,8 +805,11 @@ begin
 end;
 
 procedure TImageActions.Undo;
+var
+  prevTool: TPaintToolType;
 begin
   try
+    prevTool := CurrentTool;
     if CurrentTool in[ptMoveSelection,ptRotateSelection] then ChooseTool(ptHand);
     if ToolManager.ToolProvideCommand(tcFinish) then ToolManager.ToolCommand(tcFinish);
     if image.CanUndo then
@@ -815,6 +818,9 @@ begin
       image.Undo;
       ToolManager.ToolOpen;
     end;
+    if (prevTool in[ptMoveSelection,ptRotateSelection]) and
+      not image.SelectionMaskEmpty then
+      ChooseTool(prevTool, false);
   except
     on ex:Exception do
       FInstance.ShowError('Undo',ex.Message);
@@ -822,8 +828,11 @@ begin
 end;
 
 procedure TImageActions.Redo;
+var
+  prevTool: TPaintToolType;
 begin
   try
+    prevTool := CurrentTool;
     if CurrentTool in[ptLayerMapping,ptMoveSelection,ptRotateSelection] then
       ChooseTool(ptHand);
     if image.CanRedo then
@@ -832,6 +841,9 @@ begin
       image.Redo;
       ToolManager.ToolOpen;
     end;
+    if (prevTool in[ptMoveSelection,ptRotateSelection]) and
+      not image.SelectionMaskEmpty then
+      ChooseTool(prevTool, false);
   except
     on ex:Exception do
       FInstance.ShowError('Redo',ex.Message);
@@ -938,7 +950,7 @@ begin
     if Assigned(ALoadedImage) and Assigned(ALoadedImage^.bmp) then
     begin
       newSelection := ALoadedImage^.bmp;
-      ALoadedImage^.FreeAndNil;
+      ALoadedImage^.Release;
     end
     else
       newSelection := LoadFlatImageUTF8(AFilenameUTF8).bmp;
@@ -952,7 +964,7 @@ begin
       LayerAction.RemoveSelection;
       LayerAction.QuerySelection;
       LayerAction.CurrentSelection.PutImage(0,0,newSelection,dmSet);
-      LayerAction.NotifyChange(Image.SelectionMask,Image.SelectionMaskBounds);
+      LayerAction.NotifyChange(Image.SelectionMask,rect(0,0,newSelection.Width,newSelection.Height));
       LayerAction.Validate;
       result := true;
     end;
@@ -1541,10 +1553,24 @@ end;
 
 procedure TImageActions.DeleteSelection;
 var LayerAction: TLayerAction;
-  doErase: Boolean;
+  doErase, wasSelecting: Boolean;
+  prevTool: TPaintToolType;
 begin
-  if image.SelectionMaskEmpty then exit;
-  if not image.CheckNoAction then exit;
+  if image.SelectionMaskEmpty then
+  begin
+    prevTool := ToolManager.GetCurrentToolType;
+    if (prevTool in [ptMoveLayer, ptZoomLayer, ptRotateLayer])
+       and (image.NbLayers > 1) then
+    begin
+      ChooseTool(ptHand, false);
+      Image.RemoveLayer;
+      ChooseTool(prevTool, false);
+    end;
+    exit;
+  end;
+  wasSelecting := ToolManager.GetCurrentToolType in [ptSelectPen..ptSelectSpline];
+  if wasSelecting then ToolManager.ToolCloseDontReopen
+  else if not image.CheckNoAction then exit;
   LayerAction := nil;
   try
     doErase := Image.SelectionLayerIsEmpty;
@@ -1557,7 +1583,8 @@ begin
       FInstance.ShowError('DeleteSelection',ex.Message);
   end;
   LayerAction.Free;
-  if (CurrentTool = ptRotateSelection) or
+  if wasSelecting then ToolManager.ToolOpen
+  else if (CurrentTool = ptRotateSelection) or
      (CurrentTool = ptMoveSelection) then
     ChooseTool(ptHand);
 end;

+ 9 - 5
lazpaint/lazpaint.lpi

@@ -25,8 +25,7 @@
     <VersionInfo>
       <UseVersionInfo Value="True"/>
       <MajorVersionNr Value="7"/>
-      <MinorVersionNr Value="1"/>
-      <RevisionNr Value="6"/>
+      <MinorVersionNr Value="2"/>
       <CharSet Value="04B0"/>
       <StringTable CompanyName="http://sourceforge.net/projects/lazpaint/" FileDescription="LazPaint" InternalName="lazpaint" OriginalFilename="lazpaint.exe" ProductName="LazPaint"/>
     </VersionInfo>
@@ -413,14 +412,15 @@
     <RequiredPackages Count="5">
       <Item1>
         <PackageName Value="BGRABitmapPack"/>
-        <MinVersion Major="11" Minor="3" Release="1" Valid="True"/>
+        <MinVersion Major="11" Minor="5" Valid="True"/>
       </Item1>
       <Item2>
         <PackageName Value="bgracontrols"/>
-        <MinVersion Major="7" Minor="1" Valid="True"/>
+        <MinVersion Major="7" Minor="5" Valid="True"/>
       </Item2>
       <Item3>
         <PackageName Value="lazpaintcontrols"/>
+        <MinVersion Minor="2" Valid="True"/>
       </Item3>
       <Item4>
         <PackageName Value="Printer4Lazarus"/>
@@ -429,7 +429,7 @@
         <PackageName Value="LCL"/>
       </Item5>
     </RequiredPackages>
-    <Units Count="106">
+    <Units Count="107">
       <Unit0>
         <Filename Value="lazpaint.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -1052,6 +1052,10 @@
         <IsPartOfProject Value="True"/>
         <UnitName Value="UIconCache"/>
       </Unit105>
+      <Unit106>
+        <Filename Value="getfilesindir.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit106>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

+ 1 - 1
lazpaint/lazpaintdialogs.inc

@@ -123,7 +123,7 @@ begin
       ScriptContext.RecordingFunctionParameters.AddPixel('BackColor', bitmapRepl.GetPixel(0,0));
     end;
   end;
-  ChooseTool(ptHand);
+  ChooseTool(ptHand, true);
   image.Assign(bitmapRepl, True, False);
   Image.CurrentFilenameUTF8 := '';
   image.SetSavedFlag(0,-1,0);

+ 1 - 1
lazpaint/lazpaintembeddedpack.lpk

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

+ 34 - 13
lazpaint/lazpaintinstance.pas

@@ -213,7 +213,7 @@ type
     procedure Show; override;
     function Hide: boolean; override;
     procedure Run; override;
-    procedure Restart; override;
+    function Restart: boolean; override;
     procedure CancelRestart; override;
     destructor Destroy; override;
     procedure NotifyImageChange(RepaintNow: boolean; ARect: TRect); override;
@@ -268,7 +268,7 @@ type
     procedure InvalidateLayerStack; override;
     procedure UpdateLayerStackOnTimer; override;
     function MakeNewBitmapReplacement(AWidth, AHeight: integer; AColor: TBGRAPixel): TBGRABitmap; override;
-    procedure ChooseTool(Tool : TPaintToolType); override;
+    procedure ChooseTool(Tool : TPaintToolType; AAsFromGui: boolean); override;
     function OpenImage (FileName: string; AddToRecent: Boolean= True): boolean; override;
     procedure AddToImageList(const FileNames: array of String); override;
     procedure UpdateToolbar; override;
@@ -1263,6 +1263,7 @@ begin
     if bmp <> nil then subLaz.AssignBitmap(bmp);
     subLaz.AboutText := AboutText;
     subLaz.EmbeddedImageBackup := bmp;
+    subLaz.FMain.BorderIcons := subLaz.FMain.BorderIcons - [biMinimize];
     if AOnRun <> nil then
       AOnRun(subLaz);
     subLaz.Run;
@@ -1283,7 +1284,11 @@ begin
       ShowError('EditBitmap',ex.Message);
   end;
   ShowTopmost(topmostInfo);
-  if FMain <> nil then FMain.Enabled := true;
+  if FMain <> nil then
+  begin
+    FMain.Enabled := true;
+    FMain.BringToFront;
+  end;
   subLaz.Free;
 end;
 
@@ -1521,11 +1526,15 @@ begin
 end;
 
 procedure TLazPaintInstance.ChangeIconSize(size: integer);
+var
+  prevSize: Integer;
 begin
   if Config.DefaultIconSize(0)<>size then
   begin
+    prevSize := Config.DefaultIconSize(0);
     Config.SetDefaultIconSize(size);
-    Restart;
+    if not Restart then
+      Config.SetDefaultIconSize(prevSize);
   end;
 end;
 
@@ -1550,18 +1559,20 @@ procedure TLazPaintInstance.Run;
 begin
   if not MainFormVisible then Show;
   repeat
-    application.ProcessMessages;
-    Sleep(10);
-  until not MainFormVisible;
+    Application.ProcessMessages;
+    if not Application.Terminated then Application.Idle(True);
+  until not MainFormVisible or Application.Terminated;
 end;
 
-procedure TLazPaintInstance.Restart;
+function TLazPaintInstance.Restart: boolean;
 begin
   if FMain <> nil then
   begin
     FRestartQuery := true;
     FMain.Close;
-  end;
+    result := FRestartQuery;
+  end else
+    result := true;
 end;
 
 procedure TLazPaintInstance.CancelRestart;
@@ -1598,7 +1609,9 @@ begin
   begin
     Config.SetDefaultToolboxWindowVisible(ToolboxVisible or (FTopMostInfo.toolboxHidden > 0));
     Config.SetDefaultToolboxWindowPosition(FFormToolbox.BoundsRect);
-  end;
+  end else
+  if Assigned(FMain) then
+    Config.SetDefaultToolboxWindowVisible(FMain.Layout.ToolBoxVisible);
   ToolManager.SaveToConfig;
 
   BGRALayers.UnregisterLoadingHandler(@OnLayeredBitmapLoadStartHandler,@OnLayeredBitmapLoadProgressHandler,@OnLayeredBitmapLoadedHandler);
@@ -1875,9 +1888,17 @@ begin
 end;
 
 procedure TLazPaintInstance.ColorToFChooseColor;
+var
+  c: TBGRAPixel;
 begin
   if not Assigned(FChooseColor) or InColorFromFChooseColor then exit;
-  FChooseColor.SetCurrentColor(GetColor(FChooseColor.ColorTarget));
+  c := GetColor(FChooseColor.ColorTarget);
+  if (c.alpha = 0) and (FChooseColor.ColorTarget in [ctForeColorSolid, ctBackColorSolid, ctOutlineColorSolid]) then
+  begin
+    c := FChooseColor.GetCurrentColor;
+    c.alpha := 0;
+  end;
+  FChooseColor.SetCurrentColor(c);
 end;
 
 procedure TLazPaintInstance.ExitColorEditor;
@@ -1983,10 +2004,10 @@ begin
   result := TBGRABitmap.Create(AWidth,AHeight, AColor);
 end;
 
-procedure TLazPaintInstance.ChooseTool(Tool: TPaintToolType);
+procedure TLazPaintInstance.ChooseTool(Tool: TPaintToolType; AAsFromGui: boolean);
 begin
   FormsNeeded;
-  if Assigned(FMain) then FMain.ChooseTool(Tool);
+  if Assigned(FMain) then FMain.ChooseTool(Tool, AAsFromGui);
 end;
 
 function TLazPaintInstance.GetToolboxHeight: integer;

+ 835 - 59
lazpaint/lazpaintmainform.lfm

@@ -218,7 +218,7 @@ object FMain: TFMain
   object Panel_PenWidth: TPanel
     Left = 608
     Height = 36
-    Top = 144
+    Top = 56
     Width = 105
     ClientHeight = 36
     ClientWidth = 105
@@ -470,7 +470,7 @@ object FMain: TFMain
   object Panel_Tolerance: TPanel
     Left = 279
     Height = 36
-    Top = 296
+    Top = 336
     Width = 140
     ClientHeight = 36
     ClientWidth = 140
@@ -932,6 +932,7 @@ object FMain: TFMain
     object ComboBox_ArrowStart: TBCComboBox
       Left = 2
       Height = 21
+      Hint = 'Starting arrow'
       Top = 1
       Width = 43
       ItemIndex = -1
@@ -1036,6 +1037,7 @@ object FMain: TFMain
     object ComboBox_ArrowEnd: TBCComboBox
       Left = 47
       Height = 21
+      Hint = 'Ending arrow'
       Top = 1
       Width = 43
       ItemIndex = -1
@@ -1308,7 +1310,7 @@ object FMain: TFMain
   object Panel_Grid: TPanel
     Left = 424
     Height = 36
-    Top = 296
+    Top = 336
     Width = 172
     ClientHeight = 36
     ClientWidth = 172
@@ -1513,7 +1515,7 @@ object FMain: TFMain
   object Panel_PenWidthPreview: TPanel
     Left = 608
     Height = 104
-    Top = 176
+    Top = 92
     Width = 106
     BevelOuter = bvNone
     ClientHeight = 104
@@ -1526,7 +1528,7 @@ object FMain: TFMain
     object PaintBox_PenPreview: TPaintBox
       Left = 6
       Height = 91
-      Top = 6
+      Top = 7
       Width = 93
       Font.Height = -12
       ParentFont = False
@@ -1752,6 +1754,7 @@ object FMain: TFMain
     ParentColor = False
     ParentFont = False
     TabOrder = 19
+    OnMouseMove = Panel_TextMouseMove
     object Label_Text: TLabel
       Left = 4
       Height = 22
@@ -1762,6 +1765,7 @@ object FMain: TFMain
       Font.Height = -12
       Layout = tlCenter
       ParentFont = False
+      OnMouseMove = Panel_TextMouseMove
     end
     object ToolBar15: TToolBar
       Left = 85
@@ -1775,17 +1779,20 @@ object FMain: TFMain
       Images = ImageList16
       ParentFont = False
       TabOrder = 0
+      OnMouseMove = Panel_TextMouseMove
       object Tool_TextFont: TToolButton
         Left = 1
         Hint = 'Choose font...'
         Top = 0
         ImageIndex = 61
+        OnMouseMove = Panel_TextMouseMove
       end
       object Tool_TextPhong: TToolButton
         Left = 93
         Hint = 'Text phong shading'
         Top = 0
         ImageIndex = 74
+        OnMouseMove = Panel_TextMouseMove
         Style = tbsCheck
       end
       object Tool_TextAlignLeft: TToolButton
@@ -1795,6 +1802,7 @@ object FMain: TFMain
         Down = True
         Grouped = True
         ImageIndex = 84
+        OnMouseMove = Panel_TextMouseMove
         Style = tbsCheck
       end
       object Tool_TextAlignCenter: TToolButton
@@ -1803,6 +1811,7 @@ object FMain: TFMain
         Top = 0
         Grouped = True
         ImageIndex = 85
+        OnMouseMove = Panel_TextMouseMove
         Style = tbsCheck
       end
       object Tool_TextAlignRight: TToolButton
@@ -1811,6 +1820,7 @@ object FMain: TFMain
         Top = 0
         Grouped = True
         ImageIndex = 86
+        OnMouseMove = Panel_TextMouseMove
         Style = tbsCheck
       end
     end
@@ -1889,12 +1899,13 @@ object FMain: TFMain
       TabOrder = 1
       TabStop = True
       UseDockManager = False
+      OnMouseMove = Panel_TextMouseMove
     end
   end
   object Panel_PhongShape: TPanel
     Left = 8
     Height = 36
-    Top = 248
+    Top = 288
     Width = 306
     ClientHeight = 36
     ClientWidth = 306
@@ -2075,7 +2086,7 @@ object FMain: TFMain
   object Panel_Altitude: TPanel
     Left = 331
     Height = 36
-    Top = 248
+    Top = 288
     Width = 111
     ClientHeight = 36
     ClientWidth = 111
@@ -2332,7 +2343,7 @@ object FMain: TFMain
   object Panel_Brush: TPanel
     Left = 8
     Height = 36
-    Top = 296
+    Top = 336
     Width = 266
     ClientHeight = 36
     ClientWidth = 266
@@ -3324,9 +3335,131 @@ object FMain: TFMain
       EditingGradTexPoints = False
     end
   end
+  object Panel_TextMore: TPanel
+    Left = 9
+    Height = 30
+    Top = 243
+    Width = 265
+    ClientHeight = 30
+    ClientWidth = 265
+    TabOrder = 34
+    Visible = False
+    OnMouseMove = Panel_TextMoreMouseMove
+    object ToolBar25: TToolBar
+      Left = 1
+      Height = 22
+      Top = 1
+      Width = 247
+      Align = alNone
+      AutoSize = True
+      EdgeBorders = []
+      Font.Height = -12
+      Images = SVGRasterImageList1
+      ParentFont = False
+      TabOrder = 0
+      OnMouseMove = Panel_TextMoreMouseMove
+      object Tool_TextBold: TToolButton
+        Left = 1
+        Hint = 'Bold'
+        Top = 0
+        ImageIndex = 0
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextItalic: TToolButton
+        Left = 24
+        Hint = 'Italic'
+        Top = 0
+        ImageIndex = 1
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextUnderline: TToolButton
+        Left = 47
+        Hint = 'Underline'
+        Top = 0
+        ImageIndex = 2
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextStrikeout: TToolButton
+        Left = 70
+        Hint = 'Strikeout'
+        Top = 0
+        ImageIndex = 3
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextBidirectional: TToolButton
+        Left = 101
+        Hint = 'Bidirectional'
+        Top = 0
+        Down = True
+        Grouped = True
+        ImageIndex = 4
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextLTR: TToolButton
+        Left = 124
+        Hint = 'Left to right'
+        Top = 0
+        Grouped = True
+        ImageIndex = 5
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextRTL: TToolButton
+        Left = 147
+        Hint = 'Right to left'
+        Top = 0
+        Grouped = True
+        ImageIndex = 6
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextAlignTop: TToolButton
+        Left = 178
+        Hint = 'Align top'
+        Top = 0
+        Down = True
+        ImageIndex = 7
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextAlignMiddle: TToolButton
+        Left = 201
+        Hint = 'Center vertically'
+        Top = 0
+        ImageIndex = 8
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object Tool_TextAlignBottom: TToolButton
+        Left = 224
+        Hint = 'Align bottom'
+        Top = 0
+        ImageIndex = 9
+        OnMouseMove = Panel_TextMoreMouseMove
+        Style = tbsCheck
+      end
+      object ToolButton1: TToolButton
+        Left = 170
+        Height = 22
+        Top = 0
+        Style = tbsSeparator
+      end
+      object ToolButton2: TToolButton
+        Left = 93
+        Height = 22
+        Top = 0
+        Style = tbsSeparator
+      end
+    end
+  end
   object ImageList16: TBGRAImageList
-    Left = 40
-    Top = 496
+    Left = 27
+    Top = 514
     Bitmap = {
       4C7A8600000010000000100000006A8300000000000078DAEC5D07581457D71E
       EC5D6CB1A112628D359AA8B1A22696C45E63C70662895DB18205411101A5AB34
@@ -4384,8 +4517,8 @@ object FMain: TFMain
   end
   object ActionList1: TActionList
     Images = ImageList16
-    Left = 43
-    Top = 427
+    Left = 30
+    Top = 449
     object FileNew: TAction
       Category = 'File'
       Caption = 'New...'
@@ -5407,6 +5540,7 @@ object FMain: TFMain
       Hint = 'Center shape horizontally'
       OnExecute = EditShapeCenterHorizontallyExecute
       OnUpdate = EditShapeCenterHorizontallyUpdate
+      ShortCut = 32840
     end
     object EditShapeAlignRight: TAction
       Category = 'Edit'
@@ -5427,6 +5561,7 @@ object FMain: TFMain
       Hint = 'Center shape vertically'
       OnExecute = EditShapeCenterVerticallyExecute
       OnUpdate = EditShapeCenterVerticallyUpdate
+      ShortCut = 32854
     end
     object EditShapeAlignBottom: TAction
       Category = 'Edit'
@@ -5471,6 +5606,14 @@ object FMain: TFMain
       ImageIndex = 3
       OnExecute = LayerExportExecute
     end
+    object FileQuickSave: TAction
+      Category = 'File'
+      Caption = 'Quick save'
+      Hint = 'Save current file without dialogs'
+      OnExecute = FileQuickSaveExecute
+      OnUpdate = FileSaveUpdate
+      ShortCut = 16465
+    end
   end
   object ColorDialog1: TColorDialog
     Title = 'Choose color'
@@ -5497,13 +5640,13 @@ object FMain: TFMain
       'ColorS=F0FBFF'
       'ColorT=A4A0A0'
     )
-    Left = 219
-    Top = 427
+    Left = 204
+    Top = 385
   end
   object MainMenu1: TMainMenu
     Images = ImageList16
-    Left = 43
-    Top = 363
+    Left = 30
+    Top = 385
     object MenuFile: TMenuItem
       Caption = 'File'
       OnClick = MenuFileClick
@@ -5537,11 +5680,9 @@ object FMain: TFMain
     end
     object MenuEdit: TMenuItem
       Caption = 'Edit'
-      Visible = False
     end
     object MenuSelect: TMenuItem
       Caption = 'Select'
-      Visible = False
     end
     object MenuView: TMenuItem
       Caption = 'View'
@@ -5562,7 +5703,6 @@ object FMain: TFMain
     end
     object MenuImage: TMenuItem
       Caption = 'Image'
-      Visible = False
       object MenuRemoveTransparency: TMenuItem
         Caption = 'Remove transparency'
         Visible = False
@@ -5570,15 +5710,12 @@ object FMain: TFMain
     end
     object MenuColors: TMenuItem
       Caption = 'Colors'
-      Visible = False
     end
     object MenuTool: TMenuItem
       Caption = 'Tools'
-      Visible = False
     end
     object MenuFilter: TMenuItem
       Caption = 'Filter'
-      Visible = False
       object MenuRadialBlur: TMenuItem
         Caption = 'Radial blur'
         Visible = False
@@ -5586,23 +5723,20 @@ object FMain: TFMain
     end
     object MenuRender: TMenuItem
       Caption = 'Render'
-      Visible = False
     end
     object MenuScript: TMenuItem
       Caption = 'Script'
-      Visible = False
     end
     object MenuHelp: TMenuItem
       Caption = 'Help'
-      Visible = False
     end
   end
   object TimerHidePenPreview: TTimer
     Enabled = False
     Interval = 3000
     OnTimer = TimerHidePenPreviewTimer
-    Left = 646
-    Top = 288
+    Left = 653
+    Top = 514
   end
   object FontDialog1: TFontDialog
     Font.CharSet = ANSI_CHARSET
@@ -5612,73 +5746,73 @@ object FMain: TFMain
     Font.Quality = fqDraft
     MinFontSize = 0
     MaxFontSize = 0
-    Left = 216
-    Top = 496
+    Left = 204
+    Top = 449
   end
   object LoadSelectionDialog: TOpenPictureDialog
     Title = 'Load selection'
     Options = [ofNoDereferenceLinks, ofEnableSizing, ofViewDetail]
-    Left = 335
-    Top = 363
+    Left = 306
+    Top = 385
   end
   object OpenPictureDialog1: TOpenDialog
     Title = 'Open existing image'
     Options = [ofNoDereferenceLinks, ofEnableSizing, ofViewDetail]
-    Left = 456
-    Top = 363
+    Left = 427
+    Top = 385
   end
   object OpenTextureDialog: TOpenDialog
     Title = 'Open texture'
     DefaultExt = '.png'
     Options = [ofNoDereferenceLinks, ofEnableSizing, ofViewDetail]
-    Left = 332
-    Top = 496
+    Left = 303
+    Top = 514
   end
   object TimerUpdate: TTimer
     Interval = 50
     OnTimer = TimerUpdateTimer
-    Left = 219
-    Top = 363
+    Left = 653
+    Top = 328
   end
   object Open3DObjectDialog: TOpenDialog
     Title = 'Import 3D object'
     DefaultExt = '.obj'
     Filter = 'Wavefront Object file (*.obj)|*.obj;*.Obj;*.OBJ'
     Options = [ofNoDereferenceLinks, ofEnableSizing, ofViewDetail]
-    Left = 453
-    Top = 496
+    Left = 424
+    Top = 514
   end
   object SavePictureDialog1: TSaveDialog
     Title = 'Save file as...'
     DefaultExt = '.png'
     Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail]
-    Left = 456
-    Top = 427
+    Left = 427
+    Top = 449
   end
   object TimerLoadToolWin: TTimer
     Interval = 200
     OnTimer = TimerLoadToolWinTimer
-    Left = 680
-    Top = 427
+    Left = 653
+    Top = 385
   end
   object SaveSelectionDialog: TSaveDialog
     Title = 'Save selection as...'
     DefaultExt = '.lzp'
     Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail]
-    Left = 335
-    Top = 427
+    Left = 306
+    Top = 449
   end
   object OpenBrushDialog: TOpenDialog
     Title = 'Open brush'
     DefaultExt = '.lzp'
     Options = [ofNoDereferenceLinks, ofEnableSizing, ofViewDetail]
-    Left = 578
-    Top = 363
+    Left = 544
+    Top = 385
   end
   object PopupToolbar: TPopupMenu
     OnPopup = PopupToolbarPopup
-    Left = 130
-    Top = 427
+    Left = 115
+    Top = 449
     object MenuFileToolbar: TMenuItem
       Caption = 'Show file toolbar'
       OnClick = MenuFileToolbarClick
@@ -5706,8 +5840,8 @@ object FMain: TFMain
   end
   object PopupToolbox: TPopupMenu
     OnPopup = PopupToolboxPopup
-    Left = 130
-    Top = 363
+    Left = 115
+    Top = 385
     object MenuDockToolboxLeft: TMenuItem
       Caption = 'Dock left'
       OnClick = MenuDockToolboxLeftClick
@@ -5724,8 +5858,8 @@ object FMain: TFMain
   object ImageList48: TBGRAImageList
     Height = 48
     Width = 48
-    Left = 127
-    Top = 496
+    Left = 112
+    Top = 514
     Bitmap = {
       4C7A860000003000000030000000756303000000000078DAEC9D057C1457F7F7
       135CFA94FAD33E155ADA52A0B4B8BBBBBBBBBB3B418B1477777709094112E2EE
@@ -12674,21 +12808,663 @@ object FMain: TFMain
     Enabled = False
     Interval = 50
     OnTimer = TimerArrangeTimer
-    Left = 578
-    Top = 496
+    Left = 544
+    Top = 514
   end
   object TimerHideFill: TTimer
     Enabled = False
     Interval = 3000
     OnTimer = TimerHideFillTimer
-    Left = 680
-    Top = 496
+    Left = 653
+    Top = 449
   end
   object ExportPictureDialog: TSaveDialog
     Title = 'Export as...'
     DefaultExt = '.png'
     Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail]
-    Left = 578
-    Top = 427
+    Left = 544
+    Top = 449
+  end
+  object SVGImageList1: TBGRASVGImageList
+    Width = 16
+    Height = 16
+    TargetRasterImageList = SVGRasterImageList1
+    Left = 200
+    Top = 514
+    Items = {
+      3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574
+      662D38223F3E0D0A3C434F4E46494720436F756E743D223130223E0D0A20203C
+      4974656D30205356473D22266C743B3F786D6C2076657273696F6E3D2671756F
+      743B312E302671756F743B20656E636F64696E673D2671756F743B7574662D38
+      2671756F743B3F2667743B262378443B262378413B266C743B73766720776964
+      74683D2671756F743B33322671756F743B20786D6C6E733D2671756F743B6874
+      74703A2F2F7777772E77332E6F72672F323030302F7376672671756F743B2068
+      65696768743D2671756F743B33322671756F743B2076696577426F783D267175
+      6F743B3020302033322033322671756F743B20786D6C6E733A696E6B73636170
+      653D2671756F743B687474703A2F2F7777772E696E6B73636170652E6F72672F
+      6E616D657370616365732F696E6B73636170652671756F743B2667743B262378
+      443B262378413B2020266C743B67206F7061636974793D2671756F743B312671
+      756F743B20786D6C6E733A626772613D2671756F743B68747470733A2F2F7769
+      6B692E6672656570617363616C2E6F72672F4C617A5061696E745F5356475F66
+      6F726D61742671756F743B20696E6B73636170653A6C6162656C3D2671756F74
+      3B4C61796572312671756F743B20696E6B73636170653A67726F75706D6F6465
+      3D2671756F743B6C617965722671756F743B20626772613A6F726967696E616C
+      56696577426F783D2671756F743B3020302032392032382671756F743B266774
+      3B262378443B262378413B20202020266C743B7061746820643D2671756F743B
+      4D32382E383433373520362E353933373520302E303933373520302E30333132
+      352671756F743B2066696C6C3D2671756F743B626C61636B2671756F743B2073
+      74726F6B653D2671756F743B6E6F6E652671756F743B2066696C6C2D6F706163
+      6974793D2671756F743B312671756F743B2F2667743B262378443B262378413B
+      20202020266C743B7061746820643D2671756F743B4D39203238203920332031
+      352033203135203238207A2671756F743B2066696C6C3D2671756F743B626C61
+      636B2671756F743B207374726F6B653D2671756F743B6E6F6E652671756F743B
+      2066696C6C2D6F7061636974793D2671756F743B302E37393231353639267175
+      6F743B2F2667743B262378443B262378413B20202020266C743B706174682064
+      3D2671756F743B4D31352032382031382E38383436312032372E393434373120
+      5132322E37363932332032372E38383934322032342E38363239382032352E36
+      303831372032362E39353637332032332E33323639322032362E393738333620
+      32302E31363334362032372031372032352E37352031352E32352032342E3520
+      31332E352032322E32352031322E37352032302031322031372E35203132204C
+      3135203132203135203136203137203136205131392031362032302E35203137
+      2032322031382032312E38323231312032302E30333834362032312E36343432
+      332032322E30373639322032302E32363932332032322E39383331372031382E
+      38393432332032332E38383934322031362E39343731312032332E3934343731
+      204C3135203234207A2671756F743B2066696C6C3D2671756F743B626C61636B
+      2671756F743B207374726F6B653D2671756F743B6E6F6E652671756F743B2066
+      696C6C2D6F7061636974793D2671756F743B302E373932313536392671756F74
+      3B2F2667743B262378443B262378413B2020266C743B2F672667743B26237844
+      3B262378413B266C743B2F7376672667743B262378443B262378413B222F3E0D
+      0A20203C4974656D31205356473D22266C743B3F786D6C2076657273696F6E3D
+      2671756F743B312E302671756F743B20656E636F64696E673D2671756F743B75
+      74662D382671756F743B3F2667743B262378443B262378413B266C743B737667
+      2077696474683D2671756F743B33322671756F743B20786D6C6E733D2671756F
+      743B687474703A2F2F7777772E77332E6F72672F323030302F7376672671756F
+      743B206865696768743D2671756F743B33322671756F743B2076696577426F78
+      3D2671756F743B3020302033322033322671756F743B20786D6C6E733A696E6B
+      73636170653D2671756F743B687474703A2F2F7777772E696E6B73636170652E
+      6F72672F6E616D657370616365732F696E6B73636170652671756F743B266774
+      3B262378443B262378413B2020266C743B67206F7061636974793D2671756F74
+      3B312671756F743B20786D6C6E733A626772613D2671756F743B68747470733A
+      2F2F77696B692E6672656570617363616C2E6F72672F4C617A5061696E745F53
+      56475F666F726D61742671756F743B20696E6B73636170653A6C6162656C3D26
+      71756F743B4C61796572312671756F743B20696E6B73636170653A67726F7570
+      6D6F64653D2671756F743B6C617965722671756F743B20626772613A6F726967
+      696E616C56696577426F783D2671756F743B3020302032392032382671756F74
+      3B2667743B262378443B262378413B20202020266C743B7061746820643D2671
+      756F743B4D32382E383433373520362E353933373520302E303933373520302E
+      30333132352671756F743B2066696C6C3D2671756F743B626C61636B2671756F
+      743B207374726F6B653D2671756F743B6E6F6E652671756F743B2066696C6C2D
+      6F7061636974793D2671756F743B312671756F743B2F2667743B262378443B26
+      2378413B20202020266C743B7061746820643D2671756F743B4D313120323820
+      31362E352031332032302E35203133203135203238207A2671756F743B206669
+      6C6C3D2671756F743B626C61636B2671756F743B207374726F6B653D2671756F
+      743B6E6F6E652671756F743B2066696C6C2D6F7061636974793D2671756F743B
+      302E373932313536392671756F743B2F2667743B262378443B262378413B2020
+      2020266C743B7061746820643D2671756F743B4D313820313020313920362032
+      3320362032312E37313837352031302E3039333735207A2671756F743B206669
+      6C6C3D2671756F743B626C61636B2671756F743B207374726F6B653D2671756F
+      743B6E6F6E652671756F743B2066696C6C2D6F7061636974793D2671756F743B
+      302E373932313536392671756F743B2F2667743B262378443B262378413B2020
+      2020266C743B7061746820643D2671756F743B4D32342E34303632352031342E
+      333433373520312E303933373520302E3033313235207A2671756F743B206669
+      6C6C3D2671756F743B626C61636B2671756F743B207374726F6B653D2671756F
+      743B6E6F6E652671756F743B2066696C6C2D6F7061636974793D2671756F743B
+      302E373932313536392671756F743B2F2667743B262378443B262378413B2020
+      266C743B2F672667743B262378443B262378413B266C743B2F7376672667743B
+      262378443B262378413B222F3E0D0A20203C4974656D32205356473D22266C74
+      3B3F786D6C2076657273696F6E3D2671756F743B312E302671756F743B20656E
+      636F64696E673D2671756F743B7574662D382671756F743B3F2667743B262378
+      443B262378413B266C743B7376672077696474683D2671756F743B3332267175
+      6F743B20786D6C6E733D2671756F743B687474703A2F2F7777772E77332E6F72
+      672F323030302F7376672671756F743B206865696768743D2671756F743B3332
+      2671756F743B2076696577426F783D2671756F743B3020302033322033322671
+      756F743B20786D6C6E733A696E6B73636170653D2671756F743B687474703A2F
+      2F7777772E696E6B73636170652E6F72672F6E616D657370616365732F696E6B
+      73636170652671756F743B2667743B262378443B262378413B2020266C743B67
+      206F7061636974793D2671756F743B312671756F743B20786D6C6E733A626772
+      613D2671756F743B68747470733A2F2F77696B692E6672656570617363616C2E
+      6F72672F4C617A5061696E745F5356475F666F726D61742671756F743B20696E
+      6B73636170653A6C6162656C3D2671756F743B4C61796572312671756F743B20
+      696E6B73636170653A67726F75706D6F64653D2671756F743B6C617965722671
+      756F743B20626772613A6F726967696E616C56696577426F783D2671756F743B
+      2D3331202D352039342033352671756F743B2667743B262378443B262378413B
+      20202020266C743B7465787420783D2671756F743B302671756F743B20793D26
+      71756F743B2D352671756F743B2066696C6C3D2671756F743B626C61636B2671
+      756F743B207374726F6B653D2671756F743B6E6F6E652671756F743B20666F6E
+      742D73697A653D2671756F743B33312671756F743B20666F6E742D7374796C65
+      3D2671756F743B6E6F726D616C2671756F743B20666F6E742D66616D696C793D
+      2671756F743B4672656553616E732671756F743B20666F6E742D776569676874
+      3D2671756F743B6E6F726D616C2671756F743B2066696C6C2D6F706163697479
+      3D2671756F743B302E373932313536392671756F743B20746578742D6465636F
+      726174696F6E3D2671756F743B2671756F743B2667743B262378443B26237841
+      3B202020202020266C743B747370616E20783D2671756F743B372E3337373836
+      372671756F743B20793D2671756F743B32332671756F743B2064697265637469
+      6F6E3D2671756F743B6C74722671756F743B20746578744C656E6774683D2671
+      756F743B31372E32343432372671756F743B2667743B75266C743B2F74737061
+      6E2667743B262378443B262378413B20202020266C743B2F746578742667743B
+      262378443B262378413B20202020266C743B7061746820643D2671756F743B4D
+      362E3520333020362E352032362032352E352032362032352E35203330207A26
+      71756F743B2066696C6C3D2671756F743B626C61636B2671756F743B20737472
+      6F6B653D2671756F743B6E6F6E652671756F743B2066696C6C2D6F7061636974
+      793D2671756F743B302E373932313536392671756F743B2F2667743B26237844
+      3B262378413B2020266C743B2F672667743B262378443B262378413B266C743B
+      2F7376672667743B262378443B262378413B222F3E0D0A20203C4974656D3320
+      5356473D22266C743B3F786D6C2076657273696F6E3D2671756F743B312E3026
+      71756F743B20656E636F64696E673D2671756F743B7574662D382671756F743B
+      3F2667743B262378443B262378413B266C743B7376672077696474683D267175
+      6F743B33322671756F743B20786D6C6E733D2671756F743B687474703A2F2F77
+      77772E77332E6F72672F323030302F7376672671756F743B206865696768743D
+      2671756F743B33322671756F743B2076696577426F783D2671756F743B302030
+      2033322033322671756F743B20786D6C6E733A696E6B73636170653D2671756F
+      743B687474703A2F2F7777772E696E6B73636170652E6F72672F6E616D657370
+      616365732F696E6B73636170652671756F743B2667743B262378443B26237841
+      3B2020266C743B67206F7061636974793D2671756F743B312671756F743B2078
+      6D6C6E733A626772613D2671756F743B68747470733A2F2F77696B692E667265
+      6570617363616C2E6F72672F4C617A5061696E745F5356475F666F726D617426
+      71756F743B20696E6B73636170653A6C6162656C3D2671756F743B4C61796572
+      312671756F743B20696E6B73636170653A67726F75706D6F64653D2671756F74
+      3B6C617965722671756F743B20626772613A6F726967696E616C56696577426F
+      783D2671756F743B3520392032322031392671756F743B2667743B262378443B
+      262378413B20202020266C743B7061746820643D2671756F743B4D352E352032
+      3020352E352031362032362E352031362032362E35203230207A2671756F743B
+      2066696C6C3D2671756F743B626C61636B2671756F743B207374726F6B653D26
+      71756F743B6E6F6E652671756F743B2066696C6C2D6F7061636974793D267175
+      6F743B302E373932313536392671756F743B2F2667743B262378443B26237841
+      3B20202020266C743B7061746820643D2671756F743B4D31322E373532353120
+      32322E30343231372031332E30393533342032332E3139313232205131332E34
+      333831372032342E33343032372031342E38373239312032342E363838343620
+      31362E33303736352032352E30333636352031372E37323138372032352E3030
+      3331382031392E31333630382032342E39363937312031392E36323232322032
+      342E32313834312032302E31303833352032332E34363731312031392E383433
+      31392032322E30393730392031392E35373830322032302E3732373037203137
+      2E36333334382032302E31353235342031352E36383839332031392E35373830
+      322031332E3635362031392E30343736392031312E36323330372031382E3531
+      3733362031302E363530382031372E353839323820392E363738353235203136
+      2E3636313220392E3731353133372031352E303138343420392E373531373439
+      2031332E33373536372031302E33373439312031322E33353639392031302E39
+      393830372031312E333338332031322E34303639322031302E36343935203133
+      2E383135373720392E3936303639342031362E303732383220392E3930353737
+      372031382E333239383620392E38353038362031392E35303730322031302E33
+      393633352032302E36383431382031302E39343138352032312E343832383120
+      31312E37353437332032322E32383134352031322E35363736312032322E3432
+      3437352031332E3235363431204C32322E35363830362031332E393435323220
+      31392E33363436332031342E30353530352031382E383334332031332E343532
+      3432205131382E33303339372031322E38343937382031362E36393639203132
+      2E39313030362031352E30383938322031322E39373033342031342E30363335
+      352031332E35393434322031332E30333732382031342E323138352031322E39
+      3438392031342E38363533332031322E38363035312031352E35313231362031
+      352E35353633352031362E33393630342031382E32353231392031372E323739
+      39322031392E35333338332031372E37323138362032302E3831353436203138
+      2E31363338312032312E37343335342031382E39313531312032322E36373136
+      312031392E36363634312032322E38393235382032312E31323438322032332E
+      31313335362032322E35383332332032322E37362032332E3930393035203232
+      2E34303634352032352E32333438382032302E35383530362032362E36323633
+      342031382E37363336382032382E30313738312031362E33353739372032372E
+      39393633362031332E39353232362032372E39373439312031322E3930333234
+      2032372E34353433392031312E38353432332032362E39333338362031302E38
+      353437362032362E303834333720392E3835353330322032352E323334383820
+      392E3732303439382032332E3632303232204C392E3538353639342032322E30
+      30353536207A2671756F743B2066696C6C3D2671756F743B626C61636B267175
+      6F743B207374726F6B653D2671756F743B6E6F6E652671756F743B2066696C6C
+      2D6F7061636974793D2671756F743B302E373932313536392671756F743B2F26
+      67743B262378443B262378413B2020266C743B2F672667743B262378443B2623
+      78413B266C743B2F7376672667743B262378443B262378413B222F3E0D0A2020
+      3C4974656D34205356473D22266C743B3F786D6C2076657273696F6E3D267175
+      6F743B312E302671756F743B20656E636F64696E673D2671756F743B7574662D
+      382671756F743B3F2667743B262378443B262378413B266C743B737667207769
+      6474683D2671756F743B33322671756F743B20786D6C6E733D2671756F743B68
+      7474703A2F2F7777772E77332E6F72672F323030302F7376672671756F743B20
+      6865696768743D2671756F743B33322671756F743B2076696577426F783D2671
+      756F743B3020302033322033322671756F743B20786D6C6E733A696E6B736361
+      70653D2671756F743B687474703A2F2F7777772E696E6B73636170652E6F7267
+      2F6E616D657370616365732F696E6B73636170652671756F743B2667743B2623
+      78443B262378413B2020266C743B67206F7061636974793D2671756F743B3126
+      71756F743B20786D6C6E733A626772613D2671756F743B68747470733A2F2F77
+      696B692E6672656570617363616C2E6F72672F4C617A5061696E745F5356475F
+      666F726D61742671756F743B20696E6B73636170653A6C6162656C3D2671756F
+      743B4C61796572312671756F743B20696E6B73636170653A67726F75706D6F64
+      653D2671756F743B6C617965722671756F743B20626772613A6F726967696E61
+      6C56696577426F783D2671756F743B2D313520302036322032392671756F743B
+      2667743B262378443B262378413B20202020266C743B7061746820643D267175
+      6F743B4D332E352032322031302031352E352031302032302032322032302032
+      322031352E352032382E352032322032322032382E3520323220323420313020
+      32342031302032382E35207A2671756F743B2066696C6C3D2671756F743B626C
+      61636B2671756F743B207374726F6B653D2671756F743B6E6F6E652671756F74
+      3B2066696C6C2D6F7061636974793D2671756F743B302E373932313536392671
+      756F743B2F2667743B262378443B262378413B20202020266C743B7465787420
+      783D2671756F743B302671756F743B20793D2671756F743B302671756F743B20
+      66696C6C3D2671756F743B626C61636B2671756F743B207374726F6B653D2671
+      756F743B6E6F6E652671756F743B20666F6E742D73697A653D2671756F743B31
+      352671756F743B20666F6E742D7374796C653D2671756F743B6E6F726D616C26
+      71756F743B20666F6E742D66616D696C793D2671756F743B4672656553616E73
+      2671756F743B20666F6E742D7765696768743D2671756F743B6E6F726D616C26
+      71756F743B2066696C6C2D6F7061636974793D2671756F743B302E3936383632
+      37352671756F743B20746578742D6465636F726174696F6E3D2671756F743B26
+      71756F743B2667743B262378443B262378413B202020202020266C743B747370
+      616E20783D2671756F743B31312E3832382671756F743B20793D2671756F743B
+      31342671756F743B20646972656374696F6E3D2671756F743B6C74722671756F
+      743B20746578744C656E6774683D2671756F743B382E3334343030312671756F
+      743B2667743B3F266C743B2F747370616E2667743B262378443B262378413B20
+      202020266C743B2F746578742667743B262378443B262378413B2020266C743B
+      2F672667743B262378443B262378413B266C743B2F7376672667743B26237844
+      3B262378413B222F3E0D0A20203C4974656D35205356473D22266C743B3F786D
+      6C2076657273696F6E3D2671756F743B312E302671756F743B20656E636F6469
+      6E673D2671756F743B7574662D382671756F743B3F2667743B262378443B2623
+      78413B266C743B7376672077696474683D2671756F743B33322671756F743B20
+      786D6C6E733D2671756F743B687474703A2F2F7777772E77332E6F72672F3230
+      30302F7376672671756F743B206865696768743D2671756F743B33322671756F
+      743B2076696577426F783D2671756F743B3020302033322033322671756F743B
+      20786D6C6E733A696E6B73636170653D2671756F743B687474703A2F2F777777
+      2E696E6B73636170652E6F72672F6E616D657370616365732F696E6B73636170
+      652671756F743B2667743B262378443B262378413B2020266C743B67206F7061
+      636974793D2671756F743B312671756F743B20786D6C6E733A626772613D2671
+      756F743B68747470733A2F2F77696B692E6672656570617363616C2E6F72672F
+      4C617A5061696E745F5356475F666F726D61742671756F743B20696E6B736361
+      70653A6C6162656C3D2671756F743B4C61796572312671756F743B20696E6B73
+      636170653A67726F75706D6F64653D2671756F743B6C617965722671756F743B
+      20626772613A6F726967696E616C56696577426F783D2671756F743B2D313020
+      2D312035362033302671756F743B2667743B262378443B262378413B20202020
+      266C743B7061746820643D2671756F743B4D3420323020323220323020323220
+      31352E352032382E352032322032322032382E35203232203234203420323420
+      7A2671756F743B2066696C6C3D2671756F743B626C61636B2671756F743B2073
+      74726F6B653D2671756F743B6E6F6E652671756F743B2066696C6C2D6F706163
+      6974793D2671756F743B302E373932313536392671756F743B2F2667743B2623
+      78443B262378413B20202020266C743B7465787420783D2671756F743B342671
+      756F743B20793D2671756F743B2D312671756F743B2066696C6C3D2671756F74
+      3B626C61636B2671756F743B207374726F6B653D2671756F743B6E6F6E652671
+      756F743B20666F6E742D73697A653D2671756F743B31342671756F743B20666F
+      6E742D7374796C653D2671756F743B6E6F726D616C2671756F743B20666F6E74
+      2D66616D696C793D2671756F743B4672656553616E732671756F743B20666F6E
+      742D7765696768743D2671756F743B6E6F726D616C2671756F743B2066696C6C
+      2D6F7061636974793D2671756F743B302E393638363237352671756F743B2074
+      6578742D6465636F726174696F6E3D2671756F743B2671756F743B2667743B26
+      2378443B262378413B202020202020266C743B747370616E20783D2671756F74
+      3B342671756F743B20793D2671756F743B31322671756F743B20646972656374
+      696F6E3D2671756F743B6C74722671756F743B20746578744C656E6774683D26
+      71756F743B32332E31353431332671756F743B2667743BCEB1CEB2CEB3266C74
+      3B2F747370616E2667743B262378443B262378413B20202020266C743B2F7465
+      78742667743B262378443B262378413B2020266C743B2F672667743B26237844
+      3B262378413B266C743B2F7376672667743B262378443B262378413B222F3E0D
+      0A20203C4974656D36205356473D22266C743B3F786D6C2076657273696F6E3D
+      2671756F743B312E302671756F743B20656E636F64696E673D2671756F743B75
+      74662D382671756F743B3F2667743B262378443B262378413B266C743B737667
+      2077696474683D2671756F743B33322671756F743B20786D6C6E733D2671756F
+      743B687474703A2F2F7777772E77332E6F72672F323030302F7376672671756F
+      743B206865696768743D2671756F743B33322671756F743B2076696577426F78
+      3D2671756F743B3020302033322033322671756F743B20786D6C6E733A696E6B
+      73636170653D2671756F743B687474703A2F2F7777772E696E6B73636170652E
+      6F72672F6E616D657370616365732F696E6B73636170652671756F743B266774
+      3B262378443B262378413B2020266C743B67206F7061636974793D2671756F74
+      3B312671756F743B20786D6C6E733A626772613D2671756F743B68747470733A
+      2F2F77696B692E6672656570617363616C2E6F72672F4C617A5061696E745F53
+      56475F666F726D61742671756F743B20696E6B73636170653A6C6162656C3D26
+      71756F743B4C61796572312671756F743B20696E6B73636170653A67726F7570
+      6D6F64653D2671756F743B6C617965722671756F743B20626772613A6F726967
+      696E616C56696577426F783D2671756F743B2D31352030203539203239267175
+      6F743B2667743B262378443B262378413B20202020266C743B7061746820643D
+      2671756F743B4D332E352032322031302031352E352031302032302032382032
+      302032382032342031302032342031302032382E35207A2671756F743B206669
+      6C6C3D2671756F743B626C61636B2671756F743B207374726F6B653D2671756F
+      743B6E6F6E652671756F743B2066696C6C2D6F7061636974793D2671756F743B
+      302E373932313536392671756F743B2F2667743B262378443B262378413B2020
+      2020266C743B7465787420783D2671756F743B302671756F743B20793D267175
+      6F743B302671756F743B2066696C6C3D2671756F743B626C61636B2671756F74
+      3B207374726F6B653D2671756F743B6E6F6E652671756F743B20666F6E742D73
+      697A653D2671756F743B31352671756F743B20666F6E742D7374796C653D2671
+      756F743B6E6F726D616C2671756F743B20666F6E742D66616D696C793D267175
+      6F743B4672656553616E732671756F743B20666F6E742D7765696768743D2671
+      756F743B6E6F726D616C2671756F743B2066696C6C2D6F7061636974793D2671
+      756F743B302E393638363237352671756F743B20746578742D6465636F726174
+      696F6E3D2671756F743B2671756F743B2667743B262378443B262378413B2020
+      20202020266C743B747370616E20783D2671756F743B32392671756F743B2079
+      3D2671756F743B31342671756F743B20646972656374696F6E3D2671756F743B
+      72746C2671756F743B20746578744C656E6774683D2671756F743B32322E3536
+      382671756F743B2667743BD790D791D792266C743B2F747370616E2667743B26
+      2378443B262378413B20202020266C743B2F746578742667743B262378443B26
+      2378413B2020266C743B2F672667743B262378443B262378413B266C743B2F73
+      76672667743B262378443B262378413B222F3E0D0A20203C4974656D37205356
+      473D22266C743B3F786D6C2076657273696F6E3D2671756F743B312E30267175
+      6F743B20656E636F64696E673D2671756F743B7574662D382671756F743B3F26
+      67743B262378443B262378413B266C743B7376672077696474683D2671756F74
+      3B33322671756F743B20786D6C6E733D2671756F743B687474703A2F2F777777
+      2E77332E6F72672F323030302F7376672671756F743B206865696768743D2671
+      756F743B33322671756F743B2076696577426F783D2671756F743B3020302033
+      322033322671756F743B20786D6C6E733A696E6B73636170653D2671756F743B
+      687474703A2F2F7777772E696E6B73636170652E6F72672F6E616D6573706163
+      65732F696E6B73636170652671756F743B2667743B262378443B262378413B20
+      20266C743B67206F7061636974793D2671756F743B312671756F743B20786D6C
+      6E733A626772613D2671756F743B68747470733A2F2F77696B692E6672656570
+      617363616C2E6F72672F4C617A5061696E745F5356475F666F726D6174267175
+      6F743B20696E6B73636170653A6C6162656C3D2671756F743B4C617965723126
+      71756F743B20696E6B73636170653A67726F75706D6F64653D2671756F743B6C
+      617965722671756F743B20626772613A6F726967696E616C56696577426F783D
+      2671756F743B3220342032382031342671756F743B2667743B262378443B2623
+      78413B20202020266C743B646566732667743B262378443B262378413B202020
+      202020266C743B6C696E6561724772616469656E742069643D2671756F743B6C
+      61796572312D66696C6C67726164312671756F743B2078313D2671756F743B31
+      352671756F743B2078323D2671756F743B31352671756F743B2079313D267175
+      6F743B322E352671756F743B2079323D2671756F743B362E352671756F743B20
+      7370726561644D6574686F643D2671756F743B7265706561742671756F743B20
+      6772616469656E74556E6974733D2671756F743B7573657253706163654F6E55
+      73652671756F743B20636F6C6F722D696E746572706F6C6174696F6E3D267175
+      6F743B6C696E6561725247422671756F743B2667743B262378443B262378413B
+      2020202020202020266C743B73746F70206F66667365743D2671756F743B3026
+      71756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671756F
+      743B2073746F702D6F7061636974793D2671756F743B302E3439383033393226
+      71756F743B2F2667743B262378443B262378413B2020202020202020266C743B
+      73746F70206F66667365743D2671756F743B302E303632352671756F743B2073
+      746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F70
+      2D6F7061636974793D2671756F743B302E333039383033392671756F743B2F26
+      67743B262378443B262378413B2020202020202020266C743B73746F70206F66
+      667365743D2671756F743B302E3132352671756F743B2073746F702D636F6C6F
+      723D2671756F743B626C61636B2671756F743B2073746F702D6F706163697479
+      3D2671756F743B302E3134353039382671756F743B2F2667743B262378443B26
+      2378413B2020202020202020266C743B73746F70206F66667365743D2671756F
+      743B302E313837352671756F743B2073746F702D636F6C6F723D2671756F743B
+      626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B30
+      2E30333532393431322671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B302E3235
+      2671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B267175
+      6F743B2073746F702D6F7061636974793D2671756F743B302671756F743B2F26
+      67743B262378443B262378413B2020202020202020266C743B73746F70206F66
+      667365743D2671756F743B302E333132352671756F743B2073746F702D636F6C
+      6F723D2671756F743B626C61636B2671756F743B2073746F702D6F7061636974
+      793D2671756F743B302E30333532393431322671756F743B2F2667743B262378
+      443B262378413B2020202020202020266C743B73746F70206F66667365743D26
+      71756F743B302E3337352671756F743B2073746F702D636F6C6F723D2671756F
+      743B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F74
+      3B302E3134353039382671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B302E3433
+      37352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B26
+      71756F743B2073746F702D6F7061636974793D2671756F743B302E3330393830
+      33392671756F743B2F2667743B262378443B262378413B202020202020202026
+      6C743B73746F70206F66667365743D2671756F743B302E352671756F743B2073
+      746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F70
+      2D6F7061636974793D2671756F743B302E343938303339322671756F743B2F26
+      67743B262378443B262378413B2020202020202020266C743B73746F70206F66
+      667365743D2671756F743B302E353632352671756F743B2073746F702D636F6C
+      6F723D2671756F743B626C61636B2671756F743B2073746F702D6F7061636974
+      793D2671756F743B302E363930313936312671756F743B2F2667743B26237844
+      3B262378413B2020202020202020266C743B73746F70206F66667365743D2671
+      756F743B302E3632352671756F743B2073746F702D636F6C6F723D2671756F74
+      3B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B
+      302E3835343930322671756F743B2F2667743B262378443B262378413B202020
+      2020202020266C743B73746F70206F66667365743D2671756F743B302E363837
+      352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671
+      756F743B2073746F702D6F7061636974793D2671756F743B302E393634373035
+      392671756F743B2F2667743B262378443B262378413B2020202020202020266C
+      743B73746F70206F66667365743D2671756F743B302E37352671756F743B2073
+      746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F70
+      2D6F7061636974793D2671756F743B312671756F743B2F2667743B262378443B
+      262378413B2020202020202020266C743B73746F70206F66667365743D267175
+      6F743B302E383132352671756F743B2073746F702D636F6C6F723D2671756F74
+      3B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B
+      302E393634373035392671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B302E3837
+      352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671
+      756F743B2073746F702D6F7061636974793D2671756F743B302E383534393032
+      2671756F743B2F2667743B262378443B262378413B2020202020202020266C74
+      3B73746F70206F66667365743D2671756F743B302E393337352671756F743B20
+      73746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F
+      702D6F7061636974793D2671756F743B302E363930313936312671756F743B2F
+      2667743B262378443B262378413B2020202020202020266C743B73746F70206F
+      66667365743D2671756F743B312671756F743B2073746F702D636F6C6F723D26
+      71756F743B626C61636B2671756F743B2073746F702D6F7061636974793D2671
+      756F743B302E343938303339322671756F743B2F2667743B262378443B262378
+      413B202020202020266C743B2F6C696E6561724772616469656E742667743B26
+      2378443B262378413B20202020266C743B2F646566732667743B262378443B26
+      2378413B20202020266C743B7061746820643D2671756F743B4D352E35203420
+      352E352036203720382037203130203220313220322031382033302031382033
+      3020313220323520313020323520382032362E3520362032362E352034207A26
+      71756F743B2066696C6C3D2671756F743B75726C28236C61796572312D66696C
+      6C6772616431292671756F743B207374726F6B653D2671756F743B6E6F6E6526
+      71756F743B2F2667743B262378443B262378413B2020266C743B2F672667743B
+      262378443B262378413B266C743B2F7376672667743B262378443B262378413B
+      222F3E0D0A20203C4974656D38205356473D22266C743B3F786D6C2076657273
+      696F6E3D2671756F743B312E302671756F743B20656E636F64696E673D267175
+      6F743B7574662D382671756F743B3F2667743B262378443B262378413B266C74
+      3B7376672077696474683D2671756F743B33322671756F743B20786D6C6E733D
+      2671756F743B687474703A2F2F7777772E77332E6F72672F323030302F737667
+      2671756F743B206865696768743D2671756F743B33322671756F743B20766965
+      77426F783D2671756F743B3020302033322033322671756F743B20786D6C6E73
+      3A696E6B73636170653D2671756F743B687474703A2F2F7777772E696E6B7363
+      6170652E6F72672F6E616D657370616365732F696E6B73636170652671756F74
+      3B2667743B262378443B262378413B2020266C743B67206F7061636974793D26
+      71756F743B312671756F743B20786D6C6E733A626772613D2671756F743B6874
+      7470733A2F2F77696B692E6672656570617363616C2E6F72672F4C617A506169
+      6E745F5356475F666F726D61742671756F743B20696E6B73636170653A6C6162
+      656C3D2671756F743B4C61796572312671756F743B20696E6B73636170653A67
+      726F75706D6F64653D2671756F743B6C617965722671756F743B20626772613A
+      6F726967696E616C56696577426F783D2671756F743B32203920323820313426
+      71756F743B2667743B262378443B262378413B20202020266C743B6465667326
+      67743B262378443B262378413B202020202020266C743B6C696E656172477261
+      6469656E742069643D2671756F743B6C61796572312D66696C6C677261643126
+      71756F743B2078313D2671756F743B31352671756F743B2078323D2671756F74
+      3B31352671756F743B2079313D2671756F743B372E352671756F743B2079323D
+      2671756F743B31312E352671756F743B207370726561644D6574686F643D2671
+      756F743B7265706561742671756F743B206772616469656E74556E6974733D26
+      71756F743B7573657253706163654F6E5573652671756F743B20636F6C6F722D
+      696E746572706F6C6174696F6E3D2671756F743B6C696E656172524742267175
+      6F743B2667743B262378443B262378413B2020202020202020266C743B73746F
+      70206F66667365743D2671756F743B302671756F743B2073746F702D636F6C6F
+      723D2671756F743B626C61636B2671756F743B2073746F702D6F706163697479
+      3D2671756F743B302E343938303339322671756F743B2F2667743B262378443B
+      262378413B2020202020202020266C743B73746F70206F66667365743D267175
+      6F743B302E303632352671756F743B2073746F702D636F6C6F723D2671756F74
+      3B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B
+      302E333039383033392671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B302E3132
+      352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671
+      756F743B2073746F702D6F7061636974793D2671756F743B302E313435303938
+      2671756F743B2F2667743B262378443B262378413B2020202020202020266C74
+      3B73746F70206F66667365743D2671756F743B302E313837352671756F743B20
+      73746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F
+      702D6F7061636974793D2671756F743B302E30333532393431322671756F743B
+      2F2667743B262378443B262378413B2020202020202020266C743B73746F7020
+      6F66667365743D2671756F743B302E32352671756F743B2073746F702D636F6C
+      6F723D2671756F743B626C61636B2671756F743B2073746F702D6F7061636974
+      793D2671756F743B302671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B302E3331
+      32352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B26
+      71756F743B2073746F702D6F7061636974793D2671756F743B302E3033353239
+      3431322671756F743B2F2667743B262378443B262378413B2020202020202020
+      266C743B73746F70206F66667365743D2671756F743B302E3337352671756F74
+      3B2073746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073
+      746F702D6F7061636974793D2671756F743B302E3134353039382671756F743B
+      2F2667743B262378443B262378413B2020202020202020266C743B73746F7020
+      6F66667365743D2671756F743B302E343337352671756F743B2073746F702D63
+      6F6C6F723D2671756F743B626C61636B2671756F743B2073746F702D6F706163
+      6974793D2671756F743B302E333039383033392671756F743B2F2667743B2623
+      78443B262378413B2020202020202020266C743B73746F70206F66667365743D
+      2671756F743B302E352671756F743B2073746F702D636F6C6F723D2671756F74
+      3B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B
+      302E343938303339322671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B302E3536
+      32352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B26
+      71756F743B2073746F702D6F7061636974793D2671756F743B302E3639303139
+      36312671756F743B2F2667743B262378443B262378413B202020202020202026
+      6C743B73746F70206F66667365743D2671756F743B302E3632352671756F743B
+      2073746F702D636F6C6F723D2671756F743B626C61636B2671756F743B207374
+      6F702D6F7061636974793D2671756F743B302E3835343930322671756F743B2F
+      2667743B262378443B262378413B2020202020202020266C743B73746F70206F
+      66667365743D2671756F743B302E363837352671756F743B2073746F702D636F
+      6C6F723D2671756F743B626C61636B2671756F743B2073746F702D6F70616369
+      74793D2671756F743B302E393634373035392671756F743B2F2667743B262378
+      443B262378413B2020202020202020266C743B73746F70206F66667365743D26
+      71756F743B302E37352671756F743B2073746F702D636F6C6F723D2671756F74
+      3B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B
+      312671756F743B2F2667743B262378443B262378413B2020202020202020266C
+      743B73746F70206F66667365743D2671756F743B302E383132352671756F743B
+      2073746F702D636F6C6F723D2671756F743B626C61636B2671756F743B207374
+      6F702D6F7061636974793D2671756F743B302E393634373035392671756F743B
+      2F2667743B262378443B262378413B2020202020202020266C743B73746F7020
+      6F66667365743D2671756F743B302E3837352671756F743B2073746F702D636F
+      6C6F723D2671756F743B626C61636B2671756F743B2073746F702D6F70616369
+      74793D2671756F743B302E3835343930322671756F743B2F2667743B26237844
+      3B262378413B2020202020202020266C743B73746F70206F66667365743D2671
+      756F743B302E393337352671756F743B2073746F702D636F6C6F723D2671756F
+      743B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F74
+      3B302E363930313936312671756F743B2F2667743B262378443B262378413B20
+      20202020202020266C743B73746F70206F66667365743D2671756F743B312671
+      756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671756F74
+      3B2073746F702D6F7061636974793D2671756F743B302E343938303339322671
+      756F743B2F2667743B262378443B262378413B202020202020266C743B2F6C69
+      6E6561724772616469656E742667743B262378443B262378413B20202020266C
+      743B2F646566732667743B262378443B262378413B20202020266C743B706174
+      6820643D2671756F743B4D352E35203920352E35203131203720313320372031
+      3520322031372032203233203330203233203330203137203235203135203235
+      2031332032362E352031312032362E352039207A2671756F743B2066696C6C3D
+      2671756F743B75726C28236C61796572312D66696C6C6772616431292671756F
+      743B207374726F6B653D2671756F743B6E6F6E652671756F743B2F2667743B26
+      2378443B262378413B2020266C743B2F672667743B262378443B262378413B26
+      6C743B2F7376672667743B262378443B262378413B222F3E0D0A20203C497465
+      6D39205356473D22266C743B3F786D6C2076657273696F6E3D2671756F743B31
+      2E302671756F743B20656E636F64696E673D2671756F743B7574662D38267175
+      6F743B3F2667743B262378443B262378413B266C743B7376672077696474683D
+      2671756F743B33322671756F743B20786D6C6E733D2671756F743B687474703A
+      2F2F7777772E77332E6F72672F323030302F7376672671756F743B2068656967
+      68743D2671756F743B33322671756F743B2076696577426F783D2671756F743B
+      3020302033322033322671756F743B20786D6C6E733A696E6B73636170653D26
+      71756F743B687474703A2F2F7777772E696E6B73636170652E6F72672F6E616D
+      657370616365732F696E6B73636170652671756F743B2667743B262378443B26
+      2378413B2020266C743B67206F7061636974793D2671756F743B312671756F74
+      3B20786D6C6E733A626772613D2671756F743B68747470733A2F2F77696B692E
+      6672656570617363616C2E6F72672F4C617A5061696E745F5356475F666F726D
+      61742671756F743B20696E6B73636170653A6C6162656C3D2671756F743B4C61
+      796572312671756F743B20696E6B73636170653A67726F75706D6F64653D2671
+      756F743B6C617965722671756F743B20626772613A6F726967696E616C566965
+      77426F783D2671756F743B322031362032382031352671756F743B2667743B26
+      2378443B262378413B20202020266C743B646566732667743B262378443B2623
+      78413B202020202020266C743B6C696E6561724772616469656E742069643D26
+      71756F743B6C61796572312D66696C6C67726164312671756F743B2078313D26
+      71756F743B31352671756F743B2078323D2671756F743B31352671756F743B20
+      79313D2671756F743B31342E35343136372671756F743B2079323D2671756F74
+      3B31382E35343136372671756F743B207370726561644D6574686F643D267175
+      6F743B7265706561742671756F743B206772616469656E74556E6974733D2671
+      756F743B7573657253706163654F6E5573652671756F743B20636F6C6F722D69
+      6E746572706F6C6174696F6E3D2671756F743B6C696E6561725247422671756F
+      743B2667743B262378443B262378413B2020202020202020266C743B73746F70
+      206F66667365743D2671756F743B302671756F743B2073746F702D636F6C6F72
+      3D2671756F743B626C61636B2671756F743B2073746F702D6F7061636974793D
+      2671756F743B302E343938303339322671756F743B2F2667743B262378443B26
+      2378413B2020202020202020266C743B73746F70206F66667365743D2671756F
+      743B302E303632352671756F743B2073746F702D636F6C6F723D2671756F743B
+      626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B30
+      2E333039383033392671756F743B2F2667743B262378443B262378413B202020
+      2020202020266C743B73746F70206F66667365743D2671756F743B302E313235
+      2671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B267175
+      6F743B2073746F702D6F7061636974793D2671756F743B302E31343530393826
+      71756F743B2F2667743B262378443B262378413B2020202020202020266C743B
+      73746F70206F66667365743D2671756F743B302E313837352671756F743B2073
+      746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F70
+      2D6F7061636974793D2671756F743B302E30333532393431322671756F743B2F
+      2667743B262378443B262378413B2020202020202020266C743B73746F70206F
+      66667365743D2671756F743B302E32352671756F743B2073746F702D636F6C6F
+      723D2671756F743B626C61636B2671756F743B2073746F702D6F706163697479
+      3D2671756F743B302671756F743B2F2667743B262378443B262378413B202020
+      2020202020266C743B73746F70206F66667365743D2671756F743B302E333132
+      352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671
+      756F743B2073746F702D6F7061636974793D2671756F743B302E303335323934
+      31322671756F743B2F2667743B262378443B262378413B202020202020202026
+      6C743B73746F70206F66667365743D2671756F743B302E3337352671756F743B
+      2073746F702D636F6C6F723D2671756F743B626C61636B2671756F743B207374
+      6F702D6F7061636974793D2671756F743B302E3134353039382671756F743B2F
+      2667743B262378443B262378413B2020202020202020266C743B73746F70206F
+      66667365743D2671756F743B302E343337352671756F743B2073746F702D636F
+      6C6F723D2671756F743B626C61636B2671756F743B2073746F702D6F70616369
+      74793D2671756F743B302E333039383033392671756F743B2F2667743B262378
+      443B262378413B2020202020202020266C743B73746F70206F66667365743D26
+      71756F743B302E352671756F743B2073746F702D636F6C6F723D2671756F743B
+      626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B30
+      2E343938303339322671756F743B2F2667743B262378443B262378413B202020
+      2020202020266C743B73746F70206F66667365743D2671756F743B302E353632
+      352671756F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671
+      756F743B2073746F702D6F7061636974793D2671756F743B302E363930313936
+      312671756F743B2F2667743B262378443B262378413B2020202020202020266C
+      743B73746F70206F66667365743D2671756F743B302E3632352671756F743B20
+      73746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F
+      702D6F7061636974793D2671756F743B302E3835343930322671756F743B2F26
+      67743B262378443B262378413B2020202020202020266C743B73746F70206F66
+      667365743D2671756F743B302E363837352671756F743B2073746F702D636F6C
+      6F723D2671756F743B626C61636B2671756F743B2073746F702D6F7061636974
+      793D2671756F743B302E393634373035392671756F743B2F2667743B26237844
+      3B262378413B2020202020202020266C743B73746F70206F66667365743D2671
+      756F743B302E37352671756F743B2073746F702D636F6C6F723D2671756F743B
+      626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B31
+      2671756F743B2F2667743B262378443B262378413B2020202020202020266C74
+      3B73746F70206F66667365743D2671756F743B302E383132352671756F743B20
+      73746F702D636F6C6F723D2671756F743B626C61636B2671756F743B2073746F
+      702D6F7061636974793D2671756F743B302E393634373035392671756F743B2F
+      2667743B262378443B262378413B2020202020202020266C743B73746F70206F
+      66667365743D2671756F743B302E3837352671756F743B2073746F702D636F6C
+      6F723D2671756F743B626C61636B2671756F743B2073746F702D6F7061636974
+      793D2671756F743B302E3835343930322671756F743B2F2667743B262378443B
+      262378413B2020202020202020266C743B73746F70206F66667365743D267175
+      6F743B302E393337352671756F743B2073746F702D636F6C6F723D2671756F74
+      3B626C61636B2671756F743B2073746F702D6F7061636974793D2671756F743B
+      302E363930313936312671756F743B2F2667743B262378443B262378413B2020
+      202020202020266C743B73746F70206F66667365743D2671756F743B31267175
+      6F743B2073746F702D636F6C6F723D2671756F743B626C61636B2671756F743B
+      2073746F702D6F7061636974793D2671756F743B302E34393830333932267175
+      6F743B2F2667743B262378443B262378413B202020202020266C743B2F6C696E
+      6561724772616469656E742667743B262378443B262378413B20202020266C74
+      3B2F646566732667743B262378443B262378413B20202020266C743B70617468
+      20643D2671756F743B4D352E352031362E303431363620352E352031382E3034
+      31363620372032302E303431363620372032322E303431363620322032342E30
+      3431363620322033302E30343136362033302033302E30343136362033302032
+      342E30343136362032352032322E30343136362032352032302E303431363620
+      32362E352031382E30343136362032362E352031362E3034313636207A267175
+      6F743B2066696C6C3D2671756F743B75726C28236C61796572312D66696C6C67
+      72616431292671756F743B207374726F6B653D2671756F743B6E6F6E65267175
+      6F743B2F2667743B262378443B262378413B2020266C743B2F672667743B2623
+      78443B262378413B266C743B2F7376672667743B262378443B262378413B222F
+      3E0D0A3C2F434F4E4649473E0D0A
+    }
+  end
+  object SVGRasterImageList1: TBGRAImageList
+    Scaled = True
+    Left = 653
+    Top = 216
+    Bitmap = {
+      4C7A0A0000001000000010000000D90300000000000078DAED9AEB4B145118C6
+      77575D3745BBA1959154BA84A56592D98D0AA220A80F29DDCBB2302FA4D03D2A
+      A3AB9154DA05CC2222A1A2E80A417401A53B5B7D32128CBEF4298220A83FA0E7
+      D0B3701866C63367B6B5705EF831EC719E3967CE9CF73DEF7BD0E78BB915814A
+      52A4A117BA08A9ECE7FA765E3BC165B01C2469E8659A81DFC1F81340189C97DA
+      8B35DE7F8CD4BE5A435F20B5AF70A04F0685E0AAD49EE762FE0E6ACCFF73700D
+      94733E3D8BAF35F03BCCD7D4DF032F40AA8B318434754BB9A6066968878337E0
+      7E2F3E6F65EB396F559A63BF497DB6867602B59734FBDE417D998636113CE637
+      4FD7D0CF61DFC73DD78BBBD5839986F5BE1DCC50D43FA2BF05A4B667A04251DF
+      01AA0D7A27B9C0BFA0DF2CED53E90EF54F4093A45FE0502F7CE6153802F682EB
+      0EF503C13EEEB7621C59A011CC8BC3DA6B35C9178CB4FE45BD67B135BF42BE6D
+      6622BFBCC0752CBED91DEE09AA7BCF43F01AEC67DC69E75E94A5A0CF649F270D
+      3140A56E13BAB7E03BF8057E802FE083610D16D9E805EFC027F015FCE4B3BE81
+      F7367A2B0B329E09DD1285FBA37546BD212688B6950A7A11B71EF0DB1D039B58
+      333D653EA562D9D47490168EAB3F59126BAF10D7B4134B609C1375EF477E4B27
+      6B7928D80546D1173F731D39B561E0369FA553B7AD03A7C000CD395CC6BA37E0
+      D05FE49A3953CA85820ADA169BBFB7D83C23AA8DD8E82316CF90B52A189FE156
+      EF76FCB1983F9FC2370AC6D17727B1762A5058FB41D66B22EF1E0F66315F6BE4
+      B5803E99225D659B0E6A402D3804CE809DCC051B78DEB3182CE235D3A017FBC3
+      36309BDA5BFC5DCF3DB49A35C00DB015A419F41BC11E500A2E527F94E735A2FF
+      0D6037BF7FB9C9FB17B25DF473009CA3DF8B3ED7704EAAF8EC628B3C6304C805
+      A3390E113B4AD8EE67FEBA4A710F1279C25843DC116DE35CC422D5F5EBD3F49F
+      884BFF75AB773BFE78CC5FBCFCBFAF4CC499C1CC19C43A1DC233B7007388E8FB
+      A758E847B27EAFA5AF74B20614EDF9602D7392C336F9BEC84D4FF0BE0C709AB9
+      7B1ACF0116829716FA14F6D12CE53C15F4DD69E02EEBE3B316EF3E155CE13A99
+      CB7C57C4912D7CA732B637999C4526307E4C061379DE51CA9C57C4CC299C073F
+      DF215563FF52C91D222EB5AAC452EF76FCB198BFFEE2E35626F6BA1E454A2C7C
+      57D45DE15EC8F6599F85D729F45D67A24B664E92A3D07F0EEF4D96F43D9A442D
+      AC49ACFAF7CCB3FFDD12996FA860769E21F6DE6E059FE9E6BD6696A1E0B31916
+      5A5127B429F4DFC67B8DDA5C077123D7F08CBE8E5F759A78E699677F4C9C4B74
+      2962768611A04FE6F742D8E63CB346A1EF1A135D88F1284FA1FF3CDE2BFF3F46
+      972651CBD72456FD6BDB6F31F08DBA
+    }
+  end
+  object TimerHideTextMore: TTimer
+    Enabled = False
+    Interval = 3000
+    OnTimer = TimerHideFillTimer
+    Left = 653
+    Top = 272
   end
 end

+ 14 - 0
lazpaint/lazpaintmainform.lrj

@@ -26,6 +26,8 @@
 {"hash":142786864,"name":"tfmain.tool_capsquare.hint","sourcebytes":[83,113,117,97,114,101,32,99,97,112],"value":"Square cap"},
 {"hash":224157463,"name":"tfmain.spinedit_arrowsizex.hint","sourcebytes":[72,111,114,105,122,111,110,116,97,108,32,115,105,122,101,32,111,102,32,116,104,101,32,97,114,114,111,119],"value":"Horizontal size of the arrow"},
 {"hash":47574855,"name":"tfmain.spinedit_arrowsizey.hint","sourcebytes":[86,101,114,116,105,99,97,108,32,115,105,122,101,32,111,102,32,116,104,101,32,97,114,114,111,119],"value":"Vertical size of the arrow"},
+{"hash":65090695,"name":"tfmain.combobox_arrowstart.hint","sourcebytes":[83,116,97,114,116,105,110,103,32,97,114,114,111,119],"value":"Starting arrow"},
+{"hash":229386535,"name":"tfmain.combobox_arrowend.hint","sourcebytes":[69,110,100,105,110,103,32,97,114,114,111,119],"value":"Ending arrow"},
 {"hash":199465278,"name":"tfmain.tool_joinbevel.hint","sourcebytes":[66,101,118,101,108,32,106,111,105,110],"value":"Bevel join"},
 {"hash":73704254,"name":"tfmain.tool_joinround.hint","sourcebytes":[82,111,117,110,100,32,106,111,105,110],"value":"Round join"},
 {"hash":205804894,"name":"tfmain.tool_joinmiter.hint","sourcebytes":[77,105,116,101,114,32,106,111,105,110],"value":"Miter join"},
@@ -78,6 +80,16 @@
 {"hash":264792562,"name":"tfmain.image_swapcolors.hint","sourcebytes":[83,119,105,116,99,104,32,99,111,108,111,114],"value":"Switch color"},
 {"hash":296859,"name":"tfmain.label_back.caption","sourcebytes":[66,97,99,107],"value":"Back"},
 {"hash":76172398,"name":"tfmain.button_donate.caption","sourcebytes":[68,111,110,97,116,101,46,46,46],"value":"Donate..."},
+{"hash":300580,"name":"tfmain.tool_textbold.hint","sourcebytes":[66,111,108,100],"value":"Bold"},
+{"hash":84574963,"name":"tfmain.tool_textitalic.hint","sourcebytes":[73,116,97,108,105,99],"value":"Italic"},
+{"hash":180974597,"name":"tfmain.tool_textunderline.hint","sourcebytes":[85,110,100,101,114,108,105,110,101],"value":"Underline"},
+{"hash":151125108,"name":"tfmain.tool_textstrikeout.hint","sourcebytes":[83,116,114,105,107,101,111,117,116],"value":"Strikeout"},
+{"hash":39152780,"name":"tfmain.tool_textbidirectional.hint","sourcebytes":[66,105,100,105,114,101,99,116,105,111,110,97,108],"value":"Bidirectional"},
+{"hash":63280628,"name":"tfmain.tool_textltr.hint","sourcebytes":[76,101,102,116,32,116,111,32,114,105,103,104,116],"value":"Left to right"},
+{"hash":65854964,"name":"tfmain.tool_textrtl.hint","sourcebytes":[82,105,103,104,116,32,116,111,32,108,101,102,116],"value":"Right to left"},
+{"hash":266351424,"name":"tfmain.tool_textaligntop.hint","sourcebytes":[65,108,105,103,110,32,116,111,112],"value":"Align top"},
+{"hash":116886537,"name":"tfmain.tool_textalignmiddle.hint","sourcebytes":[67,101,110,116,101,114,32,118,101,114,116,105,99,97,108,108,121],"value":"Center vertically"},
+{"hash":34882909,"name":"tfmain.tool_textalignbottom.hint","sourcebytes":[65,108,105,103,110,32,98,111,116,116,111,109],"value":"Align bottom"},
 {"hash":88908046,"name":"tfmain.filenew.caption","sourcebytes":[78,101,119,46,46,46],"value":"New..."},
 {"hash":111833829,"name":"tfmain.filenew.hint","sourcebytes":[67,114,101,97,116,101,32,97,32,110,101,119,32,102,105,108,101],"value":"Create a new file"},
 {"hash":107745630,"name":"tfmain.fileopen.caption","sourcebytes":[79,112,101,110,46,46,46],"value":"Open..."},
@@ -279,6 +291,8 @@
 {"hash":51121525,"name":"tfmain.toolopenedcurve.hint","sourcebytes":[79,112,101,110,101,100,32,99,117,114,118,101],"value":"Opened curve"},
 {"hash":124337662,"name":"tfmain.fileexport.caption","sourcebytes":[69,120,112,111,114,116,46,46,46],"value":"Export..."},
 {"hash":124337662,"name":"tfmain.layerexport.hint","sourcebytes":[69,120,112,111,114,116,46,46,46],"value":"Export..."},
+{"hash":164762421,"name":"tfmain.filequicksave.caption","sourcebytes":[81,117,105,99,107,32,115,97,118,101],"value":"Quick save"},
+{"hash":215358547,"name":"tfmain.filequicksave.hint","sourcebytes":[83,97,118,101,32,99,117,114,114,101,110,116,32,102,105,108,101,32,119,105,116,104,111,117,116,32,100,105,97,108,111,103,115],"value":"Save current file without dialogs"},
 {"hash":66536946,"name":"tfmain.colordialog1.title","sourcebytes":[67,104,111,111,115,101,32,99,111,108,111,114],"value":"Choose color"},
 {"hash":315429,"name":"tfmain.menufile.caption","sourcebytes":[70,105,108,101],"value":"File"},
 {"hash":167619026,"name":"tfmain.itemuseimagebrowser.caption","sourcebytes":[85,115,101,32,105,109,97,103,101,32,98,114,111,119,115,101,114],"value":"Use image browser"},

+ 132 - 32
lazpaint/lazpaintmainform.pas

@@ -8,13 +8,15 @@ interface
 uses
   Classes, LMessages, SysUtils, LazFileUtils, LResources, Forms, Controls,
   Graphics, Dialogs, Menus, ExtDlgs, ComCtrls, ActnList, StdCtrls, ExtCtrls,
-  Buttons, types, LCLType, BGRAImageList, BCTrackbarUpdown, BCComboBox, BCButton,
+  Buttons, types, LCLType, BGRAImageList, BCTrackbarUpdown, BCComboBox,
+  BCButton, BGRASVGImageList,
 
   BGRABitmap, BGRABitmapTypes, BGRALayers, BGRASVGOriginal, BGRAGradientScanner, BGRAGradientOriginal,
 
   LazPaintType, UMainFormLayout, UTool, UImage, UImageAction, UZoom,
   UImageObservation, UConfig, LCScaleDPI, UResourceStrings, UMenu, uscripting,
-  ubrowseimages, UToolPolygon, UToolVectorial, LCVectorRectShapes,
+  ubrowseimages, UToolPolygon, UToolVectorial, UToolDeformationGrid, UToolSelect,
+  UToolBasic, UToolBrush, LCVectorRectShapes,
   LCVectorialFillControl, LCVectorialFill,
 
   udarktheme, UScriptType;
@@ -23,6 +25,10 @@ type
   { TFMain }
 
   TFMain = class(TForm)
+    FileQuickSave: TAction;
+    SVGRasterImageList1: TBGRAImageList;
+    Panel_TextMore: TPanel;
+    SVGImageList1: TBGRASVGImageList;
     Button_Donate: TBCButton;
     LayerExport: TAction;
     FileExport: TAction;
@@ -30,6 +36,19 @@ type
     MenuScript: TMenuItem;
     Panel_OutlineFill: TPanel;
     Panel_Donate: TPanel;
+    TimerHideTextMore: TTimer;
+    ToolBar25: TToolBar;
+    ToolButton1: TToolButton;
+    ToolButton2: TToolButton;
+    Tool_TextAlignBottom: TToolButton;
+    Tool_TextAlignMiddle: TToolButton;
+    Tool_TextAlignTop: TToolButton;
+    Tool_TextRTL: TToolButton;
+    Tool_TextBidirectional: TToolButton;
+    Tool_TextLTR: TToolButton;
+    Tool_TextItalic: TToolButton;
+    Tool_TextUnderline: TToolButton;
+    Tool_TextStrikeout: TToolButton;
     ToolOpenedCurve: TAction;
     ToolPolyline: TAction;
     FileRunScript: TAction;
@@ -56,6 +75,7 @@ type
     Tool_EraseSharpen: TToolButton;
     Tool_EraseLighten: TToolButton;
     Tool_EraseDarken: TToolButton;
+    Tool_TextBold: TToolButton;
     VectorialFill_Outline: TLCVectorialFillControl;
     VectorialFill_Pen: TLCVectorialFillControl;
     VectorialFill_Back: TLCVectorialFillControl;
@@ -468,6 +488,7 @@ type
     procedure FileExportExecute(Sender: TObject);
     procedure FileImport3DUpdate(Sender: TObject);
     procedure FilePrintExecute(Sender: TObject);
+    procedure FileQuickSaveExecute(Sender: TObject);
     procedure FileRememberSaveFormatExecute(Sender: TObject);
     procedure FileRunScriptExecute(Sender: TObject);
     procedure FileSaveAsInSameFolderExecute(Sender: TObject);
@@ -496,6 +517,10 @@ type
     procedure MenuZoomToolbarClick(Sender: TObject);
     procedure PaintBox_PenPreviewMouseDown(Sender: TObject;
       {%H-}Button: TMouseButton; {%H-}Shift: TShiftState; X, Y: Integer);
+    procedure Panel_TextMoreMouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
+      {%H-}Y: Integer);
+    procedure Panel_TextMouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
+      {%H-}Y: Integer);
     procedure PopupToolbarPopup(Sender: TObject);
     procedure PopupToolboxPopup(Sender: TObject);
     procedure SelectionHorizontalFlipUpdate(Sender: TObject);
@@ -564,6 +589,7 @@ type
     procedure SpinEdit_TextShadowYChange(Sender: TObject; AByUser: boolean);
     procedure TimerUpdateTimer(Sender: TObject);
     procedure TimerHidePenPreviewTimer(Sender: TObject);
+    procedure TimerHideTextMoreTimer(Sender: TObject);
     procedure ToolChangeDockingExecute(Sender: TObject);
     procedure ToolHotSpotUpdate(Sender: TObject);
     procedure ToolRotateSelectionUpdate(Sender: TObject);
@@ -577,6 +603,8 @@ type
     procedure Tool_PhongShapeVerticalCylinderClick(Sender: TObject);
     procedure ToolLayerMappingUpdate(Sender: TObject);
     procedure Tool_TextAlignClick(Sender: TObject);
+    procedure Tool_TextBidiModeClick(Sender: TObject);
+    procedure Tool_TextStyleClick(Sender: TObject);
     procedure Tool_TextPhongClick(Sender: TObject);
     procedure Tool_GridMoveWithoutDeformationClick(Sender: TObject);
     procedure Tool_PhongShapeConeClick(Sender: TObject);
@@ -675,6 +703,7 @@ type
     procedure VectorialFill_Change(Sender: TObject);
     procedure vectorialFill_ClickLabel(Sender: TObject);
     procedure VectorialFill_TypeChange(Sender: TObject);
+    procedure VectorialFill_OpacityChange(Sender: TObject);
     procedure VectorialFill_Resize(Sender: TObject);
     procedure VectorialFill_EditGradTexPoints(Sender: TObject);
     procedure VectorialFill_AdjustToShape(Sender: TObject);
@@ -781,11 +810,13 @@ type
     procedure ToggleLayersVisible;
     function ShowColorDialogFor(ATarget: TColorTarget): boolean;
     procedure ShowPenPreview(ShouldRepaint: boolean= False);
+    procedure ShowTextMore;
     procedure HidePenPreview(ATimeMs: Integer = 300; AClearTime: boolean = false);
+    procedure HideTextMore(ATimeMs: Integer = 300; AClearTime: boolean = false);
     procedure ShowFill(AFillControl: TLCVectorialFillControl; APanel: TPanel);
     procedure HideFill(ATimeMs: Integer = 300; AClearTime: boolean = false);
     procedure OnImageChangedHandler({%H-}AEvent: TLazPaintImageObservationEvent);
-    procedure OnImageRenderChanged({%H-}Sender: TObject);
+    procedure OnImageRenderChanged({%H-}Sender: TLazPaintImage; AInvalidateAll: boolean);
     procedure LabelAutosize(ALabel: TLabel; ATargetDPI: integer);
     procedure AskMergeSelection(ACaption: string);
     procedure UpdateSpecialKeys({%H-}Shift: TShiftState);
@@ -825,12 +856,14 @@ type
     procedure CallScriptFunction(AName:string); overload;
     procedure CallScriptFunction(AParams:TVariableSet); overload;
     procedure ZoomFitIfTooBig;
+    function RunToolCommand(AToolCommand: TToolCommand): boolean;
     property Scripting: TScriptContext read GetScriptContext;
     property Image: TLazPaintImage read GetImage;
 
   public
     { public declarations }
     Zoom: TZoom;
+    Closing: boolean;
 
     procedure PaintPictureNow;
     procedure PaintPictureLater;
@@ -845,7 +878,7 @@ type
     procedure AddDockedControl(AControl: TControl);
     procedure RemoveDockedControl(AControl: TControl);
     procedure QueryArrange;
-    function ChooseTool(Tool : TPaintToolType): boolean;
+    function ChooseTool(Tool : TPaintToolType; AAsFromGui: boolean = true): boolean;
     procedure PictureSelectedLayerIndexChanged({%H-}sender: TLazPaintImage);
     procedure PictureSelectedLayerIndexChanging({%H-}sender: TLazPaintImage);
     property LazPaintInstance: TLazPaintCustomInstance read FLazPaintInstance write SetLazPaintInstance;
@@ -1097,6 +1130,10 @@ begin
   Panel_Coordinates.Visible := Config.DefaultCoordinatesToolbarVisible;
   FLayout.ToolBoxPopup := PopupToolbox;
 
+  {$IFDEF DARWIN}
+  ImageHorizontalFlip.ShortCut := ShortCut(VK_H, [ssMeta, ssCtrl]);
+  {$ENDIF}
+
   if not LazPaintInstance.Embedded then
   begin
     FOnlineUpdater := LazPaintInstance.GetOnlineUpdater;
@@ -1163,6 +1200,8 @@ begin
     m.Apply;
     FLayout.Menu := m;
 
+    SVGImageList1.Width := iconSize;
+    SVGImageList1.Height := iconSize;
     Button_Donate.Images := m.ImageList;
     w := Button_Donate.Width; h := Button_Donate.Height;
     Button_Donate.GetPreferredSize(w, h);
@@ -1481,7 +1520,6 @@ begin
     {$WARNINGS ON}
     filename := ExtractFileName(filename);
   end else initialDir:= '';
-  if filename = '' then filename := rsNoName;
   if initialDir = '' then
   begin
     if AVars.Booleans['Export'] then
@@ -1489,6 +1527,11 @@ begin
     else
       initialDir:= FSaveInitialDir;
   end;
+  if filename = '' then
+  begin
+    if initialDir = '' then initialDir := DefaultPicturesDirectory;
+    filename := FileManager.GetDefaultFilename(initialDir);
+  end;
   if saveDlg.FilterIndex > 1 then
     filename := ApplySelectedFilterExtension(filename,saveDlg.Filter,saveDlg.FilterIndex);
   if not Image.AbleToSaveAsUTF8(filename) then
@@ -1568,7 +1611,7 @@ end;
 function TFMain.ScriptFileSave(AVars: TVariableSet): TScriptResult;
 begin
   if (Image.CurrentFilenameUTF8 = '') or not Image.AbleToSaveAsUTF8(Image.CurrentFilenameUTF8) then
-    result := Scripting.CallScriptFunction('FileSaveAs', True) else
+    result := Scripting.CallScriptFunction('FileSaveAs', True, AVars) else
     begin
       AskMergeSelection(rsSave);
       try
@@ -1708,6 +1751,7 @@ end;
 procedure TFMain.FileSaveUpdate(Sender: TObject);
 begin
    FileSave.Enabled := image.IsFileModified;
+   FileQuickSave.Enabled := image.IsFileModified;
 end;
 
 procedure TFMain.FilterAnyExecute(Sender: TObject);
@@ -1839,6 +1883,12 @@ begin
       Key := 0;
       if not ToolManager.ToolSleeping and ([ssLeft,ssRight] * FLayout.MouseButtonState = []) then ToolManager.ToolSleep;
     end else
+    If (Key = VK_ESCAPE) and not Image.SelectionMaskEmpty and Image.SelectionLayerIsEmpty
+     and EditDeselect.Enabled then
+    begin
+      if EditDeselect.Execute then
+        Key := 0;
+    end else
     if LazPaintInstance.ImageListWindowVisible then
       LazPaintInstance.ImageListWindowVisibleKeyDown(Key,Shift);
     If Key = 0 then UpdateToolbar;
@@ -2126,8 +2176,15 @@ var
   svgOrig: TBGRALayerSVGOriginal;
 begin
   if Length(FileNames)<1 then exit;
-  if Length(FileNames)= 1
-     then TryOpenFileUTF8(FileNames[0])
+  if Length(FileNames)= 1 then
+  begin
+    if Image.IsFileModified then
+      case LazPaintInstance.SaveQuestion(rsOpen) of
+        IDYES: Scripting.CallScriptFunction('FileSave');
+        IDCANCEL: exit;
+      end;
+    TryOpenFileUTF8(FileNames[0]);
+  end
   else
      begin
        {$IFNDEF LINUX}
@@ -2274,7 +2331,7 @@ begin
     end else
     if UTF8Key <> '' then
     begin
-      if UTF8UpperCase(UTF8Key) = 'X' then
+      if UTF8UpperCase(UTF8Key) = SwitchColorShortcut then
       begin
         SwitchColors;
         UTF8Key:= '';
@@ -2484,6 +2541,7 @@ begin
   if ToolManager.ToolSleeping then
   begin
     CanClose := false;
+    LazPaintInstance.CancelRestart;
     exit;
   end;
   if CurrentTool in [ptDeformation,ptLayerMapping] then
@@ -2492,6 +2550,7 @@ begin
     if not Image.CheckNoAction then
     begin
       CanClose := false;
+      LazPaintInstance.CancelRestart;
       exit;
     end;
   if not LazPaintInstance.Embedded and image.IsFileModified and not image.Empty then
@@ -2499,12 +2558,19 @@ begin
     topmostInfo:= LazPaintInstance.HideTopmost;
 
     case LazPaintInstance.SaveQuestion(rsExitRequest) of
-    IDYES: FileSave.Execute;
+    IDYES: if scripting.CallScriptFunction('FileSave') <> srOk then
+           begin
+             CanClose := false;
+             LazPaintInstance.CancelRestart;
+             LazPaintInstance.ShowTopmost(topmostInfo);
+             exit;
+           end;
     IDNO: ;
     IDCANCEL: begin
                 CanClose := false;
                 LazPaintInstance.CancelRestart;
                 LazPaintInstance.ShowTopmost(topmostInfo);
+                exit;
               end;
     end;
   end else
@@ -2611,15 +2677,17 @@ begin
 end;
 
 procedure TFMain.LanguageClick(Sender: TObject);
-var language: string;
+var language, prevLanguage: string;
 begin
   if Sender is TMenuItem then
   begin
     language := (Sender as TMenuItem).Caption;
     if Config.DefaultLangage <> language then
     begin
+      prevLanguage := Config.DefaultLangage;
       Config.SetDefaultLangage(language);
-      LazPaintInstance.Restart;
+      if not LazPaintInstance.Restart then
+        Config.SetDefaultLangage(prevLanguage);
     end;
   end;
 end;
@@ -2802,12 +2870,12 @@ begin
   end;
 end;
 
-function TFMain.ChooseTool(Tool: TPaintToolType): boolean;
+function TFMain.ChooseTool(Tool: TPaintToolType; AAsFromGui: boolean): boolean;
 var params: TVariableSet;
 begin
   params := TVariableSet.Create('ChooseTool');
   params.AddString('Name', PaintToolTypeStr[Tool]);
-  params.AddBoolean('FromGUI', true);
+  params.AddBoolean('FromGUI', AAsFromGui);
   result := Scripting.CallScriptFunction(params) = srOk;
   params.Free;
 end;
@@ -3329,7 +3397,7 @@ end;
 
 procedure TFMain.EditShapeAlignBottomExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcAlignBottom);
+  RunToolCommand(tcAlignBottom);
 end;
 
 procedure TFMain.EditShapeAlignBottomUpdate(Sender: TObject);
@@ -3339,7 +3407,7 @@ end;
 
 procedure TFMain.EditShapeAlignLeftExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcAlignLeft);
+  RunToolCommand(tcAlignLeft);
 end;
 
 procedure TFMain.EditShapeAlignLeftUpdate(Sender: TObject);
@@ -3349,7 +3417,7 @@ end;
 
 procedure TFMain.EditShapeAlignRightExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcAlignRight);
+  RunToolCommand(tcAlignRight);
 end;
 
 procedure TFMain.EditShapeAlignRightUpdate(Sender: TObject);
@@ -3359,7 +3427,7 @@ end;
 
 procedure TFMain.EditShapeAlignTopExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcAlignTop);
+  RunToolCommand(tcAlignTop);
 end;
 
 procedure TFMain.EditShapeAlignTopUpdate(Sender: TObject);
@@ -3369,7 +3437,7 @@ end;
 
 procedure TFMain.EditShapeCenterHorizontallyExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcCenterHorizontally);
+  RunToolCommand(tcCenterHorizontally);
 end;
 
 procedure TFMain.EditShapeCenterHorizontallyUpdate(Sender: TObject);
@@ -3379,7 +3447,7 @@ end;
 
 procedure TFMain.EditShapeCenterVerticallyExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcCenterVertically);
+  RunToolCommand(tcCenterVertically);
 end;
 
 procedure TFMain.EditShapeCenterVerticallyUpdate(Sender: TObject);
@@ -3390,7 +3458,7 @@ end;
 procedure TFMain.EditShapeToCurveExecute(Sender: TObject);
 begin
   if ToolManager.CurrentTool is TVectorialTool then ChooseTool(ptEditShape);
-  ToolManager.ToolCommand(tcShapeToSpline);
+  RunToolCommand(tcShapeToSpline);
 end;
 
 procedure TFMain.EditShapeToCurveUpdate(Sender: TObject);
@@ -3424,7 +3492,7 @@ end;
 
 procedure TFMain.EditCopyExecute(Sender: TObject);
 begin
-  if not ToolManager.ToolCommand(tcCopy) then
+  if not RunToolCommand(tcCopy) then
     Scripting.CallScriptFunction('EditCopy');
 end;
 
@@ -3435,7 +3503,7 @@ end;
 
 procedure TFMain.EditCutExecute(Sender: TObject);
 begin
-  if not ToolManager.ToolCommand(tcCut) then
+  if not RunToolCommand(tcCut) then
     Scripting.CallScriptFunction('EditCut');
 end;
 
@@ -3448,19 +3516,22 @@ end;
 
 procedure TFMain.EditDeleteSelectionExecute(Sender: TObject);
 begin
-  if not ToolManager.ToolCommand(tcDelete) then
+  if not RunToolCommand(tcDelete) then
     Scripting.CallScriptFunction('EditDeleteSelection');
 end;
 
 procedure TFMain.EditDeleteSelectionUpdate(Sender: TObject);
 begin
-  EditDeleteSelection.Enabled := ToolManager.ToolProvideCommand(tcDelete) or not image.SelectionMaskEmpty;
+  EditDeleteSelection.Enabled := ToolManager.ToolProvideCommand(tcDelete)
+                                 or not image.SelectionMaskEmpty
+                                 or ((ToolManager.GetCurrentToolType in [ptMoveLayer,
+                                     ptZoomLayer, ptRotateLayer]) and (image.NbLayers > 1));
 end;
 
 procedure TFMain.EditMoveDownExecute(Sender: TObject);
 begin
   if ToolManager.CurrentTool is TVectorialTool then ChooseTool(ptEditShape);
-  ToolManager.ToolCommand(tcMoveDown);
+  RunToolCommand(tcMoveDown);
 end;
 
 procedure TFMain.EditMoveDownUpdate(Sender: TObject);
@@ -3471,7 +3542,7 @@ end;
 procedure TFMain.EditMoveToBackExecute(Sender: TObject);
 begin
   if ToolManager.CurrentTool is TVectorialTool then ChooseTool(ptEditShape);
-  ToolManager.ToolCommand(tcMoveToBack);
+  RunToolCommand(tcMoveToBack);
 end;
 
 procedure TFMain.EditMoveToBackUpdate(Sender: TObject);
@@ -3481,7 +3552,7 @@ end;
 
 procedure TFMain.EditMoveToFrontExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcMoveToFront);
+  RunToolCommand(tcMoveToFront);
 end;
 
 procedure TFMain.EditMoveToFrontUpdate(Sender: TObject);
@@ -3491,7 +3562,7 @@ end;
 
 procedure TFMain.EditMoveUpExecute(Sender: TObject);
 begin
-  ToolManager.ToolCommand(tcMoveUp);
+  RunToolCommand(tcMoveUp);
 end;
 
 procedure TFMain.EditMoveUpUpdate(Sender: TObject);
@@ -3501,7 +3572,7 @@ end;
 
 procedure TFMain.EditPasteExecute(Sender: TObject);
 begin
-  if not ToolManager.ToolCommand(tcPaste) then
+  if not RunToolCommand(tcPaste) then
     Scripting.CallScriptFunction('EditPaste');
 end;
 
@@ -3520,6 +3591,15 @@ begin
   LazPaintInstance.ShowPrintDlg;
 end;
 
+procedure TFMain.FileQuickSaveExecute(Sender: TObject);
+var params: TVariableSet;
+begin
+  params := TVariableSet.Create('FileSave');
+  params.Booleans['SkipOptions'] := true;
+  Scripting.CallScriptFunction(params);
+  params.Free;
+end;
+
 procedure TFMain.FileRememberSaveFormatExecute(Sender: TObject);
 begin
   FileRememberSaveFormat.Checked := not FileRememberSaveFormat.Checked;
@@ -3590,6 +3670,13 @@ begin
   Config.SetDefaultRetrieveSelectionAnswer(0);
   for m := low(TToolPopupMessage) to high(TToolPopupMessage) do
     Config.SetToolPopupMessageShownCount(ord(m), 0);
+  UToolPolygon.TToolPolygon.ForgetHintShown;
+  UToolVectorial.TVectorialTool.ForgetHintShown;
+  UToolDeformationGrid.TToolTextureMapping.ForgetHintShown;
+  UToolDeformationGrid.TToolDeformationGrid.ForgetHintShown;
+  UToolSelect.TToolRotateSelection.ForgetHintShown;
+  UToolBasic.TToolPen.ForgetHintShown;
+  UToolBrush.TToolBrush.ForgetHintShown;
 end;
 
 procedure TFMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
@@ -4056,6 +4143,17 @@ begin
   end;
 end;
 
+function TFMain.RunToolCommand(AToolCommand: TToolCommand): boolean;
+begin
+  if ToolManager.ToolCommand(AToolCommand) then
+  begin
+    PaintPictureNow;
+    UpdateToolbar;
+    result := true;
+  end
+  else result := false;
+end;
+
 function TFMain.TryOpenFileUTF8(filenameUTF8: string; AddToRecent: Boolean;
      ALoadedImage: PImageEntry; ASkipDialogIfSingleImage: boolean;
      AAllowDuplicate: boolean; AEntryToLoad: integer): Boolean;
@@ -4214,9 +4312,9 @@ begin
   end;
 end;
 
-procedure TFMain.OnImageRenderChanged(Sender: TObject);
+procedure TFMain.OnImageRenderChanged(Sender: TLazPaintImage; AInvalidateAll: boolean);
 begin
-  InvalidatePicture(false);
+  InvalidatePicture(AInvalidateAll);
 end;
 
 procedure TFMain.UpdateEditPicture(ADelayed: boolean = false);
@@ -4255,6 +4353,7 @@ end;
 procedure TFMain.PictureMouseMove(Sender: TObject; APosition: TPointF);
 begin
   HidePenPreview;
+  HideTextMore;
   HideFill;
 
   FCoordinatesCaption := IntToStr(round(APosition.X))+','+IntToStr(round(APosition.Y));
@@ -4469,6 +4568,7 @@ begin
   begin
     Layout.DarkTheme := AValue;
     DarkThemeInstance.Apply(Panel_PenWidthPreview, AValue);
+    DarkThemeInstance.Apply(Panel_TextMore, AValue);
     Invalidate;
     UpdateToolImage(true);
   end;

+ 10 - 3
lazpaint/lazpainttype.pas

@@ -11,7 +11,7 @@ uses
   {$IFDEF LINUX}, InterfaceBase{$ENDIF};
 
 const
-  LazPaintVersion = 7010600;
+  LazPaintVersion = 7020000;
 
   function LazPaintVersionStr: string;
 
@@ -129,6 +129,7 @@ type
       class function Empty: TImageEntry; static;
       class function NewFrameIndex: integer; static;
       procedure FreeAndNil;
+      procedure Release;
     end;
     ArrayOfImageEntry = array of TImageEntry;
 
@@ -244,7 +245,7 @@ type
     procedure Show; virtual; abstract;
     function Hide: boolean; virtual; abstract;
     procedure Run; virtual; abstract;
-    procedure Restart; virtual; abstract;
+    function Restart: boolean; virtual; abstract;
     procedure CancelRestart; virtual; abstract;
     procedure NotifyImageChange(RepaintNow: boolean; ARect: TRect); virtual; abstract;
     procedure NotifyImageChangeCompletely(RepaintNow: boolean); virtual; abstract;
@@ -306,7 +307,7 @@ type
     procedure InvalidateLayerStack; virtual; abstract;
     procedure UpdateLayerStackOnTimer; virtual; abstract;
     function MakeNewBitmapReplacement(AWidth, AHeight: integer; AColor: TBGRAPixel): TBGRABitmap; virtual; abstract;
-    procedure ChooseTool(Tool : TPaintToolType); virtual; abstract;
+    procedure ChooseTool(Tool : TPaintToolType; AAsFromGui: boolean); virtual; abstract;
     function GetOnlineUpdater: TLazPaintCustomOnlineUpdater; virtual;
 
     property GridVisible: boolean read GetGridVisible write SetGridVisible;
@@ -603,6 +604,12 @@ begin
   bpp := 0;
 end;
 
+procedure TImageEntry.Release;
+begin
+  bmp := nil;
+  bpp := 0;
+end;
+
 function TLazPaintCustomInstance.GetDarkTheme: boolean;
 begin
   if Assigned(Config) then

+ 124 - 4
lazpaint/maintoolbar.inc

@@ -1,4 +1,6 @@
 // SPDX-License-Identifier: GPL-3.0-only
+const SwitchColorShortcut = 'R';
+
 procedure TFMain.CreateToolbarElements;
 
   procedure InitVectorialFill(vf: TLCVectorialFillControl; grad: TBGRALayerGradientOriginal;
@@ -11,6 +13,7 @@ procedure TFMain.CreateToolbarElements;
     vf.OnFillChange:=    @VectorialFill_Change;
     vf.AutoSize := False;
     vf.OnFillTypeChange:=    @VectorialFill_TypeChange;
+    vf.OnOpacityChange:=     @VectorialFill_OpacityChange;
     vf.OnAdjustToShape:=     @VectorialFill_AdjustToShape;
     vf.OnEditGradTexPoints:= @VectorialFill_EditGradTexPoints;
     vf.OnResize:= @VectorialFill_Resize;
@@ -110,15 +113,28 @@ begin
   Tool_TextAlignLeft.OnClick := @Tool_TextAlignClick;
   Tool_TextAlignCenter.OnClick := @Tool_TextAlignClick;
   Tool_TextAlignRight.OnClick := @Tool_TextAlignClick;
+  Tool_TextBidirectional.OnClick := @Tool_TextBidiModeClick;
+  Tool_TextLTR.OnClick := @Tool_TextBidiModeClick;
+  Tool_TextRTL.OnClick := @Tool_TextBidiModeClick;
+  Tool_TextAlignTop.OnClick := @Tool_TextAlignClick;
+  Tool_TextAlignMiddle.OnClick := @Tool_TextAlignClick;
+  Tool_TextAlignBottom.OnClick := @Tool_TextAlignClick;
+  Tool_TextBold.OnClick := @Tool_TextStyleClick;
+  Tool_TextItalic.OnClick := @Tool_TextStyleClick;
+  Tool_TextUnderline.OnClick := @Tool_TextStyleClick;
+  Tool_TextStrikeout.OnClick := @Tool_TextStyleClick;
   Tool_TextPhong.OnClick := @Tool_TextPhongClick;
   Tool_TextShadow.OnClick := @Tool_TextShadowClick;
   Tool_TextOutline.OnClick := @Tool_TextOutlineClick;
+  Panel_TextMore.AutoSize := true;
   Panel_ToolbarBackground.OnMouseMove := @Panel_ToolbarBackgroundMouseMove;
   TimerHidePenPreview.OnTimer := @TimerHidePenPreviewTimer;
+  TimerHideTextMore.OnTimer := @TimerHideTextMoreTimer;
   ComboBox_BrushSelect.OnChange := @ComboBox_BrushSelectChange;
   ComboBox_BrushSelect.OnDrawItem := @ComboBox_BrushSelectDrawItem;
   ComboBox_BrushSelect.OnDrawSelectedItem:= @ComboBox_BrushSelectDrawSelectedItem;
   ComboBox_BrushSelect.CanvasScaleMode:= csmFullResolution;
+  Combo_Ratio.Items.Add(rsImage);
   Combo_Ratio.OnChange := @Combo_RatioChange;
 
   Panel_LineCap_FullSize := Panel_LineCap.Width;
@@ -225,7 +241,7 @@ begin
   Label_Coordinates.Caption := '';
   FCoordinatesCaption:= '';
   FCoordinatesCaptionCount := 0;
-  Image_SwapColors.Hint := Image_SwapColors.Hint + ' (X)';
+  Image_SwapColors.Hint := Image_SwapColors.Hint + ' (' + SwitchColorShortcut + ')';
 
   Tool_CurveModeAuto.Hint := Tool_CurveModeAuto.Hint + ' (A)';
   Tool_CurveModeAngle.Hint := Tool_CurveModeAngle.Hint + ' (X)';
@@ -418,6 +434,10 @@ begin
   if FInTextFont and not AForce then exit;
   SpinEdit_TextSize.Value := round(ToolManager.TextFontSize);
   UpdateTextSizeIncrement;
+  Tool_TextBold.Down := fsBold in ToolManager.TextFontStyle;
+  Tool_TextItalic.Down := fsItalic in ToolManager.TextFontStyle;
+  Tool_TextUnderline.Down := fsUnderline in ToolManager.TextFontStyle;
+  Tool_TextStrikeout.Down := fsStrikeOut in ToolManager.TextFontStyle;
 end;
 
 procedure TFMain.UpdateTextAlign;
@@ -428,6 +448,9 @@ begin
   taCenter: Tool_TextAlignCenter.Down := true;
   taRightJustify: Tool_TextAlignRight.Down := true;
   end;
+  Tool_TextAlignTop.Down := ToolManager.TextVerticalAlign = tlTop;
+  Tool_TextAlignMiddle.Down := ToolManager.TextVerticalAlign = tlCenter;
+  Tool_TextAlignBottom.Down := ToolManager.TextVerticalAlign = tlBottom;
 end;
 
 procedure TFMain.UpdateTextOutlineToolbar;
@@ -1050,6 +1073,11 @@ begin
   vf.Width := vf.PreferredSize.cx;
 end;
 
+procedure TFMain.VectorialFill_OpacityChange(Sender: TObject);
+begin
+  HideFill(3000, true);
+end;
+
 procedure TFMain.VectorialFill_ShowBackFill(Sender: TObject; Shift: TShiftState; X, Y: Integer);
 begin
   ShowFill(VectorialFill_Back, Panel_BackFill);
@@ -1120,7 +1148,7 @@ end;
 procedure TFMain.Image_SwapColorsMouseDown(Sender: TObject; Button: TMouseButton;
   Shift: TShiftState; X, Y: Integer);
 begin
-  SwitchColors;
+  if Button = mbLeft then SwitchColors;
 end;
 
 procedure TFMain.SpinEdit_ToleranceChange(Sender: TObject; AByUser: boolean);
@@ -1547,6 +1575,17 @@ begin
   HidePenPreview(3000, true);
 end;
 
+procedure TFMain.ShowTextMore;
+begin
+  if not Panel_TextMore.Visible then
+  begin
+    Panel_TextMore.Left := min(Panel_Text.Left, ClientWidth-Panel_TextMore.Width);
+    Panel_TextMore.Top := Panel_Text.Top+Panel_Text.Height;
+    Panel_TextMore.Visible := True;
+  end;
+  HideTextMore(3000, true);
+end;
+
 procedure TFMain.HidePenPreview(ATimeMs: Integer; AClearTime: boolean);
 begin
   if AClearTime then TimerHidePenPreview.Enabled := false;
@@ -1557,6 +1596,16 @@ begin
   end;
 end;
 
+procedure TFMain.HideTextMore(ATimeMs: Integer; AClearTime: boolean);
+begin
+  if AClearTime then TimerHideTextMore.Enabled := false;
+  if Panel_TextMore.Visible then
+  begin
+    TimerHideTextMore.Interval := ATimeMs;
+    TimerHideTextMore.Enabled := true;
+  end;
+end;
+
 procedure TFMain.ShowFill(AFillControl: TLCVectorialFillControl; APanel: TPanel);
 begin
   AFillControl.BringToFront;
@@ -1581,6 +1630,7 @@ procedure TFMain.Panel_ToolbarBackgroundMouseMove(Sender: TObject;
   Shift: TShiftState; X, Y: Integer);
 begin
   HidePenPreview;
+  HideTextMore;
   HideFill;
 end;
 
@@ -1629,6 +1679,18 @@ begin
   ShowPenPreview(False);
 end;
 
+procedure TFMain.Panel_TextMoreMouseMove(Sender: TObject; Shift: TShiftState;
+  X, Y: Integer);
+begin
+  ShowTextMore;
+end;
+
+procedure TFMain.Panel_TextMouseMove(Sender: TObject; Shift: TShiftState; X,
+  Y: Integer);
+begin
+  ShowTextMore;
+end;
+
 procedure TFMain.PopupToolbarPopup(Sender: TObject);
 begin
   MenuFileToolbar.Checked := Config.DefaultFileToolbarVisible;
@@ -1716,6 +1778,12 @@ begin
   TimerHidePenPreview.Enabled := false;
 end;
 
+procedure TFMain.TimerHideTextMoreTimer(Sender: TObject);
+begin
+  Panel_TextMore.Visible := False;
+  TimerHideTextMore.Enabled := false;
+end;
+
 procedure TFMain.ToolChangeDockingExecute(Sender: TObject);
 begin
   if Layout.ToolBoxDocking = twLeft then
@@ -1823,17 +1891,66 @@ end;
 
 procedure TFMain.Tool_TextAlignClick(Sender: TObject);
 var newAlign: TAlignment;
+    newVAlign: TTextLayout;
 begin
   if initialized then
   begin
     newAlign := taLeftJustify;
+    newVAlign:= ToolManager.TextVerticalAlign;
     if Tool_TextAlignCenter.Down then newAlign:= taCenter;
     if Tool_TextAlignRight.Down then newAlign := taRightJustify;
-    if newAlign <> ToolManager.TextAlign then
+    if Tool_TextAlignTop.Down and (sender = Tool_TextAlignTop) then newVAlign := tlTop;
+    if Tool_TextAlignMiddle.Down and (sender = Tool_TextAlignMiddle) then newVAlign := tlCenter;
+    if Tool_TextAlignBottom.Down and (sender = Tool_TextAlignBottom) then newVAlign := tlBottom;
+    FInTextAlign := true;
+    Tool_TextAlignTop.Down := newVAlign = tlTop;
+    Tool_TextAlignMiddle.Down := newVAlign = tlCenter;
+    Tool_TextAlignBottom.Down := newVAlign = tlBottom;
+    FInTextAlign := false;
+    if (newAlign <> ToolManager.TextAlign) or (newVAlign <> ToolManager.TextVerticalAlign) then
     begin
       FInTextAlign := true;
       ToolManager.TextAlign := newAlign;
+      ToolManager.TextVerticalAlign := newVAlign;
+      FInTextAlign := false;
+      UpdateEditPicture;
+    end;
+  end;
+end;
+
+procedure TFMain.Tool_TextBidiModeClick(Sender: TObject);
+var newMode: TFontBidiMode;
+begin
+  if initialized then
+  begin
+    newMode := fbmAuto;
+    if Tool_TextLTR.Down then newMode:= fbmLeftToRight;
+    if Tool_TextRTL.Down then newMode:= fbmRightToLeft;
+    if newMode <> ToolManager.TextBidiMode then
+    begin
+      FInTextAlign := true;
+      ToolManager.TextBidiMode := newMode;
       FInTextAlign := false;
+      UpdateTextAlign;
+    end;
+  end;
+end;
+
+procedure TFMain.Tool_TextStyleClick(Sender: TObject);
+var newStyle: TFontStyles;
+begin
+  if initialized then
+  begin
+    newStyle := [];
+    if Tool_TextBold.Down then include(newStyle, fsBold);
+    if Tool_TextItalic.Down then include(newStyle, fsItalic);
+    if Tool_TextUnderline.Down then include(newStyle, fsUnderline);
+    if Tool_TextStrikeout.Down then include(newStyle, fsStrikeOut);
+    if newStyle <> ToolManager.TextFontStyle then
+    begin
+      FInTextFont := true;
+      ToolManager.TextFontStyle := newStyle;
+      FInTextFont := false;
       UpdateEditPicture;
     end;
   end;
@@ -1951,7 +2068,10 @@ var
 begin
   if initialized then
   begin
-    newRatio := ComputeRatio(Combo_Ratio.Text);
+    if CompareText(Combo_Ratio.Text, rsImage)=0 then
+      newRatio := Image.Width/Image.Height
+    else
+      newRatio := ComputeRatio(Combo_Ratio.Text);
     if newRatio <> ToolManager.ShapeRatio then
     begin
       FInShapeRatio := true;

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.ar.po

@@ -650,6 +650,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "سحب اللون..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr ""
@@ -841,6 +849,14 @@ msgstr "فتح ملف موجود"
 msgid "Print..."
 msgstr "طباعة..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1923,6 +1939,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "ملء  متدرج"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr ""
@@ -1931,15 +1951,39 @@ msgstr ""
 msgid "Align left"
 msgstr ""
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr ""
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "اختيار الخط..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1950,11 +1994,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "نص بتظليل فونغ"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "ظل النص"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2850,6 +2906,10 @@ msgstr "طلب الغلق"
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "وصف اللون : انقر في اللون مع لوحة المفاتيح باستخدام أسماء الألوان أو بتدوين CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3163,6 +3223,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr ""
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "صورة"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "الصورة كبيرة جدا"
@@ -3550,6 +3616,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr ""
@@ -3717,6 +3787,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.bg.po

@@ -648,6 +648,14 @@ msgctxt "TFMAIN.COLORSHIFTCOLORS.CAPTION"
 msgid "Shift colors..."
 msgstr "Цветово разместване..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Вид на чертата"
@@ -838,6 +846,14 @@ msgstr "Отварянето на съществуващ файл"
 msgid "Print..."
 msgstr "Разпечатване..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1910,6 +1926,10 @@ msgctxt "TFMAIN.TOOL_PROGRESSIVEFLOODFILL.HINT"
 msgid "Progressive floodfill"
 msgstr ""
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr ""
@@ -1918,15 +1938,39 @@ msgstr ""
 msgid "Align left"
 msgstr "Подравняване вляво"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Подравняване вдясно"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Избор на шрифт..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1937,11 +1981,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr ""
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Сянка на текста"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2838,6 +2894,10 @@ msgstr "Заявка за затваряне"
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Описание на цвета: цъкнете, за да напишете цвят по име или по CSS означение."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3146,6 +3206,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Размер на значетата"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Изображение"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Изображението е твърде голямо"
@@ -3534,6 +3600,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "ЧЗС"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Укажете източника с ДЕСЕН цък"
@@ -3699,6 +3769,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.cs.po

@@ -653,6 +653,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Posunutí barev..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Styl pera"
@@ -843,6 +851,14 @@ msgstr "Otevřít existující soubor"
 msgid "Print..."
 msgstr "Tisk..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1923,6 +1939,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Vzrůstající výplň"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Centrovat"
@@ -1931,15 +1951,39 @@ msgstr "Centrovat"
 msgid "Align left"
 msgstr "Zarovnat vlevo"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Zarovnat vpravo"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Vyberte písmo..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1950,11 +1994,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Phongové stínování textu"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Stín textu"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2852,6 +2908,10 @@ msgstr "Uzavřít požadavek"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Popis barvy: klikněte pro zadání barvy klávesnicí pomocí jména barvy nebo zápisu CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3172,6 +3232,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Velikost ikony"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Obrázek"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Obrázek je příliš velký"
@@ -3569,6 +3635,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Použijte PRAVÝ klik k určení zdroje"
@@ -3736,6 +3806,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

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

@@ -660,6 +660,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Farben tauschen..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Stiftstil"
@@ -851,6 +859,14 @@ msgstr "Datei öffnen"
 msgid "Print..."
 msgstr "Drucken..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1934,6 +1950,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Progressive Füllung"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Zentrieren"
@@ -1942,15 +1962,39 @@ msgstr "Zentrieren"
 msgid "Align left"
 msgstr "Links angleichen"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Rechts angleichen"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Schriftart auswählen..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1961,11 +2005,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Text Phong-Schattierung"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Textschatten"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2861,6 +2917,10 @@ msgstr "Anforderung schließen"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Farbbeschreibung: Anklicken, um Farbnamen oder CSS Farbcode mit der Tastatur einzugeben."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr "Farbüberlagerung"
@@ -3174,6 +3234,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Ikongröße"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Bild"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Bild ist zu groß"
@@ -3379,7 +3445,7 @@ msgstr "Neues Bild"
 
 #: uresourcestrings.rsnewmask
 msgid "New mask"
-msgstr "Neue Maske"
+msgstr "Neue Maske\"                         "
 
 #: uresourcestrings.rsno
 msgid "No"
@@ -3561,6 +3627,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "RECHTS-Klick um die Quelle zu wählen"
@@ -3728,6 +3798,10 @@ msgstr "Version"
 msgid "Vertical size"
 msgstr "Vertikal Größe"
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr "Sichtbar"
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr "Gelb"

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.es.po

@@ -652,6 +652,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Intercambiar colores..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr "Flecha final"
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr "Flecha inicial"
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Estilo de lápiz"
@@ -842,6 +850,14 @@ msgstr "Abrir archivo existente"
 msgid "Print..."
 msgstr "Imprimir..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1927,6 +1943,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Relleno de flujo progresivo"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Centrar"
@@ -1935,15 +1955,39 @@ msgstr "Centrar"
 msgid "Align left"
 msgstr "Alinear a la izquierda"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Alinear a la derecha"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Elegir fuente..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1954,11 +1998,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Texto sombreado Phong"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Sombra de Texto"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2856,6 +2912,10 @@ msgstr "Solicitud de cierre"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Descripción del color: hacer clic para escribir el nombre de un color o usar notación CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr "Color superpuesto"
@@ -3176,6 +3236,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Tamaño de ícono"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Imágen"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "La imágen es muy grande"
@@ -3573,6 +3639,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr "Usa clic DERECHO para acabar la forma"
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Usa clic DERECHO para definir fuente"
@@ -3741,6 +3811,10 @@ msgstr "Versión"
 msgid "Vertical size"
 msgstr "Tamaño vertical"
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr "Amarillo"

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.fi.po

@@ -639,6 +639,14 @@ msgctxt "TFMAIN.COLORSHIFTCOLORS.CAPTION"
 msgid "Shift colors..."
 msgstr ""
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr ""
@@ -830,6 +838,14 @@ msgstr "Avaa tiedosto"
 msgid "Print..."
 msgstr "Tulosta..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1913,6 +1929,10 @@ msgctxt "TFMAIN.TOOL_PROGRESSIVEFLOODFILL.HINT"
 msgid "Progressive floodfill"
 msgstr ""
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr ""
@@ -1921,15 +1941,39 @@ msgstr ""
 msgid "Align left"
 msgstr ""
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr ""
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Valitse kirjaisin..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1940,11 +1984,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr ""
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr ""
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2843,6 +2899,10 @@ msgstr ""
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr ""
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3155,6 +3215,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr ""
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Kuva"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Kuva on liian iso"
@@ -3542,6 +3608,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr ""
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr ""
@@ -3708,6 +3778,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.fr.po

@@ -650,6 +650,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Décaler les couleurs..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr "Flèche de fin"
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr "Flèche de départ"
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Style de pinceau"
@@ -841,6 +849,14 @@ msgstr "Ouvrir un fichier existant"
 msgid "Print..."
 msgstr "Imprimer..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1925,6 +1941,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Pot de peinture progressif"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr "Aligner en bas"
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Centrer"
@@ -1933,15 +1953,39 @@ msgstr "Centrer"
 msgid "Align left"
 msgstr "Aligner à gauche"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr "Centrer verticallement"
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Aligner à droite"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr "Aligner en haut"
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr "Bidirectionnel"
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr "Gras"
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Choisir la police..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr "Italique"
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr "Gauche à droite"
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1952,11 +1996,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Texte avec ombrage Phong"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr "Droite à gauche"
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Ombre de texte"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr "Barré"
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr "Souligné"
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2854,6 +2910,10 @@ msgstr "Fermeture"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Description de la couleur : cliquez pour entrer une couleur avec le clavier en utilisant les noms de couleurs ou la notation CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr "Couleur superposée"
@@ -3174,6 +3234,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Taille d'icône"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Image"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Image trop grande"
@@ -3571,6 +3637,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Utiliser le clic DROIT pour définir la source"
@@ -3739,6 +3809,10 @@ msgstr "Version"
 msgid "Vertical size"
 msgstr "Taille verticale"
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr "Visible"
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr "Jaune"

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.it.po

@@ -639,6 +639,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Cambia colori..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Penna"
@@ -829,6 +837,14 @@ msgstr "Apri un file esistente"
 msgid "Print..."
 msgstr "Stampa"
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1912,6 +1928,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Riempimento progressivo"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr ""
@@ -1920,15 +1940,39 @@ msgstr ""
 msgid "Align left"
 msgstr "Allinea a sinistra"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Allinea a destra"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Scegli carattere"
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1939,11 +1983,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr ""
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Testo ombrato"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2842,6 +2898,10 @@ msgstr ""
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr ""
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3161,6 +3221,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr ""
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Immagine"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "L'immagine è troppo grande"
@@ -3558,6 +3624,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr ""
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr ""
@@ -3725,6 +3795,10 @@ msgstr "Versione"
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr "Visibile"
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.ja.po

@@ -648,6 +648,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "色シフト..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr ""
@@ -839,6 +847,14 @@ msgstr "既存ファイルを開く"
 msgid "Print..."
 msgstr ""
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1920,6 +1936,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "プログレッシブで塗りつぶす"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr ""
@@ -1928,15 +1948,39 @@ msgstr ""
 msgid "Align left"
 msgstr ""
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr ""
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "フォント選択..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1947,11 +1991,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr ""
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "テキストシャドゥ"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2848,6 +2904,10 @@ msgstr "Close request"
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr ""
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3160,6 +3220,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr ""
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "イメージ"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr ""
@@ -3547,6 +3613,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr ""
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr ""
@@ -3713,6 +3783,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.kab.po

@@ -653,6 +653,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Sekḥer initen..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Aɣanib n yimru"
@@ -843,6 +851,14 @@ msgstr "Ldi afaylu yellan"
 msgid "Print..."
 msgstr "Siggez..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1925,6 +1941,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Taqbuct n teklut tafarayt"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Talemmast"
@@ -1933,15 +1953,39 @@ msgstr "Talemmast"
 msgid "Align left"
 msgstr "Derrec s azelmaḍ"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Derrec s ayfus"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Fren tasefsit..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1952,11 +1996,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Aḍris s tili Phong"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Tili n uḍris"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2854,6 +2910,10 @@ msgstr "Mdel asuter"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Aglam n yini: sit iwakken ad teskecmeḍ ini s unasiw s yismawen-nnsen neɣ s tira n CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3174,6 +3234,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Tiddi n tignit"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Tugna"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Tugna temeqqer aṭas"
@@ -3573,6 +3639,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Seqdec asiti ayfus iwakken ad tesbaduḍ aɣbalu"
@@ -3740,6 +3810,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.lv.po

@@ -658,6 +658,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Nobīdīt krāsas ..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Līnijas veids"
@@ -848,6 +856,14 @@ msgstr "Atvērt esošu attēlu"
 msgid "Print..."
 msgstr "Izdrukāt ..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1928,6 +1944,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Vienmērīgs aizpildījums"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Iecentrēt"
@@ -1936,15 +1956,39 @@ msgstr "Iecentrēt"
 msgid "Align left"
 msgstr "Līdzināt pa kreisi"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Līdzināt pa labi"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Izvēlies fontu ..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1955,11 +1999,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Telpiski burti"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Teksta ēna"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2858,6 +2914,10 @@ msgstr "Aizvērt pieprasījumu"
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Krāsas apraksts: ieklikškini, lai ierakstītu krāsas vārdu angliski vai CSS pierakstā."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3178,6 +3238,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Ikonas izmērs"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Attēls"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Attēls ir par lielu"
@@ -3575,6 +3641,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Ar peles labo pogu norādi avotu"
@@ -3745,6 +3815,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.nl.po

@@ -676,6 +676,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Kleuren verschuiven..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Penstijl"
@@ -866,6 +874,14 @@ msgstr "Bestaand bestand openen"
 msgid "Print..."
 msgstr "Print..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1946,6 +1962,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Progressieve vloedvulling"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Middelste"
@@ -1954,15 +1974,39 @@ msgstr "Middelste"
 msgid "Align left"
 msgstr "Links uitlijnen"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Rechts uitlijnen"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Lettertype kiezen..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1973,11 +2017,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Tekst phong shading"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Tekstschaduw"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2872,6 +2928,10 @@ msgstr "Verzoek om te sluiten"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Kleurbeschrijving: klik om een kleur in te typen met het toetsenbord middels kleurnamen of CSS notatie."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3185,6 +3245,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Ikoon grootte"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Afbeelding"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Afbeelding is te groot"
@@ -3572,6 +3638,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Gebruik RECHTS klikken om de bron te definiëren"
@@ -3739,6 +3809,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr "Zichtbaar"
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.pl.po

@@ -660,6 +660,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Zmień kolory..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Styl pióra"
@@ -851,6 +859,14 @@ msgstr "Otwórz istniejący plik"
 msgid "Print..."
 msgstr "Drukuj..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1934,6 +1950,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Wypełnienie progresywne"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Wyśrodkuj"
@@ -1942,15 +1962,39 @@ msgstr "Wyśrodkuj"
 msgid "Align left"
 msgstr "Wyrównaj do lewej"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Wyrównaj do prawej"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Wybierz czcionkę..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1961,11 +2005,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Cień tekstu phong"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Cień tekstu"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2863,6 +2919,10 @@ msgstr "Zamknij polecenie"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Opis koloru: kliknij, aby wpisać kolor za pomocą klawiatury, używając nazw kolorów lub notacji CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3176,6 +3236,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Rozmiar ikon"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Obraz"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Obraz jest za duży"
@@ -3567,6 +3633,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Użyj prawokliku, aby zdefiniować źródło"
@@ -3734,6 +3804,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr "Widoczna"
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.pot

@@ -606,6 +606,14 @@ msgstr ""
 msgid "Shift colors..."
 msgstr ""
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr ""
@@ -791,6 +799,14 @@ msgstr ""
 msgid "Print..."
 msgstr ""
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgid "Quit"
 msgstr ""
@@ -1291,6 +1307,7 @@ msgid "Help"
 msgstr ""
 
 #: tfmain.menuimage.caption
+msgctxt "tfmain.menuimage.caption"
 msgid "Image"
 msgstr ""
 
@@ -1782,6 +1799,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr ""
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr ""
@@ -1790,14 +1811,38 @@ msgstr ""
 msgid "Align left"
 msgstr ""
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr ""
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgid "Choose font..."
 msgstr ""
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "tfmain.tool_textoutline.hint"
 msgid "Text outline"
@@ -1807,10 +1852,22 @@ msgstr ""
 msgid "Text phong shading"
 msgstr ""
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgid "Text shadow"
 msgstr ""
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "tfmain.viewcolors.caption"
 msgid "Colors"
@@ -2681,6 +2738,10 @@ msgstr ""
 msgid "CMD"
 msgstr ""
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr ""
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -2987,6 +3048,11 @@ msgstr ""
 msgid "Icon size"
 msgstr ""
 
+#: uresourcestrings.rsimage
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr ""
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr ""
@@ -3370,6 +3436,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr ""
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr ""
@@ -3532,6 +3602,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.pt_BR.po

@@ -649,6 +649,14 @@ msgctxt "TFMAIN.COLORSHIFTCOLORS.CAPTION"
 msgid "Shift colors..."
 msgstr "Mudar as cores..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Estilo caneta"
@@ -840,6 +848,14 @@ msgstr "Abrir arquivo existente"
 msgid "Print..."
 msgstr "Imprimir..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1921,6 +1937,10 @@ msgctxt "TFMAIN.TOOL_PROGRESSIVEFLOODFILL.HINT"
 msgid "Progressive floodfill"
 msgstr "Preenchimento progressivo"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Centrar"
@@ -1929,15 +1949,39 @@ msgstr "Centrar"
 msgid "Align left"
 msgstr "Alinhar à esquerda"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Alinhar à direita"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Escolher tipo de letra..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1948,11 +1992,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Texto Phong de sombreamento"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Sombra do texto"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2861,6 +2917,10 @@ msgstr "Solicitação de fechar"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Descrição cor: clique para digitar uma cor com o teclado usando nomes de cores ou a notação CSS."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3174,6 +3234,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Tamanho do ícone"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Imagem"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Imagem é muito grande"
@@ -3562,6 +3628,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Use o botão DIREITO para definir a origem"
@@ -3729,6 +3799,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr "Visível"
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 172 - 116
lazpaint/release/bin/i18n/lazpaint.ru.po


+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.sv.po

@@ -649,6 +649,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "Skifta färger..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "Stil på pennan"
@@ -840,6 +848,14 @@ msgstr "Öppna befintlig fil"
 msgid "Print..."
 msgstr "Skriva ut..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1922,6 +1938,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "Progressiv flodfyllning"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "Mitten"
@@ -1930,15 +1950,39 @@ msgstr "Mitten"
 msgid "Align left"
 msgstr "Justera till vänster"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "Justera till höger"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "Välj typsnitt..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1949,11 +1993,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "Phongskuggning för text"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "Textskugga"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2853,6 +2909,10 @@ msgstr "Stäng förfrågan"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "Färgbeskrivning: klicka för att skriva in en färg med tangentbordet genom färgnamn eller CSS-notation."
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3166,6 +3226,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "Ikonstorlek"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "Bild"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "Bilden är för stor"
@@ -3553,6 +3619,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "Använd Högerklick för att välja källa"
@@ -3719,6 +3789,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

+ 74 - 0
lazpaint/release/bin/i18n/lazpaint.zh_CN.po

@@ -652,6 +652,14 @@ msgctxt "tfmain.colorshiftcolors.caption"
 msgid "Shift colors..."
 msgstr "转移颜色..."
 
+#: tfmain.combobox_arrowend.hint
+msgid "Ending arrow"
+msgstr ""
+
+#: tfmain.combobox_arrowstart.hint
+msgid "Starting arrow"
+msgstr ""
+
 #: tfmain.combobox_penstyle.hint
 msgid "Pen style"
 msgstr "线型"
@@ -842,6 +850,14 @@ msgstr "打开文件"
 msgid "Print..."
 msgstr "打印..."
 
+#: tfmain.filequicksave.caption
+msgid "Quick save"
+msgstr ""
+
+#: tfmain.filequicksave.hint
+msgid "Save current file without dialogs"
+msgstr ""
+
 #: tfmain.filequit.hint
 msgctxt "TFMAIN.FILEQUIT.HINT"
 msgid "Quit"
@@ -1922,6 +1938,10 @@ msgctxt "tfmain.tool_progressivefloodfill.hint"
 msgid "Progressive floodfill"
 msgstr "渐进式填充"
 
+#: tfmain.tool_textalignbottom.hint
+msgid "Align bottom"
+msgstr ""
+
 #: tfmain.tool_textaligncenter.hint
 msgid "Center"
 msgstr "居中"
@@ -1930,15 +1950,39 @@ msgstr "居中"
 msgid "Align left"
 msgstr "向左对齐"
 
+#: tfmain.tool_textalignmiddle.hint
+msgid "Center vertically"
+msgstr ""
+
 #: tfmain.tool_textalignright.hint
 msgid "Align right"
 msgstr "向右对齐"
 
+#: tfmain.tool_textaligntop.hint
+msgid "Align top"
+msgstr ""
+
+#: tfmain.tool_textbidirectional.hint
+msgid "Bidirectional"
+msgstr ""
+
+#: tfmain.tool_textbold.hint
+msgid "Bold"
+msgstr ""
+
 #: tfmain.tool_textfont.hint
 msgctxt "TFMAIN.TOOL_TEXTFONT.HINT"
 msgid "Choose font..."
 msgstr "选择字体..."
 
+#: tfmain.tool_textitalic.hint
+msgid "Italic"
+msgstr ""
+
+#: tfmain.tool_textltr.hint
+msgid "Left to right"
+msgstr ""
+
 #: tfmain.tool_textoutline.hint
 msgctxt "TFMAIN.TOOL_TEXTOUTLINE.HINT"
 msgid "Text outline"
@@ -1949,11 +1993,23 @@ msgctxt "TFMAIN.TOOL_TEXTPHONG.HINT"
 msgid "Text phong shading"
 msgstr "文本高光渲染"
 
+#: tfmain.tool_textrtl.hint
+msgid "Right to left"
+msgstr ""
+
 #: tfmain.tool_textshadow.hint
 msgctxt "TFMAIN.TOOL_TEXTSHADOW.HINT"
 msgid "Text shadow"
 msgstr "文本阴影"
 
+#: tfmain.tool_textstrikeout.hint
+msgid "Strikeout"
+msgstr ""
+
+#: tfmain.tool_textunderline.hint
+msgid "Underline"
+msgstr ""
+
 #: tfmain.viewcolors.caption
 msgctxt "TFMAIN.VIEWCOLORS.CAPTION"
 msgid "Colors"
@@ -2851,6 +2907,10 @@ msgstr "关闭请求"
 msgid "CMD"
 msgstr "CMD"
 
+#: uresourcestrings.rscolordescription
+msgid "Color description: click to type in a color with the keyboard using color names or CSS notation."
+msgstr "颜色说明:单击以键入颜色名称或 CSS 表示。"
+
 #: uresourcestrings.rscoloroverlay
 msgid "Color overlay"
 msgstr ""
@@ -3171,6 +3231,12 @@ msgctxt "uresourcestrings.rsiconsize"
 msgid "Icon size"
 msgstr "图标大小"
 
+#: uresourcestrings.rsimage
+#, fuzzy
+msgctxt "uresourcestrings.rsimage"
+msgid "Image"
+msgstr "图像"
+
 #: uresourcestrings.rsimagetoobig
 msgid "Image is too big"
 msgstr "图像太大"
@@ -3568,6 +3634,10 @@ msgctxt "uresourcestrings.rsrgb"
 msgid "RGB"
 msgstr "RGB"
 
+#: uresourcestrings.rsrightclickfinishshape
+msgid "Use RIGHT click to finish shape"
+msgstr ""
+
 #: uresourcestrings.rsrightclickforsource
 msgid "Use RIGHT click to define source"
 msgstr "单击右键来定义源"
@@ -3735,6 +3805,10 @@ msgstr ""
 msgid "Vertical size"
 msgstr ""
 
+#: uresourcestrings.rsvisible
+msgid "Visibile"
+msgstr ""
+
 #: uresourcestrings.rsyellow
 msgid "Yellow"
 msgstr ""

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

@@ -167,5 +167,5 @@ msgstr "Повторить по оси Y"
 
 #: lcresourcestring.rsunknownshapeclass
 msgid "Unknown shape class \"%1\""
-msgstr "Неизвестный класс формы "%1""
+msgstr "Неизвестный класс формы \"%1\""
 

+ 64 - 0
lazpaint/release/debian/debian/changelog

@@ -1,3 +1,67 @@
+lazpaint (7.2) stable; urgency=low
+
+  * MacOS: handle right-click on layerstack
+  * MacOS: fixed light theme interface
+  * MacOS: avoid key binding conflict with CMD-H
+  * interface: handle cancel language or icon size change
+  * interface: restore main form after embedded editor
+  * interface: rester selection tool after delete
+  * interface: fix shift-arrows in file list
+  * interface: handle right click on switch color button
+  * interface: remember docked toolbox visibility
+  * interface: center on zoom fit
+  * interface: less margin to select outside of color circle
+  * interface: tooltip on arrow start/end
+  * interface: show hotkey in toolbar
+  * interface: update workspace when resizing/rotating
+  * interface: handle keys in embedded editors
+  * interface: prevent ALT key from opening menu
+  * interface: handle ALT-wheel only when applicable
+  * interface: keep fill options visible when changing opacity
+  * layer stack: tooltip for visible and opacity controls
+  * blend mode: removed horizontal scrollbar in blend mode lists
+  * language: tool shortcuts for Cyrillic keyboard
+  * language: translation of color description
+  * language: completed Russian translation
+  * file: prevent saving incorrect filename
+  * file: handle path in file textbook
+  * file: generate new filename with number
+  * file: added quick save action (Ctlr-Q shortcut)
+  * file: overwrite prompt when saving palette
+  * file: experimental support for AVIF format
+  * file: show save prompt when drag'n'drop image to the program
+  * file: save CUR and ICO with command line
+  * SVG: close path when export as SVG
+  * SVG: fixed RTL text export
+  * new file: better handling of ratios
+  * motion blur: fixed sticky mouse click
+  * canvas size: restrict percent to max accepted size
+  * tools: update shape when pressing/releasing SHIFT key
+  * tools: ignore 0 alpha with solid colors
+  * tools: improved hints timing
+  * tools: disambiguation of shortcut keys (Y, K, F and R)
+  * deformation grid tool: handle extreme deformation
+  * déformation grid tool: ESCAPE to exit tool
+  * layer perspective tool: change cursor when hovering points
+  * layer tools: delete current layer with DELETE key
+  * rectangle tool: fixed bug when changing join type
+  * text tool: update when change antialiasing
+  * text tool: provide text style, bidi mode, vertical alignment in toolbar
+  * text tool: allow travel mode with space
+  * text tool: display flipped text
+  * vector tools: avoid error after rasterizing
+  * polygon/closed curve tools: hide center point when ALT key pressed
+  * polyline/opened curve tool: don't reopen shape
+  * poly tools: added RIGHT-click hint
+  * selection tools: deselect when ESCAPE pressed and selection layer empty
+  * selection tools: keep selection mode after undo/redo
+  * rectangle selection tool: include ratio of current image
+  * selection pen: show circular cursor
+  * filter: added negative angle for twirl
+  * script: ignore some Python errors
+
+ -- circular <[email protected]>  Sat, 6 Aug 2022 10:38:00 +0100
+
 lazpaint (7.1.6) stable; urgency=low
 
   * Debian: various icon sizes for Linux application menu

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

@@ -5,7 +5,7 @@ Maintainer: circular <[email protected]>
 Homepage: https://wiki.freepascal.org/LazPaint
 Package: lazpaint
 Architecture: any
-Version: 7.1.6
+Version: 7.2
 Depends: ${shlibs:Depends}
 Conflicts: lazpaint-gtk2, lazpaint-gtk3, lazpaint-qt4, lazpaint-qt5
 Description: Image editor with raster and vector layers

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

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

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

@@ -8,7 +8,7 @@ if ! [ ${OSTYPE:0:6} = "darwin" ]; then
 fi
 
 appname=LazPaint
-appversion=7.1.6
+appversion=7.2
 pkgversion=0
 appnamenospaces=lazpaint
 appbundle="$appname.app"

+ 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.1.6"
+#define MyAppVersion "7.2"
 #define MyAppPublisher "Circular, Fabien Wang, Lainz and others"
 #define MyAppURL "http://sourceforge.net/projects/lazpaint/"
 #define MyAppExeName "lazpaint.exe"

+ 92 - 14
lazpaint/tools/utool.pas

@@ -165,7 +165,7 @@ type
   TToolClass = class of TGenericTool;
 
   TToolPopupMessage= (tpmNone, tpmHoldKeyForSquare, tpmHoldKeySnapToPixel,
-    tpmReturnValides, tpmBackspaceRemoveLastPoint, tpmHoldKeyRestrictRotation,
+    tpmReturnValides, tpmBackspaceRemoveLastPoint, tpmRightClickFinishShape, tpmHoldKeyRestrictRotation,
     tpmHoldKeysScaleMode, tpmCurveModeHint, tpmBlendOpBackground,
     tpmRightClickForSource, tpmNothingToBeDeformed);
 
@@ -199,7 +199,6 @@ type
     FToolCurrentCursorPos: TPointF;
     FSleepingTool: TGenericTool;
     FSleepingToolType: TPaintToolType;
-    FReturnValidatesHintShown: boolean;
     FOnToolChangedHandler: TOnToolChangedHandler;
     FOnToolRenderChanged: TNotifyEvent;
     FOnToolbarChanged: TNotifyEvent;
@@ -221,6 +220,8 @@ type
     FTextFontSize: single;
     FTextFontStyle: TFontStyles;
     FTextAlign: TAlignment;
+    FTextVerticalAlign: TTextLayout;
+    FTextBidiMode: TFontBidiMode;
     FTextOutline: boolean;
     FTextOutlineWidth: single;
     FTextPhong: boolean;
@@ -336,6 +337,8 @@ type
     function ScriptGetShapeRatio(AVars: TVariableSet): TScriptResult;
     function ScriptGetSplineStyle(AVars: TVariableSet): TScriptResult;
     function ScriptGetTextAlign(AVars: TVariableSet): TScriptResult;
+    function ScriptGetTextVerticalAlign(AVars: TVariableSet): TScriptResult;
+    function ScriptGetTextBidiMode(AVars: TVariableSet): TScriptResult;
     function ScriptGetTextOutline(AVars: TVariableSet): TScriptResult;
     function ScriptGetTextPhong(AVars: TVariableSet): TScriptResult;
     function ScriptGetTolerance(AVars: TVariableSet): TScriptResult;
@@ -397,6 +400,8 @@ type
     function ScriptSetShapeRatio(AVars: TVariableSet): TScriptResult;
     function ScriptSetSplineStyle(AVars: TVariableSet): TScriptResult;
     function ScriptSetTextAlign(AVars: TVariableSet): TScriptResult;
+    function ScriptSetTextVerticalAlign(AVars: TVariableSet): TScriptResult;
+    function ScriptSetTextBidiMode(AVars: TVariableSet): TScriptResult;
     function ScriptSetTextOutline(AVars: TVariableSet): TScriptResult;
     function ScriptSetTextPhong(AVars: TVariableSet): TScriptResult;
     function ScriptSetTolerance(AVars: TVariableSet): TScriptResult;
@@ -428,6 +433,9 @@ type
     procedure SetShapeRatio(AValue: Single);
     procedure SetSplineStyle(AValue: TSplineStyle);
     procedure SetTextAlign(AValue: TAlignment);
+    procedure SetTextVerticalAlign(AValue: TTextLayout);
+    procedure SetTextBidiMode(AValue: TFontBidiMode);
+    procedure SetTextFontStyle(AValue: TFontStyles);
     procedure SetTextPhong(AValue: boolean);
     procedure SetTextShadow(AValue: boolean);
     procedure SetTextShadowBlurRadius(AValue: single);
@@ -450,6 +458,7 @@ type
     PerspectiveControls,FillControls,OutlineFillControls,
     BrushControls, RatioControls, DonateControls: TList;
     CanvasScale: integer;
+    PenWidthVisible: boolean;
 
     constructor Create(AImage: TLazPaintImage; AConfigProvider: IConfigProvider;
       ABitmapToVirtualScreen: TBitmapToVirtualScreenFunction = nil;
@@ -490,7 +499,6 @@ type
     function ToolUpdate: boolean;
     function ToolUpdateNeeded: boolean;
     procedure ToolPopup(AMessage: TToolPopupMessage; AKey: Word = 0; AAlways: boolean = false);
-    procedure HintReturnValidates;
 
     function IsSelectingTool: boolean;
     function DisplayFilledSelection: boolean;
@@ -551,8 +559,10 @@ type
     property BrushSpacing: integer read FBrushSpacing write SetBrushSpacing;
     property TextFontName: string read GetTextFontName;
     property TextFontSize: single read GetTextFontSize;
-    property TextFontStyle: TFontStyles read GetTextFontStyle;
+    property TextFontStyle: TFontStyles read GetTextFontStyle write SetTextFontStyle;
     property TextAlign: TAlignment read FTextAlign write SetTextAlign;
+    property TextVerticalAlign: TTextLayout read FTextVerticalAlign write SetTextVerticalAlign;
+    property TextBidiMode: TFontBidiMode read FTextBidiMode write SetTextBidiMode;
     property TextOutline: boolean read FTextOutline;
     property TextOutlineWidth: single read FTextOutlineWidth;
     property TextPhong: boolean read FTextPhong write SetTextPhong;
@@ -748,6 +758,7 @@ begin
   tpmHoldKeySnapToPixel: result := ReplaceKey(rsHoldKeySnapToPixel, AKey);
   tpmReturnValides: result := rsReturnValides;
   tpmBackspaceRemoveLastPoint: result := rsBackspaceRemoveLastPoint;
+  tpmRightClickFinishShape: result := rsRightClickFinishShape;
   tpmHoldKeyRestrictRotation: result := ReplaceKey(rsHoldKeyRestrictRotation, AKey);
   tpmHoldKeysScaleMode: result := ReplaceKey(ReplaceKey(rsHoldKeysScaleMode, AKey, 2), VK_MENU);
   tpmCurveModeHint: result := rsCurveModeHint;
@@ -779,15 +790,6 @@ begin
     Result:= Manager.Image.SelectionLayerReadonly;
 end;
 
-procedure TToolManager.HintReturnValidates;
-begin
-  if not FReturnValidatesHintShown then
-  begin
-    ToolPopup(tpmReturnValides);
-    FReturnValidatesHintShown:= true;
-  end;
-end;
-
 { TGenericTool }
 
 {$hints off}
@@ -1507,6 +1509,30 @@ begin
   if Assigned(FOnTextAlignChanged) then FOnTextAlignChanged(self);
 end;
 
+procedure TToolManager.SetTextVerticalAlign(AValue: TTextLayout);
+begin
+  if FTextVerticalAlign=AValue then Exit;
+  FTextVerticalAlign:=AValue;
+  ToolUpdate;
+  if Assigned(FOnTextAlignChanged) then FOnTextAlignChanged(self);
+end;
+
+procedure TToolManager.SetTextBidiMode(AValue: TFontBidiMode);
+begin
+  if FTextBidiMode=AValue then Exit;
+  FTextBidiMode:=AValue;
+  ToolUpdate;
+  if Assigned(FOnTextAlignChanged) then FOnTextAlignChanged(self);
+end;
+
+procedure TToolManager.SetTextFontStyle(AValue: TFontStyles);
+begin
+  if FTextFontStyle=AValue then Exit;
+  FTextFontStyle:=AValue;
+  ToolUpdate;
+  if Assigned(FOnTextFontChanged) then FOnTextFontChanged(self);
+end;
+
 procedure TToolManager.SetTextPhong(AValue: boolean);
 begin
   if FTextPhong=AValue then Exit;
@@ -2173,6 +2199,28 @@ begin
   result := srOk;
 end;
 
+function TToolManager.ScriptGetTextVerticalAlign(AVars: TVariableSet): TScriptResult;
+begin
+  case TextVerticalAlign of
+  tlTop: AVars.Strings['Result'] := 'Top';
+  tlCenter: AVars.Strings['Result'] := 'Middle';
+  tlBottom: AVars.Strings['Result'] := 'Bottom';
+  else exit(srException);
+  end;
+  result := srOk;
+end;
+
+function TToolManager.ScriptGetTextBidiMode(AVars: TVariableSet): TScriptResult;
+begin
+  case TextBidiMode of
+  fbmAuto: AVars.Strings['Result'] := 'BidiAuto';
+  fbmLeftToRight: AVars.Strings['Result'] := 'LeftToRight';
+  fbmRightToLeft: AVars.Strings['Result'] := 'RightToLeft';
+  else exit(srException);
+  end;
+  result := srOk;
+end;
+
 function TToolManager.ScriptGetTextOutline(AVars: TVariableSet): TScriptResult;
 begin
   if TextOutline then
@@ -2780,6 +2828,28 @@ begin
   result := srOk;
 end;
 
+function TToolManager.ScriptSetTextVerticalAlign(AVars: TVariableSet): TScriptResult;
+begin
+  case AVars.Strings['Align'] of
+  'Top': TextVerticalAlign:= tlTop;
+  'Middle': TextVerticalAlign:= tlCenter;
+  'Bottom': TextVerticalAlign:= tlBottom;
+  else exit(srInvalidParameters);
+  end;
+  result := srOk;
+end;
+
+function TToolManager.ScriptSetTextBidiMode(AVars: TVariableSet): TScriptResult;
+begin
+  case AVars.Strings['BidiMode'] of
+  'BidiAuto': TextBidiMode:= fbmAuto;
+  'LeftToRight': TextBidiMode:= fbmLeftToRight;
+  'RightToLeft': TextBidiMode:= fbmRightToLeft;
+  else exit(srInvalidParameters);
+  end;
+  result := srOk;
+end;
+
 function TToolManager.ScriptSetTextOutline(AVars: TVariableSet): TScriptResult;
 begin
   if AVars.IsDefined('Width') and (AVars.Floats['Width'] > 0) then
@@ -2830,6 +2900,7 @@ constructor TToolManager.Create(AImage: TLazPaintImage; AConfigProvider: IConfig
 begin
   FImage:= AImage;
   CanvasScale := 1;
+  PenWidthVisible := false;
   BitmapToVirtualScreen := ABitmapToVirtualScreen;
   FShouldExitTool:= false;
   FConfigProvider := AConfigProvider;
@@ -2881,6 +2952,8 @@ begin
   FTextFontName := TTextShape.DefaultFontName;
   FTextFontStyle:= [];
   FTextAlign := taLeftJustify;
+  FTextVerticalAlign := tlTop;
+  FTextBidiMode := fbmAuto;
   FTextPhong := False;
   FTextShadowBlurRadius := 4;
   FTextShadowOffset := Point(5,5);
@@ -3198,7 +3271,8 @@ begin
 
   OrResult(SetControlsVisible(BrushControls, ctBrush in contextualToolbars));
   OrResult(SetControlsVisible(ShapeControls, ctShape in contextualToolbars));
-  OrResult(SetControlsVisible(PenWidthControls, (ctPenWidth in contextualToolbars) and hasPen));
+  PenWidthVisible := (ctPenWidth in contextualToolbars) and hasPen;
+  OrResult(SetControlsVisible(PenWidthControls, PenWidthVisible));
   OrResult(SetControlsVisible(JoinStyleControls, (ctJoinStyle in contextualToolbars) and hasPen));
   OrResult(SetControlsVisible(PenStyleControls, (ctPenStyle in contextualToolbars) and hasPen));
   OrResult(SetControlsVisible(CloseShapeControls, ctCloseShape in contextualToolbars));
@@ -3292,6 +3366,10 @@ begin
   FScriptContext.RegisterScriptFunction('ToolGetFontStyle', @ScriptGetFontStyle, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetTextAlign', @ScriptSetTextAlign, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetTextAlign', @ScriptGetTextAlign, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetTextVerticalAlign', @ScriptSetTextVerticalAlign, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetTextVerticalAlign', @ScriptGetTextVerticalAlign, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolSetTextBidiMode', @ScriptSetTextBidiMode, ARegister);
+  FScriptContext.RegisterScriptFunction('ToolGetTextBidiMode', @ScriptGetTextBidiMode, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetTextOutline', @ScriptSetTextOutline, ARegister);
   FScriptContext.RegisterScriptFunction('ToolGetTextOutline', @ScriptGetTextOutline, ARegister);
   FScriptContext.RegisterScriptFunction('ToolSetTextPhong', @ScriptSetTextPhong, ARegister);

+ 9 - 3
lazpaint/tools/utoolbasic.pas

@@ -46,7 +46,7 @@ type
 
   TToolPen = class(TGenericTool)
   protected
-    class var HintShowed: boolean;
+    class var HintShown: boolean;
     penDrawing, penDrawingRight: boolean;
     shiftClicking, shiftClickingRight: boolean;
     penOrigin: TPointF;
@@ -59,6 +59,7 @@ type
     function DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect; override;
     function DoToolShiftClick(toolDest: TBGRABitmap; ptF: TPointF; rightBtn: boolean): TRect; virtual;
   public
+    class procedure ForgetHintShown;
     function ToolUp: TRect; override;
     function GetContextualToolbars: TContextualToolbars; override;
     destructor Destroy; override;
@@ -369,10 +370,10 @@ end;
 
 function TToolPen.DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect;
 begin
-  if (manager.PenWidth <= 3) and not HintShowed then
+  if (manager.PenWidth <= 3) and not HintShown then
   begin
     Manager.ToolPopup(tpmHoldKeySnapToPixel, VK_CONTROL);
-    HintShowed:= true;
+    HintShown:= true;
   end;
   if ssSnap in ShiftState then ptF := PointF(pt.X,pt.Y);
   result := EmptyRect;
@@ -397,6 +398,11 @@ begin
   result := EmptyRect;
 end;
 
+class procedure TToolPen.ForgetHintShown;
+begin
+  HintShown:= false;
+end;
+
 function TToolPen.ToolUp: TRect;
 begin
   if penDrawing then

+ 12 - 1
lazpaint/tools/utoolbrush.pas

@@ -54,6 +54,7 @@ type
 
   TToolClone = class(TToolGenericBrush)
   protected
+    class var RightClickHintShown: boolean;
     definingSource: boolean;
     class var sourceLayerId: integer;
     class var sourcePosition: TPoint;
@@ -67,6 +68,7 @@ type
     function DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect; override;
     function DoToolShiftClick({%H-}toolDest: TBGRABitmap; {%H-}ptF: TPointF; {%H-}rightBtn: boolean): TRect; override;
   public
+    class procedure ForgetHintShown;
     function SubPixelAccuracy: boolean; override;
     constructor Create(AManager: TToolManager); override;
     destructor Destroy; override;
@@ -162,7 +164,11 @@ end;
 function TToolClone.DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF
   ): TRect;
 begin
-  Manager.ToolPopup(tpmRightClickForSource);
+  if not RightClickHintShown then
+  begin
+    Manager.ToolPopup(tpmRightClickForSource);
+    RightClickHintShown := true;
+  end;
   Result:=inherited DoToolMove(toolDest, pt, ptF);
 end;
 
@@ -172,6 +178,11 @@ begin
   Result:= EmptyRect;
 end;
 
+class procedure TToolClone.ForgetHintShown;
+begin
+  RightClickHintShown:= false;
+end;
+
 function TToolClone.SubPixelAccuracy: boolean;
 begin
   Result:=false;

+ 115 - 40
lazpaint/tools/utooldeformationgrid.pas

@@ -20,6 +20,7 @@ type
     function ToolDeformationGridNeeded: boolean;
     procedure ValidateDeformationGrid;
   protected
+    class var ReturnHintShown: boolean;
     deformationGridNbX,deformationGridNbY,deformationGridX,deformationGridY: integer;
     deformationGridMoving: boolean;
     deformationOrigin: TPointF;
@@ -35,6 +36,7 @@ type
     function GetIsSelectingTool: boolean; override;
     function DoToolUpdate({%H-}toolDest: TBGRABitmap): TRect; override;
   public
+    class procedure ForgetHintShown;
     constructor Create(AManager: TToolManager); override;
     function ToolUp: TRect; override;
     function GetContextualToolbars: TContextualToolbars; override;
@@ -48,7 +50,7 @@ type
 
   TToolTextureMapping = class(TGenericTool)
   private
-    class var FHintShowed: boolean;
+    class var ScaleHintShown, ReturnHintShown: boolean;
     FCurrentBounds: TRect;
     FLastTexture: TBGRABitmap;
     FTextureAfterAlpha: TBGRABitmap;
@@ -70,7 +72,8 @@ type
     quadMovingIndex: integer;
     quadMoving,quadMovingBounds: boolean;
     quadMovingDelta: TPointF;
-    function SnapIfNecessary(ptF: TPointF): TPointF;
+    function SnapIfNecessary(const ptF: TPointF): TPointF;
+    function GetClosestPoint(const ptF: TPointF; out pointFound: TPointF): integer;
     function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF;
       {%H-}rightBtn: boolean): TRect; override;
     function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF): TRect;
@@ -88,6 +91,7 @@ type
     function GetStatusText: string; override;
     function GetAllowedBackFillTypes: TVectorialFillTypes; override;
   public
+    class procedure ForgetHintShown;
     constructor Create(AManager: TToolManager); override;
     function ToolUp: TRect; override;
     function GetContextualToolbars: TContextualToolbars; override;
@@ -169,7 +173,9 @@ end;
 function TToolLayerMapping.GetTextureRepetition: TTextureRepetition;
 begin
   if poRepeat in Manager.PerspectiveOptions then
-    Result:= trRepeatBoth;
+    Result:= trRepeatBoth
+  else
+    result:= trNone;
 end;
 
 procedure TToolLayerMapping.ValidateQuad;
@@ -409,18 +415,42 @@ begin
   end;
 end;
 
-function TToolTextureMapping.SnapIfNecessary(ptF: TPointF): TPointF;
+function TToolTextureMapping.SnapIfNecessary(const ptF: TPointF): TPointF;
 begin
   if not (ssSnap in ShiftState) then result := ptF else
     result := PointF(round(ptF.X),round(ptF.Y));
 end;
 
+function TToolTextureMapping.GetClosestPoint(const ptF: TPointF; out pointFound: TPointF): integer;
+var
+  minDist, curDist: single;
+  pts: array of TPointF;
+  n: Integer;
+begin
+  if boundsMode then
+    pts := boundsPts
+  else
+    pts := quad;
+  result := -1;
+  pointFound := EmptyPointF;
+  minDist := sqr(DoScaleX(10,OriginalDPI));
+  for n := 0 to high(pts) do
+  begin
+    curDist := sqr(ptF.x-pts[n].x)+sqr(ptF.y-pts[n].y);
+    if curDist < minDist then
+    begin
+      minDist := curDist;
+      result := n;
+      pointFound := pts[n];
+    end;
+  end;
+end;
+
 function TToolTextureMapping.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF; rightBtn: boolean): TRect;
 var
   n: Integer;
-  curDist,minDist: single;
-  pts: array of TPointF;
+  selPt: TPointF;
 begin
   result := EmptyRect;
   if rightBtn then exit;
@@ -445,26 +475,16 @@ begin
   end;
 
   UpdateBoundsMode(result);
-  if boundsMode then
-    pts := boundsPts
-  else
-    pts := quad;
 
-  minDist := sqr(DoScaleX(10,OriginalDPI));
-  for n := 0 to high(pts) do
+  n := GetClosestPoint(ptF, selPt);
+  if n <> -1 then
   begin
-    curDist := sqr(ptF.x-pts[n].x)+sqr(ptF.y-pts[n].y);
-    if curDist < minDist then
-    begin
-      minDist := curDist;
-      quadMovingIndex := n;
-      quadMovingDelta := pts[n]-PtF;
-      quadMoving := True;
-      quadMovingBounds  := boundsMode;
-    end;
-  end;
-
-  if not quadMoving and IsPointInPolygon(pts, ptF, true) then
+    quadMovingIndex := n;
+    quadMovingDelta := selPt-PtF;
+    quadMoving := True;
+    quadMovingBounds  := boundsMode;
+  end else
+  if IsPointInPolygon(quad, ptF, true) then
   begin
     quadMovingIndex := -1;
     quadMovingDelta := (quad[0]+quad[2])*0.5-ptF;
@@ -482,7 +502,7 @@ end;
 function TToolTextureMapping.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF): TRect;
 var n: integer;
-  delta,prevSize,newSize: TPointF;
+  delta,prevSize,newSize,selPt: TPointF;
   curBounds: array of TPointF;
   ratioX,ratioY,ratio: single;
   avgSize: single;
@@ -493,12 +513,13 @@ begin
     begin
       if (GetTexture <> nil) and (GetTexture.Height <> 0)
         and (GetTexture.Width <> 0) then
+      begin
         ratio := GetTexture.Width/GetTexture.Height;
-
-      newSize := ptF - quad[0];
-      avgSize := (abs(newSize.x)+abs(newSize.y))/2;
-      ptF.x := quad[0].x+avgSize*NonZero(sign(newSize.x),1)*ratio/((ratio+1)/2);
-      ptF.y := quad[0].y+avgSize*NonZero(sign(newSize.y),1)*1/((ratio+1)/2);
+        newSize := ptF - quad[0];
+        avgSize := (abs(newSize.x)+abs(newSize.y))/2;
+        ptF.x := quad[0].x+avgSize*NonZero(sign(newSize.x),1)*ratio/((ratio+1)/2);
+        ptF.y := quad[0].y+avgSize*NonZero(sign(newSize.y),1)*1/((ratio+1)/2);
+      end;
     end;
     quad[2] := ptF;
     quad[1].x := ptF.x;
@@ -508,12 +529,11 @@ begin
   end;
 
   result := EmptyRect;
-  if not FHintShowed then
+  if not ScaleHintShown then
   begin
     Manager.ToolPopup(tpmHoldKeysScaleMode, VK_SHIFT);
-    FHintShowed:= true;
+    ScaleHintShown:= true;
   end;
-  Manager.HintReturnValidates;
   if quadMoving then
   begin
     if quadMovingIndex = -1 then
@@ -591,6 +611,13 @@ begin
     result := FCurrentBounds;
   end;
   UpdateBoundsMode(result);
+  if not quadMoving then
+  begin
+    if GetClosestPoint(ptF, selPt) <> -1 then
+      Cursor := crSizeAll
+    else
+      Cursor := crDefault;
+  end;
 end;
 
 function TToolTextureMapping.GetIsSelectingTool: boolean;
@@ -699,6 +726,12 @@ begin
   Result:= [vftTexture];
 end;
 
+class procedure TToolTextureMapping.ForgetHintShown;
+begin
+  ScaleHintShown:= false;
+  ReturnHintShown:= false;
+end;
+
 constructor TToolTextureMapping.Create(AManager: TToolManager);
 begin
   inherited Create(AManager);
@@ -758,6 +791,11 @@ begin
     DrawQuad;
     FCanReadaptTexture:= false;
     result := FCurrentBounds;
+    if not ReturnHintShown then
+    begin
+      Manager.ToolPopup(tpmreturnValides);
+      ReturnHintShown:= true;
+    end;
     exit;
   end;
   if quadMoving then
@@ -1009,7 +1047,6 @@ var xb,yb,NbX,NbY: integer;
 
 begin
   result := EmptyRect;
-  Manager.HintReturnValidates;
 
   if not deformationGridMoving then
   begin
@@ -1090,6 +1127,32 @@ begin
                   DeformationGrid[yb+1,xb+1],DeformationGrid[yb+1,xb]],backupLayer,dmDrawWithTransparency);
             gridDone[yb,xb] := true;
           end;
+      //drawing zones that are inverted
+      for yb := gridMinY to gridMaxY-1 do
+        for xb := gridMinX to gridMaxX-1 do
+          if not gridDone[yb,xb] and
+             not IsMostlyClockwise([DeformationGrid[yb,xb],DeformationGrid[yb,xb+1],
+                DeformationGrid[yb+1,xb+1],DeformationGrid[yb+1,xb]]) then
+          begin
+            layer.FillQuadLinearMapping(DeformationGrid[yb,xb],DeformationGrid[yb,xb+1],
+                  DeformationGrid[yb+1,xb+1],DeformationGrid[yb+1,xb],backupLayer,
+                  DeformationGridTexCoord[yb,xb],DeformationGridTexCoord[yb,xb+1],DeformationGridTexCoord[yb+1,xb+1],
+                  DeformationGridTexCoord[yb+1,xb],true, fcKeepCW);
+            gridDone[yb,xb] := true;
+          end;
+      //drawing zones that are intersecting
+      for yb := gridMinY to gridMaxY-1 do
+        for xb := gridMinX to gridMaxX-1 do
+          if not gridDone[yb,xb] and
+             DoesQuadIntersect(DeformationGrid[yb,xb],DeformationGrid[yb,xb+1],
+                DeformationGrid[yb+1,xb+1],DeformationGrid[yb+1,xb]) then
+          begin
+            layer.FillQuadLinearMapping(DeformationGrid[yb,xb],DeformationGrid[yb,xb+1],
+                  DeformationGrid[yb+1,xb+1],DeformationGrid[yb+1,xb],backupLayer,
+                  DeformationGridTexCoord[yb,xb],DeformationGridTexCoord[yb,xb+1],DeformationGridTexCoord[yb+1,xb+1],
+                  DeformationGridTexCoord[yb+1,xb],true, fcKeepCW);
+            gridDone[yb,xb] := true;
+          end;
       //drawing zones that are concave
       for yb := gridMinY to gridMaxY-1 do
         for xb := gridMinX to gridMaxX-1 do
@@ -1141,12 +1204,19 @@ begin
     result := EmptyRect;
 end;
 
+class procedure TToolDeformationGrid.ForgetHintShown;
+begin
+  ReturnHintShown := false;
+end;
+
 constructor TToolDeformationGrid.Create(AManager: TToolManager);
 begin
   inherited Create(AManager);
   deformationGridNbX:= 0;
   deformationGridNbY:= 0;
   DoingDeformation:= false;
+  deformationGrid := nil;
+  deformationGridTexCoord := nil;
 end;
 
 function TToolDeformationGrid.Render(VirtualScreen: TBGRABitmap;
@@ -1215,19 +1285,24 @@ begin
   if Key = VK_ESCAPE then
   begin
     if DoingDeformation then
-    begin
       CancelActionPartially;
-      result := OnlyRenderChange;
-      manager.QueryExitTool;
-      Key := 0;
-    end;
+    result := OnlyRenderChange;
+    manager.QueryExitTool;
+    Key := 0;
   end;
 end;
 
 function TToolDeformationGrid.ToolUp: TRect;
 begin
   if deformationGridMoving then
-    result := OnlyRenderChange
+  begin
+    result := OnlyRenderChange;
+    if not ReturnHintShown then
+    begin
+      Manager.ToolPopup(tpmreturnValides);
+      ReturnHintShown := true;
+    end;
+  end
   else
     Result:=EmptyRect;
   deformationGridMoving := false;

+ 41 - 1
lazpaint/tools/utoolpolygon.pas

@@ -32,17 +32,21 @@ type
 
   TToolPolygon = class(TVectorialTool)
   protected
+    class var RightClickHintShown: boolean;
+    class var RemovePointHintShown: boolean;
     initiallyClosed : boolean;
     function ShapeClass: TVectorShapeAny; override;
     function CreateShape: TVectorShape; override;
     function ShouldCloseShape: boolean; virtual;
     procedure UpdateManagerCloseShape({%H-}AClose: boolean); virtual;
+    procedure AssignShapeStyleClosed(AShape: TVectorShape); virtual;
     procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
     procedure UpdateUserMode; virtual;
     procedure ShapeValidated; override;
     function DoToolKeyDown(var key: Word): TRect; override;
     function RoundCoordinate(constref ptF: TPointF): TPointF; override;
   public
+    class procedure ForgetHintShown;
     function ToolUp: TRect; override;
     function ToolKeyPress(var key: TUTF8Char): TRect; override;
   end;
@@ -51,7 +55,9 @@ type
 
   TToolPolyline = class(TToolPolygon)
   protected
+    function CreateShape: TVectorShape; override;
     function ShouldCloseShape: boolean; override;
+    procedure AssignShapeStyleClosed(AShape: TVectorShape); override;
     procedure UpdateManagerCloseShape({%H-}AClose: boolean); override;
     function GetManagerShapeOptions: TShapeOptions; override;
     function HasBrush: boolean; override;
@@ -131,11 +137,22 @@ end;
 
 { TToolPolyline }
 
+function TToolPolyline.CreateShape: TVectorShape;
+begin
+  Result:=inherited CreateShape;
+  inherited AssignShapeStyleClosed(Result);
+end;
+
 function TToolPolyline.ShouldCloseShape: boolean;
 begin
   result := false;
 end;
 
+procedure TToolPolyline.AssignShapeStyleClosed(AShape: TVectorShape);
+begin
+  //nothing
+end;
+
 procedure TToolPolyline.UpdateManagerCloseShape(AClose: boolean);
 begin
   //nothing
@@ -271,6 +288,11 @@ function TToolPolygon.CreateShape: TVectorShape;
 begin
   result := inherited CreateShape;
   initiallyClosed := ShouldCloseShape;
+  if not RightClickHintShown then
+  begin
+    Manager.ToolPopup(tpmRightClickFinishShape);
+    RightClickHintShown := true;
+  end;
 end;
 
 function TToolPolygon.ShouldCloseShape: boolean;
@@ -290,10 +312,15 @@ begin
   Manager.ShapeOptions:= opt;
 end;
 
+procedure TToolPolygon.AssignShapeStyleClosed(AShape: TVectorShape);
+begin
+  (AShape as TCustomPolypointShape).Closed := ShouldCloseShape;
+end;
+
 procedure TToolPolygon.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
 begin
   inherited AssignShapeStyle(AMatrix, AAlwaysFit);
-  TCustomPolypointShape(FShape).Closed := ShouldCloseShape;
+  AssignShapeStyleClosed(TCustomPolypointShape(FShape));
   TCustomPolypointShape(FShape).ArrowStartKind := Manager.ArrowStart;
   TCustomPolypointShape(FShape).ArrowEndKind := Manager.ArrowEnd;
   TCustomPolypointShape(FShape).ArrowSize := Manager.ArrowSize;
@@ -317,7 +344,14 @@ function TToolPolygon.ToolUp: TRect;
 begin
   Result:=inherited ToolUp;
   if Assigned(FShape) then
+  begin
     UpdateManagerCloseShape((FShape as TCustomPolypointShape).Closed);
+    if not RemovePointHintShown and ((FShape as TCustomPolypointShape).ValidatedPointCount >= 3) then
+    begin
+      Manager.ToolPopup(tpmBackspaceRemoveLastPoint);
+      RemovePointHintShown := true;
+    end;
+  end;
 end;
 
 function TToolPolygon.ToolKeyPress(var key: TUTF8Char): TRect;
@@ -357,6 +391,12 @@ begin
     result := ptF;
 end;
 
+class procedure TToolPolygon.ForgetHintShown;
+begin
+  RemovePointHintShown := false;
+  RemovePointHintShown := false;
+end;
+
 initialization
 
   RegisterTool(ptRect,TToolRectangle);

+ 9 - 3
lazpaint/tools/utoolselect.pas

@@ -118,7 +118,7 @@ type
 
   TToolRotateSelection = class(TTransformSelectionTool)
   protected
-    class var HintShowed: boolean;
+    class var HintShown: boolean;
     FHandRotating, FHandTranslating: boolean;
     FHandOrigin: TPointF;
     FSnapMode: boolean;
@@ -135,6 +135,7 @@ type
     function GetStatusText: string; override;
     procedure UpdateTransform;
   public
+    class procedure ForgetHintShown;
     constructor Create(AManager: TToolManager); override;
     function ToolUp: TRect; override;
     function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
@@ -421,10 +422,10 @@ function TToolRotateSelection.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
 var angleDiff: single;
   finalCenter, newOfs: TPointF;
 begin
-  if not HintShowed then
+  if not HintShown then
   begin
     Manager.ToolPopup(tpmHoldKeyRestrictRotation, VK_CONTROL);
-    HintShowed:= true;
+    HintShown:= true;
   end;
   if FHandRotating and ((FHandOrigin.X <> ptF.X) or (FHandOrigin.Y <> ptF.Y)) then
   begin
@@ -480,6 +481,11 @@ begin
                                    FOriginalTransform;
 end;
 
+class procedure TToolRotateSelection.ForgetHintShown;
+begin
+  HintShown:= false;
+end;
+
 constructor TToolRotateSelection.Create(AManager: TToolManager);
 begin
   inherited Create(AManager);

+ 27 - 2
lazpaint/tools/utooltext.pas

@@ -20,6 +20,7 @@ type
     FPrevShadowOffset: TPoint;
     FPrevShadowRadius: single;
     function ShapeClass: TVectorShapeAny; override;
+    function CreateShape: TVectorShape; override;
     function AlwaysRasterizeShape: boolean; override;
     procedure IncludeShadowBounds(var ARect: TRect);
     function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; ADraft: boolean): TRect; override;
@@ -49,6 +50,13 @@ begin
   result := TTextShape;
 end;
 
+function TToolText.CreateShape: TVectorShape;
+begin
+  Result:=inherited CreateShape;
+  if result is TTextShape then
+    (result as TTextShape).FontBidiMode:= Manager.TextBidiMode
+end;
+
 function TToolText.AlwaysRasterizeShape: boolean;
 begin
   Result:= Manager.TextShadow;
@@ -138,7 +146,12 @@ end;
 procedure TToolText.ShapeEditingChange(ASender: TObject);
 begin
   with (FShape as TTextShape) do
+  begin
+    Manager.TextFontStyle := FontStyle;
+    Manager.TextBidiMode := FontBidiMode;
     Manager.TextAlign := ParagraphAlignment;
+    Manager.TextVerticalAlign := VerticalAlignment;
+  end;
   inherited ShapeEditingChange(ASender);
 end;
 
@@ -159,7 +172,14 @@ begin
     Aliased := Manager.ShapeOptionAliasing;
     LightPosition := AMatrix*Manager.LightPosition;
     AltitudePercent:= Manager.PhongShapeAltitude;
-    ParagraphAlignment:= Manager.TextAlign;
+    if FontBidiMode <> Manager.TextBidiMode then
+    begin
+      FontBidiMode:= Manager.TextBidiMode;
+      Manager.TextAlign := ParagraphAlignment; // alignment depend on bidi mode
+    end
+    else
+      ParagraphAlignment:= Manager.TextAlign;
+    VerticalAlignment := Manager.TextVerticalAlign;
     PenPhong := Manager.TextPhong;
   end;
   if (Manager.TextShadow <> FPrevShadow) or
@@ -199,12 +219,15 @@ function TToolText.DoToolKeyDown(var key: Word): TRect;
 var
   keyUtf8: TUTF8Char;
   handled: Boolean;
+  alignBefore: TAlignment;
 begin
+  if FShape is TTextShape then
+    alignBefore := (FShape as TTextShape).ParagraphAlignment;
   if Key = VK_SPACE then
   begin
     keyUtf8:= ' ';
     result := ToolKeyPress(keyUtf8);
-    Key := 0;
+    if keyUtf8 <> ' ' then Key := 0;
   end else
   if (Key = VK_ESCAPE) and Assigned(FShape) then
   begin
@@ -222,6 +245,8 @@ begin
     Key := 0;
   end else
     Result:=inherited DoToolKeyDown(key);
+  if (FShape is TTextShape) and (alignBefore <> (FShape as TTextShape).ParagraphAlignment) then
+    Manager.TextAlign := (FShape as TTextShape).ParagraphAlignment;
 end;
 
 function TToolText.ToolCommand(ACommand: TToolCommand): boolean;

+ 64 - 23
lazpaint/tools/utoolvectorial.pas

@@ -28,13 +28,14 @@ type
     function GetIsHandDrawing: boolean;
     function GetIsIdle: boolean;
   protected
+    class var SquareHintShown: boolean;
     FLayerWasEmpty: boolean;
     FShape: TVectorShape;
     FTemporaryStorage: TBGRACustomOriginalStorage;
     FLastDraftUpdate: Boolean;
     FSwapColor: boolean;
     FQuickDefine: Boolean;
-    FQuickDefineStartPoint, FQuickDefineEndPoint: TPointF;
+    FQuickDefineStartPoint, FQuickDefineUserEndPoint, FQuickDefineEndPoint: TPointF;
     FPreviousUpdateBounds, FPreviousEditorBounds: TRect;
     FEditor: TBGRAOriginalEditor;
     FRightDown, FLeftDown: boolean;
@@ -59,6 +60,7 @@ type
     function VectorTransform(APixelCentered: boolean): TAffineMatrix;
     procedure UpdateCursor(ACursor: TOriginalEditorCursor);
     function FixLayerOffset: boolean; override;
+    function UpdateQuickDefine: TRect;
     function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF; rightBtn: boolean): TRect; override;
     function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF): TRect; override;
     function DoToolUpdate({%H-}toolDest: TBGRABitmap): TRect; override;
@@ -89,6 +91,7 @@ type
     function GetGridMatrix: TAffineMatrix; virtual;
     property Editor: TBGRAOriginalEditor read GetEditor;
   public
+    class procedure ForgetHintShown;
     function ValidateShape: TRect;
     function CancelShape: TRect;
     constructor Create(AManager: TToolManager); override;
@@ -497,6 +500,7 @@ begin
     Manager.LightPosition := m*LightPosition;
     Manager.PhongShapeAltitude := round(AltitudePercent);
     Manager.TextAlign:= ParagraphAlignment;
+    Manager.TextVerticalAlign:= VerticalAlignment;
     Manager.SetTextFont(FontName, FontEmHeight*zoom*72/Manager.Image.DPI, FontStyle);
     Manager.TextShadow:= false;
     if Aliased then
@@ -704,7 +708,13 @@ begin
         PenPhong := Manager.TextPhong;
         LightPosition := m*Manager.LightPosition;
         AltitudePercent := Manager.PhongShapeAltitude;
-        ParagraphAlignment := Manager.TextAlign;
+        if FontBidiMode <> Manager.TextBidiMode then
+        begin
+          FontBidiMode:= Manager.TextBidiMode;
+          Manager.TextAlign:= ParagraphAlignment;
+        end else
+          ParagraphAlignment := Manager.TextAlign;
+        VerticalAlignment:= Manager.TextVerticalAlign;
         FontName:= Manager.TextFontName;
         FontEmHeight:= Manager.TextFontSize*zoom*Manager.Image.DPI/72;
         FontStyle := Manager.TextFontStyle;
@@ -1605,6 +1615,8 @@ var
   r: TRect;
   matrix: TAffineMatrix;
 begin
+  if isEmptyPointF(ABounds.TopLeft) or isEmptyPointF(ABounds.BottomRight) then
+    raise exception.Create('Unexpected empty point');
   toolDest := GetToolDrawingLayer;
   matrix := VectorTransform(false);
   r := (matrix*TAffineBox.AffineBox(ABounds)).RectBounds;
@@ -1813,6 +1825,11 @@ begin
   end;
 end;
 
+class procedure TVectorialTool.ForgetHintShown;
+begin
+  SquareHintShown:= false;
+end;
+
 function TVectorialTool.ValidateShape: TRect;
 var
   layerId: LongInt;
@@ -2034,6 +2051,28 @@ begin
   Result:= false;
 end;
 
+function TVectorialTool.UpdateQuickDefine: TRect;
+var
+  s: TPointF;
+  avg: single;
+begin
+  if ssShift in ShiftState then
+  begin
+    s := FQuickDefineUserEndPoint-FQuickDefineStartPoint;
+    avg := sqrt(abs(s.x*s.y));
+    if s.x > 0 then FQuickDefineEndPoint.x := FQuickDefineStartPoint.x + avg else FQuickDefineEndPoint.x := FQuickDefineStartPoint.x - avg;
+    if s.y > 0 then FQuickDefineEndPoint.y := FQuickDefineStartPoint.y + avg else FQuickDefineEndPoint.y := FQuickDefineStartPoint.y - avg;
+  end else
+    FQuickDefineEndPoint := FQuickDefineUserEndPoint;
+  FShape.BeginUpdate;
+  QuickDefineShape(FQuickDefineStartPoint, FQuickDefineEndPoint);
+  FLastShapeTransform := AffineMatrixInverse(VectorTransform(false));
+  FShape.Transform(FLastShapeTransform);
+  AssignShapeStyle(FLastShapeTransform, true);
+  FShape.EndUpdate;
+  result := OnlyRenderChange;
+end;
+
 function TVectorialTool.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF; rightBtn: boolean): TRect;
 var
@@ -2063,6 +2102,7 @@ begin
 
   if FShape=nil then
   begin
+    UpdateUseOriginal;
     if UseOriginal and
       ((Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TVectorOriginal).GetShapesCost >= MediumShapeCost) then
     begin
@@ -2088,6 +2128,7 @@ begin
       FShape.TemporaryStorage := FTemporaryStorage;
       FQuickDefine := true;
       FQuickDefineStartPoint := RoundCoordinate(FLastPos);
+      FQuickDefineUserEndPoint := FQuickDefineStartPoint;
       FQuickDefineEndPoint := FQuickDefineStartPoint;
       FShape.BeginUpdate;
         QuickDefineShape(FQuickDefineStartPoint,FQuickDefineEndPoint);
@@ -2102,8 +2143,11 @@ begin
       FShape.OnEditingChange:=@ShapeEditingChange;
       FShape.OnRemoveQuery:= @ShapeRemoveQuery;
       result := RectUnion(result, UpdateShape(toolDest));
-      if FShape is TCustomRectShape then
+      if not SquareHintShown and (FShape is TCustomRectShape) then
+      begin
+        SquareHintShown := true;
         Manager.ToolPopup(tpmHoldKeyForSquare, VK_SHIFT);
+      end;
     end;
   end;
 end;
@@ -2111,8 +2155,6 @@ end;
 function TVectorialTool.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
   ptF: TPointF): TRect;
 var
-  s: TPointF;
-  avg: single;
   viewPt, shapePt: TPointF;
   handled: boolean;
   cur: TOriginalEditorCursor;
@@ -2122,21 +2164,8 @@ begin
     FLastPos := AffineMatrixTranslation(X,Y)*ptF;
   if FQuickDefine then
   begin
-    FQuickDefineEndPoint := RoundCoordinate(ptF);
-    if ssShift in ShiftState then
-    begin
-      s := FQuickDefineEndPoint-FQuickDefineStartPoint;
-      avg := sqrt(abs(s.x*s.y));
-      if s.x > 0 then FQuickDefineEndPoint.x := FQuickDefineStartPoint.x + avg else FQuickDefineEndPoint.x := FQuickDefineStartPoint.x - avg;
-      if s.y > 0 then FQuickDefineEndPoint.y := FQuickDefineStartPoint.y + avg else FQuickDefineEndPoint.y := FQuickDefineStartPoint.y - avg;
-    end;
-    FShape.BeginUpdate;
-      QuickDefineShape(FQuickDefineStartPoint, FQuickDefineEndPoint);
-      FLastShapeTransform := AffineMatrixInverse(VectorTransform(false));
-      FShape.Transform(FLastShapeTransform);
-      AssignShapeStyle(FLastShapeTransform, true);
-    FShape.EndUpdate;
-    result := OnlyRenderChange;
+    FQuickDefineUserEndPoint := RoundCoordinate(ptF);
+    result := UpdateQuickDefine;
   end else
   begin
     viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
@@ -2224,6 +2253,11 @@ begin
     result := CancelShape;
     Key := 0;
   end else
+  if (Key = VK_SHIFT) and FQuickDefine and Assigned(FShape) then
+  begin
+    result := UpdateQuickDefine;
+    Key := 0;
+  end else
   begin
     Editor.KeyDown(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
     if not handled and Assigned(FShape) then FShape.KeyDown(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
@@ -2246,9 +2280,16 @@ var
   handled: boolean;
 begin
   result := EmptyRect;
-  Editor.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
-  if not handled and Assigned(FShape) then FShape.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
-  if handled then Key := 0;
+  if (Key = VK_SHIFT) and FQuickDefine and Assigned(FShape) then
+  begin
+    result := UpdateQuickDefine;
+    Key := 0;
+  end else
+  begin
+    Editor.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
+    if not handled and Assigned(FShape) then FShape.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
+    if handled then Key := 0;
+  end;
 end;
 
 function TVectorialTool.ToolCommand(ACommand: TToolCommand): boolean;

+ 1 - 1
lazpaint/uchoosecolor.pas

@@ -54,6 +54,7 @@ begin
   FInterface := TChooseColorInterface.Create(ChooseColorControl, TFChooseColor_CustomDPI);
   BorderStyle := ToolWindowSizeable;
   FormStyle := ToolWindowStyle;
+  Position := poDesigned;
 end;
 
 procedure TFChooseColor.FormDeactivate(Sender: TObject);
@@ -70,7 +71,6 @@ end;
 
 procedure TFChooseColor.FormShow(Sender: TObject);
 begin
-  Position := poDesigned;
   self.EnsureVisible(False);
 end;
 

+ 41 - 13
lazpaint/ucommandline.pas

@@ -86,7 +86,7 @@ implementation
 uses
   SysUtils, BGRAUTF8, LazFileUtils, BGRABitmap, BGRABitmapTypes, Dialogs, uparse,
   UImage, UImageAction, ULayerAction, UScripting, UPython, Forms, StdCtrls, Controls,
-  UFileSystem;
+  UFileSystem, BGRAIconCursor;
 
 function ParamStrUTF8(AIndex: integer): string;
 begin
@@ -98,7 +98,6 @@ procedure InternalProcessCommands(instance: TLazPaintCustomInstance; commandsUTF
 var
   commandPrefix: set of char;
   InputFilename:string;
-  OutputFilename:string;
 
   i,iStart: integer;
   errPos: integer; //number conversion
@@ -263,10 +262,49 @@ var
     {$ENDIF}
   end;
 
+  procedure DoSaveFile(outputFilename: string);
+  var
+    icoCur: TBGRAIconCursor;
+    stream: TStream;
+    ext: String;
+  begin
+    instance.StartSavingImage(outputFilename);
+    try
+      ext := ExtractFileExt(outputFilename);
+      // normally ICO and CUR cannot be saved directly but make an exception
+      if (CompareText(ext, '.ico')=0) or (CompareText(ext, '.cur')=0) then
+      begin
+        icoCur := TBGRAIconCursor.Create;
+        try
+          if CompareText(ext, '.cur') = 0 then
+            icoCur.FileType := ifCur
+            else icoCur.FileType := ifIco;
+          icoCur.Add(instance.Image.RenderedImage, BGRABitDepthIconCursor(instance.Image.RenderedImage));
+          stream := FileManager.CreateFileStream(outputFilename, fmCreate);
+          try
+            icoCur.SaveToStream(stream);
+          finally
+            stream.Free;
+          end;
+        finally
+          icoCur.Free;
+        end;
+      end else
+        instance.Image.SaveToFileUTF8(outputFilename)
+    except
+      on ex: Exception do
+      begin
+        instance.ShowError(rsSave, rsUnableToSaveFile+outputFilename);
+      end;
+    end;
+    instance.EndSavingImage;
+  end;
+
 begin
   fileSaved := True;
   quitQuery:= false;
   errorEncountered := false;
+  enableScript:= false;
   if commandsUTF8.count = 0 then exit;
 
   commandPrefix := ['-'];
@@ -375,17 +413,7 @@ begin
     end else
     begin
       ForcePathDelims(CommandStr);
-      OutputFilename := CommandStr;
-      instance.StartSavingImage(OutputFilename);
-      try
-        instance.Image.SaveToFileUTF8(OutputFilename)
-      except
-        on ex: Exception do
-        begin
-          instance.ShowError(rsSave, rsUnableToSaveFile+OutputFilename);
-        end;
-      end;
-      instance.EndSavingImage;
+      DoSaveFile(commandStr);
       fileSaved:= true;
       exit;
     end;

+ 16 - 11
lazpaint/udarktheme.pas

@@ -264,11 +264,13 @@ begin
       begin
         { Button Down }
         Bitmap := TBGRABitmap.Create(Sender.Width, Sender.Height);
-        Bitmap.Rectangle(0, 0, Sender.Width, Sender.Height - 1, BGRA(58, 58, 58),
-          BGRA(71, 71, 71), dmSet);
-        Bitmap.Rectangle(1, 1, Sender.Width - 1, Sender.Height - 2, BGRA(65, 65, 65),
-          BGRA(71, 71, 71), dmSet);
-        Bitmap.SetHorizLine(0, Sender.Height - 1, Sender.Width - 1, BGRA(93, 93, 93));
+        Bitmap.Rectangle(0, 0, Sender.Width, Sender.Height - 1,
+          GetColorPanelShadow(ADarkTheme), dmSet);
+        Bitmap.Rectangle(1, 1, Sender.Width - 1, Sender.Height - 2,
+          MergeBGRA(ColorToBGRA(GetColorPanelShadow(ADarkTheme)), 2, ColorToBGRA(GetColorButtonFace(ADarkTheme)), 1),
+          MergeBGRA(ColorToBGRA(GetColorPanelShadow(ADarkTheme)), 1, ColorToBGRA(GetColorButtonFace(ADarkTheme)), 2), dmSet);
+        Bitmap.SetHorizLine(0, Sender.Height - 1, Sender.Width - 1,
+          GetColorButtonFace(ADarkTheme));
       end
       else
       begin
@@ -276,13 +278,16 @@ begin
         begin
           { Button Hovered }
           Bitmap := TBGRABitmap.Create(Sender.Width, Sender.Height);
-          Bitmap.GradientFill(0, 0, Sender.Width, Sender.Height, BGRA(132, 132, 132),
-            BGRA(109, 109, 109), gtLinear, PointF(0, 0),
+          Bitmap.GradientFill(0, 0, Sender.Width, Sender.Height, GetColorPanelHighlight(ADarkTheme),
+            GetColorButtonFace(ADarkTheme), gtLinear, PointF(0, 0),
             PointF(0, Sender.Height), dmSet);
           Bitmap.Rectangle(0, 0, Sender.Width, Sender.Height - 1,
-            BGRA(48, 48, 48), dmSet);
-          Bitmap.SetHorizLine(1, 1, Sender.Width - 2, BGRA(160, 160, 160));
-          Bitmap.SetHorizLine(0, Sender.Height - 1, Sender.Width - 1, BGRA(83, 83, 83));
+            GetColorPanelShadow(ADarkTheme),
+            dmSet);
+          Bitmap.SetHorizLine(1, 1, Sender.Width - 2,
+            MergeBGRA(ColorToBGRA(GetColorPanelHighlight(ADarkTheme)), ColorToBGRA(GetColorButtonHighlight(ADarkTheme))));
+          Bitmap.SetHorizLine(0, Sender.Height - 1, Sender.Width - 1,
+            MergeBGRA(ColorToBGRA(GetColorPanelShadow(ADarkTheme)), ColorToBGRA(GetColorButtonFace(ADarkTheme))));
         end
         else
           { Button Normal }
@@ -350,7 +355,7 @@ end;
 
 procedure TDarkTheme.ToolBarPaintButtonDark(Sender: TToolButton; State: integer);
 begin
-  ToolBarPaintButton(Sender, State, false);
+  ToolBarPaintButton(Sender, State, true);
 end;
 
 procedure TDarkTheme.Apply(AForm: TForm; AThemeEnabled: boolean; ARecursive: boolean);

+ 1 - 0
lazpaint/ufileextensions.pas

@@ -311,6 +311,7 @@ initialization
 
   RegisterPicExt(rsLayeredImage,'lzp;ora;pdn;oXo', [eoReadable]);
   RegisterPicExt(rsLayeredImage,'lzp;ora;oXo', [eoWritable]);
+  RegisterPicExt('AVIF','avif', [eoReadable,eoWritable]);
   RegisterPicExt(rsBitmap,'bmp', [eoReadable,eoWritable]);
   RegisterPicExt(rsAnimatedGIF,'gif', [eoReadable,eoWritable]);
   RegisterPicExt(rsIconOrCursor,'ico;cur', [eoReadable,eoWritable]);

+ 25 - 0
lazpaint/ufilesystem.pas

@@ -88,11 +88,13 @@ type
           AResult: TFileInfoList; AFileSortType: TFileSortType = fstNone);
     function IsDirectory(APathUTF8: string): boolean;
     function IsDirectoryEmpty(APathUTF8: string): boolean;
+    function IsValidFileName(AName: string): boolean;
     procedure CreateDirectory(APathUTF8: string);
     function DeleteDirectory(APathUTF8: string): boolean;
     function FileExists(AFilenameUTF8: string): boolean;
     procedure DeleteFile(AFilenameUTF8: string);
     function GetValidFilename(ASuggested: string): string;
+    function GetDefaultFilename(ADirectory: string): string;
   end;
 
 var
@@ -1137,6 +1139,11 @@ begin
   result := true;
 end;
 
+function TFileManager.IsValidFileName(AName: string): boolean;
+begin
+  result := AName = GetValidFilename(AName);
+end;
+
 procedure TFileManager.CreateDirectory(APathUTF8: string);
 var
   str: TStream;
@@ -1209,6 +1216,24 @@ begin
     end;
 end;
 
+function TFileManager.GetDefaultFilename(ADirectory: string): string;
+var
+  nonameCounter: Integer;
+  foundFiles: TFileInfoList;
+begin
+  result := rsNoName;
+  nonameCounter := 1;
+  foundFiles := TFileInfoList.Create;
+  repeat
+    foundFiles.Clear;
+    GetDirectoryElements(ADirectory, result+'.*', [otNonFolders], foundFiles);
+    if foundFiles.Count = 0 then exit;
+    inc(nonameCounter);
+    result := rsNoName+IntToStr(nonameCounter);
+  until nonameCounter > 999;
+  result := '?';
+end;
+
 initialization
 
   FileManager := TFileManager.Create;

+ 34 - 10
lazpaint/ugraph.pas

@@ -16,6 +16,7 @@ var
 
 function ComputeRatio(ARatio: string): single;
 function RatioToStr(ARatio: single): string;
+function InverseRatio(ARatio: string): string;
 
 function RectUnion(const rect1,Rect2: TRect): TRect;
 function RectInter(const rect1,Rect2: TRect): TRect;
@@ -104,7 +105,8 @@ var
     inc(num, AValue*denom);
   end;
 
-const MaxDev = 3;
+const MaxDev = 6;
+  MaxDenom = 99;
 var
   dev: array[1..MaxDev] of integer;
   devCount, i: integer;
@@ -116,21 +118,43 @@ begin
   devCount := 0;
   repeat
     inc(devCount);
-    dev[devCount] := trunc(ARatio);
+    dev[devCount] := trunc(curVal);
     remain := frac(curVal);
     if abs(remain) < 1e-3 then break;
+    if devCount = MaxDev then
+    begin
+      if remain > 0.5 then inc(dev[devCount]);
+      break;
+    end;
     curVal := 1/remain;
-  until devCount = MaxDev;
-  num := dev[devCount];
-  denom := 1;
-  for i := devCount-1 downto 1 do
-  begin
-    InvFrac;
-    AddFrac(dev[i]);
-  end;
+  until false;
+  repeat
+    num := dev[devCount];
+    denom := 1;
+    for i := devCount-1 downto 1 do
+    begin
+      InvFrac;
+      AddFrac(dev[i]);
+    end;
+    if ((num >= denom) and (denom <= MaxDenom))
+       or ((num < denom) and (num <= MaxDenom))
+       or (devCount = 1) then break;
+    dec(devCount);
+  until false;
   result := IntToStr(num)+':'+IntToStr(denom);
 end;
 
+function InverseRatio(ARatio: string): string;
+var
+  elements: TStringArray;
+begin
+  elements := ARatio.Split([':']);
+  if length(elements) = 2 then
+    result := elements[1] + ':' + elements[0]
+  else
+    result := ARatio;
+end;
+
 function RectUnion(const rect1, Rect2: TRect): TRect;
 begin
   if IsRectEmpty(rect1) then

+ 1 - 0
lazpaint/uimagelist.pas

@@ -423,6 +423,7 @@ end;
 
 procedure TFImageList.FormShow(Sender: TObject);
 begin
+  EnsureVisible(False);
   tbAutoUncheck.Down:= LazPaintInstance.Config.ImageListAutoUncheck;
   tbAutoZoomFit.Down:= LazPaintInstance.Config.ImageListAutoZoom;
   pmAutouncheckOnSave.Checked:=LazPaintInstance.Config.ImageListAutoUncheckMode=0;

+ 8 - 3
lazpaint/uimageview.pas

@@ -73,6 +73,7 @@ type
     FTablet: TLazTablet;
     FImagePos: TPointF;
     FCanvasScale: integer;
+    FAltKeyUsedForPenSize: boolean;
     function GetImage: TLazPaintImage;
     function GetPictureCanvas: TCanvas;
     function GetWorkArea: TRect;
@@ -293,10 +294,11 @@ procedure TImageView.PaintBoxMouseWheel(Sender: TObject; Shift: TShiftState;
   WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
 begin
   if not PictureCoordsDefined then exit;
-  if ssAlt in Shift then
+  if LazPaintInstance.ToolManager.PenWidthVisible and (ssAlt in Shift) then
   begin
     if WheelDelta > 0 then LazPaintInstance.ToolManager.StepPenSize(false)
     else if WheelDelta < 0 then LazPaintInstance.ToolManager.StepPenSize(true);
+    FAltKeyUsedForPenSize := true;
   end else
   begin
     Zoom.SetPosition(FormToBitmap(MousePos.X,MousePos.Y), MousePos);
@@ -610,6 +612,7 @@ begin
   FInstance := AInstance;
   FZoom := AZoom;
   FCanvasScale:= round(APaintBox.GetCanvasScaleFactor);
+  FAltKeyUsedForPenSize:= false;
   AInstance.ToolManager.CanvasScale := FCanvasScale;
   ugraph.CanvasScale:= FCanvasScale;
 
@@ -677,6 +680,7 @@ function TImageView.CatchToolKeyDown(var AKey: Word): boolean;
 begin
   FCatchPaintPicture:= true;
   FPaintPictureCatched := false;
+  if AKey = VK_MENU then FAltKeyUsedForPenSize := false;
   try
     result := LazPaintInstance.ToolManager.ToolKeyDown(AKey) or FPaintPictureCatched;
   finally
@@ -689,7 +693,8 @@ begin
   FCatchPaintPicture:= true;
   FPaintPictureCatched := false;
   try
-     result := LazPaintInstance.ToolManager.ToolKeyUp(AKey) or FPaintPictureCatched;
+    result := LazPaintInstance.ToolManager.ToolKeyUp(AKey) or FPaintPictureCatched;
+    if (AKey = VK_MENU) and FAltKeyUsedForPenSize then AKey := 0;
   finally
     FCatchPaintPicture:= false;
   end;
@@ -999,7 +1004,7 @@ begin
   virtualScreenPenCursorBefore := FPenCursorVisible;
   FPenCursorVisible := false;
   wantedCursor := LazPaintInstance.ToolManager.Cursor;
-  if LazPaintInstance.ToolManager.GetCurrentToolType in[ptPen,ptEraser,ptBrush,ptClone] then UseVSPenCursor;
+  if LazPaintInstance.ToolManager.GetCurrentToolType in[ptPen,ptEraser,ptBrush,ptClone,ptSelectPen] then UseVSPenCursor;
   if not PtInRect(WorkArea, Point(X,Y)) then wantedCursor:= crDefault;
   if FPaintBox.Cursor <> wantedCursor then FPaintBox.Cursor := wantedCursor;
   if virtualScreenPenCursorBefore or FPenCursorVisible then

+ 1 - 0
lazpaint/ulayerstack.pas

@@ -93,6 +93,7 @@ end;
 
 procedure TFLayerStack.FormShow(Sender: TObject);
 begin
+  EnsureVisible(False);
   CreateStackInterface;
 end;
 

+ 1 - 0
lazpaint/uloading.pas

@@ -127,6 +127,7 @@ begin
     Timer1.Enabled:= false
   else
     begin
+      Timer1.Enabled := false;
       Timer1.Interval := AMillisecond;
       Timer1.Enabled := true;
     end;

+ 32 - 11
lazpaint/umenu.pas

@@ -17,7 +17,10 @@ type
   private
     FActionList: TActionList;
     FDarkTheme: boolean;
-    FMainMenus: array of TMenuItem;
+    FMainMenus: array of record
+                  menu: TMenuItem;
+                  used: boolean;
+                end;
     FToolsShortcuts: array[TPaintToolType] of TUTF8Char;
     FToolbars: array of record
                  tb: TPanel;
@@ -237,10 +240,10 @@ begin
       break;
     end;
   for i := 0 to high(FMainMenus) do
-    if FMainMenus[i].Name = AMenuName then
+    if FMainMenus[i].menu.Name = AMenuName then
     begin
-      AddMenus(FMainMenus[i], FActionList, AActionsCommaText);
-      FMainMenus[i].Visible := true;
+      AddMenus(FMainMenus[i].menu, FActionList, AActionsCommaText);
+      FMainMenus[i].used := true;
     end;
 end;
 
@@ -388,7 +391,10 @@ var i: NativeInt;
 begin
   setlength(FMainMenus, length(AMainMenus));
   for i := 0 to high(AMainMenus) do
-    FMainMenus[i] := AMainMenus[i];
+  begin
+    FMainMenus[i].menu := AMainMenus[i];
+    FMainMenus[i].used := false;
+  end;
 end;
 
 procedure TMainFormMenu.Toolbars(const AToolbars: array of TPanel; AToolbarBackground: TPanel);
@@ -426,18 +432,31 @@ end;
 
 procedure TMainFormMenu.CycleTool(var ATool: TPaintToolType;
   var AShortCut: TUTF8Char);
+const cyrillicMap = 'ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯ';
 var
   curTool: TPaintToolType;
+  latinShortCut: TUTF8Char;
+  idx: integer;
 begin
-  AShortCut := UTF8UpperCase(AShortCut);
+  latinShortCut := UTF8UpperCase(AShortCut);
   curTool := ATool;
+  if (length(latinShortCut) <> 1) or
+    ((length(latinShortCut) = 1) and not (latinShortCut[1] in ['A'..'Z'])) then
+  begin
+    idx := pos(latinShortCut, cyrillicMap);
+    if idx <> 0 then
+    begin
+      idx := UTF8Length(copy(cyrillicMap, 1, idx));
+      latinShortCut := chr(idx+64);
+    end;
+  end;
   repeat
     if curTool = high(TPaintToolType) then
       curTool := low(TPaintToolType)
     else
       curTool := succ(curTool);
 
-    if (FToolsShortcuts[curTool] = AShortCut) and not
+    if (FToolsShortcuts[curTool] = latinShortCut) and not
        ((curTool = ptHotSpot) and not FInstance.Image.IsCursor) then
     begin
       ATool := curTool;
@@ -469,7 +488,8 @@ begin
   AddMenus('MenuScript', 'FileRunScript,-,InstalledScripts');
   AddMenus('MenuHelp',   'HelpIndex,-,HelpAbout');
   for i := 0 to high(FMainMenus) do
-    if FMainMenus[i].Count = 0 then FMainMenus[i].visible := false;
+    if not FMainMenus[i].used then
+       FMainMenus[i].menu.Visible := false;
 
   ApplyShortcuts;
 
@@ -612,6 +632,7 @@ begin
   ActionShortcut('ToolHotSpot','H');
   ActionShortcut('ToolPen','P');
   ActionShortcut('ToolBrush','B');
+  ActionShortcut('ToolClone','K');
   ActionShortcut('ToolColorPicker','C');
   ActionShortcut('ToolEraser','E');
   ActionShortcut('ToolEditShape','J');
@@ -623,12 +644,12 @@ begin
   ActionShortcut('ToolSpline','D');
   ActionShortcut('ToolFloodfill','G');
   ActionShortcut('ToolGradient','G');
-  ActionShortcut('ToolPhong','G');
+  ActionShortcut('ToolPhong','Y');
   ActionShortcut('ToolText','T');
   ActionShortcut('ToolSelectRect','M');
   ActionShortcut('ToolSelectEllipse','M');
-  ActionShortcut('ToolSelectPoly','A');
-  ActionShortcut('ToolSelectSpline','A');
+  ActionShortcut('ToolSelectPoly','F');
+  ActionShortcut('ToolSelectSpline','F');
   ActionShortcut('ToolMoveSelection','V');
   ActionShortcut('ToolRotateSelection','V');
   ActionShortcut('ToolSelectPen','O');

+ 57 - 12
lazpaint/umyslv.pas

@@ -55,6 +55,7 @@ type
     end;
     FActualRowHeight,FIconsPerLine: integer;
     FSelectedIndex,FKeySelectionRangeStart: integer;
+    FKeySelectionRangeDescending: boolean;
     FVScrollBar: TVolatileScrollBar;
     FVerticalScrollPos: integer;
     FWantedItemVisible: integer;
@@ -689,8 +690,26 @@ var i: integer;
 begin
   TVolatileScrollBar.InitDPI((Sender as TControl).GetCanvasScaleFactor);
 
-  if SelectedIndex = -1 then FKeySelectionRangeStart := -1
-  else if FKeySelectionRangeStart = -1 then FKeySelectionRangeStart:= SelectedIndex;
+  if not ItemSelected[FKeySelectionRangeStart] then FKeySelectionRangeStart := -1;
+  if FKeySelectionRangeStart = -1 then
+  begin
+    if FKeySelectionRangeDescending then
+    begin
+       for i := ItemCount-1 downto 0 do
+         if ItemSelected[i] then
+         begin
+           FKeySelectionRangeStart:= i;
+           break;
+         end;
+    end else
+      for i := 0 to ItemCount-1 do
+        if ItemSelected[i] then
+        begin
+          FKeySelectionRangeStart:= i;
+          break;
+        end;
+  end;
+
   for i := 0 to ColumnCount-1 do
     FColumns[i].displayRect := EmptyRect;
   w := ABitmap.Width;
@@ -750,12 +769,14 @@ procedure TLCShellListView.KeyDown(Sender: TObject; var Key: Word;
   Shift: TShiftState);
 
   procedure KeySelectRange(curItem: integer);
-  var i: integer;
+  var i, prevKeyRangeStart: integer;
   begin
+    prevKeyRangeStart := FKeySelectionRangeStart;
     DeselectAll;
-    if (ssShift in Shift) and (FKeySelectionRangeStart >= 0) and (FKeySelectionRangeStart < ItemCount) and
+    if (ssShift in Shift) and (prevKeyRangeStart >= 0) and (prevKeyRangeStart < ItemCount) and
       FAllowMultiSelect then
       begin
+        FKeySelectionRangeStart:= prevKeyRangeStart;
         i := curItem;
         FSelectedIndex:= curItem;
         ItemSelected[i] := true;
@@ -764,6 +785,7 @@ procedure TLCShellListView.KeyDown(Sender: TObject; var Key: Word;
           if i< FKeySelectionRangeStart then inc(i) else dec(i);
           ItemSelected[i]:= true;
         end;
+        FKeySelectionRangeDescending := curItem < FKeySelectionRangeStart;
       end else
       begin
         FSelectedIndex:= curItem;
@@ -774,6 +796,7 @@ procedure TLCShellListView.KeyDown(Sender: TObject; var Key: Word;
     MakeItemVisible(curItem);
   end;
 
+var j: integer;
 begin
   if ItemCount = 0 then exit;
 
@@ -781,14 +804,35 @@ begin
     begin
       if SelectedIndex = -1 then
       begin
-        Key := 0;
-        DeselectAll;
-        FSelectedIndex:= 0;
-        ItemSelected[0] := true;
-        InvalidateView;
-        MakeItemVisible(0);
-        if Assigned(FOnSelectItem) then FOnSelectItem(self,0,true);
-        exit;
+        if FKeySelectionRangeStart <> -1 then
+        begin
+          if FKeySelectionRangeDescending then
+          begin
+            for j := 0 to ItemCount-1 do
+              if ItemSelected[j] then
+              begin
+                FSelectedIndex := j;
+                break;
+              end;
+          end else
+            for j := ItemCount-1 downto 0 do
+              if ItemSelected[j] then
+              begin
+                FSelectedIndex := j;
+                break;
+              end;
+        end
+        else
+        begin
+          Key := 0;
+          DeselectAll;
+          FSelectedIndex:= 0;
+          ItemSelected[0] := true;
+          InvalidateView;
+          MakeItemVisible(0);
+          if Assigned(FOnSelectItem) then FOnSelectItem(self,0,true);
+          exit;
+        end;
       end
     end;
   if Key = VK_HOME then
@@ -876,6 +920,7 @@ begin
   begin
     if idx <> FSelectedIndex then
     begin
+      FKeySelectionRangeDescending:= idx < FSelectedIndex;
       while idx <> FSelectedIndex do
       begin
         if FSelectedIndex > idx then dec(FSelectedIndex) else inc(FSelectedIndex);

+ 1 - 0
lazpaint/upalettetoolbar.pas

@@ -396,6 +396,7 @@ begin
       saveDialog.InitialDir := '';
     saveDialog.Filter := BGRARegisteredPaletteFormatFilter(rsAllSupportedFiletypes);
     saveDialog.DefaultExt := 'txt';
+    saveDialog.Options := saveDialog.Options + [ofOverwritePrompt];
     if saveDialog.Execute then
     begin
       if Assigned(FLazPaintInstance) then

+ 1 - 1
lazpaint/upython.pas

@@ -68,7 +68,7 @@ var versionStr: string;
 begin
   if (PythonVersionCache.Bin <> APythonBin) or (PythonVersionCache.Version = '?') then
   begin
-    RunCommand(APythonBin, ['-V'], versionStr, [poStderrToOutPut]);
+    RunCommand(APythonBin, ['-V'], versionStr, []);
     PythonVersionCache.Bin := APythonBin;
     if versionStr.StartsWith(PythonVersionPrefix) then
       PythonVersionCache.Version := trim(copy(versionStr,length(PythonVersionPrefix)+1,

+ 7 - 1
lazpaint/uresourcestrings.pas

@@ -36,6 +36,7 @@ resourcestring
   rsErrorDecodingRaw='Error decoding raw image.';
   rsErrorLoadingOriginal='Error while loading original however layer can be rasterized.';
   rsRasterLayer = 'Raster layer';
+  rsVisible = 'Visibile';
   rsTransformedRasterLayer = 'Transformed raster layer';
   rsVectorialLayer = 'Vectorial layer';
   rsUnknownOriginal = 'Unknown original';
@@ -86,6 +87,7 @@ resourcestring
   rsHoldKeySnapToPixel = 'Hold %1 to snap to pixels';
   rsReturnValides = 'Press ENTER to validate';
   rsBackspaceRemoveLastPoint = 'Press BACKSPACE to remove last point';
+  rsRightClickFinishShape = 'Use RIGHT click to finish shape';
   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';
@@ -100,6 +102,7 @@ resourcestring
   rsEmptyLayer='Layer is empty';
   rsKeepEmptySpace='Keep empty space around opaque pixels?';
 
+  rsImage='Image';
   rsRepeatImage='Repeat image';
   rsCanvasSize='Canvas size';
   rsResamplingImage='Resampling image...';
@@ -135,6 +138,7 @@ resourcestring
 
   rsIntensity='Intensity';
   rsLightness='Lightness';
+  rsColorDescription='Color description: click to type in a color with the keyboard using color names or CSS notation.';
 
   rsHotSpot='Hot spot';
   rsEntries='Entries';
@@ -299,8 +303,10 @@ end;
 
 procedure AppendShortcut(AAction: TAction; AShortcut: string);
 begin
+  if AAction.Hint <> '' then
+    AAction.Hint := ApplyShortcutStr(AAction.Hint, AShortcut);
   if AAction.Caption = '' then
-    AAction.Caption := ApplyShortcutStr(AAction.Hint, AShortcut)
+    AAction.Caption := AAction.Hint
   else
     AAction.Caption := ApplyShortcutStr(AAction.Caption, AShortcut);
 end;

+ 1 - 1
lazpaint/utoolbox.pas

@@ -45,7 +45,6 @@ uses math, UDarkTheme;
 
 procedure TFToolbox.FormShow(Sender: TObject);
 begin
-  Position := poDesigned;
   self.EnsureVisible(False);
 end;
 
@@ -124,6 +123,7 @@ procedure TFToolbox.FormCreate(Sender: TObject);
 begin
   BorderStyle := ToolWindowFixedSize;
   FormStyle := ToolWindowStyle;
+  Position := poDesigned;
 end;
 
 {$R *.lfm}

+ 11 - 3
lazpaint/uzoom.pas

@@ -33,13 +33,15 @@ type
     FOnZoomChangedHandler : TOnZoomChangedHandler;
     FBitmapPosition: TPointF;
     FMousePosition: TPoint;
+    FOnCenterQuery: TNotifyEvent;
     function GetEditingZoom: boolean;
     function GetPositionDefined: boolean;
     function GetZoomFactor: single;
     procedure SetEditingZoom(AValue: boolean);
     procedure SetMaxFactor(AValue: single);
     procedure SetMinFactor(AValue: single);
-    procedure SetZoomFactor(AValue: single);
+    procedure SetZoomFactor(AValue: single); overload;
+    procedure SetZoomFactor(AValue: single; ACenter: boolean); overload;
   protected
     procedure EditZoom_KeyPress(Sender: TObject; var Key: char);
     procedure EditZoom_ZoomExit(Sender: TObject);
@@ -66,6 +68,7 @@ type
     property BitmapPosition: TPointF read FBitmapPosition;
     property MousePosition: TPoint read FMousePosition;
     property PositionDefined: boolean read GetPositionDefined;
+    property OnCenterQuery: TNotifyEvent read FOnCenterQuery write FOnCenterQuery;
   end;
 
 implementation
@@ -120,12 +123,17 @@ begin
 end;
 
 procedure TZoom.SetZoomFactor(AValue: single);
+begin
+  SetZoomFactor(AValue, false);
+end;
+
+procedure TZoom.SetZoomFactor(AValue: single; ACenter: boolean);
 begin
   if (FMinFactor <> 0) and (AValue < FMinFactor) then AValue := FMinFactor;
   if (FMaxFactor <> 0) and (AValue > FMaxFactor) then AValue := FMaxFactor;
-  if AValue = FZoomFactor then exit;
   EditingZoom:= False;
   FZoomFactor:= AValue;
+  if ACenter and Assigned(OnCenterQuery) then OnCenterQuery(self);
   if Assigned(FOnZoomChangedHandler) then
     FOnZoomChangedHandler(self, AValue);
   UpdateLabel;
@@ -236,7 +244,7 @@ begin
   try
     zx := (pictureArea.right-pictureArea.left-pixelMargin)/AImageWidth;
     zy := (pictureArea.bottom-pictureArea.top-pixelMargin)/AImageheight;
-    Factor:= min(zx,zy);
+    SetZoomFactor(min(zx,zy), true);
   except
     on ex:Exception do
     begin end;

+ 3 - 2
lazpaintcontrols/lazpaintcontrols.lpk

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
-  <Package Version="4">
+  <Package Version="5">
     <Name Value="lazpaintcontrols"/>
     <Type Value="RunAndDesignTime"/>
     <CompilerOptions>
@@ -20,7 +20,7 @@
         </Debugging>
       </Linking>
     </CompilerOptions>
-    <Version Minor="1"/>
+    <Version Minor="2"/>
     <Files Count="13">
       <Item1>
         <Filename Value="lctoolbars.pas"/>
@@ -76,6 +76,7 @@
         <UnitName Value="LCVectorMultishape"/>
       </Item13>
     </Files>
+    <CompatibilityMode Value="True"/>
     <i18n>
       <EnableI18N Value="True"/>
       <OutDir Value="../lazpaint/release/bin/i18n"/>

+ 9 - 0
lazpaintcontrols/lcvectorialfillcontrol.pas

@@ -75,6 +75,7 @@ type
     FOnEditGradTexPoints: TNotifyEvent;
     FOnChooseColor: TChooseColorEvent;
     FOnFillChange: TNotifyEvent;
+    FOnOpacityChange: TNotifyEvent;
     FOnFillTypeChange: TNotifyEvent;
     FOnTextureClick: TNotifyEvent;
     FOnTextureChange: TNotifyEvent;
@@ -84,6 +85,7 @@ type
     procedure DoOnEditGradTexPoints(Sender: TObject);
     procedure DoOnFillChange(Sender: TObject);
     procedure DoOnFillTypeChange(Sender: TObject);
+    procedure DoOnOpacityChange(Sender: TObject);
     procedure DoOnTextureClick(Sender: TObject);
     procedure DoOnTextureChange(Sender: TObject);
     procedure DoOnResize; override;
@@ -122,6 +124,7 @@ type
     property EditingGradTexPoints: boolean read GetEditingGradTexPoints write SetEditingGradTexPoints;
     property OnChooseColor: TChooseColorEvent read FOnChooseColor write SetOnChooseColor;
     property OnFillChange: TNotifyEvent read FOnFillChange write FOnFillChange;
+    property OnOpacityChange: TNotifyEvent read FOnOpacityChange write FOnOpacityChange;
     property OnTextureChange: TNotifyEvent read FOnTextureChange write FOnTextureChange;
     property OnAdjustToShape: TNotifyEvent read FOnAdjustToShape write FOnAdjustToShape;
     property OnEditGradTexPoints: TNotifyEvent read FOnEditGradTexPoints write FOnEditGradTexPoints;
@@ -421,6 +424,11 @@ begin
   if Assigned(FOnFillTypeChange) then FOnFillTypeChange(self);
 end;
 
+procedure TLCVectorialFillControl.DoOnOpacityChange(Sender: TObject);
+begin
+  if Assigned(FOnOpacityChange) then FOnOpacityChange(self);
+end;
+
 procedure TLCVectorialFillControl.DoOnTextureChange(Sender: TObject);
 begin
   if Assigned(FOnTextureChange) then FOnTextureChange(self);
@@ -443,6 +451,7 @@ begin
   FInterface.OnAdjustToShape:=@DoOnAdjustToShape;
   FInterface.OnEditGradTexPoints:=@DoOnEditGradTexPoints;
   FInterface.OnFillTypeChange:=@DoOnFillTypeChange;
+  FInterface.OnOpacityChange:=@DoOnOpacityChange;
   FInterface.OnMouseMove:=@InterfaceMouseMove;
   FInterface.OnMouseDown:=@InterfaceMouseDown;
   FInterface.OnMouseUp:=@InterfaceMouseUp;

+ 7 - 1
lazpaintcontrols/lcvectorialfillinterface.pas

@@ -80,7 +80,7 @@ type
     FPreview: TImage;
     FButtonFillNone, FButtonFillSolid,
     FButtonFillGradient, FButtonFillTexture: TToolButton;
-    FOnFillChange, FOnFillTypeChange: TNotifyEvent;
+    FOnFillChange, FOnFillTypeChange, FOnOpacityChange: TNotifyEvent;
     FButtonEditGradTexPoints, FButtonAdjustToShape: TToolButton;
     FOnEditGradTexPoints, FOnAdjustToShape: TNotifyEvent;
 
@@ -204,6 +204,7 @@ type
     property OnAdjustToShape: TNotifyEvent read FOnAdjustToShape write FOnAdjustToShape;
     property OnEditGradTexPoints: TNotifyEvent read FOnEditGradTexPoints write FOnEditGradTexPoints;
     property OnFillTypeChange: TNotifyEvent read FOnFillTypeChange write FOnFillTypeChange;
+    property OnOpacityChange: TNotifyEvent read FOnOpacityChange write FOnOpacityChange;
     property OnChooseColor: TChooseColorEvent read FOnChooseColor write FOnChooseColor;
     property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
     property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove;
@@ -574,6 +575,7 @@ begin
     c := GradEndColor;
     c.alpha := FUpDownEndAlpha.Value;
     GradEndColor:= c;
+    if assigned(FOnOpacityChange) then FOnOpacityChange(self);
   end;
 end;
 
@@ -581,7 +583,10 @@ procedure TVectorialFillInterface.UpDownSolidAlphaChange(Sender: TObject;
   AByUser: boolean);
 begin
   if AByUser then
+  begin
     SolidColor:= ColorToBGRA(FShapeSolidColor.Brush.Color, FUpDownSolidAlpha.Value);
+    if assigned(FOnOpacityChange) then FOnOpacityChange(self);
+  end;
 end;
 
 procedure TVectorialFillInterface.UpDownStartAlphaChange(Sender: TObject;
@@ -594,6 +599,7 @@ begin
     c := GradStartColor;
     c.alpha := FUpDownStartAlpha.Value;
     GradStartColor:= c;
+    if assigned(FOnOpacityChange) then FOnOpacityChange(self);
   end;
 end;
 

+ 2 - 0
lazpaintcontrols/lcvectororiginal.pas

@@ -1976,6 +1976,8 @@ begin
   if FUpdateCount = 0 then
   begin
     FBoundsBeforeUpdate := GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
+    if isEmptyPointF(FBoundsBeforeUpdate.TopLeft) or isEmptyPointF(FBoundsBeforeUpdate.BottomRight) then
+      raise exception.Create('Unexpected empty point');
     Inc(FRenderIteration);
   end;
   inc(FUpdateCount);

+ 78 - 13
lazpaintcontrols/lcvectorpolyshapes.pas

@@ -67,6 +67,7 @@ type
     function GetLineCap: TPenEndCap;
     function GetPoint(AIndex: integer): TPointF;
     function GetPointCount: integer;
+    function GetValidatedPointCount: integer;
     procedure SetArrowEndKind(AValue: TArrowKind);
     procedure SetArrowSize(AValue: TPointF);
     procedure SetArrowStartKind(AValue: TArrowKind);
@@ -80,7 +81,7 @@ type
     FCenterPoint: TPointF;
     FCenterPointEditorIndex: integer;
     FCurPoint: integer;
-    FAddingPoint: boolean;
+    FAddingPoint, FAltPressed: boolean;
     FMousePos: TPointF;
     FHoverPoint: integer;
     FHoverCenter: boolean;
@@ -91,7 +92,8 @@ type
     procedure OnMoveCenterPoint({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF; {%H-}AShift: TShiftState);
     procedure OnStartMove({%H-}ASender: TObject; APointIndex: integer; {%H-}AShift: TShiftState);
     function GetCurve(AMatrix: TAffineMatrix): ArrayOfTPointF; virtual;
-    function GetPath(AMatrix: TAffineMatrix): TBGRAPath; virtual;
+    function GetPath(AMatrix: TAffineMatrix): TBGRAPath; virtual; overload;
+    function GetPath(const APoints: array of TPointF): TBGRAPath; overload;
     procedure SetUsermode(AValue: TVectorShapeUsermode); override;
     function GetClosed: boolean; virtual;
     procedure SetClosed(AValue: boolean); virtual;
@@ -117,6 +119,7 @@ type
     procedure MouseMove({%H-}Shift: TShiftState; X, Y: single; var {%H-}ACursor: TOriginalEditorCursor; var AHandled: boolean); override;
     procedure MouseDown(RightButton: boolean; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: single; var {%H-}ACursor: TOriginalEditorCursor; var AHandled: boolean); override;
     procedure KeyDown({%H-}Shift: TShiftState; Key: TSpecialKey; var AHandled: boolean); override;
+    procedure KeyUp(Shift: TShiftState; Key: TSpecialKey; var AHandled: boolean); override;
     procedure QuickDefine(constref APoint1,APoint2: TPointF); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
@@ -126,6 +129,7 @@ type
     class function DefaultArrowSize: TPointF;
     property Points[AIndex:integer]: TPointF read GetPoint write SetPoint;
     property PointCount: integer read GetPointCount;
+    property ValidatedPointCount: integer read GetValidatedPointCount;
     property Closed: boolean read GetClosed write SetClosed;
     property HoverPoint: integer read GetHoverPoint write SetHoverPoint;
     property HoverCenter: boolean read FHoverCenter write SetHoverCenter;
@@ -474,6 +478,14 @@ begin
   result:= length(FPoints);
 end;
 
+function TCustomPolypointShape.GetValidatedPointCount: integer;
+begin
+  if (PointCount > 1) and FAddingPoint then
+    result := PointCount - 1
+  else
+    result := PointCount;
+end;
+
 procedure TCustomPolypointShape.SetArrowEndKind(AValue: TArrowKind);
 begin
   if FArrowEndKind=AValue then Exit;
@@ -610,9 +622,38 @@ begin
     result[i] := m*Points[i];
 end;
 
+function TCustomPolypointShape.GetPath(const APoints: array of TPointF): TBGRAPath;
+var p: TPointF;
+  subPoly: boolean;
+begin
+  result := TBGRAPath.Create;
+  subPoly := true;
+  for p in APoints do
+  begin
+    if isEmptyPointF(p) then
+    begin
+      if not result.IsEmpty and Closed then result.closePath;
+      subPoly := true;
+    end else
+    begin
+      if subPoly then
+      begin
+        result.moveTo(p);
+        subPoly := false;
+      end
+      else
+        result.lineTo(p);
+    end;
+  end;
+  if not result.IsEmpty and Closed then result.closePath;
+end;
+
 function TCustomPolypointShape.GetPath(AMatrix: TAffineMatrix): TBGRAPath;
+var
+  pts: array of TPointF;
 begin
-  result := TBGRAPath.Create(GetCurve(AMatrix));
+  pts := GetCurve(AMatrix);
+  result := GetPath(pts);
 end;
 
 class function TCustomPolypointShape.Usermodes: TVectorShapeUsermodes;
@@ -1034,6 +1075,7 @@ begin
     skRight: d := dx;
     skUp: d := -dy;
     skDown: d := dy;
+    else d := PointF(0,0);
     end;
     if HoverCenter then
       Center := Center + d
@@ -1041,9 +1083,30 @@ begin
       Points[HoverPoint] := Points[HoverPoint] + d;
     AHandled := true;
   end else
+  if Key = skAlt then
+  begin
+    BeginUpdate;
+    FAltPressed := true;
+    EndUpdate;
+    AHandled := true;
+  end
+  else
     inherited KeyDown(Shift, Key, AHandled);
 end;
 
+procedure TCustomPolypointShape.KeyUp(Shift: TShiftState; Key: TSpecialKey;
+  var AHandled: boolean);
+begin
+  if Key = skAlt then
+  begin
+    BeginUpdate;
+    FAltPressed := false;
+    EndUpdate;
+    AHandled := true;
+  end
+  else inherited KeyUp(Shift, Key, AHandled);
+end;
+
 procedure TCustomPolypointShape.QuickDefine(constref APoint1, APoint2: TPointF);
 begin
   BeginUpdate(TCustomPolypointShapeDiff);
@@ -1088,8 +1151,8 @@ var
   i: Integer;
 begin
   inherited SaveToStorage(AStorage);
-  setlength(x, PointCount);
-  setlength(y, PointCount);
+  setlength({%H-}x, PointCount);
+  setlength({%H-}y, PointCount);
   for i:= 0 to PointCount-1 do
   begin
     x[i] := Points[i].x;
@@ -1147,7 +1210,8 @@ begin
     FCenterPoint *= 1/nbTotal
     else FCenterPoint := EmptyPointF;
 
-  if (FAddingPoint and (nbTotal > 2)) or (not FAddingPoint and (nbTotal > 1)) then
+  if ((FAddingPoint and (nbTotal > 2)) or (not FAddingPoint and (nbTotal > 1)))
+     and not FAltPressed then
   begin
     FCenterPointEditorIndex := AEditor.AddPoint(FCenterPoint, @OnMoveCenterPoint, true);
     AEditor.PointHighlighted[FCenterPointEditorIndex] := HoverCenter;
@@ -1346,7 +1410,7 @@ var pts: ArrayOfTPointF;
 begin
   if not GetPenVisible and not GetBackVisible or (PointCount = 0) then exit(false);
 
-  setlength(pts, PointCount);
+  setlength({%H-}pts, PointCount);
   for i := 0 to high(pts) do
     pts[i] := AMatrix * Points[i];
 
@@ -1434,7 +1498,7 @@ begin
   pts := inherited GetCurve(AMatrix);
   if FSplineStyle = ssEasyBezier then
   begin
-    setlength(cm, PointCount);
+    setlength({%H-}cm, PointCount);
     for i := 0 to PointCount-1 do
       cm[i] := CurveMode[i];
     eb := EasyBezierCurve(pts, Closed, cm, CosineAngle);
@@ -1454,18 +1518,19 @@ var
   eb: TEasyBezierCurve;
 begin
   pts := inherited GetCurve(AMatrix);
-  result := TBGRAPath.Create;
   if FSplineStyle = ssEasyBezier then
   begin
-    setlength(cm, PointCount);
+    setlength({%H-}cm, PointCount);
     for i := 0 to PointCount-1 do
       cm[i] := CurveMode[i];
     eb := EasyBezierCurve(pts, Closed, cm, CosineAngle);
+    result := TBGRAPath.Create;
     eb.CopyToPath(result);
   end else
   begin
-    if Closed then result.closedSpline(pts, FSplineStyle)
-    else result.openedSpline(pts, FSplineStyle);
+    if Closed then pts := ComputeClosedSpline(pts, FSplineStyle)
+    else pts := ComputeOpenedSpline(pts, FSplineStyle);
+    result := GetPath(pts);
   end;
 end;
 
@@ -1664,7 +1729,7 @@ begin
   AStorage.RawString['spline-style'] := s;
   if SplineStyle = ssEasyBezier then
   begin
-    setlength(cm, PointCount);
+    setlength({%H-}cm, PointCount);
     for i := 0 to PointCount-1 do
       cm[i] := ord(CurveMode[i]);
     AStorage.FloatArray['curve-mode'] := cm;

+ 2 - 1
lazpaintcontrols/lcvectorrectshapes.pas

@@ -988,7 +988,7 @@ var
   i: Integer;
 begin
   pts := GetAffineBox(AMatrix, true).AsPolygon;
-  If GetBackVisible then
+  If GetBackVisible and (Width <> 0) and (Height <> 0) then
   begin
     if (BackFill.FillType = vftSolid) then backScan := nil
     else backScan := BackFill.CreateScanner(AMatrix, ADraft);
@@ -1101,6 +1101,7 @@ begin
       begin
         pts := ComputeStroke(GetAffineBox(AMatrix, false).AsPolygon, true, AMatrix);
         for i := 0 to high(pts) do
+        if not IsEmptyPointF(pts[i]) then
         begin
           if pts[i].x < result.Left then result.Left := pts[i].x;
           if pts[i].x > result.Right then result.Right := pts[i].x;

+ 42 - 17
lazpaintcontrols/lcvectortextshapes.pas

@@ -101,15 +101,15 @@ type
     function GetHasSelection: boolean;
     function GetParagraphAlignment: TAlignment;
     procedure InvalidateParagraphLayout(AFrom, ATo: integer);
-    procedure LayoutBrokenLinesChanged(ASender: TObject;
+    procedure LayoutBrokenLinesChanged({%H-}ASender: TObject;
       AParagraphIndex: integer; ASubBrokenStart, ASubBrokenChangedCountBefore,
       ASubBrokenChangedCountAfter: integer; ASubBrokenTotalCountBefore,
       ASubBrokenTotalCountAfter: integer);
-    procedure LayoutParagraphDeleted(ASender: TObject; AParagraphIndex: integer);
-    procedure LayoutParagraphMergedWithNext(ASender: TObject;
+    procedure LayoutParagraphDeleted({%H-}ASender: TObject; AParagraphIndex: integer);
+    procedure LayoutParagraphMergedWithNext({%H-}ASender: TObject;
       AParagraphIndex: integer);
-    procedure LayoutParagraphSplit(ASender: TObject; AParagraphIndex: integer;
-      ASubBrokenIndex, ACharIndex: integer);
+    procedure LayoutParagraphSplit({%H-}ASender: TObject; AParagraphIndex: integer;
+      {%H-}ASubBrokenIndex, {%H-}ACharIndex: integer);
     procedure OnMoveLightPos({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF;
       {%H-}AShift: TShiftState);
     procedure SetAliased(AValue: boolean);
@@ -153,6 +153,7 @@ type
     procedure InsertUnicodeValue;
     procedure FillChange(ASender: TObject; var ADiff: TCustomVectorialFillDiff); override;
     procedure InvalidateAll;
+    function GetVerticalAlignMatrix(tl: TBidiTextLayout): TAffineMatrix;
   public
     constructor Create(AContainer: TVectorOriginal); override;
     procedure QuickDefine(constref APoint1,APoint2: TPointF); override;
@@ -685,6 +686,7 @@ begin
   if FAliased=AValue then Exit;
   BeginUpdate(TTextShapeFontDiff);
   FAliased:=AValue;
+  InvalidateAll;
   EndUpdate;
 end;
 
@@ -818,6 +820,7 @@ begin
   if FVertAlign=AValue then Exit;
   BeginUpdate(TTextShapeTextDiff);
   FVertAlign:=AValue;
+  InvalidateAll; // could be more subtle
   EndUpdate;
 end;
 
@@ -1073,6 +1076,19 @@ begin
   FParagraphLayout := nil;
 end;
 
+function TTextShape.GetVerticalAlignMatrix(tl: TBidiTextLayout): TAffineMatrix;
+var
+  th: Single;
+begin
+  th := max(tl.TotalTextHeight - tl.ParagraphSpacingBelow * tl.LineHeight, 0);
+  if th < tl.AvailableHeight then
+  case VerticalAlignment of
+  tlBottom: exit(AffineMatrixTranslation(0, tl.AvailableHeight-th));
+  tlCenter: exit(AffineMatrixTranslation(0, (tl.AvailableHeight-th)/2));
+  end;
+  exit(AffineMatrixIdentity);
+end;
+
 constructor TTextShape.Create(AContainer: TVectorOriginal);
 begin
   inherited Create(AContainer);
@@ -1175,6 +1191,11 @@ begin
     tl.ParagraphAlignment[i] := AlignmentToBidiTextAlignment(alignment, tl.ParagraphRightToLeft[i]);
   end;
   paraAlignList.Free;
+  case AStorage.RawString['vertical-align'] of
+  'middle': VerticalAlignment:= tlCenter;
+  'bottom': VerticalAlignment:= tlBottom;
+  else VerticalAlignment:= tlTop;
+  end;
   EndUpdate;
 end;
 
@@ -1219,6 +1240,11 @@ begin
     end;
   AStorage.RawString['paragraph-align'] := paraAlignList.DelimitedText;
   paraAlignList.Free;
+  case VerticalAlignment of
+  tlTop: AStorage.RemoveAttribute('vertical-align');
+  tlCenter: AStorage.RawString['vertical-align'] := 'middle';
+  tlBottom: AStorage.RawString['vertical-align'] := 'bottom';
+  end;
 end;
 
 destructor TTextShape.Destroy;
@@ -1276,7 +1302,7 @@ begin
     tl := GetTextLayout;
     caret:= tl.GetCaret(FSelEnd);
     zoom := GetTextRenderZoom;
-    m := AffineMatrixTranslation(-0.5,-0.5)*GetUntransformedMatrix*AffineMatrixScale(1/zoom,1/zoom);
+    m := AffineMatrixTranslation(-0.5,-0.5)*GetUntransformedMatrix*AffineMatrixScale(1/zoom,1/zoom)*GetVerticalAlignMatrix(tl);
     if FSelStart<>FSelEnd then
     begin
       pts := tl.GetTextEnveloppe(FSelStart, FSelEnd, false, true, true);
@@ -1730,7 +1756,7 @@ var
                TAffineBox.AffineBox(sourceRectF);
     wholeImage := TAffineBox.AffineBox(PointF(-1,-1), PointF(-1,ADest.Height+1),
                                        PointF(ADest.Width+1,-1));
-    ADest.FillMode := fmWinding;
+    ADest.FillMode := fmAlternate;
     ADest.ErasePolyAntialias( ConcatPointsF([wholeImage.AsPolygon, maskBox.AsPolygon], true),
                                   255, false);
   end;
@@ -1760,6 +1786,7 @@ begin
 
   tl := GetTextLayout;
   sourceRectF := RectF(-pad,0,tl.AvailableWidth+pad,min(tl.TotalTextHeight,tl.AvailableHeight));
+  m *= GetVerticalAlignMatrix(tl);
 
   if CanHaveRenderStorage then
   begin
@@ -1832,12 +1859,6 @@ begin
   sourceRectF.Right := floor(sourceRectF.Right);
   sourceRectF.Bottom := sourceRectF.Bottom;
 
-  if tl.TotalTextHeight < tl.AvailableHeight then
-  case VerticalAlignment of
-  tlBottom: m *= AffineMatrixTranslation(0, tl.AvailableHeight-tl.TotalTextHeight);
-  tlCenter: m *= AffineMatrixTranslation(0, (tl.AvailableHeight-tl.TotalTextHeight)/2);
-  end;
-
   with transfRectF do
     transfRect := Rect(floor(Left),floor(Top),ceil(Right),ceil(Bottom));
 
@@ -2147,7 +2168,7 @@ begin
     else DeleteTextAfter(1);
     AHandled:= true;
   end else
-  if Key in [skLeft,skRight] then
+  if (Key in [skLeft,skRight]) and not (ssAlt in Shift) then
   begin
     tl := GetTextLayout;
     if (Key = skLeft) xor tl.ParagraphRightToLeft[tl.GetParagraphAt(FSelEnd)] then
@@ -2167,7 +2188,7 @@ begin
     end;
     AHandled := true;
   end else
-  if Key in [skUp,skDown] then
+  if (Key in [skUp,skDown]) and not (ssAlt in Shift)  then
   begin
     tl := GetTextLayout;
     if Key = skUp then
@@ -2289,10 +2310,13 @@ begin
       begin
         Usermode := vsuEditText;
         InsertText(UTF8Key);
+        AHandled := true;
       end;
     end else
+    begin
       InsertText(UTF8Key);
-    AHandled := true;
+      AHandled := true;
+    end;
   end;
 end;
 
@@ -2455,8 +2479,9 @@ begin
       else span.textDirection:= stdLtr;
     with rF do
     begin
-      setlength(a, 1);
+      setlength({%H-}a, 1);
       a[0] := FloatWithCSSUnit(Left/zoom, cuCustom);
+      if span.textDirection = stdRtl then a[0].value += Width/zoom;
       span.x := a;
       a[0] := FloatWithCSSUnit((Top + fm.Baseline)/zoom, cuCustom);
       span.y := a;

+ 10 - 0
resources/scripts/lazpaint/tools.py

@@ -67,6 +67,10 @@ ALIGN_LEFT = 'Left'
 ALIGN_CENTER = 'Center'
 ALIGN_RIGHT = 'Right'
 
+BIDI_AUTO = 'BidiAuto'
+BIDI_LEFT_TO_RIGHT = 'LeftToRight'
+BIDI_RIGHT_TO_LEFT = 'RightToLeft'
+
 SHAPE_OPTION_DRAW_SHAPE = 'DrawShape'
 SHAPE_OPTION_FILL_SHAPE = 'FillShape'
 SHAPE_OPTION_CLOSE_SHAPE = 'CloseShape'
@@ -345,6 +349,12 @@ def set_text_align(align):
 def get_text_align():
   return command.send('ToolGetTextAlign?')
 
+def set_text_bidi_mode(bidi_mode):
+  command.send('ToolSetTextBidiMode', BidiMode=bidi_mode)
+
+def get_text_bidi_mode():
+  return command.send('ToolGetTextBidiMode?')
+
 def set_text_outline(width: float):
   command.send('ToolSetTextOutline', Width=width)
 

BIN
resources/vector/textalignbottom32.lzp


+ 27 - 0
resources/vector/textalignbottom32.svg

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="2 16 28 15">
+    <defs>
+      <linearGradient id="layer1-fillgrad1" x1="15" x2="15" y1="14.54167" y2="18.54167" spreadMethod="repeat" gradientUnits="userSpaceOnUse" color-interpolation="linearRGB">
+        <stop offset="0" stop-color="black" stop-opacity="0.4980392"/>
+        <stop offset="0.0625" stop-color="black" stop-opacity="0.3098039"/>
+        <stop offset="0.125" stop-color="black" stop-opacity="0.145098"/>
+        <stop offset="0.1875" stop-color="black" stop-opacity="0.03529412"/>
+        <stop offset="0.25" stop-color="black" stop-opacity="0"/>
+        <stop offset="0.3125" stop-color="black" stop-opacity="0.03529412"/>
+        <stop offset="0.375" stop-color="black" stop-opacity="0.145098"/>
+        <stop offset="0.4375" stop-color="black" stop-opacity="0.3098039"/>
+        <stop offset="0.5" stop-color="black" stop-opacity="0.4980392"/>
+        <stop offset="0.5625" stop-color="black" stop-opacity="0.6901961"/>
+        <stop offset="0.625" stop-color="black" stop-opacity="0.854902"/>
+        <stop offset="0.6875" stop-color="black" stop-opacity="0.9647059"/>
+        <stop offset="0.75" stop-color="black" stop-opacity="1"/>
+        <stop offset="0.8125" stop-color="black" stop-opacity="0.9647059"/>
+        <stop offset="0.875" stop-color="black" stop-opacity="0.854902"/>
+        <stop offset="0.9375" stop-color="black" stop-opacity="0.6901961"/>
+        <stop offset="1" stop-color="black" stop-opacity="0.4980392"/>
+      </linearGradient>
+    </defs>
+    <path d="M5.5 16.04166 5.5 18.04166 7 20.04166 7 22.04166 2 24.04166 2 30.04166 30 30.04166 30 24.04166 25 22.04166 25 20.04166 26.5 18.04166 26.5 16.04166 z" fill="url(#layer1-fillgrad1)" stroke="none"/>
+  </g>
+</svg>

BIN
resources/vector/textalignmiddle32.lzp


+ 27 - 0
resources/vector/textalignmiddle32.svg

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="2 9 28 14">
+    <defs>
+      <linearGradient id="layer1-fillgrad1" x1="15" x2="15" y1="7.5" y2="11.5" spreadMethod="repeat" gradientUnits="userSpaceOnUse" color-interpolation="linearRGB">
+        <stop offset="0" stop-color="black" stop-opacity="0.4980392"/>
+        <stop offset="0.0625" stop-color="black" stop-opacity="0.3098039"/>
+        <stop offset="0.125" stop-color="black" stop-opacity="0.145098"/>
+        <stop offset="0.1875" stop-color="black" stop-opacity="0.03529412"/>
+        <stop offset="0.25" stop-color="black" stop-opacity="0"/>
+        <stop offset="0.3125" stop-color="black" stop-opacity="0.03529412"/>
+        <stop offset="0.375" stop-color="black" stop-opacity="0.145098"/>
+        <stop offset="0.4375" stop-color="black" stop-opacity="0.3098039"/>
+        <stop offset="0.5" stop-color="black" stop-opacity="0.4980392"/>
+        <stop offset="0.5625" stop-color="black" stop-opacity="0.6901961"/>
+        <stop offset="0.625" stop-color="black" stop-opacity="0.854902"/>
+        <stop offset="0.6875" stop-color="black" stop-opacity="0.9647059"/>
+        <stop offset="0.75" stop-color="black" stop-opacity="1"/>
+        <stop offset="0.8125" stop-color="black" stop-opacity="0.9647059"/>
+        <stop offset="0.875" stop-color="black" stop-opacity="0.854902"/>
+        <stop offset="0.9375" stop-color="black" stop-opacity="0.6901961"/>
+        <stop offset="1" stop-color="black" stop-opacity="0.4980392"/>
+      </linearGradient>
+    </defs>
+    <path d="M5.5 9 5.5 11 7 13 7 15 2 17 2 23 30 23 30 17 25 15 25 13 26.5 11 26.5 9 z" fill="url(#layer1-fillgrad1)" stroke="none"/>
+  </g>
+</svg>

BIN
resources/vector/textaligntop32.lzp


+ 27 - 0
resources/vector/textaligntop32.svg

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="2 4 28 14">
+    <defs>
+      <linearGradient id="layer1-fillgrad1" x1="15" x2="15" y1="2.5" y2="6.5" spreadMethod="repeat" gradientUnits="userSpaceOnUse" color-interpolation="linearRGB">
+        <stop offset="0" stop-color="black" stop-opacity="0.4980392"/>
+        <stop offset="0.0625" stop-color="black" stop-opacity="0.3098039"/>
+        <stop offset="0.125" stop-color="black" stop-opacity="0.145098"/>
+        <stop offset="0.1875" stop-color="black" stop-opacity="0.03529412"/>
+        <stop offset="0.25" stop-color="black" stop-opacity="0"/>
+        <stop offset="0.3125" stop-color="black" stop-opacity="0.03529412"/>
+        <stop offset="0.375" stop-color="black" stop-opacity="0.145098"/>
+        <stop offset="0.4375" stop-color="black" stop-opacity="0.3098039"/>
+        <stop offset="0.5" stop-color="black" stop-opacity="0.4980392"/>
+        <stop offset="0.5625" stop-color="black" stop-opacity="0.6901961"/>
+        <stop offset="0.625" stop-color="black" stop-opacity="0.854902"/>
+        <stop offset="0.6875" stop-color="black" stop-opacity="0.9647059"/>
+        <stop offset="0.75" stop-color="black" stop-opacity="1"/>
+        <stop offset="0.8125" stop-color="black" stop-opacity="0.9647059"/>
+        <stop offset="0.875" stop-color="black" stop-opacity="0.854902"/>
+        <stop offset="0.9375" stop-color="black" stop-opacity="0.6901961"/>
+        <stop offset="1" stop-color="black" stop-opacity="0.4980392"/>
+      </linearGradient>
+    </defs>
+    <path d="M5.5 4 5.5 6 7 8 7 10 2 12 2 18 30 18 30 12 25 10 25 8 26.5 6 26.5 4 z" fill="url(#layer1-fillgrad1)" stroke="none"/>
+  </g>
+</svg>

+ 8 - 0
resources/vector/textbold32.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="0 0 29 28">
+    <path d="M28.84375 6.59375 0.09375 0.03125" fill="black" stroke="none" fill-opacity="1"/>
+    <path d="M9 28 9 3 15 3 15 28 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <path d="M15 28 18.88461 27.94471 Q22.76923 27.88942 24.86298 25.60817 26.95673 23.32692 26.97836 20.16346 27 17 25.75 15.25 24.5 13.5 22.25 12.75 20 12 17.5 12 L15 12 15 16 17 16 Q19 16 20.5 17 22 18 21.82211 20.03846 21.64423 22.07692 20.26923 22.98317 18.89423 23.88942 16.94711 23.94471 L15 24 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+  </g>
+</svg>

+ 9 - 0
resources/vector/textdirectionany32.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="-15 0 62 29">
+    <path d="M3.5 22 10 15.5 10 20 22 20 22 15.5 28.5 22 22 28.5 22 24 10 24 10 28.5 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <text x="0" y="0" fill="black" stroke="none" font-size="15" font-style="normal" font-family="FreeSans" font-weight="normal" fill-opacity="0.9686275" text-decoration="">
+      <tspan x="11.828" y="14" direction="ltr" textLength="8.344001">?</tspan>
+    </text>
+  </g>
+</svg>

+ 9 - 0
resources/vector/textdirectionltr32.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="-10 -1 56 30">
+    <path d="M4 20 22 20 22 15.5 28.5 22 22 28.5 22 24 4 24 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <text x="4" y="-1" fill="black" stroke="none" font-size="14" font-style="normal" font-family="FreeSans" font-weight="normal" fill-opacity="0.9686275" text-decoration="">
+      <tspan x="4" y="12" direction="ltr" textLength="23.15413">αβγ</tspan>
+    </text>
+  </g>
+</svg>

+ 9 - 0
resources/vector/textdirectionrtl32.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="-15 0 59 29">
+    <path d="M3.5 22 10 15.5 10 20 28 20 28 24 10 24 10 28.5 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <text x="0" y="0" fill="black" stroke="none" font-size="15" font-style="normal" font-family="FreeSans" font-weight="normal" fill-opacity="0.9686275" text-decoration="">
+      <tspan x="29" y="14" direction="rtl" textLength="22.568">אבג</tspan>
+    </text>
+  </g>
+</svg>

+ 9 - 0
resources/vector/textitalic32.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="0 0 29 28">
+    <path d="M28.84375 6.59375 0.09375 0.03125" fill="black" stroke="none" fill-opacity="1"/>
+    <path d="M11 28 16.5 13 20.5 13 15 28 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <path d="M18 10 19 6 23 6 21.71875 10.09375 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <path d="M24.40625 14.34375 1.09375 0.03125 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+  </g>
+</svg>

+ 7 - 0
resources/vector/textstrikeout32.svg

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="5 9 22 19">
+    <path d="M5.5 20 5.5 16 26.5 16 26.5 20 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+    <path d="M12.75251 22.04217 13.09534 23.19122 Q13.43817 24.34027 14.87291 24.68846 16.30765 25.03665 17.72187 25.00318 19.13608 24.96971 19.62222 24.21841 20.10835 23.46711 19.84319 22.09709 19.57802 20.72707 17.63348 20.15254 15.68893 19.57802 13.656 19.04769 11.62307 18.51736 10.6508 17.58928 9.678525 16.6612 9.715137 15.01844 9.751749 13.37567 10.37491 12.35699 10.99807 11.3383 12.40692 10.6495 13.81577 9.960694 16.07282 9.905777 18.32986 9.85086 19.50702 10.39635 20.68418 10.94185 21.48281 11.75473 22.28145 12.56761 22.42475 13.25641 L22.56806 13.94522 19.36463 14.05505 18.8343 13.45242 Q18.30397 12.84978 16.6969 12.91006 15.08982 12.97034 14.06355 13.59442 13.03728 14.2185 12.9489 14.86533 12.86051 15.51216 15.55635 16.39604 18.25219 17.27992 19.53383 17.72186 20.81546 18.16381 21.74354 18.91511 22.67161 19.66641 22.89258 21.12482 23.11356 22.58323 22.76 23.90905 22.40645 25.23488 20.58506 26.62634 18.76368 28.01781 16.35797 27.99636 13.95226 27.97491 12.90324 27.45439 11.85423 26.93386 10.85476 26.08437 9.855302 25.23488 9.720498 23.62022 L9.585694 22.00556 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+  </g>
+</svg>

+ 9 - 0
resources/vector/textunderline32.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="32" xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+  <g opacity="1" xmlns:bgra="https://wiki.freepascal.org/LazPaint_SVG_format" inkscape:label="Layer1" inkscape:groupmode="layer" bgra:originalViewBox="-31 -5 94 35">
+    <text x="0" y="-5" fill="black" stroke="none" font-size="31" font-style="normal" font-family="FreeSans" font-weight="normal" fill-opacity="0.7921569" text-decoration="">
+      <tspan x="7.377867" y="23" direction="ltr" textLength="17.24427">u</tspan>
+    </text>
+    <path d="M6.5 30 6.5 26 25.5 26 25.5 30 z" fill="black" stroke="none" fill-opacity="0.7921569"/>
+  </g>
+</svg>

+ 1 - 1
web/config.toml

@@ -5,7 +5,7 @@ disableKinds = ["taxonomyTerm"]
 
 [params]
   repo = "https://github.com/bgrabitmap/lazpaint/releases/download/"
-  version = "7.1.6"
+  version = "7.2"
 
 [languages]
   [languages.de]

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.