Explorar o código

Merge pull request #195 from bgrabitmap/dev-lazpaint

Dev lazpaint 7.1.4
circular17 %!s(int64=5) %!d(string=hai) anos
pai
achega
1769fb4e72
Modificáronse 100 ficheiros con 2939 adicións e 1590 borrados
  1. 4 0
      .gitignore
  2. 0 0
      COPYING.txt
  3. 101 0
      Makefile
  4. 2 5
      lazpaint.logic
  5. 2 1
      lazpaint/dialog/color/uadjustcurves.lfm
  6. 15 1
      lazpaint/dialog/color/uadjustcurves.pas
  7. 1 0
      lazpaint/dialog/color/ucolorintensity.pas
  8. 1 0
      lazpaint/dialog/color/ucolorize.pas
  9. 1 0
      lazpaint/dialog/color/ushiftcolors.pas
  10. 1 0
      lazpaint/dialog/filter/ucustomblur.pas
  11. 21 16
      lazpaint/dialog/filter/uemboss.pas
  12. 1 0
      lazpaint/dialog/filter/ufilterfunction.pas
  13. 2 1
      lazpaint/dialog/filter/uformrain.pas
  14. 30 24
      lazpaint/dialog/filter/umotionblur.pas
  15. 1 0
      lazpaint/dialog/filter/unoisefilter.pas
  16. 1 0
      lazpaint/dialog/filter/uphongfilter.pas
  17. 1 0
      lazpaint/dialog/filter/upixelate.pas
  18. 1 0
      lazpaint/dialog/filter/uposterize.pas
  19. 1 0
      lazpaint/dialog/filter/uradialblur.pas
  20. 1 0
      lazpaint/dialog/filter/usharpen.pas
  21. 1 0
      lazpaint/dialog/filter/utwirl.pas
  22. 1 0
      lazpaint/dialog/filter/uwavedisplacement.pas
  23. 3 2
      lazpaint/dialog/uabout.pas
  24. 18 9
      lazpaint/dialog/ublendop.pas
  25. 14 0
      lazpaint/dialog/ubrowseimages.pas
  26. 1 1
      lazpaint/dialog/ucanvassize.lfm
  27. 17 12
      lazpaint/dialog/ucanvassize.pas
  28. 304 203
      lazpaint/dialog/uchoosecolorinterface.pas
  29. 1 0
      lazpaint/dialog/ugeometricbrush.pas
  30. 29 14
      lazpaint/dialog/ulayerstackinterface.pas
  31. 1 0
      lazpaint/dialog/umultiimage.pas
  32. 1 1
      lazpaint/dialog/unewimage.lfm
  33. 16 6
      lazpaint/dialog/unewimage.pas
  34. 4 2
      lazpaint/dialog/uobject3d.pas
  35. 1 0
      lazpaint/dialog/upreviewdialog.pas
  36. 56 17
      lazpaint/dialog/uprint.pas
  37. 1 0
      lazpaint/dialog/uquestion.pas
  38. 1 1
      lazpaint/dialog/uresample.lfm
  39. 21 12
      lazpaint/dialog/uresample.pas
  40. 1 0
      lazpaint/dialog/usaveoption.pas
  41. BIN=BIN
      lazpaint/fpc-res.obj
  42. BIN=BIN
      lazpaint/fpc-res.res
  43. 30 0
      lazpaint/image/uimage.pas
  44. 1 0
      lazpaint/image/uimageaction.pas
  45. 4 1
      lazpaint/image/uimagediff.pas
  46. 1 0
      lazpaint/image/uimageobservation.pas
  47. 48 2
      lazpaint/image/uimagestate.pas
  48. 1 0
      lazpaint/image/uimagetype.pas
  49. 1 0
      lazpaint/image/ulayeraction.pas
  50. 1 0
      lazpaint/image/ustatetype.pas
  51. 6 6
      lazpaint/lazpaint.lpi
  52. 28 8
      lazpaint/lazpaint.lpr
  53. 1355 0
      lazpaint/lazpaint.prj
  54. 31 0
      lazpaint/lazpaintdialogs.inc
  55. 1 1
      lazpaint/lazpaintembeddedpack.lpk
  56. 59 8
      lazpaint/lazpaintinstance.pas
  57. 1 26
      lazpaint/lazpaintmainform.lfm
  58. 119 417
      lazpaint/lazpaintmainform.pas
  59. 10 2
      lazpaint/lazpainttype.pas
  60. 124 89
      lazpaint/maintoolbar.inc
  61. 1 0
      lazpaint/quote.inc
  62. 5 0
      lazpaint/release/bin/i18n/lazpaint.ar.po
  63. 5 0
      lazpaint/release/bin/i18n/lazpaint.bg.po
  64. 5 0
      lazpaint/release/bin/i18n/lazpaint.cs.po
  65. 5 0
      lazpaint/release/bin/i18n/lazpaint.de.po
  66. 5 0
      lazpaint/release/bin/i18n/lazpaint.es.po
  67. 5 0
      lazpaint/release/bin/i18n/lazpaint.fi.po
  68. 5 0
      lazpaint/release/bin/i18n/lazpaint.fr.po
  69. 6 1
      lazpaint/release/bin/i18n/lazpaint.ja.po
  70. 5 0
      lazpaint/release/bin/i18n/lazpaint.kab.po
  71. 5 0
      lazpaint/release/bin/i18n/lazpaint.lv.po
  72. 5 0
      lazpaint/release/bin/i18n/lazpaint.nl.po
  73. 5 0
      lazpaint/release/bin/i18n/lazpaint.po
  74. 5 0
      lazpaint/release/bin/i18n/lazpaint.pt_BR.po
  75. 5 0
      lazpaint/release/bin/i18n/lazpaint.ru.po
  76. 5 0
      lazpaint/release/bin/i18n/lazpaint.sv.po
  77. 5 0
      lazpaint/release/bin/i18n/lazpaint.zh_CN.po
  78. 0 213
      lazpaint/release/changelog
  79. 3 3
      lazpaint/release/debian/applications/lazpaint.desktop
  80. 184 152
      lazpaint/release/debian/debian/changelog
  81. 15 0
      lazpaint/release/debian/debian/control
  82. 0 0
      lazpaint/release/debian/debian/copyright
  83. 0 213
      lazpaint/release/debian/linux32/DEBIAN/changelog
  84. 0 12
      lazpaint/release/debian/linux32/DEBIAN/control
  85. 0 6
      lazpaint/release/debian/linux32/usr/bin/lazpaint
  86. 0 0
      lazpaint/release/debian/linux32/usr/share/lazpaint/delete.me
  87. BIN=BIN
      lazpaint/release/debian/linux32/usr/share/pixmaps/lazpaint.png
  88. 0 12
      lazpaint/release/debian/linux64/DEBIAN/control
  89. 0 28
      lazpaint/release/debian/linux64/DEBIAN/copyright
  90. 0 6
      lazpaint/release/debian/linux64/usr/bin/lazpaint
  91. 0 12
      lazpaint/release/debian/linux64/usr/share/applications/lazpaint.desktop
  92. 0 0
      lazpaint/release/debian/linux64/usr/share/lazpaint/delete.me
  93. 52 30
      lazpaint/release/debian/makedeb.sh
  94. 88 0
      lazpaint/release/debian/man/man1/lazpaint.1
  95. 0 0
      lazpaint/release/debian/pixmaps/lazpaint.png
  96. 2 2
      lazpaint/release/macOS/LazPaint.app/Contents/Info.plist
  97. 2 2
      lazpaint/release/macOS/makedmg.sh
  98. 1 1
      lazpaint/release/stable/latest.txt
  99. 7 7
      lazpaint/release/stable/pad_file.xml
  100. 2 2
      lazpaint/release/windows/lazpaint.iss

+ 4 - 0
.gitignore

@@ -39,3 +39,7 @@ lazpaint/release/windows/lazpaint64
 lazpaint/release/bin/i18n/lazpaint32.*
 lazpaint/release/bin/i18n/lazpaint_x64.*
 /lazpaint/dialog/color/backup
+
+resources/createresource/backup/
+
+lazpaint/units/

+ 0 - 0
lazpaint/COPYING.GPL.txt → COPYING.txt


+ 101 - 0
Makefile

@@ -0,0 +1,101 @@
+prefix = /usr/local
+USER_DIR = $(DESTDIR)$(prefix)
+BIN_DIR = $(USER_DIR)/bin
+SHARE_DIR=$(USER_DIR)/share
+RESOURCE_DIR=$(SHARE_DIR)/lazpaint
+DOC_DIR=$(SHARE_DIR)/doc/lazpaint
+SOURCE_BIN_DIR=lazpaint/release/bin
+SOURCE_SCRIPT_DIR=resources/scripts
+SOURCE_DEBIAN_DIR=lazpaint/release/debian
+PO_FILES:=$(shell find "$(SOURCE_BIN_DIR)/i18n" -maxdepth 1 -type f -name *.po -printf "\"%f\" ")
+MODEL_FILES:=$(shell find "$(SOURCE_BIN_DIR)/models" -maxdepth 1 -type f -printf "\"%f\" ")
+SCRIPT_FILES:=$(shell find "$(SOURCE_SCRIPT_DIR)" -maxdepth 1 -type f -name *.py -printf "\"%f\" ")
+SCRIPT_RUNTIME_FILES:=$(shell find "$(SOURCE_SCRIPT_DIR)/lazpaint" -maxdepth 1 -type f -name *.py -printf "\"%f\" ")
+
+ifeq ($(OS),Windows_NT)     # true for Windows_NT or later
+  COPY := winmake\copyfile
+  REMOVE := winmake\remove
+  REMOVEDIR := winmake\removedir
+  THEN := &
+  RUN :=
+else
+  COPY := cp
+  REMOVE := rm -f
+  REMOVEDIR := rm -rf
+  THEN := ;
+  RUN := ./
+endif
+
+all: compile
+
+install: 
+ifeq ($(OS),Windows_NT)     # true for Windows_NT or later
+	echo Under Windows, use installation generated by InnoSetup with lazpaint/release/windows/lazpaint.iss
+else ifeq ($(shell uname),Linux)
+	install -D "$(SOURCE_BIN_DIR)/lazpaint" "$(BIN_DIR)/lazpaint"
+	for f in $(PO_FILES); do install -D "$(SOURCE_BIN_DIR)/i18n/$$f" "${RESOURCE_DIR}/i18n/$$f"; done
+	for f in $(MODEL_FILES); do install -D "$(SOURCE_BIN_DIR)/models/$$f" "${RESOURCE_DIR}/models/$$f"; done
+	for f in $(SCRIPT_FILES); do install -D "$(SOURCE_SCRIPT_DIR)/$$f" "${RESOURCE_DIR}/scripts/$$f"; done
+	for f in $(SCRIPT_RUNTIME_FILES); do install -D "$(SOURCE_SCRIPT_DIR)/lazpaint/$$f" "${RESOURCE_DIR}/scripts/lazpaint/$$f"; done
+	install -D "$(SOURCE_DEBIAN_DIR)/applications/lazpaint.desktop" "$(SHARE_DIR)/applications/lazpaint.desktop"
+	install -D "$(SOURCE_DEBIAN_DIR)/pixmaps/lazpaint.png" "$(SHARE_DIR)/pixmaps/lazpaint.png"
+	install -d "$(SHARE_DIR)/man/man1"
+	gzip -9 -n -c "$(SOURCE_DEBIAN_DIR)/man/man1/lazpaint.1" >"$(SHARE_DIR)/man/man1/lazpaint.1.gz"
+	chmod 0644 "$(SHARE_DIR)/man/man1/lazpaint.1.gz"
+	install -d "$(DOC_DIR)"
+	gzip -9 -n -c "$(SOURCE_DEBIAN_DIR)/debian/changelog" >"$(DOC_DIR)/changelog.gz"
+	chmod 0644 "$(DOC_DIR)/changelog.gz"
+	install "$(SOURCE_DEBIAN_DIR)/debian/copyright" "$(DOC_DIR)/copyright"
+	install "$(SOURCE_BIN_DIR)/readme.txt" "$(DOC_DIR)/README"
+else
+	echo Unhandled OS
+endif
+
+uninstall: 
+ifeq ($(OS),Windows_NT)     # true for Windows_NT or later
+	echo Under Windows, go to Add/Remove programs
+else ifeq ($(shell uname),Linux)
+	$(REMOVE) $(BIN_DIR)/lazpaint
+	$(REMOVEDIR) $(RESOURCE_DIR)
+	$(REMOVEDIR) $(DOC_DIR)
+	$(REMOVE) "$(SHARE_DIR)/applications/lazpaint.desktop"
+	$(REMOVE) "$(SHARE_DIR)/pixmaps/lazpaint.png"
+	$(REMOVE) "$(SHARE_DIR)/man/man1/lazpaint.1.gz"
+else
+	echo Unhandled OS
+endif
+
+clean: clean_lazpaintcontrols clean_vectoredit clean_lazpaint
+
+clean_lazpaintcontrols:
+	$(REMOVEDIR) "lazpaintcontrols/lib"
+	$(REMOVEDIR) "lazpaintcontrols/backup"
+
+clean_vectoredit:
+	$(REMOVEDIR) "vectoredit/lib"
+	$(REMOVEDIR) "vectoredit/backup"
+
+clean_lazpaint:
+	$(REMOVEDIR) "lazpaint/debug"
+	$(REMOVEDIR) "lazpaint/release/lib"
+	$(REMOVE) "lazpaint/lazpaint.res"
+	$(REMOVE) "lazpaint/release/bin/lazpaint"
+	$(REMOVE) "lazpaint/release/bin/lazpaint32.exe"
+	$(REMOVE) "lazpaint/release/bin/lazpaint_x64.exe"
+	$(REMOVEDIR) "lazpaint/backup"
+	$(REMOVEDIR) "lazpaint/dialog/backup"
+	$(REMOVEDIR) "lazpaint/image/backup"
+	$(REMOVEDIR) "lazpaint/tablet/backup"
+	$(REMOVEDIR) "lazpaint/test_embedded/backup"
+	$(REMOVEDIR) "lazpaint/tools/backup"
+
+compile: lazpaintcontrols vectoredit lazpaint
+lazbuild:
+	#lazbuild will determine what to recompile
+lazpaintcontrols: lazbuild lazpaintcontrols/lazpaintcontrols.lpk
+	lazbuild lazpaintcontrols/lazpaintcontrols.lpk
+vectoredit: lazbuild vectoredit/vectoredit.lpi
+	lazbuild vectoredit/vectoredit.lpi
+lazpaint: lazbuild lazpaint/lazpaint.lpi
+	lazbuild lazpaint/lazpaint.lpi
+

+ 2 - 5
lazpaint.logic

@@ -3,11 +3,8 @@ project lazpaint.lpi
 package lazpaintembeddedpack.lpk
 const lazpainttype.pas LazPaintVersion
 text release/windows/lazpaint.iss "#define MyAppVersion ""$(Version)"""
-text release/debian/linux32/DEBIAN/control "Version: $(Version)"
-text release/debian/linux64/DEBIAN/control "Version: $(Version)"
-echo "Don't forget to UPDATE changelog file"
-copy release/changelog release/debian/linux32/DEBIAN/changelog
-copy release/changelog release/debian/linux64/DEBIAN/changelog
+text release/debian/debian/control "Version: $(Version)"
+echo "DON'T FORGET TO UPDATE release/debian/changelog"
 text release/macOS/makedmg.sh "appversion=$(Version)"
 bundle release/macOS/LazPaint.app
 copy ../resources/icon/lazpaint.icns release/macOS/LazPaint.app/Contents/Resources/lazpaint.icns

+ 2 - 1
lazpaint/dialog/color/uadjustcurves.lfm

@@ -33,6 +33,7 @@ object FAdjustCurves: TFAdjustCurves
       'Alpha'
     )
     Align = alClient
+    Anchors = [akLeft, akTop, akRight, akBottom]
     TabOrder = 0
     object vsChart: TBGRAVirtualScreen
       Left = 2
@@ -64,7 +65,7 @@ object FAdjustCurves: TFAdjustCurves
         Top = 0
         Width = 90
         Align = alNone
-        Anchors = [akTop, akRight]
+        Anchors = [akTop, akLeft]
         EdgeBorders = []
         Images = FMain.ImageList16
         ParentShowHint = False

+ 15 - 1
lazpaint/dialog/color/uadjustcurves.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit uadjustcurves;
 
 {$mode objfpc}{$H+}
@@ -67,6 +68,7 @@ type
     FGridColor: TBGRAPixel;
     FTickSize: integer;
     FPointSize, FCurvePenWidth: single;
+    FScaling: single;
     FHueTabPrecomputed: boolean;
     FSelectedPoint: integer;
     FMovingPoint: boolean;
@@ -126,6 +128,7 @@ var
   i: Integer;
 begin
   ScaleControl(Self, OriginalDPI);
+  vsChart.BitmapAutoScale:= false;
 
   CheckOKCancelBtns(Button_OK, Button_Cancel);
   FSelectedPoint:= -1;
@@ -379,6 +382,8 @@ end;
 procedure TFAdjustCurves.vsChartMouseDown(Sender: TObject;
   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if Button = mbLeft then
   begin
     FSelectedPoint:= NearestPoint(X,Y);
@@ -391,6 +396,8 @@ end;
 procedure TFAdjustCurves.vsChartMouseMove(Sender: TObject; Shift: TShiftState;
   X, Y: Integer);
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if FMovingPoint then
   begin
     SetPointCoord(FSelectedPoint, BitmapToCoord(X,Y));
@@ -538,8 +545,9 @@ begin
     if length(labels[i])>maxLabelLength then maxLabelLength := length(labels[i]);
   totalLabelLength:= maxLabelLength + length(labels[0]) + (1+maxLabelLength)*(length(labels)-1);
 
+  FScaling := GetCanvasScaleFactor;
   th := Min(AHeight div (length(labels)+2), round(AWidth*1.8/totalLabelLength));
-  th := Min(th, DoScaleY(20,96));
+  th := Min(th, DoScaleY(round(20*FScaling),96));
   FCurvePenWidth := th/10;
   FPointSize := th/4;
   FTickSize := th div 4;
@@ -621,6 +629,10 @@ begin
   result := -1;
   curve := SelectedCurve;
   if curve = nil then exit;
+  if xBmp < FPoint0.x then xBmp := FPoint0.x;
+  if xBmp > FPoint1.x then xBmp := FPoint1.x;
+  if yBmp > FPoint0.y then yBmp := FPoint0.y;
+  if yBmp < FPoint1.y then yBmp := FPoint1.y;
   pointList := curve.GetVariable('Points');
   pointCount := curve.GetListCount(pointList);
   minDist := sqr(ScaleX(20,96)+0.0);
@@ -656,6 +668,8 @@ begin
     if (pt1.x <= xBmp-1) and (pt2.x >= xBmp+1) then
     begin
       coord := BitmapToCoord(xBmp,yBmp);
+      if coord.y < 0 then coord.y := 0;
+      if coord.y > 1 then coord.y := 1;
       curve.AppendPoint(pointList, curve.GetPoint2DAt(pointList, pointCount-1));
       for j := pointCount-1 downto i do curve.AssignPointAt(pointList, j+1, curve.GetPoint2DAt(pointList, j));
       curve.AssignPointAt(pointList, i, coord);

+ 1 - 0
lazpaint/dialog/color/ucolorintensity.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UColorintensity;
 
 {$mode objfpc}{$H+}

+ 1 - 0
lazpaint/dialog/color/ucolorize.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UColorize;
 
 {$mode objfpc}{$H+}

+ 1 - 0
lazpaint/dialog/color/ushiftcolors.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UShiftColors;
 
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UCustomblur;
 
 {$mode objfpc}{$H+}

+ 21 - 16
lazpaint/dialog/filter/uemboss.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UEmboss;
 
 {$mode objfpc}{$H+}
@@ -145,23 +146,27 @@ var bmp: TBGRABitmap;
     x1,y1,x2,y2: single;
     dx,dy,t: single;
     c: TBGRAPixel;
+    scaling: Double;
 begin
-    bmp := TBGRABitmap.Create(PaintBox1.Width,PaintBox1.Height);
-    bmp.Fill(ColorToRGB(clBtnFace));
-    c := ColorToBGRA(ColorToRGB(clWindowText));
-    t := min(PaintBox1.Width/2,PaintBox1.Height/2);
-    dx := cos(angle*Pi/180);
-    dy := sin(angle*Pi/180);
-    x1 := PaintBox1.Width/2;
-    y1 := PaintBox1.Height/2;
-    x2 := x1+dx*(t-2);
-    y2 := y1+dy*(t-2);
-    bmp.FillEllipseAntialias(x1,y1,t-1,t-1,BGRA(c.red,c.green,c.blue,48));
-    bmp.DrawLineAntialias(x1,y1,x2,y2,c,2,true);
-    bmp.DrawLineAntialias(x2+dy*5-dx*5,y2-dx*5-dy*5,x2,y2,c,2,false);
-    bmp.DrawLineAntialias(x2-dy*5-dx*5,y2+dx*5-dy*5,x2,y2,c,2,false);
-    bmp.Draw(PaintBox1.Canvas,0,0,true);
-    bmp.Free;
+  scaling := GetCanvasScaleFactor;
+  bmp := TBGRABitmap.Create(round(PaintBox1.Width*scaling),round(PaintBox1.Height*scaling));
+  bmp.Fill(clForm);
+  c := ColorToBGRA(ColorToRGB(clWindowText));
+  t := min(bmp.Width/2,bmp.Height/2);
+  dx := cos(angle*Pi/180);
+  dy := sin(angle*Pi/180);
+  x1 := bmp.Width/2;
+  y1 := bmp.Height/2;
+  x2 := x1+dx*(t-2);
+  y2 := y1+dy*(t-2);
+  bmp.FillEllipseAntialias(x1,y1,t-1,t-1,BGRA(c.red,c.green,c.blue,48));
+  bmp.DrawLineAntialias(x1,y1,x2,y2,c,2*scaling,true);
+  bmp.DrawLineAntialias(x2+dy*5*scaling-dx*5*scaling,
+    y2-dx*5*scaling-dy*5*scaling,x2,y2,c,2*scaling,false);
+  bmp.DrawLineAntialias(x2-dy*5*scaling-dx*5*scaling,
+    y2+dx*5*scaling-dy*5*scaling,x2,y2,c,2*scaling,false);
+  bmp.Draw(PaintBox1.Canvas, rect(0,0,PaintBox1.Width,PaintBox1.Height), true);
+  bmp.Free;
 end;
 
 procedure TFEmboss.TrackBar_StrengthChange(Sender: TObject);

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UFilterFunction;
 
 {$mode objfpc}{$H+}

+ 2 - 1
lazpaint/dialog/filter/uformrain.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UFormRain;
 
 {$mode objfpc}{$H+}
@@ -161,7 +162,7 @@ var bmp: TBGRABitmap;
 begin
     if wind = 0 then exit;
     bmp := TBGRABitmap.Create(PaintBox_Wind.Width,PaintBox_Wind.Height);
-    bmp.Fill(ColorToRGB(clBtnFace));
+    bmp.Fill(clForm);
     c := ColorToBGRA(ColorToRGB(clWindowText));
     if wind < 0 then angle := 180 else angle := 0;
     t := PaintBox_Wind.Width/2*abs(wind);

+ 30 - 24
lazpaint/dialog/filter/umotionblur.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UMotionBlur;
 
 {$mode objfpc}{$H+}
@@ -101,31 +102,36 @@ var bmp: TBGRABitmap;
     x0,y0,x1,y1,x2,y2: single;
     dx,dy,t: single;
     c: TBGRAPixel;
+    scaling: Double;
 begin
-    bmp := TBGRABitmap.Create(PaintBox1.Width,PaintBox1.Height);
-    bmp.Fill(ColorToRGB(clBtnFace));
-    c := ColorToBGRA(ColorToRGB(clWindowText));
-    t := min(PaintBox1.Width/2,PaintBox1.Height/2);
-    dx := cos(angle*Pi/180);
-    dy := sin(angle*Pi/180);
-    x1 := PaintBox1.Width/2;
-    y1 := PaintBox1.Height/2;
-    x0 := x1-dx*(t-2);
-    y0 := y1-dy*(t-2);
-    x2 := x1+dx*(t-2);
-    y2 := y1+dy*(t-2);
-    bmp.FillEllipseAntialias(x1,y1,t-1,t-1,BGRA(c.red,c.green,c.blue,48));
-    if Checkbox_Oriented.Checked then
-    begin
-      bmp.DrawLineAntialias(x1,y1,x2,y2,c,2,true);
-      bmp.DrawLineAntialias(x2+dy*5-dx*5,y2-dx*5-dy*5,x2,y2,c,2,false);
-      bmp.DrawLineAntialias(x2-dy*5-dx*5,y2+dx*5-dy*5,x2,y2,c,2,false);
-    end else
-    begin
-      bmp.DrawLineAntialias(x0,y0,x2,y2,c,2,true);
-    end;
-    bmp.Draw(PaintBox1.Canvas,0,0,true);
-    bmp.Free;
+  scaling := GetCanvasScaleFactor;
+  bmp := TBGRABitmap.Create(round(PaintBox1.Width*scaling),
+    round(PaintBox1.Height*scaling));
+  bmp.Fill(clForm);
+  c := ColorToBGRA(ColorToRGB(clWindowText));
+  t := min(bmp.Width/2,bmp.Height/2);
+  dx := cos(angle*Pi/180);
+  dy := sin(angle*Pi/180);
+  x1 := bmp.Width/2;
+  y1 := bmp.Height/2;
+  x0 := x1-dx*(t-2);
+  y0 := y1-dy*(t-2);
+  x2 := x1+dx*(t-2);
+  y2 := y1+dy*(t-2);
+  bmp.FillEllipseAntialias(x1,y1,t-1,t-1,BGRA(c.red,c.green,c.blue,48));
+  if Checkbox_Oriented.Checked then
+  begin
+    bmp.DrawLineAntialias(x1,y1,x2,y2,c,2*scaling,true);
+    bmp.DrawLineAntialias(x2+dy*5*scaling-dx*5*scaling,
+      y2-dx*5*scaling-dy*5*scaling,x2,y2,c,2*scaling,false);
+    bmp.DrawLineAntialias(x2-dy*5*scaling-dx*5*scaling,
+      y2+dx*5*scaling-dy*5*scaling,x2,y2,c,2*scaling,false);
+  end else
+  begin
+    bmp.DrawLineAntialias(x0,y0,x2,y2,c,2*scaling,true);
+  end;
+  bmp.Draw(PaintBox1.Canvas, rect(0,0,PaintBox1.Width,PaintBox1.Height), true);
+  bmp.Free;
 end;
 
 procedure TFMotionBlur.SpinEdit_DistanceChange(Sender: TObject);

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit unoisefilter;
 
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UPhongFilter;
 
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UPixelate;
 
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit uposterize;
 
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit URadialBlur;
 
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit USharpen;
 
 {$mode objfpc}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UTwirl;
 
 {$mode objfpc}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UWaveDisplacement;
 
 {$mode objfpc}{$H+}

+ 3 - 2
lazpaint/dialog/uabout.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UAbout;
 
 {$mode objfpc}{$H+}
@@ -90,12 +91,12 @@ var bmp: TBGRABitmap;
 begin
   shader.LightPosition := Point(round((cos(angle)+1)/2*Image_Title.Width),round((sin(angle)+1)*Image_Title.height));
   inc(frameNumber);
-  bmp := TBGRABitmap.Create(Image_Title.Width,Image_Title.Height,ColorToRGB({$IFDEF DARWIN}clWindow{$ELSE}clBtnFace{$ENDIF}));
+  bmp := TBGRABitmap.Create(Image_Title.Width,Image_Title.Height,clForm);
 
   if xTxt = -1 then xTxt := bmp.Width;
   if xTxt > bmp.Width div 2 then dec(xTxt);
   fx.DrawShaded(bmp,xTxt,0, shader, 1,
-    MergeBGRA(ColorToBGRA(ColorToRGB(clBtnFace)),ColorToBGRA(ColorToRGB(clWindowText))),
+    MergeBGRA(ColorToBGRA(clForm),ColorToBGRA(clWindowText)),
     taCenter, false);
 
   bmp.Draw(Image_Title.Picture.Bitmap.Canvas,0,0,true);

+ 18 - 9
lazpaint/dialog/ublendop.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UBlendOp;
 
 {$mode objfpc}{$H+}
@@ -92,6 +93,7 @@ begin
       exit;
     end;
   end;
+  BGRAThumbnail.CheckersScale:= GetCanvasScaleFactor;
   if APattern = 'Under' then
   begin
     result := GetBitmapThumbnail(PatternUnder,AWidth,AHeight,BGRAPixelTransparent,ACheckers) as TBGRABitmap;
@@ -118,6 +120,7 @@ begin
       result.GradientFill(0,0,result.Width,result.Height,lColor,BGRABlack,gtRadial,PointF((result.Width-1)/2,(result.Height-1)/2),PointF(0,(result.Height-1)/2),dmSet,False);
     BGRAReplace(result,GetBitmapThumbnail(result,AWidth,AHeight,BGRAPixelTransparent,false));
   end;
+  BGRAThumbnail.CheckersScale:= 1;
   setlength(FPatterns,length(FPatterns)+1);
   FPatterns[high(FPatterns)].name := fullPatternName;
   FPatterns[high(FPatterns)].bmp := result;
@@ -148,12 +151,15 @@ end;
 
 procedure TFBlendOp.DrawPattern(ACanvas: TCanvas; ARect: TRect; APattern: string; State: TOwnerDrawState);
 var bmp: TBGRABitmap;
+  scaling: Double;
 begin
   if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
-  bmp := TBGRABitmap.Create(ARect.Right-ARect.Left,ARect.Bottom-ARect.Top,ColorToRGB(clBtnFace));
-  bmp.PutImage(0,0,GetPattern(bmp.width,bmp.height,APattern,True),dmDrawWithTransparency);
+  scaling := GetCanvasScaleFactor;
+  bmp := TBGRABitmap.Create(round(ARect.Width*scaling),
+    round(ARect.Height*scaling), ColorToRGB(clBtnFace));
+  bmp.PutImage(0,0, GetPattern(bmp.width,bmp.height,APattern,True), dmDrawWithTransparency);
   if odSelected in State then DrawPatternHighlight(bmp);
-  bmp.Draw(ACanvas,ARect.Left,ARect.Top,false);
+  bmp.Draw(ACanvas,ARect,false);
   bmp.Free;
 end;
 
@@ -355,9 +361,10 @@ procedure TFBlendOp.ListBox_DrawBlendItem(Control: TWinControl; Index: Integer;
   ARect: TRect; State: TOwnerDrawState);
 var
   background,preview,over: TBGRABitmap;
-  w,h: integer;
+  w,h, checkerSize: integer;
   BlendStr: string;
   fx: TBGRATextEffect;
+  scaling: Double;
 begin
   {$IFDEF LINUX}
   ARect.Right := ARect.Left+Control.Width-FListBoxInternalMargin;
@@ -368,22 +375,24 @@ begin
   begin
     if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
     BlendStr := (Control as TListBox).Items[Index];
-    w := ARect.Right-ARect.Left;
-    h := ARect.Bottom-ARect.Top;
+    scaling := GetCanvasScaleFactor;
+    checkerSize := DoScaleX(round(8*scaling), OriginalDPI);
+    w := round(ARect.Width*scaling);
+    h := round(ARect.Height*scaling);
     background := TBGRABitmap.Create(w,h,ColorToBGRA(ColorToRGB(clBtnFace)));
-    background.DrawCheckers(background.ClipRect, ImageCheckersColor1, ImageCheckersColor2);
+    background.DrawCheckers(background.ClipRect, ImageCheckersColor1, ImageCheckersColor2, checkerSize, checkerSize);
     preview := GetPattern(w,h,ListBox_PatternUnder.Items[ListBox_PatternUnder.ItemIndex],False).Duplicate as TBGRABitmap;
     over := GetPattern(w,h,ListBox_PatternOver.Items[ListBox_PatternOver.ItemIndex],False);
     preview.BlendImageOver(0,0,over,StrToBlendOperation(BlendStr));
     background.PutImage(0,0,preview,dmDrawWithTransparency);
     preview.Free;
     if odSelected in State then DrawPatternHighlight(background);
-    fx := TBGRATextEffect.Create(BlendStr,'Arial',Max(DoScaleY(12,OriginalDPI),h div 10),true);
+    fx := TBGRATextEffect.Create(BlendStr,'Arial',Max(DoScaleY(round(12*scaling),OriginalDPI),h div 10),true);
     fx.DrawOutline(background,1,1,BGRABlack);
     fx.Draw(background,1,1,BGRAWhite);
     fx.Free;
     background.FontName := 'Arial';
-    background.Draw((Control as TListBox).Canvas,ARect.Left,ARect.Top,True);
+    background.Draw((Control as TListBox).Canvas,ARect,True);
     background.Free;
   end;
 end;

+ 14 - 0
lazpaint/dialog/ubrowseimages.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit ubrowseimages;
 
 {$mode objfpc}{$H+}
@@ -268,6 +269,7 @@ begin
   FChosenImage := TImageEntry.Empty;
 
   DarkThemeInstance.Apply(ComboBox_FileExtension, False, 0.40);
+  vsList.BitmapAutoScale:= false;
 
   bmp := TBitmap.Create;
   ImageList128.GetBitmap(0,bmp);
@@ -338,6 +340,7 @@ procedure TFBrowseImages.FormHide(Sender: TObject);
 begin
   FCacheComputeIconIndexes := nil;
   StopCaching(true);
+  BGRAThumbnail.CheckersScale:= 1;
 
   FLastBigIcon := (ShellListView1.ViewStyle = vsIcon);
   if not IsSaveDialog then FFilename:= FPreviewFilename;
@@ -384,6 +387,17 @@ var r:TRect; i: integer;
 begin
   if FInFormShow then exit;
   FInFormShow:= true;
+
+  BGRAThumbnail.CheckersScale:= GetCanvasScaleFactor;
+  ShellListView1.FontHeight:= ScaleY(round(13*GetCanvasScaleFactor),OriginalDPI);
+  ShellListView1.SmallIconSize := round(ScaleX(round(64*GetCanvasScaleFactor),OriginalDPI)/16)*16;
+  if ShellListView1.SmallIconSize > 128 then
+    ShellListView1.SmallIconSize := 128;
+  ShellListView1.LargeIconSize:= ShellListView1.SmallIconSize*2;
+  if ShellListView1.LargeIconSize > 192 then
+    ShellListView1.LargeIconSize := 192;
+  ShellListView1.DetailIconSize:= ShellListView1.SmallIconSize;
+
   ListBox_RecentDirs.Clear;
   for i := 0 to LazPaintInstance.Config.RecentDirectoriesCount-1 do
     ListBox_RecentDirs.Items.Add(LazPaintInstance.Config.RecentDirectory[i]);

+ 1 - 1
lazpaint/dialog/ucanvassize.lfm

@@ -120,7 +120,7 @@ object FCanvasSize: TFCanvasSize
     Width = 144
     OnRedraw = vsPreviewRedraw
     Alignment = taLeftJustify
-    Color = clBtnFace
+    Color = clForm
     ParentColor = False
     TabOrder = 6
   end

+ 17 - 12
lazpaint/dialog/ucanvassize.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UCanvassize;
 
 {$mode objfpc}{$H+}
@@ -184,6 +185,7 @@ procedure TFCanvasSize.FormCreate(Sender: TObject);
 begin
   FIgnoreInput:= true;
   ScaleControl(Self,OriginalDPI);
+  vsPreview.BitmapAutoScale:= false;
 
   SpinEdit_Width.MaxValue := MaxImageWidth;
   SpinEdit_Height.MaxValue := MaxImageHeight;
@@ -306,7 +308,10 @@ var
   tx,ty,px,py,x,y,px2,py2,x2,y2: NativeInt;
   ratio,zoom: double;
   anchor: string;
+  scale: single;
 begin
+  scale := DoScaleX(60, OriginalDPI)/60 * GetCanvasScaleFactor;
+
   case FMUnit of
     0: begin //pixels
          tx:=SpinEdit_Width.Value;
@@ -330,21 +335,21 @@ begin
   if (tx > 0) and (ty > 0) then
   begin
     ratio := tx/ty;
-    if vsPreview.Width/ratio < vsPreview.Height then
-      zoom := vsPreview.Width/tx
+    if Bitmap.Width/ratio < Bitmap.Height then
+      zoom := Bitmap.Width/tx
     else
-      zoom := vsPreview.height/ty;
+      zoom := Bitmap.height/ty;
 
     px := round(px*zoom);
     py := round(py*zoom);
-    x := (vsPreview.Width-px) div 2;
-    y := (vsPreview.height-py) div 2;
+    x := (Bitmap.Width-px) div 2;
+    y := (Bitmap.height-py) div 2;
 
     px2 := round(LazPaintInstance.Image.Width*zoom);
     py2 := round(LazPaintInstance.Image.Height*zoom);
 
-    x2 := (vsPreview.Width-px2) div 2;
-    y2 := (vsPreview.height-py2) div 2;
+    x2 := (Bitmap.Width-px2) div 2;
+    y2 := (Bitmap.height-py2) div 2;
     anchor := LowerCase(SelectedAnchor);
     if (anchor='topleft') or (anchor='top') or (anchor='topright') then y2 := y;
     if (anchor='bottomleft') or (anchor='bottom') or (anchor='bottomright') then y2 := y+py-py2;
@@ -353,19 +358,19 @@ begin
 
     Bitmap.StretchPutImage(rect(x2,y2,x2+px2,y2+py2),LazPaintInstance.Image.RenderedImage,dmDrawWithTransparency,128);
     Bitmap.ClipRect := rect(x,y,x+px,y+py);
-    DrawCheckers(Bitmap,rect(x,y,x+px,y+py));
+    DrawCheckers(Bitmap,rect(x,y,x+px,y+py),scale);
     Bitmap.StretchPutImage(rect(x2,y2,x2+px2,y2+py2),LazPaintInstance.Image.RenderedImage,dmDrawWithTransparency);
     Bitmap.NoClip;
 
     if (px2 = 1) or (py2 = 1) then
-      Bitmap.DrawLineAntialias(x2,y2,x2+px2-1,y2+py2-1,BGRA(0,0,0,160),BGRA(255,255,255,160),1,True)
+      Bitmap.DrawLineAntialias(x2,y2,x2+px2-1,y2+py2-1,BGRA(0,0,0,160),BGRA(255,255,255,160),round(scale),True)
     else
-      Bitmap.DrawPolyLineAntialias([Point(x2,y2),Point(x2+px2-1,y2),Point(x2+px2-1,y2+py2-1),Point(x2,y2+py2-1),Point(x2,y2)],BGRA(0,0,0,160),BGRA(255,255,255,160),1,False);
+      Bitmap.DrawPolyLineAntialias([Point(x2,y2),Point(x2+px2-1,y2),Point(x2+px2-1,y2+py2-1),Point(x2,y2+py2-1),Point(x2,y2)],BGRA(0,0,0,160),BGRA(255,255,255,160),round(scale),False);
 
     if (px = 1) or (py = 1) then
-      Bitmap.DrawLineAntialias(x,y,x+px-1,y+py-1,BGRA(0,0,0,160),BGRA(255,255,255,160),1,True)
+      Bitmap.DrawLineAntialias(x,y,x+px-1,y+py-1,BGRA(0,0,0,160),BGRA(255,255,255,160),round(scale),True)
     else
-      Bitmap.DrawPolyLineAntialias([Point(x,y),Point(x+px-1,y),Point(x+px-1,y+py-1),Point(x,y+py-1),Point(x,y)],BGRA(0,0,0,160),BGRA(255,255,255,160),1,False);
+      Bitmap.DrawPolyLineAntialias([Point(x,y),Point(x+px-1,y),Point(x+px-1,y+py-1),Point(x,y+py-1),Point(x,y)],BGRA(0,0,0,160),BGRA(255,255,255,160),round(scale),False);
 
   end;
 end;

+ 304 - 203
lazpaint/dialog/uchoosecolorinterface.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UChooseColorInterface;
 
 {$mode objfpc}{$H+}
@@ -24,6 +25,7 @@ type
     EColor: TEdit;
     LColor: TLabel;
     procedure ContainerResize(Sender: TObject);
+    procedure SetColorTarget(AValue: TColorTarget);
     procedure vsColorViewMouseDown(Sender: TObject; Button: TMouseButton;
       {%H-}Shift: TShiftState; X, Y: Integer);
     procedure vsColorViewMouseMove(Sender: TObject; {%H-}Shift: TShiftState; X,
@@ -44,47 +46,54 @@ type
     FTextAreaHeightComputed: Boolean;
     FBarsAlign, FButtonsAlign: TAlign;
     FButtonsCenter: boolean;
-    FTitleFontHeight: integer;
+    FTitleFontHeight: single;
     FColorTitleVisible: boolean;
-    FWheelArea: TRect;
     FFormBackgroundColor, FFormTextColor: TBGRAPixel;
     FColorBeforeEColor: TBGRAPixel;
 
     FInFormMouseMove: Boolean;
-    FormMouseMovePos: TPoint;
+    FormMouseMovePos: TPointF;
 
+    FColorTarget: TColorTarget;
     FCurrentColor: TBGRAPixel;
     FColorLight: word;
-    ColorX,colorY: integer;
+    FColorX,FColorY: single;
     FSelectZone: (szNone, szColorCircle, szLightScale, szAlphascale);
+    FBitmapScale: single;
     FColorCircle: record center: TPointF;
-                         bounds: TRect;
+                         bounds: TRectF;
                          bmp,bmpMaxlight: TBGRABitmap; end;
-    FLightscale: record bounds: TRect;
+    FLightscale: record bounds: TRectF;
                         bmp: TBGRABitmap;
-                        cursorRect: TRect; end;
-    FAlphascale: record bounds: TRect;
+                        cursorRect: TRectF; end;
+    FAlphascale: record bounds: TRectF;
                        bmp: TBGRABitmap;
-                       cursorRect: TRect; end;
+                       cursorRect: TRectF; end;
 
-    FTopMargin, FBarWidth, FButtonSize, FCursorPlace, FMargin, FInternalMargin,
-    FCursorMargin, FCursorSize, FColorXYSize, FCursorXYOpacity: integer;
+    FTopMargin, FBarWidth, FCursorPlace, FMargin, FInternalMargin,
+    FCursorMargin, FCursorSize, FColorXYSize, FCursorXYWidth: single;
+    FButtonSize: integer;
 
     FInitialized: boolean;
     FLazPaintInstance: TLazPaintCustomInstance;
 
-    function GetAvailableBmpHeight: integer;
-    function GetAvailableBmpWidth: integer;
+    function GetAvailableVSHeight: integer;
+    function GetAvailableVSWidth: integer;
+    function InterfaceToPixel(APoint: TPointF): TPoint;
+    function InterfaceToPixel(ARect: TRectF): TRect;
+    function LCLPosToInterface(APoint: TPoint): TPointF;
+    function PixelToInterface(APoint: TPoint): TPointF;
     function GetEditorVisible: boolean;
     procedure SetDarkTheme(AValue: boolean);
     procedure SetLazPaintInstance(AValue: TLazPaintCustomInstance);
     procedure UpdateColorview(UpdateColorCircle, UpdateLightScale, Redraw: boolean);
     procedure SetColorLight(value: word);
     function ColorWithLight(c: TBGRAPixel; light: word): TBGRAPixel;
-    function BitmapWithLight(bmpsrc: TBGRABitmap; light: word; lookFor: TBGRAPixel; var pColorX,pColorY: integer): TBGRABitmap;
+    function BitmapWithLight(bmpsrc: TBGRABitmap; light: word; lookFor: TBGRAPixel; var pColorX,pColorY: single): TBGRABitmap;
     function ColorLightOf(c: TBGRAPixel): word;
-    function DrawTriangleCursor(dest: TBGRABitmap; bounds: TRect; value: byte): TRect;
-    procedure DoSelect(X,Y: integer);
+    function DrawTriangleCursor(dest: TBGRABitmap; bounds: TRectF; value, maxValue: integer): TRectF;
+    procedure DoClick(X,Y: single);
+    procedure DoSelect(X,Y: single);
     function MakeIconBase(size: integer): TBitmap;
     function MakeAddIcon(size: integer): TBitmap;
     function MakeRemoveIcon(size: integer): TBitmap;
@@ -92,17 +101,17 @@ type
 
     procedure ApplyTheme;
     procedure UpdateButtonLayout;
-    function SetRectBounds(var ABounds: TRect; ANewBounds: TRect): boolean;
+    function SetRectBounds(var ABounds: TRectF; ANewBounds: TRectF): boolean;
     function PreferredBarsAlignWithWidth: TAlign;
     procedure UpdateLayout;
     function GetAlphaScaleBmp: TBGRABitmap;
     function GetLightScaleBmp: TBGRABitmap;
     function GetColorCircleMaxLightBmp: TBGRABitmap;
     function GetColorCircleBmp: TBGRABitmap;
-    property AvailableBmpHeight: integer read GetAvailableBmpHeight;
-    property AvailableBmpWidth: integer read GetAvailableBmpWidth;
+    property AvailableVSHeight: integer read GetAvailableVSHeight;
+    property AvailableVSWidth: integer read GetAvailableVSWidth;
   public
-    ColorTarget: TColorTarget;
+
 
     constructor Create(AContainer: TWinControl; ADPI: integer);
     destructor Destroy; override;
@@ -116,11 +125,13 @@ type
     property DarkTheme: boolean read FDarkTheme write SetDarkTheme;
     property LazPaintInstance: TLazPaintCustomInstance read FLazPaintInstance write SetLazPaintInstance;
     property EditorVisible: boolean read GetEditorVisible;
+    property ColorTarget: TColorTarget read FColorTarget write SetColorTarget;
   end;
 
 implementation
 
-uses math, Forms, UResourceStrings, LCLType, UDarkTheme, LCScaleDPI, UGraph, BGRAText;
+uses math, Forms, UResourceStrings, LCLType, UDarkTheme, LCScaleDPI, UGraph, BGRAText,
+  BGRAClasses;
 
 { TChooseColorInterface }
 
@@ -134,29 +145,16 @@ begin
       EColor.Hide;
       LColor.Show;
     end;
-    if PtInRect(Point(X,Y), FColorCircle.Bounds) then
-    begin
-      FSelectZone := szColorCircle;
-      DoSelect(X,Y);
-    end else
-    if PtInRect(Point(X,Y), FAlphascale.Bounds) or PtInRect(Point(X,Y), FAlphascale.cursorRect) then
-    begin
-      FSelectZone := szAlphascale;
-      DoSelect(X,Y);
-    end else
-    if PtInRect(Point(X,Y), FLightscale.Bounds) or PtInRect(Point(X,Y), FLightscale.cursorRect) then
-    begin
-      FSelectZone := szLightscale;
-      DoSelect(X,Y);
-    end;
+    with LCLPosToInterface(Point(X, Y)) do
+      DoClick(X,Y);
   end;
 end;
 
 procedure TChooseColorInterface.ContainerResize(Sender: TObject);
 begin
   NeedTextAreaHeight;
-  vsColorView.Width := AvailableBmpWidth;
-  vsColorView.Height := AvailableBmpHeight;
+  vsColorView.Width := AvailableVSWidth;
+  vsColorView.Height := AvailableVSHeight;
   EColor.Left := ExternalMargin;
   EColor.Width := Container.ClientWidth - 2*ExternalMargin;
   LColor.Left := ExternalMargin;
@@ -166,14 +164,21 @@ begin
   UpdateLayout;
 end;
 
+procedure TChooseColorInterface.SetColorTarget(AValue: TColorTarget);
+begin
+  if FColorTarget=AValue then Exit;
+  FColorTarget:=AValue;
+  vsColorView.DiscardBitmap;
+end;
+
 procedure TChooseColorInterface.vsColorViewMouseMove(Sender: TObject;
   Shift: TShiftState; X, Y: Integer);
 begin
-  FormMouseMovePos := Point(X,Y);
+  FormMouseMovePos := LCLPosToInterface(Point(X,Y));
   if FInFormMouseMove then Exit;
   FInFormMouseMove := True;
   Application.ProcessMessages; //empty message stack
-  DoSelect(FormMouseMovePos.X,FormMouseMovePos.Y);
+  DoSelect(FormMouseMovePos.X, FormMouseMovePos.Y);
   FInFormMouseMove := False;
 end;
 
@@ -185,80 +190,115 @@ end;
 
 procedure TChooseColorInterface.vsColorViewRedraw(Sender: TObject;
   Bitmap: TBGRABitmap);
-var x,y: integer;
-  boundRight,w: integer;
-  size: single;
+var
+  textBoundRight: single;
+
+  procedure AddTitle(xRef: single; AText: string);
+  var x, w: single;
+  begin
+    w := Bitmap.TextSize(AText).cx / FBitmapScale;
+    x := xRef - w/2;
+    x := min(x, textBoundRight - w);
+    x := max(x, FButtonSize + FMargin + FMargin / 2);
+    if x > textBoundRight - w then exit;
+    with InterfaceToPixel(PointF(x, FMargin/2)) do
+      Bitmap.TextOut(x, y, AText, FFormTextColor, taLeftJustify);
+    textBoundRight := x - FMargin/2;
+  end;
+
+var
+  bmpRect: TRect;
+  previewSize: single;
+  previewRect: TRectF;
   c: TBGRAPixel;
+  bmpColorXYSize: integer;
+  bmpCursorWidth, i: integer;
+  bmpCursorOpacity: byte;
+  s: String;
 begin
-  Bitmap.FontHeight := FTitleFontHeight;
+  if vsColorView.Width <> 0 then
+    FBitmapScale := Bitmap.Width / vsColorView.Width
+    else FBitmapScale := 1;
+  Bitmap.FontHeight := round(FTitleFontHeight * FBitmapScale);
   Bitmap.FontAntialias := True;
-  boundRight := Bitmap.Width;
+  textBoundRight := Bitmap.Width / FBitmapScale;
   if Assigned(GetAlphaScaleBmp) then
   begin
-    w := Bitmap.TextSize(rsOpacity).cx;
     if FBarsAlign = alRight then
-    begin
-      x := (FAlphascale.bounds.Left+FAlphascale.bounds.Right-w) div 2;
-      if x + w > boundRight then
-        x := boundRight-w;
-      Bitmap.TextOut(x, FMargin div 2, rsOpacity, FFormTextColor, taLeftJustify);
-      boundRight := x - FMargin div 2;
-    end;
-    Bitmap.PutImage(FAlphascale.bounds.Left, FAlphascale.bounds.top,
-                    GetAlphaScaleBmp, dmDrawWithTransparency);
-    Bitmap.Rectangle(FAlphascale.bounds,
+      AddTitle((FAlphascale.bounds.Left + FAlphascale.bounds.Right) / 2, rsOpacity);
+    bmpRect := InterfaceToPixel(FAlphascale.bounds);
+    Bitmap.PutImage(bmpRect.Left, bmpRect.Top, GetAlphaScaleBmp, dmDrawWithTransparency);
+    Bitmap.Rectangle(bmpRect,
                      BGRA(FFormTextColor.red, FFormTextColor.green, FFormTextColor.Blue,128),
                      dmDrawWithTransparency);
-    FAlphascale.cursorRect := DrawTriangleCursor(Bitmap, FAlphascale.bounds, FCurrentColor.alpha);
-  end else FAlphascale.cursorRect := EmptyRect;
+    FAlphascale.cursorRect := DrawTriangleCursor(Bitmap, FAlphascale.bounds, FCurrentColor.alpha, 255);
+  end else FAlphascale.cursorRect := EmptyRectF;
 
   if Assigned(GetLightscaleBmp) then
   begin
-    w := Bitmap.TextSize(rsLight).cx;
     if FBarsAlign = alRight then
-    begin
-      x := (FLightscale.bounds.Left + FLightscale.bounds.Right-w) div 2;
-      if x+ w > boundRight then
-        x:= boundRight-w;
-      Bitmap.TextOut(x, FMargin div 2, rsLight, FFormTextColor, taLeftJustify);
-      boundRight := x - FMargin div 2;
-    end;
-    Bitmap.PutImage(FLightscale.bounds.Left, FLightscale.bounds.top, GetLightscaleBmp, dmFastBlend);
-    Bitmap.Rectangle(FLightscale.bounds,
+      AddTitle((FLightscale.bounds.Left + FLightscale.bounds.Right) / 2, rsLight);
+    bmpRect := InterfaceToPixel(FLightscale.bounds);
+    Bitmap.PutImage(bmpRect.Left, bmpRect.top, GetLightscaleBmp, dmFastBlend);
+    Bitmap.Rectangle(bmpRect,
                      BGRA(FFormTextColor.red, FFormTextColor.green, FFormTextColor.Blue, 128),
                      dmDrawWithTransparency);
-    FLightscale.cursorRect := DrawTriangleCursor(Bitmap, FLightscale.bounds, FColorLight div 256);
-  end else FLightscale.cursorRect := EmptyRect;
+    FLightscale.cursorRect := DrawTriangleCursor(Bitmap, FLightscale.bounds, FColorLight, 65535);
+  end else FLightscale.cursorRect := EmptyRectF;
 
   if Assigned(GetColorCircleBmp) and not FColorCircle.bounds.IsEmpty then
   begin
     if FColorTitleVisible then
     begin
-      w := Bitmap.TextSize(rsColors).cx;
-      x := round(FColorCircle.center.X - w/2);
-      x := min(x, boundRight-w);
-      x := max(x, FButtonSize + FMargin + FMargin div 2);
-      if x <= boundRight-w then
-        Bitmap.TextOut(x, FMargin div 2, rsColors, FFormTextColor, taLeftJustify);
+      case ColorTarget of
+        ctForeColorSolid..ctForeColorEndGrad: s := rsPen;
+        ctBackColorSolid..ctBackColorEndGrad: s := rsBack;
+        ctOutlineColorSolid..ctOutlineColorEndGrad: s := rsTextOutline;
+        else s := rsColors;
+      end;
+      case ColorTarget of
+        ctForeColorStartGrad,ctBackColorStartGrad,ctOutlineColorStartGrad: s += '[1]';
+        ctForeColorEndGrad,ctBackColorEndGrad,ctOutlineColorEndGrad: s += '[2]';
+      end;
+      AddTitle(FColorCircle.center.X, s);
+    end;
+    bmpRect := InterfaceToPixel(FColorCircle.bounds);
+    Bitmap.PutImage(bmpRect.Left, bmpRect.top, GetColorCircleBmp, dmDrawWithTransparency);
+    bmpCursorWidth := round(FCursorXYWidth * FBitmapScale);
+    if FCursorXYWidth * FBitmapScale < 1 then
+      bmpCursorOpacity := round(FCursorXYWidth * FBitmapScale * 255)
+      else bmpCursorOpacity := 255;
+    with InterfaceToPixel(FColorCircle.bounds.TopLeft + PointF(FColorX, FColorY)) do
+    begin
+      bmpColorXYSize := round(FColorXYSize * FBitmapScale);
+      bmpRect := rect(x-bmpColorXYSize, y-bmpColorXYSize, x+bmpColorXYSize+1, y+bmpColorXYSize+1);
+      bmpRect.Inflate(-1, -1);
+      Bitmap.Rectangle(bmpRect, BGRA(0,0,0,bmpCursorOpacity), dmDrawWithTransparency);
+      bmpRect.Inflate(1, 1);
+      for i := 1 to bmpCursorWidth do
+      begin
+        Bitmap.Rectangle(bmpRect, BGRA(255,255,255,bmpCursorOpacity), dmDrawWithTransparency);
+        bmpRect.Inflate(1, 1);
+      end;
+      Bitmap.Rectangle(bmpRect, BGRA(0,0,0,bmpCursorOpacity), dmDrawWithTransparency);
+    end;
+    previewSize := round(FBarWidth*0.9);
+    previewRect.Left := FMargin - ExternalMargin;
+    if FBarsAlign = alBottom then
+      previewRect.Top := FLightscale.bounds.Top - FMargin - previewSize
+      else previewRect.Top := Bitmap.Height/FBitmapScale - FMargin - previewSize;
+    previewRect.Right := previewRect.Left + previewSize;
+    previewRect.Bottom := previewRect.Top + previewSize;
+
+    if previewRect.Top >= BCButton_RemoveFromPalette.Top + BCButton_RemoveFromPalette.Height
+                          + FMargin / 2 then
+    begin
+      c := GetCurrentColor;
+      c.alpha := 255;
+      with InterfaceToPixel(previewRect) do
+        Bitmap.RoundRectAntialias(Left, Top, Right - 1, Bottom - 1,
+            previewSize/6, previewSize/6, BGRA(0,0,0,192), bmpCursorWidth, c, []);
     end;
-    Bitmap.PutImage(FColorCircle.bounds.Left, FColorCircle.bounds.top, GetColorCircleBmp, dmDrawWithTransparency);
-    x := FColorCircle.bounds.Left+ColorX;
-    y := FColorCircle.bounds.top+ColorY;
-    Bitmap.Rectangle(x-FColorXYSize-1, y-FColorXYSize-1, x+FColorXYSize+2, y+FColorXYSize+2,
-                     BGRA(0,0,0,FCursorXYOpacity), dmDrawWithTransparency);
-    Bitmap.Rectangle(x-FColorXYSize, y-FColorXYSize, x+FColorXYSize+1, y+FColorXYSize+1,
-                     BGRA(255,255,255,FCursorXYOpacity), dmDrawWithTransparency);
-    Bitmap.Rectangle(x-FColorXYSize+1, y-FColorXYSize+1, x+FColorXYSize, y+FColorXYSize,
-                     BGRA(0,0,0,FCursorXYOpacity), dmDrawWithTransparency);
-    size := round(FBarWidth*0.9);
-    c := GetCurrentColor;
-    c.alpha := 255;
-    x := FMargin - ExternalMargin;
-    if FBarsAlign = alBottom then y := round(FLightscale.bounds.Top-FMargin-1-size)
-    else y := round(Bitmap.Height - FMargin - size);
-    if y >= BCButton_RemoveFromPalette.Top + BCButton_RemoveFromPalette.Height + FMargin div 2 then
-      Bitmap.RoundRectAntialias(x, y, x + size, y + size,
-          size/6,size/6, BGRA(0,0,0,192), 1, c, []);
   end;
 end;
 
@@ -334,16 +374,39 @@ begin
   SafeSetFocus(EColor);
 end;
 
-function TChooseColorInterface.GetAvailableBmpHeight: integer;
+function TChooseColorInterface.GetAvailableVSHeight: integer;
 begin
   result := Container.ClientHeight - FTextAreaHeight - ExternalMargin;
 end;
 
-function TChooseColorInterface.GetAvailableBmpWidth: integer;
+function TChooseColorInterface.GetAvailableVSWidth: integer;
 begin
   result := Container.ClientWidth - ExternalMargin*2;
 end;
 
+function TChooseColorInterface.InterfaceToPixel(APoint: TPointF): TPoint;
+begin
+  result := (APoint * FBitmapScale).Truncate;
+end;
+
+function TChooseColorInterface.InterfaceToPixel(ARect: TRectF): TRect;
+begin
+  result.TopLeft := InterfaceToPixel(ARect.TopLeft);
+  result.BottomRight := InterfaceToPixel(ARect.BottomRight);
+end;
+
+function TChooseColorInterface.LCLPosToInterface(APoint: TPoint): TPointF;
+begin
+  result.x := APoint.x + 0.5 / FBitmapScale;
+  result.y := APoint.y + 0.5 / FBitmapScale;
+end;
+
+function TChooseColorInterface.PixelToInterface(APoint: TPoint): TPointF;
+begin
+  result.x := (APoint.x + 0.5) / FBitmapScale;
+  result.y := (APoint.y + 0.5) / FBitmapScale;
+end;
+
 function TChooseColorInterface.GetEditorVisible: boolean;
 begin
   result := Assigned(EColor) and EColor.Visible;
@@ -420,7 +483,7 @@ begin
 end;
 
 function TChooseColorInterface.BitmapWithLight(bmpsrc: TBGRABitmap;
-  light: word; lookFor: TBGRAPixel; var pColorX, pColorY: integer): TBGRABitmap;
+  light: word; lookFor: TBGRAPixel; var pColorX, pColorY: single): TBGRABitmap;
 var xb,yb: integer;
     psrc,pdest: PBGRAPixel;
     dist,newDist: integer;
@@ -464,8 +527,12 @@ begin
   result.InvalidateBitmap;
   if colorXYnb <> 0 then
   begin
-    pColorX := (ColorXsum + colorXYnb shr 1) div colorXYnb;
-    pColorY := (ColorYsum + colorXYnb shr 1) div colorXYnb;
+    with PixelToInterface(Point((ColorXsum + colorXYnb shr 1) div colorXYnb,
+                                (ColorYsum + colorXYnb shr 1) div colorXYnb)) do
+    begin
+      pColorX := x;
+      pColorY := y;
+    end;
   end;
 end;
 
@@ -478,29 +545,52 @@ begin
 end;
 
 function TChooseColorInterface.DrawTriangleCursor(dest: TBGRABitmap;
-  bounds: TRect; value: byte): TRect;
-var x,y: integer;
+  bounds: TRectF; value, maxValue: integer): TRectF;
+var x,y: single;
+  bmpCursorSize: integer;
 begin
+  bmpCursorSize := round(FCursorSize * FBitmapScale);
   if FBarsAlign = alRight then
   begin
     x := bounds.right + FCursorMargin;
-    y := bounds.bottom-1 - round(value/255*(bounds.height-1));
-    dest.FillPolyAntialias([pointF(x, y), pointF(x+FCursorSize, y-FCursorSize),
-                            pointF(x+FCursorSize, y+FCursorSize)], FFormTextColor);
-    result := rect(floor(x-FCursorSize/2), floor(y-FCursorSize*1.5),
-                   ceil(x+FCursorSize*1.5), ceil(y+FCursorSize*1.5));
+    y := bounds.top + (maxValue - value) / (maxValue + 1) * bounds.height;
+    with InterfaceToPixel(PointF(x, y)) do
+      dest.FillPolyAntialias([pointF(x, y), pointF(x+bmpCursorSize, y-bmpCursorSize),
+                              pointF(x+bmpCursorSize, y+bmpCursorSize)], FFormTextColor);
+    result := rectF(x - FCursorSize/2, y - FCursorSize*1.5,
+                    x + FCursorSize*1.5, y + FCursorSize*1.5);
   end else
   begin
-    x := bounds.left + round(value/255*(bounds.Width-1));
+    x := bounds.left + value / (maxValue + 1) * bounds.Width;
     y := bounds.bottom + FCursorMargin;
-    dest.FillPolyAntialias([pointF(x, y), pointF(x+FCursorSize,y+FCursorSize),
-                            pointF(x-FCursorSize, y+FCursorSize)], FFormTextColor);
-    result := rect(floor(x-FCursorSize*1.5), floor(y-FCursorSize/2),
-                   ceil(x+FCursorSize*1.5), ceil(y+FCursorSize*1.5));
+    with InterfaceToPixel(PointF(x, y)) do
+      dest.FillPolyAntialias([pointF(x, y), pointF(x+bmpCursorSize,y+bmpCursorSize),
+                              pointF(x-bmpCursorSize, y+bmpCursorSize)], FFormTextColor);
+    result := rectF(x - FCursorSize*1.5, y - FCursorSize/2,
+                    x + FCursorSize*1.5, y + FCursorSize*1.5);
   end;
 end;
 
-procedure TChooseColorInterface.DoSelect(X, Y: integer);
+procedure TChooseColorInterface.DoClick(X, Y: single);
+begin
+  if FColorCircle.Bounds.Contains(PointF(X,Y)) then
+  begin
+    FSelectZone := szColorCircle;
+    DoSelect(X,Y);
+  end else
+  if FAlphascale.Bounds.Contains(PointF(X,Y)) or FAlphascale.cursorRect.Contains(PointF(X,Y)) then
+  begin
+    FSelectZone := szAlphascale;
+    DoSelect(X,Y);
+  end else
+  if FLightscale.Bounds.Contains(PointF(X,Y)) or FLightscale.cursorRect.Contains(PointF(X,Y)) then
+  begin
+    FSelectZone := szLightscale;
+    DoSelect(X,Y);
+  end;
+end;
+
+procedure TChooseColorInterface.DoSelect(X, Y: single);
 var pix, newColor: TBGRAPixel;
   newLight: Word;
   dist: single;
@@ -509,8 +599,10 @@ begin
   szAlphascale:
     begin
       if FBarsAlign = alRight then
-        FCurrentColor.alpha := max(0, min(255, 255-round((Y-FAlphascale.Bounds.Top)/(FAlphascale.Bounds.Height-1)*255)))
-        else FCurrentColor.alpha := max(0, min(255, round((X-FAlphascale.Bounds.Left)/(FAlphascale.Bounds.Width-1)*255)));
+        FCurrentColor.alpha := max(0, min(255, 255 -
+          trunc((Y-FAlphascale.Bounds.Top) / FAlphascale.Bounds.Height * 256) ))
+        else FCurrentColor.alpha := max(0, min(255,
+          trunc((X-FAlphascale.Bounds.Left) / FAlphascale.Bounds.Width * 256) ));
       UpdateColorview(False, False, True);
     end;
   szColorCircle:
@@ -520,18 +612,19 @@ begin
               sqr((y-FColorCircle.center.Y)/FColorCircle.bounds.Height*2));
       if dist > 1 then
       begin
-        x := round(FColorCircle.center.X + (x-FColorCircle.center.X)/dist);
-        y := round(FColorCircle.center.Y + (y-FColorCircle.center.Y)/dist);
+        x := FColorCircle.center.X + (x - FColorCircle.center.X)/dist;
+        y := FColorCircle.center.Y + (y - FColorCircle.center.Y)/dist;
       end;
-      pix := FColorCircle.bmpMaxlight.GetPixel(x-FColorCircle.Bounds.Left,y-FColorCircle.Bounds.top);
+      with InterfaceToPixel(PointF(x,y) - FColorCircle.bounds.TopLeft) do
+        pix := FColorCircle.bmpMaxlight.GetPixel(x,y);
       if pix.alpha <> 0 then
       begin
         newColor := BGRA(pix.Red,pix.Green,pix.Blue,FCurrentColor.Alpha);
         if not FCurrentColor.EqualsExactly(newColor) then
         begin
           FCurrentColor := newColor;
-          ColorX := x-FColorCircle.Bounds.Left;
-          ColorY := y-FColorCircle.Bounds.top;
+          FColorX := x-FColorCircle.Bounds.Left;
+          FColorY := y-FColorCircle.Bounds.top;
           UpdateColorview(False, True, True);
         end;
       end;
@@ -539,8 +632,10 @@ begin
   szLightScale:
     begin
       if FBarsAlign = alRight then
-        newLight := max(0, min(65535, 65535 - round((Y-FLightscale.Bounds.Top)/(FLightscale.Bounds.Height-1)*65535)))
-        else newLight := max(0, min(65535, round((X-FLightscale.Bounds.Left)/(FLightscale.Bounds.Width-1)*65535)));
+        newLight := max(0, min(65535, 65535 -
+          trunc((Y-FLightscale.Bounds.Top) / FLightscale.Bounds.Height * 65536) ))
+        else newLight := max(0, min(65535,
+          trunc((X-FLightscale.Bounds.Left) / FLightscale.Bounds.Width * 65536)));
       SetColorLight(newLight);
     end;
   else exit;
@@ -640,8 +735,8 @@ begin
     FFormTextColor := clLightText;
   end else
   begin
-    FFormBackgroundColor := ColorToBGRA(ColorToRGB({$IFDEF DARWIN}clWindow{$ELSE}clBtnFace{$ENDIF}));
-    FFormTextColor := ColorToBGRA(ColorToRGB(clWindowText));
+    FFormBackgroundColor := clForm;
+    FFormTextColor := clWindowText;
   end;
   Container.Color := FFormBackgroundColor;
   vsColorView.Color := FFormBackgroundColor;
@@ -653,27 +748,27 @@ var
   iconSize: Integer;
   tmpIcon: TBitmap;
 begin
-  FButtonSize := FBarWidth;
+  FButtonSize := round(FBarWidth);
   BCButton_AddToPalette.Width := FButtonSize;
   BCButton_AddToPalette.Height := FButtonSize;
   BCButton_RemoveFromPalette.Width := FButtonSize;
   BCButton_RemoveFromPalette.Height := FButtonSize;
-  BCButton_AddToPalette.Left := FMargin - ExternalMargin;
-  BCButton_AddToPalette.Top := FMargin div 2;
+  BCButton_AddToPalette.Left := round(FMargin - ExternalMargin);
+  BCButton_AddToPalette.Top := round(FMargin / 2);
   if FButtonsAlign = alLeft then
   begin
     if FButtonsCenter then
-      BCButton_AddToPalette.Top := (AvailableBmpHeight -
+      BCButton_AddToPalette.Top := (AvailableVSHeight -
         BCButton_AddToPalette.Height - BCButton_RemoveFromPalette.Height) div 2;
-    BCButton_RemoveFromPalette.Left := FMargin - ExternalMargin;
-    BCButton_RemoveFromPalette.Top := BCButton_AddToPalette.Top+BCButton_AddToPalette.Height;
+    BCButton_RemoveFromPalette.Left := round(FMargin - ExternalMargin);
+    BCButton_RemoveFromPalette.Top := BCButton_AddToPalette.Top + BCButton_AddToPalette.Height;
   end else
   begin
     if FButtonsCenter then
-      BCButton_AddToPalette.Left := (AvailableBmpWidth -
+      BCButton_AddToPalette.Left := (AvailableVSWidth -
         BCButton_AddToPalette.Width - BCButton_RemoveFromPalette.Width) div 2;
-    BCButton_RemoveFromPalette.Left := BCButton_AddToPalette.Left+BCButton_AddToPalette.Width;
-    BCButton_RemoveFromPalette.Top := FMargin div 2;
+    BCButton_RemoveFromPalette.Left := BCButton_AddToPalette.Left + BCButton_AddToPalette.Width;
+    BCButton_RemoveFromPalette.Top := round(FMargin / 2);
   end;
   iconSize := FButtonSize-4;
   if not Assigned(BCButton_AddToPalette.Glyph) or (BCButton_AddToPalette.Glyph.Width <> iconSize) then
@@ -690,8 +785,8 @@ begin
   end;
 end;
 
-function TChooseColorInterface.SetRectBounds(var ABounds: TRect;
-  ANewBounds: TRect): boolean;
+function TChooseColorInterface.SetRectBounds(var ABounds: TRectF;
+  ANewBounds: TRectF): boolean;
 begin
   result := (ABounds.Width <> ANewBounds.Width) or (ABounds.Height <> ANewBounds.Height);
   ABounds := ANewBounds;
@@ -699,23 +794,23 @@ end;
 
 function TChooseColorInterface.PreferredBarsAlignWithWidth: TAlign;
 var
-  oneBarWidth, tx,ty, internalMargin, margin: Integer;
+  oneBarWidth, internalMargin, margin, tx, ty: single;
 begin
-  margin := DoScaleY(8, OriginalDPI, FDPI);
-  oneBarWidth := DoScaleX(18, OriginalDPI, FDPI) + DoScaleX(10, OriginalDPI, FDPI) +
+  margin := DoScaleYF(8, OriginalDPI, FDPI);
+  oneBarWidth := DoScaleXF(18, OriginalDPI, FDPI) + DoScaleXF(10, OriginalDPI, FDPI) +
                  margin;
   internalMargin := max(0, margin - ExternalMargin);
   if (FLazPaintInstance = nil) or LazPaintInstance.BlackAndWhite then
   begin
-    tx := AvailableBmpWidth - 2*internalMargin;
+    tx := AvailableVSWidth - 2*internalMargin;
     if tx <= oneBarWidth*4 then
       result := alRight
     else
       result := alBottom;
   end else
   begin
-    tx := AvailableBmpWidth - 2*internalMargin;
-    ty := AvailableBmpHeight - 2*margin;
+    tx := AvailableVSWidth - 2*internalMargin;
+    ty := AvailableVSHeight - 2*margin;
     if tx >= ty then
       result := alRight
       else result := alBottom;
@@ -723,33 +818,34 @@ begin
 end;
 
 procedure TChooseColorInterface.UpdateLayout;
-var bmpWidth, bmpHeight: integer;
+var vsWidth, vsHeight: single;
     prevBarsAlign: TAlign;
-    newAlphaBounds, newLightscaleBounds: TRect;
+    newAlphaBounds, newLightscaleBounds: TRectF;
+    newColorCircleArea: TRectF;
     needUpdateLightscale, needUpdateColorCircle: Boolean;
-    diffXY, delta: integer;
+    diffXY, delta: single;
     reductionFactor: single;
 
-  function AdaptSizeX(ASize: integer): integer;
+  function AdaptSizeX(ASize: integer): single;
   begin
-    result := min(DoScaleX(ASize, OriginalDPI, FDPI), round(ASize*reductionFactor));
+    result := min(DoScaleXF(ASize, OriginalDPI, FDPI), ASize * reductionFactor);
   end;
-  function AdaptSizeY(ASize: integer): integer;
+  function AdaptSizeY(ASize: integer): single;
   begin
-    result := min(DoScaleY(ASize, OriginalDPI, FDPI), round(ASize*reductionFactor));
+    result := min(DoScaleYF(ASize, OriginalDPI, FDPI), ASize * reductionFactor);
   end;
 
 begin
   if FLazPaintInstance = nil then exit;
 
   prevBarsAlign := FBarsAlign;
-  bmpWidth := AvailableBmpWidth;
-  bmpHeight := AvailableBmpHeight;
+  vsWidth := AvailableVSWidth;
+  vsHeight := AvailableVSHeight;
 
   if LazPaintInstance.BlackAndWhite then
-    reductionFactor := min(bmpWidth, bmpHeight)/105
+    reductionFactor := min(vsWidth, vsHeight)/105
   else
-    reductionFactor := max(bmpWidth, bmpHeight)/200;
+    reductionFactor := max(vsWidth, vsHeight)/200;
   FBarWidth := AdaptSizeX(18);
   FCursorPlace := AdaptSizeX(10);
   FCursorMargin := AdaptSizeX(2);
@@ -759,16 +855,15 @@ begin
   FInternalMargin := FMargin-ExternalMargin;
   if FInternalMargin < 0 then FInternalMargin := 0;
   FTitleFontHeight := max(AdaptSizeY(12), 10);
-  FColorXYSize := DoScaleX(3, OriginalDPI, FDPI);
-  FCursorXYOpacity := DoScaleX(128, OriginalDPI, FDPI);
-  if FCursorXYOpacity > 255 then FCursorXYOpacity := 255;
+  FColorXYSize := DoScaleXF(3, OriginalDPI, FDPI);
+  FCursorXYWidth := DoScaleXF(0.5, OriginalDPI, FDPI);
 
-  FWheelArea := Rect(FInternalMargin, FMargin, bmpWidth - FInternalMargin, bmpHeight - FMargin);
+  newColorCircleArea := RectF(FInternalMargin, FMargin, vsWidth - FInternalMargin, vsHeight - FMargin);
 
   if FLazPaintInstance.BlackAndWhite then
   begin
     FButtonsCenter := true;
-    if FWheelArea.Width <= FWheelArea.Height then
+    if newColorCircleArea.Width <= newColorCircleArea.Height then
     begin
       FButtonsAlign := alLeft;
       FBarsAlign := alRight;
@@ -784,78 +879,78 @@ begin
   begin
     FButtonsAlign := alLeft;
     FButtonsCenter := false;
-    if FWheelArea.Width >= FWheelArea.Height then
+    if newColorCircleArea.Width >= newColorCircleArea.Height then
       FBarsAlign := alRight else FBarsAlign := alBottom;
     UpdateButtonLayout;
   end;
 
-  FWheelArea.Top := FTopMargin;
+  newColorCircleArea.Top := FTopMargin;
 
   if FBarsAlign = alRight then
   begin
-    newAlphaBounds := RectWithSize(FWheelArea.Right - FCursorPlace - FBarWidth, FWheelArea.Top,
-                                   FBarWidth, FWheelArea.Height);
-    FWheelArea.Right := newAlphaBounds.Left - FMargin;
+    newAlphaBounds := RectWithSizeF(newColorCircleArea.Right - FCursorPlace - FBarWidth, newColorCircleArea.Top,
+                                   FBarWidth, newColorCircleArea.Height);
+    newColorCircleArea.Right := newAlphaBounds.Left - FMargin;
   end
   else
   begin
-    newAlphaBounds := RectWithSize(FWheelArea.Left, FWheelArea.Bottom - FCursorPlace - FBarWidth,
-                                   FWheelArea.Width, FBarWidth);
-    FWheelArea.Bottom := newAlphaBounds.Top - FMargin;
+    newAlphaBounds := RectWithSizeF(newColorCircleArea.Left, newColorCircleArea.Bottom - FCursorPlace - FBarWidth,
+                                   newColorCircleArea.Width, FBarWidth);
+    newColorCircleArea.Bottom := newAlphaBounds.Top - FMargin;
   end;
   if SetRectBounds(FAlphascale.bounds, newAlphaBounds) or (FBarsAlign <> prevBarsAlign) then
     FreeAndNil(FAlphascale.bmp);
 
   if FBarsAlign = alRight then
   begin
-    newLightscaleBounds := RectWithSize(FWheelArea.Right - FCursorPlace - FBarWidth, FWheelArea.Top,
-                                   FBarWidth, FWheelArea.Height);
-    FWheelArea.Right := newLightscaleBounds.Left - FMargin;
+    newLightscaleBounds := RectWithSizeF(newColorCircleArea.Right - FCursorPlace - FBarWidth, newColorCircleArea.Top,
+                                   FBarWidth, newColorCircleArea.Height);
+    newColorCircleArea.Right := newLightscaleBounds.Left - FMargin;
   end
   else
   begin
-    newLightscaleBounds := RectWithSize(FWheelArea.Left, FWheelArea.Bottom - FCursorPlace - FBarWidth,
-                                    FWheelArea.Width, FBarWidth);
-    FWheelArea.Bottom := newLightscaleBounds.Top - FMargin;
+    newLightscaleBounds := RectWithSizeF(newColorCircleArea.Left, newColorCircleArea.Bottom - FCursorPlace - FBarWidth,
+                                    newColorCircleArea.Width, FBarWidth);
+    newColorCircleArea.Bottom := newLightscaleBounds.Top - FMargin;
   end;
   needUpdateLightscale := SetRectBounds(FLightscale.bounds, newLightscaleBounds)
                           or (FBarsAlign <> prevBarsAlign);
 
   if FButtonsAlign = alLeft then
   begin
-    delta := FMargin - (FWheelArea.Left + round(min(FWheelArea.Width, FWheelArea.Height)*(1-0.8)) - (FMargin - ExternalMargin + FButtonSize));
+    delta := FMargin - (newColorCircleArea.Left +
+                        min(newColorCircleArea.Width, newColorCircleArea.Height)*(1-0.8) -
+                        (FMargin - ExternalMargin + FButtonSize) );
     if delta >= 0 then
-    begin
-      inc(FWheelArea.Left, delta);
-    end;
+      incF(newColorCircleArea.Left, delta);
   end;
 
-  diffXY := FWheelArea.Width - FWheelArea.Height;
+  diffXY := newColorCircleArea.Width - newColorCircleArea.Height;
   if diffXY > 0 then
   begin
-    inc(FWheelArea.Left, diffXY div 2);
-    FWheelArea.Right := FWheelArea.Left + FWheelArea.Height;
+    incF(newColorCircleArea.Left, diffXY / 2);
+    newColorCircleArea.Right := newColorCircleArea.Left + newColorCircleArea.Height;
   end else
   begin
-    dec(FWheelArea.Top, diffXY div 2);
-    FWheelArea.Bottom := FWheelArea.Top + FWheelArea.Width;
+    decF(newColorCircleArea.Top, diffXY / 2);
+    newColorCircleArea.Bottom := newColorCircleArea.Top + newColorCircleArea.Width;
   end;
 
-  delta := min(FWheelArea.Left - (FButtonSize + FMargin) div 2, FWheelArea.Top - FMargin div 2);
-  delta := min(delta, DoScaleX(120, OriginalDPI, FDPI) - FWheelArea.Width);
+  delta := min(newColorCircleArea.Left - (FButtonSize + FMargin) / 2, newColorCircleArea.Top - FMargin / 2);
+  delta := min(delta, DoScaleXF(120, OriginalDPI, FDPI) - newColorCircleArea.Width);
   if delta > 0 then
   begin
-    dec(FWheelArea.Left, delta div 2);
-    inc(FWheelArea.Right, (delta+1) div 2);
-    dec(FWheelArea.Top, delta);
-    FColorTitleVisible := delta <= FMargin div 2;
+    decF(newColorCircleArea.Left, delta / 2);
+    incF(newColorCircleArea.Right, (delta+1) / 2);
+    decF(newColorCircleArea.Top, delta);
+    FColorTitleVisible := delta <= FMargin / 2;
   end else
     FColorTitleVisible := true;
 
-  FColorCircle.center := PointF((FWheelArea.Left + FWheelArea.Right)/2 - 0.5,
-                               (FWheelArea.Top + FWheelArea.Bottom)/2 - 0.5);
+  FColorCircle.center := PointF((newColorCircleArea.Left + newColorCircleArea.Right)/2 - 0.5,
+                               (newColorCircleArea.Top + newColorCircleArea.Bottom)/2 - 0.5);
 
-  needUpdateColorCircle := SetRectBounds(FColorCircle.bounds, FWheelArea);
+  needUpdateColorCircle := SetRectBounds(FColorCircle.bounds, newColorCircleArea);
   if needUpdateColorCircle then FreeAndNil(FColorCircle.bmpMaxlight);
 
   UpdateColorview(needUpdateColorCircle, needUpdateLightscale, False);
@@ -865,7 +960,8 @@ function TChooseColorInterface.GetAlphaScaleBmp: TBGRABitmap;
 begin
   if (FAlphascale.bmp = nil) and not FAlphascale.Bounds.IsEmpty then
   begin
-    FAlphascale.bmp := TBGRABitmap.Create(FAlphascale.Bounds.Width, FAlphascale.Bounds.Height);
+    FAlphascale.bmp := TBGRABitmap.Create( round(FAlphascale.Bounds.Width * FBitmapScale),
+                         round(FAlphascale.Bounds.Height * FBitmapScale) );
     if FBarsAlign = alRight then
       FAlphascale.bmp.GradientFill(0, 0, FAlphascale.bmp.width, FAlphascale.bmp.height,
         FFormTextColor, vsColorView.Color, gtLinear,
@@ -875,7 +971,7 @@ begin
       FAlphascale.bmp.GradientFill(0, 0, FAlphascale.bmp.width, FAlphascale.bmp.height,
         FFormTextColor, vsColorView.Color, gtLinear,
         PointF(FAlphascale.bmp.Width-0.5, 0), PointF(-0.5, 0), dmSet, True);
-      FAlphascale.bmp.FontHeight := FTitleFontHeight;
+      FAlphascale.bmp.FontHeight := round(FTitleFontHeight * FBitmapScale);
       FAlphascale.bmp.FontVerticalAnchor:= fvaCapCenter;
       FAlphascale.bmp.TextOut(FMargin/2, FAlphascale.bmp.Height/2, rsOpacity, FFormTextColor, taLeftJustify);
       FAlphascale.bmp.FontVerticalAnchor:= fvaTop;
@@ -890,7 +986,8 @@ var
 begin
   if (FLightscale.bmp = nil) and not FLightscale.Bounds.IsEmpty then
   begin
-    FLightscale.bmp := TBGRABitmap.Create(FLightscale.Bounds.Width, FLightscale.Bounds.Height);
+    FLightscale.bmp := TBGRABitmap.Create( round(FLightscale.Bounds.Width * FBitmapScale),
+                         round(FLightscale.Bounds.Height * FBitmapScale) );
     tempColor := ColorWithLight(FCurrentColor,$FFFF);
     tempColor.alpha := 255;
     if FBarsAlign = alRight then
@@ -902,7 +999,7 @@ begin
       FLightscale.bmp.GradientFill(0, 0, FLightscale.bmp.width, FLightscale.bmp.height,
         tempColor, BGRABlack, gtLinear,
         PointF(FLightscale.bmp.width-0.5, 0), PointF(-0.5, 0), dmSet, True);
-      FLightscale.bmp.FontHeight := FTitleFontHeight;
+      FLightscale.bmp.FontHeight := round(FTitleFontHeight * FBitmapScale);
       FLightscale.bmp.FontVerticalAnchor:= fvaCapCenter;
       FLightscale.bmp.TextOut(FMargin/2, FLightscale.bmp.Height/2, rsLight, BGRA(210,210,210), taLeftJustify);
       FLightscale.bmp.FontVerticalAnchor:= fvaTop;
@@ -915,7 +1012,8 @@ function TChooseColorInterface.GetColorCircleMaxLightBmp: TBGRABitmap;
 begin
   if (FColorCircle.bmpMaxlight = nil) and not LazPaintInstance.BlackAndWhite
      and not FColorCircle.bounds.IsEmpty then
-    FColorCircle.bmpMaxlight := ComputeColorCircle(FColorCircle.Bounds.Width, FColorCircle.Bounds.Height, $FFFF);
+    FColorCircle.bmpMaxlight := ComputeColorCircle(round(FColorCircle.Bounds.Width * FBitmapScale),
+      round(FColorCircle.Bounds.Height * FBitmapScale), $FFFF);
 
   result := FColorCircle.bmpMaxlight;
 end;
@@ -924,7 +1022,7 @@ function TChooseColorInterface.GetColorCircleBmp: TBGRABitmap;
 begin
   if (FColorCircle.bmp = nil) and Assigned(GetColorCircleMaxLightBmp) then
     FColorCircle.bmp := BitmapWithLight(GetColorCircleMaxLightBmp, max(10000, FColorLight),
-                                        FCurrentColor, ColorX, ColorY);
+                                        FCurrentColor, FColorX, FColorY);
   result := FColorCircle.bmp;
 end;
 
@@ -945,10 +1043,12 @@ begin
   vsColorView := TBGRAVirtualScreen.Create(Container);
   vsColorView.Caption := '';
   vsColorView.Parent := Container;
+  vsColorView.BitmapAutoScale:= false;
   vsColorView.OnMouseDown:= @vsColorViewMouseDown;
   vsColorView.OnMouseMove:= @vsColorViewMouseMove;
   vsColorView.OnMouseUp:= @vsColorViewMouseUp;
   vsColorView.OnRedraw:= @vsColorViewRedraw;
+  FBitmapScale := 1;
   BCButton_AddToPalette := TBCButton.Create(vsColorView);
   BCButton_AddToPalette.Parent := vsColorView;
   BCButton_AddToPalette.OnClick := @BCButton_AddToPaletteClick;
@@ -1030,31 +1130,32 @@ end;
 
 procedure TChooseColorInterface.AdjustControlHeight;
 var
-  oneBarWidth, h, margin, topMargin, barWidth, buttonSize: Integer;
+  oneBarWidth, h, margin, topMargin, barWidth: single;
+  buttonSize: Integer;
 begin
   if not ((FLazPaintInstance = nil) or FLazPaintInstance.BlackAndWhite) then exit;
 
-  margin := DoScaleY(8, OriginalDPI, FDPI);
-  topMargin := DoScaleY(27, OriginalDPI, FDPI);
-  barWidth := DoScaleX(18, OriginalDPI, FDPI);
-  buttonSize := barWidth;
-  oneBarWidth := barWidth + DoScaleX(10, OriginalDPI, FDPI) +
+  margin := DoScaleYF(8, OriginalDPI, FDPI);
+  topMargin := DoScaleYF(27, OriginalDPI, FDPI);
+  barWidth := DoScaleXF(18, OriginalDPI, FDPI);
+  buttonSize := round(barWidth);
+  oneBarWidth := barWidth + DoScaleXF(10, OriginalDPI, FDPI) +
                  margin;
   if PreferredBarsAlignWithWidth = alRight then
   begin
     if (FLazPaintInstance = nil) or FLazPaintInstance.BlackAndWhite then
       h := oneBarWidth*4 + margin
     else
-      h := AvailableBmpWidth - oneBarWidth*2 + topMargin;
+      h := AvailableVSWidth - oneBarWidth*2 + topMargin;
   end else
   begin
     if (FLazPaintInstance = nil) or FLazPaintInstance.BlackAndWhite then
       h := oneBarWidth*2 + buttonSize + margin
     else
-      h := AvailableBmpWidth + oneBarWidth*2 + topMargin;
+      h := AvailableVSWidth + oneBarWidth*2 + topMargin;
   end;
   NeedTextAreaHeight;
-  Container.Height := h + FTextAreaHeight + ExternalMargin;
+  Container.Height := round(h + FTextAreaHeight + ExternalMargin);
 end;
 
 end.

+ 1 - 0
lazpaint/dialog/ugeometricbrush.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit ugeometricbrush;
 
 {$mode objfpc}{$H+}

+ 29 - 14
lazpaint/dialog/ulayerstackinterface.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit ULayerStackInterface;
 
 {$mode objfpc}{$H+}
@@ -52,6 +53,7 @@ type
     procedure LazPaint_ImageChanged(AEvent: TLazPaintImageObservationEvent);
   protected
     FDPI: integer;
+    FScaling: Double;
     FSysColorSelection: Boolean;
     FDarkTheme: boolean;
     FScrollStackItemIntoView: Boolean;
@@ -172,6 +174,8 @@ procedure TLayerStackInterface.BGRALayerStack_MouseDown(Sender: TObject;
 var i: integer;
   str: string;
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if PtInRect(Point(X,Y),FScrollButtonRect) then exit;
   If (Button = mbLeft) then
   begin
@@ -241,6 +245,8 @@ procedure TLayerStackInterface.BGRALayerStack_MouseMove(Sender: TObject;
 var
   i: Integer;
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if FMovingItemBitmap <> nil then
   begin
     FMovingItemMousePos := point(X,Y);
@@ -277,6 +283,8 @@ var destinationIndex, prevIndex: integer;
   res: TModalResult;
   topmostInfo: TTopMostInfo;
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if Button = mbLeft then
   begin
     FMovingItemStart := false;
@@ -330,7 +338,7 @@ procedure TLayerStackInterface.BGRALayerStack_MouseWheel(Sender: TObject;
   Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
   var Handled: Boolean);
 begin
-  DoScrollVertically(round(-WheelDelta*ZoomFactor*50/120));
+  DoScrollVertically(round(-WheelDelta*ZoomFactor*50/120*FScaling));
   Handled := true;
 end;
 
@@ -444,6 +452,7 @@ var i: integer;
   y: integer;
   clipping, prevClip: TRect;
   lColor, lColorTrans: TBGRAPixel;
+  penWidth: single;
 
   procedure DrawKindUnknown(rKind: TRect; out HintText: string);
   var
@@ -511,10 +520,10 @@ var i: integer;
     end else
     begin
       ABitmap.EllipseAntialias(rKind.Left+rKind.Width / 3, rKind.Top+rKind.Height / 3,rKind.Width / 3,rKind.Height / 3,
-                              lColor, 1, lColorTrans);
+                              lColor, penWidth, lColorTrans);
       ABitmap.DrawPolygonAntialias([PointF(rKind.Left+rKind.Width/4,rKind.Bottom),
                                    PointF(rKind.Left+rKind.Width/2,rKind.Top+rKind.Height/4),
-                                   PointF(rKind.Right,rKind.Bottom)],lColor,1, lColorTrans);
+                                   PointF(rKind.Right,rKind.Bottom)],lColor,penWidth, lColorTrans);
       HintText := rsVectorialLayer;
     end;
   end;
@@ -525,6 +534,9 @@ begin
     ComputeLayout(ABitmap);
     AUpdateItem := -1;
   end;
+  penWidth := 1.25/50*FLayerRectHeight;
+  if penWidth < 1 then penWidth := 1;
+  if penWidth > 3 then penWidth := 3;
   layerPos.x := -FOffset.X;
   layerPos.y := -FOffset.Y;
   SetLength(FLayerInfo, LazPaintInstance.Image.NbLayers);
@@ -563,7 +575,8 @@ begin
           lColorTrans := lColor;
           lColorTrans.alpha := lColorTrans.alpha div 3;
 
-          ABitmap.Rectangle(FLayerInfo[i].VisibleCheckbox,lColor,dmDrawWithTransparency);
+          with FLayerInfo[i].VisibleCheckbox do
+            ABitmap.RectangleAntialias(left, top, right-1, bottom-1, lColor, penWidth);
           if LayerVisible[i] then
           with FLayerInfo[i].VisibleCheckbox do
           begin
@@ -573,7 +586,7 @@ begin
 
                BezierCurve(PointF((left+right-1)/2,bottom-3),
                   PointF((left+right-1)/2,(top*2+bottom-1)/3),
-                  PointF(right-2,top-2))]),lColor,1.5);
+                  PointF(right-2,top-2))]),lColor, penWidth);
           end;
 
           FLayerInfo[i].KindIcon := FLayerInfo[i].VisibleCheckbox;
@@ -644,25 +657,26 @@ end;
 procedure TLayerStackInterface.ComputeLayout(ABitmap: TBGRABitmap);
 var i,temp,h: integer;
 begin
+  FScaling := Container.GetCanvasScaleFactor;
   FLayerInfo := nil;
-  FLayerRectWidth := round(100*zoomFactor);
-  FLayerRectHeight := round(50*zoomFactor);
+  FLayerRectWidth := round(100*zoomFactor*FScaling);
+  FLayerRectHeight := round(50*zoomFactor*FScaling);
   ABitmap.FontName := 'Arial';
   ABitmap.FontQuality := fqSystemClearType;
 
-  temp := ScaleY(20,OriginalDPI);
+  temp := ScaleY(round(20*FScaling),OriginalDPI);
   h := FLayerRectHeight div 3;
   if h > temp then h := temp;
-  temp := ScaleY(12,OriginalDPI);
+  temp := ScaleY(round(12*FScaling),OriginalDPI);
   if h < temp then h := temp;
   ABitmap.FontFullHeight := h;
 
   FInterruptorWidth := FLayerRectHeight div 4;
   FInterruptorHeight := FLayerRectHeight div 4;
-  temp := ScaleY(28,OriginalDPI);
+  temp := ScaleY(round(28*FScaling),OriginalDPI);
   if FInterruptorWidth > temp then FInterruptorWidth := temp;
   if FInterruptorHeight > temp then FInterruptorHeight := temp;
-  temp := ScaleY(7,OriginalDPI);
+  temp := ScaleY(round(7*FScaling),OriginalDPI);
   if FInterruptorHeight < temp then FInterruptorHeight := temp;
   if FInterruptorWidth < temp then FInterruptorWidth := temp;
   FStackWidth := FInterruptorWidth + FLayerRectWidth + FInterruptorWidth*6;
@@ -694,8 +708,8 @@ begin
   FreeAndNil(VolatileVertScrollBar);
   WithHorzScrollBar:= AWithHorzScrollBar;
   WithVertScrollBar:= AWithVertScrollBar;
-  FAvailableWidth := BGRALayerStack.Width;
-  FAvailableHeight := BGRALayerStack.Height;
+  FAvailableWidth := round(BGRALayerStack.Width*FScaling);
+  FAvailableHeight := round(BGRALayerStack.Height*FScaling);
   if FAvailableWidth <= VolatileThumbSize then WithHorzScrollBar := false;
   if FAvailableHeight <= VolatileThumbSize then WithVertScrollBar := false;
   if FAvailableWidth <= VolatileScrollBarSize then WithVertScrollBar:= false;
@@ -817,7 +831,7 @@ procedure TLayerStackInterface.NeedCheckers;
 var
   checkerSize: Integer;
 begin
-  checkerSize := DoScaleX(2, OriginalDPI, DPI);
+  checkerSize := DoScaleX(round(2*FScaling), OriginalDPI, DPI);
   if Assigned(FRegularBackground) and (FRegularBackground.Width <> checkerSize*2) then
   begin
     FreeAndNil(FRegularBackground);
@@ -999,6 +1013,7 @@ begin
   BGRALayerStack.OnMouseMove:=@BGRALayerStack_MouseMove;
   BGRALayerStack.OnMouseUp:=@BGRALayerStack_MouseUp;
   BGRALayerStack.OnMouseWheel:=@BGRALayerStack_MouseWheel;
+  BGRALayerStack.BitmapAutoScale:= false;
 
   TimerScroll := TTimer.Create(Container);
   TimerScroll.Enabled := false;

+ 1 - 0
lazpaint/dialog/umultiimage.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UMultiImage;
 
 {$mode objfpc}{$H+}

+ 1 - 1
lazpaint/dialog/unewimage.lfm

@@ -80,7 +80,7 @@ object FNewImage: TFNewImage
     Width = 134
     OnRedraw = vsPreviewRedraw
     Alignment = taLeftJustify
-    Color = clBtnFace
+    Color = clForm
     ParentColor = False
     TabOrder = 4
   end

+ 16 - 6
lazpaint/dialog/unewimage.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UNewimage;
 
 {$mode objfpc}{$H+}
@@ -131,15 +132,21 @@ var
   ratio: double;
   sx,sy: NativeInt;
   blur: TBGRACustomBitmap;
+  scaling: single;
+  scaledShadowOfsX, scaledShadowOfsY, scaledShadowBlur: integer;
 begin
-  sx := vsPreview.Width- shadowOffsetX - shadowBlur;
-  sy := vsPreview.Height- shadowOffsetY - shadowBlur;
+  scaling := DoScaleX(60, OriginalDPI)/60 * GetCanvasScaleFactor;
+  scaledShadowOfsX := round(shadowOffsetX*scaling);
+  scaledShadowOfsY := round(shadowOffsetY*scaling);
+  scaledShadowBlur := round(shadowBlur*scaling);
+  sx := Bitmap.Width- scaledShadowOfsX - scaledShadowBlur;
+  sy := Bitmap.Height- scaledShadowOfsY - scaledShadowBlur;
   tx := SpinEdit_Width.Value;
   ty := SpinEdit_Height.Value;
   if (tx > 0) and (ty > 0) then
   begin
     ratio := tx/ty;
-    if sx/ratio < vsPreview.Height then
+    if sx/ratio < Bitmap.Height then
     begin
       px := sx;
       py := round(sx/ratio);
@@ -152,15 +159,17 @@ begin
     end;
     x := (sx-px) div 2;
     y := (sy-py) div 2;
-    Bitmap.FillRect(x+shadowOffsetX,y+shadowOffsetY,x+shadowOffsetX+px,y+shadowOffsetY+py,BGRA(0,0,0,192),dmDrawWithTransparency);
-    blur := bitmap.FilterBlurRadial(shadowBlur,rbFast);
+    Bitmap.FillRect(x+scaledShadowOfsX, y+scaledShadowOfsY,
+      x+scaledShadowOfsX+px, y+scaledShadowOfsY+py,
+      BGRA(0,0,0,192), dmDrawWithTransparency);
+    blur := bitmap.FilterBlurRadial(scaledShadowBlur,rbFast);
     Bitmap.PutImage(0,0, blur,dmSet);
     blur.free;
     if (px = 1) or (py = 1) then
       Bitmap.FillRect(x,y,x+px,y+py,BGRABlack,dmSet)
     else
     begin
-      ugraph.DrawCheckers(Bitmap,rect(x,y,x+px,y+py));
+      ugraph.DrawCheckers(Bitmap,rect(x,y,x+px,y+py),scaling);
       Bitmap.Rectangle(x,y,x+px,y+py,BGRABlack,FBackColor,dmDrawWithTransparency);
     end;
   end;
@@ -257,6 +266,7 @@ end;
 procedure TFNewImage.FormCreate(Sender: TObject);
 begin
   ScaleControl(Self,OriginalDPI);
+  vsPreview.BitmapAutoScale:= false;
 
   FRecomputing := true;
   SpinEdit_Width.MaxValue := MaxImageWidth;

+ 4 - 2
lazpaint/dialog/uobject3d.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UObject3D;
 
 {$mode objfpc}{$H+}
@@ -324,7 +325,7 @@ end;
 procedure TFObject3D.BGRAView3DRedraw(Sender: TObject;
   Bitmap: TBGRABitmap);
 begin
-  DrawCheckers(Bitmap,rect(0,0,Bitmap.Width,Bitmap.Height));
+  DrawCheckers(Bitmap,rect(0,0,Bitmap.Width,Bitmap.Height),CanvasScale);
   scene.Surface := Bitmap;
   scene.Render;
 end;
@@ -462,6 +463,7 @@ end;
 procedure TFObject3D.FormCreate(Sender: TObject);
 begin
   ScaleControl(Self,OriginalDPI);
+  BGRAView3D.BitmapAutoScale:= false;
 
   CheckOKCancelBtns(Button_OK,Button_Cancel);
   CheckSpinEdit(SpinEdit_ColorOpacity);
@@ -609,7 +611,7 @@ begin
       x := round(pt.X*Width);
       y := round(pt.Y*Height);
       Canvas.Brush.Style := bsSolid;
-      Canvas.Brush.Color:= clBtnFace;
+      Canvas.Brush.Color:= clForm;
       Canvas.Pen.Style := psSolid;
       Canvas.Pen.Color := clWindowText;
       Canvas.Rectangle(0,0,Width,Height);

+ 1 - 0
lazpaint/dialog/upreviewdialog.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UPreviewDialog;
 
 {$mode objfpc}{$H+}

+ 56 - 17
lazpaint/dialog/uprint.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit uprint;
 
 {$mode objfpc}{$H+}
@@ -78,6 +79,8 @@ type
     FPrevMousePos: TPoint;
     FDpiAspectRatio,FAspectRatio: single;
     invZoom: TPointF;
+    FLabelCount: TLabel;
+    FPrintCount: integer;
     property RotatedSpinTop: TSpinEdit read GetRotatedSpinTop;
     property RotatedSpinLeft: TSpinEdit read GetRotatedSpinLeft;
     property RotatedSpinRight: TSpinEdit read GetRotatedSpinRight;
@@ -95,7 +98,7 @@ type
 
 implementation
 
-uses printers, UResourceStrings, Types, LCScaleDPI, umac;
+uses printers, UResourceStrings, Types, LCScaleDPI, umac, ULoading;
 
 var
   marginLeft, marginRight, marginTop, marginBottom: integer;
@@ -392,19 +395,50 @@ begin
   if (unrotatedTotalMarginInPoints.x >= paperSizeInPoints.x) or
     (unrotatedTotalMarginInPoints.y >= paperSizeInPoints.y) then exit;
 
-  FPrintTransform := AffineMatrixScale(Printer.XDPI/72, Printer.YDPI/72);
-  Printer.BeginDoc;
-  marTopLeft := FPrintTransform*unrotatedMarginTopLeftInPoints;
-  marBottomRight := FPrintTransform*(paperSizeInPoints - unrotatedMarginBottomRightInPoints);
-  area := rect(round(marTopLeft.x),round(marTopLeft.y),round(marBottomRight.x),round(marBottomRight.y));
-  Printer.Canvas.ClipRect := area;
-  Printer.Canvas.Clipping := true;
-  imgTopLeft := FPrintTransform*FImagePos;
-  imgBottomRight := FPrintTransform*(FImagePos+FImageSize);
-  Printer.Canvas.StretchDraw(rect(round(imgTopLeft.x),round(imgTopLeft.y),
-    round(imgBottomRight.x),round(imgBottomRight.y)), Instance.Image.RenderedImage.Bitmap);
-  Printer.Canvas.Clipping := false;
-  Printer.EndDoc;
+  if FLabelCount = nil then
+  begin
+    FLabelCount := TLabel.Create(self);
+    FLabelCount.Left := Button_Print.Left + Button_Print.Width;
+    FLabelCount.Top := Button_Print.Top;
+    FLabelCount.AutoSize := false;
+    FLabelCount.Height := Button_Print.Height;
+    FLabelCount.Width := BGRAVirtualScreen1.Left - FLabelCount.Left;
+    FLabelCount.Layout := tlCenter;
+    FLabelCount.Alignment := taCenter;
+    InsertControl(FLabelCount);
+  end;
+
+  FLabelCount.Caption:= '...';
+  MessagePopupForever(rsActionInProgress);
+  Self.Enabled:= false;
+  Application.ProcessMessages;
+  try
+    FPrintTransform := AffineMatrixScale(Printer.XDPI/72, Printer.YDPI/72);
+    Printer.BeginDoc;
+    if not Instance.Image.RenderedImage.Empty then
+    begin
+      marTopLeft := FPrintTransform*unrotatedMarginTopLeftInPoints;
+      marBottomRight := FPrintTransform*(paperSizeInPoints - unrotatedMarginBottomRightInPoints);
+      area := rect(round(marTopLeft.x),round(marTopLeft.y),round(marBottomRight.x),round(marBottomRight.y));
+      Printer.Canvas.ClipRect := area;
+      Printer.Canvas.Clipping := true;
+      imgTopLeft := FPrintTransform*FImagePos;
+      imgBottomRight := FPrintTransform*(FImagePos+FImageSize);
+      Printer.Canvas.StretchDraw(rect(round(imgTopLeft.x),round(imgTopLeft.y),
+        round(imgBottomRight.x),round(imgBottomRight.y)), Instance.Image.RenderedImage.Bitmap);
+      Printer.Canvas.Clipping := false;
+    end;
+    Printer.EndDoc;
+    MessagePopup(rsOkay, 4000);
+    inc(FPrintCount);
+  except on ex:exception do
+    begin
+      Instance.ShowError(Caption, ex.Message);
+      if Printer.Printing then Printer.Abort;
+    end;
+  end;
+  Self.Enabled := true;
+  FLabelCount.Caption := IntToStr(FPrintCount);
 end;
 
 procedure TFPrint.Button_ZoomFitClick(Sender: TObject);
@@ -458,7 +492,7 @@ end;
 procedure TFPrint.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap
   );
 var
-  ratio: single;
+  ratio, scaling: single;
   x,y,w,h: integer;
   marTopLeft,marBottomRight,
   imgTopLeft,imgBottomRight: TPointF;
@@ -466,6 +500,7 @@ var
   zoom: TPointF;
 begin
   if (printer.PaperSize.Height = 0) or (printer.PaperSize.Width = 0) then exit;
+  scaling := DoScaleX(60, OriginalDPI)/60 * BGRAVirtualScreen1.GetCanvasScaleFactor;
   ratio := printer.PaperSize.Width/printer.PaperSize.Height;
   if Bitmap.Height * ratio > Bitmap.Width then
     begin
@@ -498,7 +533,8 @@ begin
   marTopLeft := FPreviewTransform*unrotatedMarginTopLeftInPoints;
   marBottomRight := FPreviewTransform*(paperSizeInPoints - unrotatedMarginBottomRightInPoints);
   area := rect(round(marTopLeft.x),round(marTopLeft.y),round(marBottomRight.x),round(marBottomRight.y));
-  Bitmap.Rectangle(area,BGRA(128,160,192,128),dmDrawWithTransparency);
+  Bitmap.RectangleAntialias(area.left, area.top, area.right, area.bottom, BGRA(128,160,192,128),
+    scaling);
   if IntersectRect(area,area,Bitmap.ClipRect) then
   begin
     Bitmap.ClipRect := area;
@@ -517,7 +553,8 @@ begin
     InflateRect(bounds,1,1);
     IntersectRect(imgRect, imgRect,bounds);
     Bitmap.DrawPolyLineAntialias([imgRect.TopLeft,Point(imgRect.Right-1,imgRect.Top),Point(imgRect.Right-1, imgRect.Bottom-1),
-                                  Point(imgRect.left, imgRect.Bottom-1),imgRect.TopLeft], BGRA(128,160,192,128), BGRAPixelTransparent, 2, False);
+                                  Point(imgRect.left, imgRect.Bottom-1),imgRect.TopLeft], BGRA(0,0,0,128),
+                                  BGRA(255,255,255,128), round(2*scaling), False);
   end;
   Bitmap.NoClip;
 end;
@@ -589,6 +626,8 @@ end;
 procedure TFPrint.FormCreate(Sender: TObject);
 begin
   ScaleControl(Self,OriginalDPI);
+  BGRAVirtualScreen1.BitmapAutoScale:= false;
+  BGRAVirtualScreen1.Color := clDkGray;
 
   CheckSpinEdit(SpinEdit_DpiY);
   CheckSpinEdit(SpinEdit_DpiX);

+ 1 - 0
lazpaint/dialog/uquestion.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UQuestion;
 
 {$mode objfpc}{$H+}

+ 1 - 1
lazpaint/dialog/uresample.lfm

@@ -124,7 +124,7 @@ object FResample: TFResample
     Width = 185
     OnRedraw = vsPreviewRedraw
     Alignment = taLeftJustify
-    Color = clBtnFace
+    Color = clForm
     ParentColor = False
     TabOrder = 7
   end

+ 21 - 12
lazpaint/dialog/uresample.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UResample;
 
 {$mode objfpc}{$H+}
@@ -53,7 +54,7 @@ function ShowResampleDialog(Instance: TLazPaintCustomInstance; AParameters: TVar
 
 implementation
 
-uses BGRABitmapTypes, umac, uimage;
+uses ugraph, BGRABitmapTypes, umac, uimage;
 
 { TFResample }
 
@@ -82,6 +83,7 @@ procedure TFResample.FormCreate(Sender: TObject);
 begin
   FIgnoreInput := true;
   ScaleControl(Self,OriginalDPI);
+  vsPreview.BitmapAutoScale:= false;
 
   SpinEdit_Width.MaxValue := MaxImageWidth;
   SpinEdit_Height.MaxValue := MaxImageHeight;
@@ -199,10 +201,12 @@ end;
 procedure TFResample.vsPreviewRedraw(Sender: TObject; Bitmap: TBGRABitmap);
 var
   tx,ty,px,py,x,y,px2,py2,x2,y2: NativeInt;
-  ratio,zoom: double;
+  ratio,zoom,scaling: double;
   deltaX: NativeInt;
 begin
-  deltaX := vsPreview.Width-vsPreview.Height;
+  scaling := DoScaleX(60, OriginalDPI)/60 * GetCanvasScaleFactor;
+
+  deltaX := Bitmap.Width-Bitmap.Height;
   if deltaX < 0 then deltaX := 0;
   tx := NewWidth;
   ty := NewHeight;
@@ -211,31 +215,36 @@ begin
   if (tx > 0) and (ty > 0) then
   begin
     ratio := tx/ty;
-    if (vsPreview.Width-deltaX)/ratio < vsPreview.Height then
-      zoom := (vsPreview.Width-deltaX)/tx
+    if (Bitmap.Width-deltaX)/ratio < Bitmap.Height then
+      zoom := (Bitmap.Width-deltaX)/tx
     else
-      zoom := vsPreview.height/ty;
+      zoom := Bitmap.height/ty;
 
     px := round(NewWidth*zoom);
     py := round(NewHeight*zoom);
-    x := vsPreview.Width-px;
-    y := (vsPreview.height-py) div 2;
+    if px < 1 then px := 1;
+    if py < 1 then py := 1;
+    x := Bitmap.Width-px;
+    y := (Bitmap.height-py) div 2;
 
     px2 := round(LazPaintInstance.Image.Width*zoom);
     py2 := round(LazPaintInstance.Image.Height*zoom);
     x2 := 0;
-    y2 := (vsPreview.height-py2) div 2;
+    y2 := (Bitmap.height-py2) div 2;
 
     if (px = 1) or (py = 1) then
       Bitmap.FillRect(x,y,x+px,y+py,BGRA(0,0,0,192),dmDrawWithTransparency)
     else
-      Bitmap.Rectangle(x,y,x+px,y+py,BGRA(0,0,0,192),BGRA(255,255,255,192),dmDrawWithTransparency);
+    begin
+      Bitmap.Rectangle(x,y,x+px,y+py,BGRA(0,0,0,192),dmDrawWithTransparency);
+      DrawCheckers(Bitmap, rect(x+1,y+1,x+px-1,y+py-1), scaling);
+    end;
     Bitmap.StretchPutImage(rect(x,y,x+px,y+py),LazPaintInstance.Image.RenderedImage,dmDrawWithTransparency);
 
     if (px2 = 1) or (py2 = 1) then
-      Bitmap.DrawLineAntialias(x2,y2,x2+px2-1,y2+py2-1,BGRA(0,0,0,160),BGRA(255,255,255,160),1,True)
+      Bitmap.DrawLineAntialias(x2,y2,x2+px2-1,y2+py2-1,BGRA(0,0,0,160),BGRA(255,255,255,160),round(scaling),True)
     else
-      Bitmap.DrawPolyLineAntialias([Point(x2,y2),Point(x2+px2-1,y2),Point(x2+px2-1,y2+py2-1),Point(x2,y2+py2-1),Point(x2,y2)],BGRA(0,0,0,160),BGRA(255,255,255,160),1,False);
+      Bitmap.DrawPolyLineAntialias([Point(x2,y2),Point(x2+px2-1,y2),Point(x2+px2-1,y2+py2-1),Point(x2,y2+py2-1),Point(x2,y2)],BGRA(0,0,0,160),BGRA(255,255,255,160),round(scaling),False);
     Bitmap.StretchPutImage(rect(x2,y2,x2+px2,y2+py2),LazPaintInstance.Image.RenderedImage,dmDrawWithTransparency,48);
   end;
 end;

+ 1 - 0
lazpaint/dialog/usaveoption.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit USaveOption;
 
 {$mode objfpc}{$H+}

BIN=BIN
lazpaint/fpc-res.obj


BIN=BIN
lazpaint/fpc-res.res


+ 30 - 0
lazpaint/image/uimage.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImage;
 
 {$mode objfpc}{$H+}
@@ -105,6 +106,8 @@ type
       AOriginal: TBGRALayerCustomOriginal; var ADiff: TBGRAOriginalDiff);
     procedure OriginalEditingChange({%H-}ASender: TObject;
       {%H-}AOriginal: TBGRALayerCustomOriginal);
+    procedure OriginalLoadError(ASender: TObject; AError: string;
+      var ARaise: boolean);
     procedure SetBlendOperation(AIndex: integer; AValue: TBlendOperation);
     procedure SetCurrentFilenameUTF8(AValue: string);
     procedure LayeredBitmapReplaced;
@@ -177,6 +180,7 @@ type
 
     // image layer
     function SetCurrentLayerByIndex(AValue: integer): boolean;
+    function SelectLayerContainingPixelAt(APicturePos: TPoint): boolean;
     function CurrentLayerEmpty: boolean;
     function CurrentLayerTransparent: boolean;
     function CurrentLayerEquals(AColor: TBGRAPixel): boolean;
@@ -1097,6 +1101,13 @@ begin
   OnImageChanged.NotifyObservers;
 end;
 
+procedure TLazPaintImage.OriginalLoadError(ASender: TObject; AError: string;
+  var ARaise: boolean);
+begin
+  MessagePopup(rsErrorLoadingOriginal, 4000);
+  ARaise := false;
+end;
+
 procedure TLazPaintImage.Redo;
 var diff: TCustomImageDifference;
 begin
@@ -1571,6 +1582,23 @@ begin
   result := true;
 end;
 
+function TLazPaintImage.SelectLayerContainingPixelAt(APicturePos: TPoint): boolean;
+var
+  i: Integer;
+  ofs: TPoint;
+begin
+  for i := NbLayers-1 downto 0 do
+  begin
+    ofs := LayerOffset[i];
+    if LayerBitmap[i].GetPixel(APicturePos.x - ofs.x, APicturePos.y - ofs.y).alpha > 0 then
+    begin
+      result := SetCurrentLayerByIndex(i);
+      exit;
+    end;
+  end;
+  result := false;
+end;
+
 procedure TLazPaintImage.SetLayerOffset(AIndex: integer; AValue: TPoint;
   APrecomputedLayerBounds: TRect);
 var
@@ -1847,6 +1875,7 @@ begin
       layeredBmp.LayerName[layeredBmp.AddOwnedLayer(mask,boXor)] := 'Xor';
     end;
   end;
+  if ACaption = '' then ACaption := rsLayer+'1';
   layeredBmp.LayerName[0] := ACaption;
   layeredBmp.LayerOpacity[0] := AOpacity;
   Assign(layeredBmp,True,AUndoable);
@@ -2336,6 +2365,7 @@ begin
   FCurrentState := TImageState.Create;
   FCurrentState.OnOriginalChange:= @OriginalChange;
   FCurrentState.OnOriginalEditingChange:= @OriginalEditingChange;
+  FCurrentState.OnOriginalLoadError:=@OriginalLoadError;
   FCurrentState.OnActionProgress:= @LayeredActionProgress;
   FCurrentState.OnActionDone:=@LayeredActionDone;
   FRenderUpdateRectInPicCoord := rect(0,0,0,0);

+ 1 - 0
lazpaint/image/uimageaction.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImageAction;
 
 {$mode objfpc}{$H+}

+ 4 - 1
lazpaint/image/uimagediff.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImageDiff;
 
 {$mode objfpc}
@@ -2663,7 +2664,9 @@ begin
   begin
     self.sourceLayerId := LayeredBitmap.LayerUniqueId[SelectedImageLayerIndex];
     self.duplicateId := LayeredBitmap.ProduceLayerUniqueId;
-    self.duplicateOriginal := useOriginal and (LayeredBitmap.LayerOriginalClass[SelectedImageLayerIndex]=TVectorOriginal);
+    self.duplicateOriginal := useOriginal and
+      ((LayeredBitmap.LayerOriginalClass[SelectedImageLayerIndex]=TVectorOriginal) or
+       (LayeredBitmap.LayerOriginalClass[SelectedImageLayerIndex]=TBGRALayerGradientOriginal));
     if self.duplicateOriginal then
       CreateGUID(duplicateGuid);
   end;

+ 1 - 0
lazpaint/image/uimageobservation.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImageObservation;
 
 {$mode objfpc}{$H+}

+ 48 - 2
lazpaint/image/uimagestate.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImageState;
 
 {$mode objfpc}{$H+}
@@ -20,6 +21,7 @@ type
     FOnActionProgress: TLayeredActionProgressEvent;
     FOnOriginalChange: TEmbeddedOriginalChangeEvent;
     FOnOriginalEditingChange: TEmbeddedOriginalEditingChangeEvent;
+    FOnOriginalLoadError: TEmbeddedOriginalLoadErrorEvent;
     FSelectionMask: TBGRABitmap;
     FLastSelectionMaskBoundsIsDefined,
     FLastSelectionLayerBoundsIsDefined: TBoundsState;
@@ -52,6 +54,8 @@ type
       AOriginal: TBGRALayerCustomOriginal; var ADiff: TBGRAOriginalDiff);
     procedure OriginalEditingChange({%H-}ASender: TObject;
       AOriginal: TBGRALayerCustomOriginal);
+    procedure OriginalLoadError(ASender: TObject; AError: string;
+      var ARaise: boolean);
     procedure SelectImageLayer(AValue: TBGRABitmap);
     procedure SelectImageLayerByIndex(AValue: integer);
     procedure SetLayeredBitmap(AValue: TBGRALayeredBitmap);
@@ -59,6 +63,7 @@ type
     procedure SetOnActionDone(AValue: TNotifyEvent);
     procedure SetOnActionProgress(AValue: TLayeredActionProgressEvent);
     procedure SetSelectionMask(AValue: TBGRABitmap);
+    function MakeLayerName: string;
   public
     SelectionLayer: TBGRABitmap;
     selectedLayerId: integer;
@@ -178,6 +183,7 @@ type
     property SelectionTransform: TAffineMatrix read FSelectionTransform write FSelectionTransform;
     property OnOriginalChange: TEmbeddedOriginalChangeEvent read FOnOriginalChange write FOnOriginalChange;
     property OnOriginalEditingChange: TEmbeddedOriginalEditingChangeEvent read FOnOriginalEditingChange write FOnOriginalEditingChange;
+    property OnOriginalLoadError: TEmbeddedOriginalLoadErrorEvent read FOnOriginalLoadError write FOnOriginalLoadError;
     property OnActionProgress: TLayeredActionProgressEvent read FOnActionProgress write SetOnActionProgress;
     property OnActionDone: TNotifyEvent read FOnActionDone write SetOnActionDone;
   end;
@@ -399,6 +405,13 @@ begin
     FOnOriginalEditingChange(self, AOriginal);
 end;
 
+procedure TImageState.OriginalLoadError(ASender: TObject; AError: string;
+  var ARaise: boolean);
+begin
+  If Assigned(FOnOriginalLoadError) then
+    FOnOriginalLoadError(self, AError, ARaise);
+end;
+
 procedure TImageState.SelectImageLayer(AValue: TBGRABitmap);
 var
   i: Integer;
@@ -436,6 +449,7 @@ begin
     FLayeredBitmap.OnOriginalEditingChange:= nil;
     FLayeredBitmap.OnActionProgress:= nil;
     FLayeredBitmap.OnActionDone:= nil;
+    FLayeredBitmap.OnOriginalLoadError:= nil;
   end;
   FLayeredBitmap:=AValue;
   if Assigned(FLayeredBitmap) then
@@ -444,6 +458,7 @@ begin
     FLayeredBitmap.OnOriginalEditingChange:= @OriginalEditingChange;
     FLayeredBitmap.OnActionProgress:= @LayeredActionProgress;
     FLayeredBitmap.OnActionDone:=@LayeredActionDone;
+    FLayeredBitmap.OnOriginalLoadError:=@OriginalLoadError;
   end;
 end;
 
@@ -541,6 +556,30 @@ begin
   DiscardSelectionMaskBoundsCompletely;
 end;
 
+function TImageState.MakeLayerName: string;
+
+  function LayerNameUsed(AName: string): Boolean;
+  var
+    j: Integer;
+  begin
+    if LayeredBitmap = nil then
+      result := false else
+    begin
+      for j := 0 to NbLayers-1 do
+        if trim(LayerName[j]) = trim(AName) then exit(true);
+      result := false;
+    end;
+  end;
+
+var i: integer;
+begin
+  for i := 1 to 1000 do
+  begin
+    result := rsLayer + inttostr(i);
+    if not LayerNameUsed(result) and not LayerNameUsed('Layer' + inttostr(i)) then exit;
+  end;
+end;
+
 procedure TImageState.SetLayerBitmap(layer: integer; ABitmap: TBGRABitmap;
   AOwned: boolean);
 begin
@@ -666,6 +705,7 @@ end;
 procedure TImageState.Assign(AValue: TBGRABitmap; AOwned: boolean);
 var
   xorMask: TBGRABitmap;
+  idx: Integer;
 begin
   if LayeredBitmap = nil then
     SetLayeredBitmap(TBGRALayeredBitmap.Create);
@@ -674,7 +714,8 @@ begin
   LayeredBitmap.SetSize(AValue.Width,AValue.Height);
   if AOwned then
   begin
-    LayeredBitmap.AddOwnedLayer(AValue);
+    idx := LayeredBitmap.AddOwnedLayer(AValue);
+    LayeredBitmap.LayerName[idx] := MakeLayerName;
     if Assigned(AValue.XorMask) then
     begin
       xorMask := TBGRABitmap.Create(AValue.XorMask);
@@ -686,7 +727,8 @@ begin
   end
   else
   begin
-    LayeredBitmap.AddLayer(AValue);
+    idx := LayeredBitmap.AddLayer(AValue);
+    LayeredBitmap.LayerName[idx] := MakeLayerName;
     if Assigned(AValue.XorMask) then
     begin
       xorMask := AValue.XorMask.Duplicate as TBGRABitmap;
@@ -844,12 +886,14 @@ function TImageState.AddNewLayer(ALayer: TBGRABitmap; AName: string; AOffset: TP
 var
   idxLayer: Integer;
 begin
+  if AName = '' then AName := MakeLayerName;
   //no undo if no previous image
   if LayeredBitmap = nil then
   begin
     SetLayeredBitmap(TBGRALayeredBitmap.Create);
     idxLayer := LayeredBitmap.AddOwnedLayer(ALayer, ABlendOp, AOpacity);
     LayeredBitmap.LayerOffset[idxLayer] := AOffset;
+    LayeredBitmap.LayerName[idxLayer] := AName;
     result := nil;
   end else
   begin
@@ -863,12 +907,14 @@ function TImageState.AddNewLayer(AOriginal: TBGRALayerCustomOriginal;
 var
   idx: Integer;
 begin
+  if AName = '' then AName := MakeLayerName;
   //no undo if no previous image
   if LayeredBitmap = nil then
   begin
     SetLayeredBitmap(TBGRALayeredBitmap.Create);
     idx := LayeredBitmap.AddLayerFromOwnedOriginal(AOriginal, ABlendOp, AOpacity);
     LayeredBitmap.LayerOriginalMatrix[idx] := AMatrix;
+    LayeredBitmap.LayerName[idx] := AName;
     LayeredBitmap.RenderLayerFromOriginal(idx);
     result := nil;
   end else

+ 1 - 0
lazpaint/image/uimagetype.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImageType;
 
 {$mode objfpc}{$H+}

+ 1 - 0
lazpaint/image/ulayeraction.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit ULayerAction;
 
 {$mode objfpc}{$H+}

+ 1 - 0
lazpaint/image/ustatetype.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UStateType;
 
 {$mode objfpc}

+ 6 - 6
lazpaint/lazpaint.lpi

@@ -24,9 +24,9 @@
       <UseVersionInfo Value="True"/>
       <MajorVersionNr Value="7"/>
       <MinorVersionNr Value="1"/>
-      <RevisionNr Value="3"/>
+      <RevisionNr Value="4"/>
       <CharSet Value="04B0"/>
-      <StringTable CompanyName="http://sourceforge.net/projects/lazpaint/" ProductName="LazPaint" InternalName="lazpaint" OriginalFilename="lazpaint.exe"/>
+      <StringTable CompanyName="http://sourceforge.net/projects/lazpaint/" FileDescription="LazPaint" InternalName="lazpaint" OriginalFilename="lazpaint.exe" ProductName="LazPaint"/>
     </VersionInfo>
     <BuildModes Count="8">
       <Item1 Name="Debug" Default="True"/>
@@ -320,13 +320,13 @@
     </PublishOptions>
     <RunParams>
       <local>
-        <CommandLineParams Value="-scriptbasedir ..\..\..\scripts"/>
+        <CommandLineParams Value="-scriptbasedir ..\..\..\resources\scripts"/>
       </local>
       <FormatVersion Value="2"/>
       <Modes Count="1">
         <Mode0 Name="default">
           <local>
-            <CommandLineParams Value="-scriptbasedir ..\..\..\scripts"/>
+            <CommandLineParams Value="-scriptbasedir ..\..\..\resources\scripts"/>
           </local>
         </Mode0>
       </Modes>
@@ -334,11 +334,11 @@
     <RequiredPackages Count="5">
       <Item1>
         <PackageName Value="BGRABitmapPack"/>
-        <MinVersion Major="10" Minor="8" Valid="True"/>
+        <MinVersion Major="11" Minor="2" Release="4" Valid="True"/>
       </Item1>
       <Item2>
         <PackageName Value="bgracontrols"/>
-        <MinVersion Major="6" Minor="5" Valid="True"/>
+        <MinVersion Major="6" Minor="9" Valid="True"/>
       </Item2>
       <Item3>
         <PackageName Value="lazpaintcontrols"/>

+ 28 - 8
lazpaint/lazpaint.lpr

@@ -133,14 +133,18 @@ begin
       Report += 'Exception class: ' + E.ClassName + LineEnding;
     Report += 'Message: ' + E.Message + LineEnding;
   end;
+  {$IFDEF DEBUG}
   Report += 'Stacktrace:' + LineEnding;
   Report := Report + '  ' + BackTraceStrFunc(ExceptAddr) + LineEnding;
   Frames := ExceptFrames;
   for I := 0 to ExceptFrameCount - 1 do
     Report := Report + '  ' + BackTraceStrFunc(Frames[I]) + LineEnding;
+  {$ELSE}
+  Report += 'To get more information, use the debug version.' + LineEnding;
+  {$ENDIF}
   Report += LineEnding;
   if Initialized then
-    Report += 'It is recommanded to save a backup and restart the application.'
+    Report += 'It is recommanded to save a backup of your image and restart the application.'
   else
     Report += 'Application will now close.';
   ShowError(rsLazPaint, Report);
@@ -151,23 +155,39 @@ end;
 {$R *.res}
 
 {$IFDEF DARWIN}{$IFDEF DEBUG}
+const
+  ConsoleOutputFile = '/dev/ttys000';
 var
   OldOutput: TextFile;
+  HasTerminalOutput: boolean;
 
   procedure InitOutput;
+  var TerminalOutput: TextFile;
   begin
+    //on MacOS, you need to open the terminal before running LazPaint to get debug information
     OldOutput := Output;
-    AssignFile(Output, '/dev/ttys000');
-    Append(Output);
-    Writeln;
-    Writeln('Debug started');
+    AssignFile(TerminalOutput, ConsoleOutputFile);
+    try
+      Append(TerminalOutput);
+      Output := TerminalOutput;
+      HasTerminalOutput := true;
+      Writeln;
+      Writeln('Debug started');
+    except
+      HasTerminalOutput := false;
+    end;
   end;
 
   procedure DoneOutput;
   begin
-    Writeln('Debug ended');
-    CloseFile(Output);
-    Output := OldOutput;
+    if HasTerminalOutput then
+    begin
+      Writeln('Debug ended');
+      CloseFile(Output);
+      Output := OldOutput;
+      HasTerminalOutput := false;
+      SetHeapTraceOutput(ConsoleOutputFile);
+    end;
   end;
 {$ENDIF}{$ENDIF}
 

+ 1355 - 0
lazpaint/lazpaint.prj

@@ -0,0 +1,1355 @@
+[componentpalette]
+order0=0
+order1=0
+order2=0
+order3=0
+order4=0
+order5=0
+order6=0
+order7=0
+order8=0
+order9=0
+order10=0
+order11=0
+order12=0
+order13=0
+order14=0
+order15=0
+order16=0
+order17=0
+[projectoptions]
+findinfiledialog=50
+ [findinfileadialogfo.subdirs]
+ value=1
+ [findinfileadialogfo.incurrentfile]
+ value=0
+ [findinfileadialogfo.inopenfiles]
+ value=0
+ [findinfileadialogfo.wholeword]
+ value=0
+ [findinfileadialogfo.indirectories]
+ value=1
+ [findinfileadialogfo.inprojectdir]
+ value=0
+ [findinfileadialogfo.casesensitive]
+ value=0
+ [findinfileadialogfo.mask]
+ value="*.pas" "*.pp" "*.inc"
+ history=1
+  "*.pas" "*.pp" "*.inc"
+ [findinfileadialogfo.dir]
+ filecolwidth=174
+ x=0
+ y=0
+ cx=0
+ cy=0
+ filefilterindex=0
+ filefilter="*.pas" "*.pp" "*.inc"
+ [findinfileadialogfo.findtext]
+ value=bcaggrega
+ history=8
+  bcaggrega
+  BCComboBox
+  unit LCVectorRectShapes
+  unit LazarusPackageInt
+  LazarusPackageInt
+  cupsprinters_h
+  lapAutoAdjustForDPI
+  
+ [findinfileadialogfo]
+ stackedunder=
+ x=477
+ y=238
+ cx=339
+ cy=308
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+finddialog=8
+ [finddialogfo.selectedonly]
+ value=0
+ [finddialogfo]
+ stackedunder=
+ x=944
+ y=114
+ cx=234
+ cy=269
+options=114
+ [projectoptionsfo.toolshortcuts]
+ dropdowncolwidths=3
+  70
+  70
+  70
+ [projectoptionsfo.twidgetgrid3]
+ propcolwidthref=673
+ sortdescend0=0
+ sortdescend1=0
+ sortdescend2=0
+ sortdescend3=0
+ width4=119
+ sortdescend4=0
+ width5=234
+ sortdescend5=0
+ width6=275
+ sortdescend6=0
+ width7=47
+ sortdescend7=0
+ width8=1
+ sortdescend8=0
+ width9=275
+ sortdescend9=0
+ [projectoptionsfo.twidgetgrid4]
+ propcolwidthref=508
+ width0=96
+ sortdescend0=0
+ sortdescend1=0
+ width2=73
+ sortdescend2=0
+ width3=244
+ sortdescend3=0
+ width4=254
+ sortdescend4=0
+ sorted=0
+ col=-1073741823
+ row=-1073741823
+ rowheight=17
+ [projectoptionsfo.newfile]
+ firsttab=0
+ index=0
+ [projectoptionsfo.fontaliasgrid]
+ propcolwidthref=354
+ width0=98
+ sortdescend0=0
+ width1=343
+ sortdescend1=0
+ width2=50
+ sortdescend2=0
+ width3=50
+ sortdescend3=0
+ width4=50
+ sortdescend4=0
+ width5=50
+ sortdescend5=0
+ width6=70
+ sortdescend6=0
+ [projectoptionsfo.macrosplitter]
+ x=0
+ y=141
+ xprop=1
+ yprop=0.23920265780731
+ [projectoptionsfo.macrogrid]
+ propcolwidthref=446
+ sortdescend0=0
+ sortdescend1=0
+ sortdescend2=0
+ sortdescend3=0
+ sortdescend4=0
+ sortdescend5=0
+ sortdescend6=0
+ sortdescend7=0
+ sortdescend8=0
+ sortdescend9=0
+ width10=146
+ sortdescend10=0
+ width11=430
+ sortdescend11=0
+ [projectoptionsfo.comment_1]
+ value=
+ [projectoptionsfo.comment_B]
+ value=
+ [projectoptionsfo.comment_M]
+ value=
+ [projectoptionsfo.makegroupbox]
+ firsttab=0
+ index=2
+ [projectoptionsfo.exceptionsgrid]
+ propcolwidthref=664
+ width0=47
+ sortdescend0=0
+ width1=658
+ sortdescend1=0
+ [projectoptionsfo.ttabwidget1]
+ firsttab=0
+ index=1
+ [projectoptionsfo.filefiltergrid]
+ propcolwidthref=734
+ width0=112
+ sortdescend0=0
+ width1=727
+ sortdescend1=0
+ [projectoptionsfo.ttabwidget2]
+ firsttab=0
+ index=1
+ [projectoptionsfo.setting_tab]
+ firsttab=0
+ index=2
+ [projectoptionsfo]
+ stackedunder=
+ x=196
+ y=73
+ cx=724
+ cy=661
+settings=8
+ [settings_form]
+ x=447
+ y=148
+ cx=446
+ cy=578
+ wsize=0
+ active=1
+ visible=1
+mainfile=${PROJECTNAME}.lpr
+targetfile=${PROJECTNAME}${EXEEXT}
+messageoutputfile=
+makecommand=${COMPILER}
+makedir=
+unitdirs=27
+ ./buttons
+ ./image
+ ./tools
+ ../resources
+ ./dialog
+ ./tablet
+ ./dialog/color
+ ./dialog/filter
+ ./*
+ ../lazpaintcontrols
+ ${BGRABITMAPDIR}
+ ${lcldir}*
+ ${lcldir}/components/printers/win32
+ ${lcldir}/components/printers/unix
+ ${lcldir}/packager/registration
+ ${lcldir}/components/*
+ ${bgracontrolsdir}
+ ${lcldir}/lcl/forms
+ ${lcldir}/lcl/widgetset
+ ${lcldir}/interfaces/*
+ ${lcldir}/lcl/nonwin32
+ ${lcldir}/lcl/interfaces/gtk2
+ ${lcldir}/lcl/interfaces/qt
+ ${lcldir}/lcl/interfaces/win32
+ ${lcldir}/lcl/components/*
+ ${lcldir}/lcl/include
+ ${lcldir}/lcl
+unitpref=-Fu
+incpref=-Fi
+libpref=-Fl
+objpref=-Fo
+targpref=-o
+befcommand=0
+aftcommand=0
+makeoptions=10
+  -MObjFPC -Scgi -Cg -OoREGVAR -Xs -XX -l -vewnhibq
+ -gl
+ -ghl
+ -B
+ -O-
+ -O3 -XX -CX -Xs
+ -vi
+ -FUunits/
+ -dLCL -dLCLgtk2
+ -dLCL -dLCLwin32
+makeoptpurpose=10
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+compilerused=29
+ ${COMPILER} (Default)
+ Pascal 1
+ Pascal 2
+ Pascal 3
+ Pascal 4
+ Pascal 5
+ Pascal 6
+ Pascal 7
+ Pascal 8
+ C 1
+ C 2
+ C 3
+ C 4
+ C 5
+ C 6
+ C 7
+ C 8
+ Java 1
+ Java 2
+ Java 3
+ Java 4
+ Python 1
+ Python 2
+ Python 3
+ Python 4
+ Other 1
+ Other 2
+ Other 3
+ Other 4
+debuggerused=6
+ ${DEBUGGER} (Default)
+ Debugger 1
+ Debugger 2
+ Debugger 3
+ Debugger 4
+ None
+exeused=14
+ ${EXEEXT} (Default)
+ No Extension
+ .exe
+ .com
+ .bin
+ .prog
+ .pyc
+ .class
+ .so
+ .dll
+ .lib
+ .o
+ .res
+ .inf
+codetemplatedirs=1
+ ${TEMPLATEDIR}
+toolmenus=0
+toolfiles=0
+toolparams=0
+fontnames=0
+scriptbeforecopy=
+scriptaftercopy=
+newprojectfiles=0
+newprojectfilesdest=0
+newfinames=3
+ Program
+ Unit
+ Textfile
+newfifilters=3
+ "*.pas" "*.pp"
+ "*.pas" "*.pp"
+ 
+newfiexts=3
+ pas
+ pas
+ 
+newfisources=3
+ ${TEMPLATEDIR}default/program.pas
+ ${TEMPLATEDIR}default/unit.pas
+ 
+newfonames=11
+ Mainform
+ Simple Form
+ Docking Form
+ Datamodule
+ Subform
+ Scrollboxform
+ Tabform
+ Dockpanel
+ Report
+ Scriptform
+ Inherited Form
+newfonamebases=11
+ form
+ form
+ form
+ module
+ form
+ form
+ form
+ form
+ report
+ script
+ form
+newfosources=11
+ ${TEMPLATEDIR}default/mainform.pas
+ ${TEMPLATEDIR}default/simpleform.pas
+ ${TEMPLATEDIR}default/dockingform.pas
+ ${TEMPLATEDIR}default/datamodule.pas
+ ${TEMPLATEDIR}default/subform.pas
+ ${TEMPLATEDIR}default/scrollboxform.pas
+ ${TEMPLATEDIR}default/tabform.pas
+ ${TEMPLATEDIR}default/dockpanelform.pas
+ ${TEMPLATEDIR}default/report.pas
+ ${TEMPLATEDIR}default/pascform.pas
+ ${TEMPLATEDIR}default/inheritedform.pas
+newfoforms=11
+ ${TEMPLATEDIR}default/mainform.mfm
+ ${TEMPLATEDIR}default/simpleform.mfm
+ ${TEMPLATEDIR}default/dockingform.mfm
+ ${TEMPLATEDIR}default/datamodule.mfm
+ ${TEMPLATEDIR}default/subform.mfm
+ ${TEMPLATEDIR}default/scrollboxform.mfm
+ ${TEMPLATEDIR}default/tabform.mfm
+ ${TEMPLATEDIR}default/dockpanelform.mfm
+ ${TEMPLATEDIR}default/report.mfm
+ ${TEMPLATEDIR}default/pascform.mfm
+ ${TEMPLATEDIR}default/inheritedform.mfm
+forcezorder=0
+stripmessageesc=0
+copymessages=0
+closemessages=0
+enablepurpose=0
+enablesource=1
+checkmethods=1
+colorerror=-1610612717
+colorwarning=-1610612712
+colornote=-1610612716
+usercolors=30
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+usercolorcomment=30
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+formatmacronames=0
+formatmacrovalues=0
+settingsfile=
+settingseditor=1
+settingsdebugger=1
+settingsstorage=1
+settingsprojecttree=0
+settingsautoload=0
+settingsautosave=0
+modulenames=0
+moduletypes=0
+modulefiles=0
+befcommandon=0
+makeoptionson=10
+ 63
+ 2
+ 0
+ 6
+ 2
+ 61
+ 4095
+ 63
+ 4047
+ 48
+compilerusedon=29
+ 4039
+ 8
+ 0
+ 0
+ 0
+ 16
+ 32
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+debuggerusedon=6
+ 4095
+ 0
+ 0
+ 0
+ 0
+ 0
+exeusedon=14
+ 4047
+ 0
+ 48
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+comment_M=
+comment_B=
+comment_1=
+comment_2=
+comment_3=
+comment_4=
+comment_5=
+comment_6=
+comment_7=
+comment_8=
+comment_9=
+comment_0=
+project_name=
+project_creator=
+project_copyright=
+project_license=
+project_time=
+project_date=
+project_comment=
+aftcommandon=0
+unitdirson=27
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 983088
+ 987087
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987135
+ 987087
+ 987087
+ 983040
+ 983088
+ 987135
+ 987135
+ 987135
+macroon=0
+macronames=0
+macrovalues=0
+macrogroup=0
+groupcomments=10
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+toolsave=0
+toolhide=0
+toolparse=0
+toolmessages=0
+toolshortcuts=0
+fontalias=0
+fontancestors=0
+fontheights=0
+fontwidths=0
+fontoptions=0
+fontxscales=0
+expandprojectfilemacros=0
+loadprojectfile=0
+newinheritedforms=11
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+uid=0
+sourcefilemasks=3
+ "*.pas" "*.dpr" "*.lpr" "*.pp" "*.inc"
+ "*.c" "*.cc" "*.h"
+ "*.mfm"
+syntaxdeffiles=3
+ ${SYNTAXDEFDIR}pascal_ideu.sdef
+ ${SYNTAXDEFDIR}cpp.sdef
+ ${SYNTAXDEFDIR}objecttext.sdef
+filemasknames=3
+ Source
+ Forms
+ All Files
+filemasks=3
+ "*.pp" "*.pas" "*.inc" "*.dpr" "*.lpr"
+ *.mfm
+ *
+showgrid=1
+snaptogrid=1
+moveonfirstclick=1
+noformdesignerdocking=0
+componenthints=1
+gridsizex=8
+gridsizey=8
+autoindent=1
+blockindent=4
+linenumberson=1
+rightmarginon=1
+rightmarginchars=80
+scrollheight=0
+tabstops=4
+spacetabs=1
+showtabs=0
+tabindent=0
+editfontname=mseide_source
+editfontheight=16
+editfontwidth=0
+editfontextraspace=0
+editfontcolor=-1879048183
+editbkcolor=-1879048186
+statementcolor=14745599
+pairmarkcolor=-1610612712
+editfontantialiased=1
+editmarkbrackets=1
+editmarkpairwords=1
+fpgdesigner=1
+backupfilecount=0
+encoding=1
+eolstyle=1
+trimtrailingwhitespace=0
+codetemplatedirs=1
+ ${TEMPLATEDIR}
+debugcommand=${DEBUGGER}
+debugoptions=
+debugtarget=
+runcommand=
+xtermcommand=xterm -S${PTSN}/${PTSH}
+remoteconnection=
+uploadcommand=
+gdbprocessor=auto
+gdbservercommand=
+gdbservercommandattach=
+beforeconnect=
+afterconnect=
+beforeload=
+afterload=
+beforerun=
+sourcebase=
+sourcedirs=19
+ ./tools/
+ ../resources/
+ ./dialog/
+ ./tablet/
+ ./dialog/color/
+ ./dialog/filter/
+ ${BGRABITMAPDIR}/
+ ${bgracontrolsdir}/
+ ../lazpaintcontrols/
+ ${FPCSRCDIR}/*/
+ ${FPCSRCDIR}/*/
+ ${lcldir}*/
+ ${lcldir}/lcl/widgetset/
+ ${lcldir}/interfaces/*/
+ ${lcldir}/lcl/interfaces/gtk2/
+ ${lcldir}/lcl/components/*/
+ ${lcldir}/lcl/include/
+ ${lcldir}/lcl/
+ ./
+defines=0
+progparameters=
+progworkingdirectory=
+envvarnames=0
+envvarvalues=0
+defineson=0
+stoponexception=0
+valuehints=1
+activateonbreak=1
+raiseonbreak=1
+showconsole=1
+externalconsole=0
+settty=1
+gdbdownload=0
+downloadalways=0
+restartgdbbeforeload=0
+startupbkpt=0
+startupbkpton=0
+gdbsimulator=0
+gdbserverstartonce=0
+gdbloadtimeout=
+gdbserverwait=0
+nogdbserverexit=0
+gdbservertty=0
+exceptclassnames=1
+ EconvertError
+exceptignore=1
+ 0
+nodebugbeginend=0
+fpcgdbworkaround=1
+sigsettings=27
+ 1,1,T,F
+ 3,3,T,F
+ 4,4,T,F
+ 6,6,T,F
+ 7,7,T,F
+ 8,8,T,F
+ 9,9,T,F
+ 10,10,T,F
+ 11,11,T,F
+ 12,12,T,F
+ 13,13,T,F
+ 15,15,T,F
+ 16,16,T,F
+ 17,17,F,F
+ 18,18,T,F
+ 19,19,T,F
+ 20,20,T,F
+ 21,21,T,F
+ 22,22,T,F
+ 23,23,T,F
+ 24,24,T,F
+ 25,25,T,F
+ 26,26,T,F
+ 27,27,T,F
+ 28,28,T,F
+ 29,29,T,F
+ 30,30,T,F
+defaultmake=1
+[breakpoints]
+on=0
+path=0
+line=0
+address=0
+addbkpt=0
+ignore=0
+condition=0
+panels=1
+ panel1
+units=
+ (
+ a=0,8245,6,Pascal Units
+ c=1
+  (
+  file=lazpaint.lpr
+  kind=1
+  a=0,8196,0,lazpaint.lpr
+  )
+ )
+cmodules=
+ (
+ a=0,8228,6,C Modules
+ )
+files=
+ (
+ a=0,8228,6,Text Files
+ )
+[componentstore]
+filename=
+[components]
+[selecteditpage]
+colwidth=100
+x=0
+y=0
+cx=0
+cy=0
+[progparams]
+progparamhistory=0
+workdirparamhistory=0
+envvarons=0
+[edit]
+hintwidth=0
+hintheight=0
+finddtext=
+findhistory=0
+findoptions=1
+editpos=2
+ 6,10
+ 0,0
+bookmarks0=0
+bookmarks1=0
+sourcefiles=1
+ ${PROJECTDIR}/lazpaint.lpr
+relpaths=1
+ lazpaint.lpr
+ismoduletexts=2
+ 0
+ 0
+modules=0
+moduleoptions=0
+visiblemodules=0
+nomenumodules=0
+[sourcefo.files_tab]
+firsttab=0
+index=0
+[layout]
+windowlayout=511
+ [mainfo.basedock]
+ splitdir=2
+ useroptions=268450944
+ [mainfo]
+ splitdir=0
+ useroptions=301990011
+ stackedunder=
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=34
+ y=53
+ cx=1224
+ cy=621
+ rcx=0
+ rcy=0
+ wsize=0
+ active=1
+ visible=1
+ [targetconsolefo]
+ splitdir=0
+ useroptions=268451945
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=493
+ y=171
+ cx=497
+ cy=314
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=1
+ [threadsfo]
+ splitdir=0
+ useroptions=268451945
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=444
+ y=431
+ cx=418
+ cy=126
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [memoryfo]
+ splitdir=0
+ useroptions=268451963
+ stackedunder=dialogfilesfo
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=100
+ y=100
+ cx=453
+ cy=354
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [memoryfo.add]
+ value=0
+ [memoryfo.memon]
+ value=0
+ [memoryfo.bitwidth]
+ value=0
+ [memoryfo.cnt]
+ value=0
+ [disassfo]
+ splitdir=0
+ useroptions=268451947
+ stackedunder=
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=162
+ y=502
+ cx=564
+ cy=210
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [findinfilefo]
+ splitdir=0
+ useroptions=268451947
+ stackedunder=
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=239
+ y=115
+ cx=962
+ cy=414
+ rcx=0
+ rcy=0
+ [projecttreefo]
+ splitdir=0
+ useroptions=268484715
+ parent=mainfo.panel1.container
+ visible=1
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=0
+ y=0
+ cx=205
+ cy=451
+ rcx=0
+ rcy=0
+ [projecttreefo.grid]
+ propcolwidthref=88
+ width0=117
+ sortdescend0=0
+ width1=82
+ sortdescend1=0
+ sorted=0
+ col=1
+ row=-1073741823
+ rowheight=16
+ [stackfo]
+ splitdir=0
+ useroptions=268460137
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=423
+ y=321
+ cx=344
+ cy=155
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [watchpointsfo]
+ splitdir=0
+ useroptions=268451945
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=537
+ y=26
+ cx=483
+ cy=210
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [watchpointsfo.grid]
+ propcolwidthref=332
+ sortdescend0=0
+ values1=0
+ values1_ci=-1
+ width1=33
+ sortdescend1=0
+ values2=0
+ width2=149
+ sortdescend2=0
+ width4=34
+ sortdescend4=0
+ values5=0
+ values5_ci=-1
+ width5=38
+ sortdescend5=0
+ values6=0
+ width6=172
+ sortdescend6=0
+ [breakpointsfo]
+ splitdir=0
+ useroptions=268451947
+ stackedunder=memoryfo
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=107
+ y=404
+ cx=477
+ cy=128
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [breakpointsfo.bkptson]
+ value=1
+ [objectinspectorfo.grid]
+ propcolwidthref=480
+ width0=213
+ sortdescend0=0
+ width1=261
+ sortdescend1=0
+ [symbolfo]
+ splitdir=0
+ useroptions=268451963
+ stackedunder=
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=142
+ y=257
+ cx=361
+ cy=137
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [symbolfo.grid]
+ propcolwidthref=207
+ values0=18
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+ width0=111
+ sortdescend0=0
+ width1=125
+ sortdescend1=0
+ [symbolfo.symbol]
+ [watchfo]
+ splitdir=0
+ useroptions=268460137
+ parent=mainfo.basedock
+ visible=0
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=53
+ y=0
+ cx=247
+ cy=44
+ rcx=1262
+ rcy=583
+ [watchfo.grid]
+ propcolwidthref=121
+ values0=0
+ values0_ci=-1
+ sortdescend0=0
+ values1=0
+ width1=66
+ sortdescend1=0
+ values3=0
+ values3_ci=-1
+ sortdescend3=0
+ values4=0
+ values4_ci=-1
+ width4=13
+ sortdescend4=0
+ [watchfo.watchon]
+ [watchfo.expression]
+ [watchfo.watcheson]
+ value=1
+ [messagefo]
+ splitdir=0
+ useroptions=268517483
+ parent=mainfo.basedock
+ visible=1
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=0
+ y=507
+ cx=1212
+ cy=93
+ rcx=0
+ rcy=0
+ [componentstorefo]
+ splitdir=0
+ useroptions=268460155
+ stackedunder=
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=100
+ y=100
+ cx=445
+ cy=354
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [componentstorefo.grid]
+ propcolwidthref=435
+ width0=111
+ sortdescend0=0
+ sortdescend1=0
+ width2=160
+ sortdescend2=0
+ width3=185
+ sortdescend3=0
+ [componentstorefo.storefiledialog]
+ filenames=0
+ filecolwidth=0
+ x=0
+ y=0
+ cx=0
+ cy=0
+ lastdir=
+ filehistory=0
+ filefilterindex=0
+ filefilter=
+ [componentstorefo.groupfiledialog]
+ filenames=0
+ filecolwidth=0
+ x=0
+ y=0
+ cx=0
+ cy=0
+ lastdir=
+ filehistory=0
+ filefilterindex=0
+ filefilter=
+ [componentstorefo.compfiledialog]
+ filenames=0
+ filecolwidth=0
+ x=0
+ y=0
+ cx=0
+ cy=0
+ lastdir=
+ filehistory=0
+ filefilterindex=0
+ filefilter=
+ [componentpalettefo]
+ splitdir=0
+ useroptions=268460139
+ stackedunder=
+ parent=
+ mdistate=3
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=240
+ y=139
+ cx=956
+ cy=77
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [componentpalettefo.componentpages]
+ activetab=17
+ [debuggerfo]
+ splitdir=0
+ useroptions=24683
+ parent=mainfo.basedock
+ visible=1
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=0
+ y=0
+ cx=1212
+ cy=50
+ rcx=0
+ rcy=0
+ [debuggerfo.basedock]
+ splitdir=2
+ useroptions=268582019
+ parent=debuggerfo.container
+ visible=1
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=1197
+ ncy=36
+ x=0
+ y=0
+ cx=1212
+ cy=34
+ rcx=0
+ rcy=0
+ [debuggerfo.edit_options]
+ value=X
+ [debuggerfo.edit_compilernum]
+ value=0
+ [debuggerfo.edit_compiler]
+ value=Pascal
+ [debuggerfo.file_history]
+ [debuggerfo.project_options]
+ value=1
+ [debuggerfo.hints]
+ value=0
+ [sourcefo]
+ splitdir=0
+ useroptions=16489
+ parent=mainfo.panel1.container
+ visible=1
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=208
+ y=0
+ cx=1004
+ cy=451
+ rcx=0
+ rcy=0
+ [sourcefo.files_tab]
+ firsttab=0
+ index=0
+ [confideufo.fontname]
+ value=stf_default
+ [confideufo.usedefaulteditoroptions]
+ value=0
+ [cpuc86_64fo]
+ irqoff=0
+ splitdir=0
+ useroptions=268451947
+ stackedunder=confdebuggerfo
+ parent=
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=183
+ y=113
+ cx=352
+ cy=277
+ rcx=0
+ rcy=0
+ wsize=0
+ active=0
+ visible=0
+ [mainfo.panel1]
+ splitdir=1
+ useroptions=302087659
+ parent=mainfo.basedock
+ visible=1
+ mdistate=0
+ nx=0
+ ny=0
+ ncx=0
+ ncy=0
+ x=0
+ y=53
+ cx=1212
+ cy=451
+ rcx=0
+ rcy=0
+[targetconsole]
+finddtext=
+findhistory=0
+findoptions=1

+ 31 - 0
lazpaint/lazpaintdialogs.inc

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 procedure TLazPaintInstance.ShowPrintDlg;
 var f: TFPrint;
     wasVisible: boolean;
@@ -123,6 +124,12 @@ begin
   result := srOk;
 end;
 
+function TLazPaintInstance.ScriptGetName(AVars: TVariableSet): TScriptResult;
+begin
+  AVars.Strings['Result'] := FScriptName;
+  result := srOk;
+end;
+
 function TLazPaintInstance.ScriptImageCanvasSize(AVars: TVariableSet): TScriptResult;
 var
   w, h: Int64;
@@ -229,6 +236,30 @@ begin
     result := srCancelledByUser;
 end;
 
+function TLazPaintInstance.ScriptTranslateGetLanguage(AVars: TVariableSet
+  ): TScriptResult;
+begin
+  AVars.Strings['Result'] := ActiveLanguage;
+  result := srOk;
+end;
+
+function TLazPaintInstance.ScriptTranslateText(AVars: TVariableSet): TScriptResult;
+var
+  textVar, resVar: TScriptVariableReference;
+  i: Integer;
+begin
+  textVar := AVars.GetVariable('Text');
+  if not AVars.IsReferenceDefined(textVar) then exit(srException);
+  if AVars.IsList(textVar) then
+  begin
+    resVar := AVars.AddStringList('Result');
+    for i := 0 to AVars.GetListCount(textVar)-1 do
+      AVars.AppendString(resVar, DoTranslate('', AVars.GetStringAt(textVar, i)));
+  end else
+    AVars.Strings['Result'] := DoTranslate('', AVars.Strings['Text']);
+  result := srOk;
+end;
+
 function TLazPaintInstance.ShowResampleDialog(AParameters: TVariableSet): boolean;
 begin
   FormsNeeded;

+ 1 - 1
lazpaint/lazpaintembeddedpack.lpk

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

+ 59 - 8
lazpaint/lazpaintinstance.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit LazpaintInstance;
 
 {$mode objfpc}{$H+}
@@ -53,11 +54,14 @@ type
     function ScriptColorShiftColors(AVars: TVariableSet): TScriptResult;
     function ScriptFileGetTemporaryName(AVars: TVariableSet): TScriptResult;
     function ScriptFileNew(AVars: TVariableSet): TScriptResult;
+    function ScriptGetName(AVars: TVariableSet): TScriptResult;
     function ScriptImageCanvasSize(AVars: TVariableSet): TScriptResult;
     function ScriptImageRepeat(AVars: TVariableSet): TScriptResult;
     function ScriptImageResample(AParams: TVariableSet): TScriptResult;
     function ScriptLazPaintGetVersion(AVars: TVariableSet): TScriptResult;
     function ScriptShowDirectoryDialog(AVars: TVariableSet): TScriptResult;
+    function ScriptTranslateGetLanguage(AVars: TVariableSet): TScriptResult;
+    function ScriptTranslateText(AVars: TVariableSet): TScriptResult;
     procedure SelectionInstanceOnRun(AInstance: TLazPaintCustomInstance);
     procedure ToolFillChanged(Sender: TObject);
     procedure PythonScriptCommand({%H-}ASender: TObject; ACommand, AParam: UTF8String; out
@@ -107,6 +111,7 @@ type
     FInRunScript: boolean;
     FScriptTempFileNames: TStringList;
     FInCommandLine: boolean;
+    FUpdateStackOnTimer: boolean;
 
     function GetIcons(ASize: integer): TImageList; override;
     function GetToolBoxWindowPopup: TPopupMenu; override;
@@ -142,13 +147,16 @@ type
     function GetImage: TLazPaintImage; override;
     function GetImageAction: TImageActions; override;
     function GetToolManager: TToolManager; override;
+    function GetUpdateStackOnTimer: boolean; override;
+    procedure SetUpdateStackOnTimer(AValue: boolean); override;
     procedure CreateLayerStack;
     procedure CreateToolBox;
     procedure FormsNeeded;
     procedure Init(AEmbedded: boolean);
     procedure SetBlackAndWhite(AValue: boolean); override;
     procedure OnStackChanged({%H-}sender: TLazPaintImage; AScrollIntoView: boolean);
-    procedure OnToolPopup({%H-}sender: TToolManager; AMessage: TToolPopupMessage; AKey: Word);
+    procedure OnToolPopup({%H-}sender: TToolManager; AMessage: TToolPopupMessage; AKey: Word;
+      AAlways: boolean);
 
     function GetImageListWindowHeight: integer; override;
     function GetImageListWindowWidth: integer; override;
@@ -201,9 +209,10 @@ type
     destructor Destroy; override;
     procedure NotifyImageChange(RepaintNow: boolean; ARect: TRect); override;
     procedure NotifyImageChangeCompletely(RepaintNow: boolean); override;
+    procedure NotifyImagePaint; override;
     function TryOpenFileUTF8(filename: string; skipDialogIfSingleImage: boolean = false): boolean; override;
     function ExecuteFilter(filter: TPictureFilter; skipDialog: boolean = false): TScriptResult; override;
-    function RunScript(AFilename: string): boolean; override;
+    function RunScript(AFilename: string; ACaption: string = ''): boolean; override;
     procedure AdjustChooseColorHeight; override;
     procedure ColorFromFChooseColor; override;
     procedure ColorToFChooseColor; override;
@@ -246,6 +255,8 @@ type
     property MainFormVisible: boolean read GetMainFormVisible;
     procedure NotifyStackChange; override;
     procedure ScrollLayerStackOnItem(AIndex: integer; ADelayedUpdate: boolean = true); override;
+    procedure InvalidateLayerStack; override;
+    procedure UpdateLayerStackOnTimer; override;
     function MakeNewBitmapReplacement(AWidth, AHeight: integer; AColor: TBGRAPixel): TBGRABitmap; override;
     procedure ChooseTool(Tool : TPaintToolType); override;
     function OpenImage (FileName: string; AddToRecent: Boolean= True): boolean; override;
@@ -259,7 +270,7 @@ type
 
 implementation
 
-uses LCLType, Types, Forms, Dialogs, FileUtil, StdCtrls, LCLIntf, BGRAUTF8,
+uses LCLType, Types, Forms, Dialogs, FileUtil, StdCtrls, LCLIntf, BGRAUTF8, UTranslation,
 
      URadialBlur, UMotionBlur, UEmboss, UTwirl, UWaveDisplacement,
      unewimage, uresample, UPixelate, unoisefilter, ufilters,
@@ -386,6 +397,9 @@ begin
   ScriptContext.RegisterScriptFunction('ShowDirectoryDialog',@ScriptShowDirectoryDialog,ARegister);
   ScriptContext.RegisterScriptFunction('InputBox',@ScriptInputBox,ARegister);
   ScriptContext.RegisterScriptFunction('LazPaintGetVersion',@ScriptLazPaintGetVersion,ARegister);
+  ScriptContext.RegisterScriptFunction('TranslateText',@ScriptTranslateText,ARegister);
+  ScriptContext.RegisterScriptFunction('TranslateGetLanguage',@ScriptTranslateGetLanguage,ARegister);
+  ScriptContext.RegisterScriptFunction('ScriptGetName',@ScriptGetName,ARegister);
 end;
 
 function TLazPaintInstance.ScriptFileGetTemporaryName(AVars: TVariableSet): TScriptResult;
@@ -496,6 +510,16 @@ begin
   Result:= FToolManager;
 end;
 
+function TLazPaintInstance.GetUpdateStackOnTimer: boolean;
+begin
+  result := FUpdateStackOnTimer;
+end;
+
+procedure TLazPaintInstance.SetUpdateStackOnTimer(AValue: boolean);
+begin
+  FUpdateStackOnTimer := AValue;
+end;
+
 procedure TLazPaintInstance.CreateLayerStack;
 var
   defaultZoom: Single;
@@ -587,12 +611,13 @@ begin
     FLayerStack.InvalidateStack(AScrollIntoView);
 end;
 
-procedure TLazPaintInstance.OnToolPopup(sender: TToolManager; AMessage: TToolPopupMessage; AKey: Word);
+procedure TLazPaintInstance.OnToolPopup(sender: TToolManager; AMessage: TToolPopupMessage; AKey: Word;
+  AAlways: boolean);
 var messageStr: string;
     idx: integer;
 begin
   if FInCommandLine then exit;
-  if Assigned(Config) then
+  if Assigned(Config) and not AAlways then
   begin
     idx := ord(AMessage);
     if Config.ToolPopupMessageShownCount(idx) < MaxToolPopupShowCount then
@@ -1579,6 +1604,12 @@ begin
   If RepaintNow then FMain.Update;
 end;
 
+procedure TLazPaintInstance.NotifyImagePaint;
+begin
+  if Assigned(FMain) then
+    FMain.NotifyImagePaint;
+end;
+
 function TLazPaintInstance.TryOpenFileUTF8(filename: string; skipDialogIfSingleImage: boolean): boolean;
 begin
   FormsNeeded;
@@ -1600,7 +1631,7 @@ begin
   vars.Free;
 end;
 
-function TLazPaintInstance.RunScript(AFilename: string): boolean;
+function TLazPaintInstance.RunScript(AFilename: string; ACaption: string): boolean;
 var
   p: TPythonScript;
   fError: TForm;
@@ -1626,7 +1657,9 @@ begin
   try
     FScriptTempFileNames := TStringList.Create;
     p := TPythonScript.Create;
-    FScriptName := AFilename;
+    if Trim(ACaption).Length > 0 then
+      FScriptName:= Trim(ACaption)
+      else FScriptName := AFilename;
     p.OnCommand:=@PythonScriptCommand;
     p.OnBusy := @PythonBusy;
     p.Run(AFilename);
@@ -1641,6 +1674,7 @@ begin
         memo := TMemo.Create(fError);
         memo.Align:= alClient;
         memo.Parent := fError;
+        memo.ScrollBars := ssVertical;
         memo.Font.Name:= 'monospace';
         memo.Text := p.ErrorText;
         fError.ShowModal;
@@ -1777,10 +1811,21 @@ begin
   begin
     if not Assigned(FMain) then ADelayedUpdate:= false;
     FLayerStack.ScrollToItem(AIndex, not ADelayedUpdate);
-    if ADelayedUpdate then FMain.UpdateStackOnTimer := true;
+    if ADelayedUpdate then UpdateStackOnTimer := true;
   end;
 end;
 
+procedure TLazPaintInstance.InvalidateLayerStack;
+begin
+  if FLayerStack<> nil then
+    FLayerStack.InvalidateStack(false);
+end;
+
+procedure TLazPaintInstance.UpdateLayerStackOnTimer;
+begin
+  UpdateStackOnTimer := true;
+end;
+
 function TLazPaintInstance.MakeNewBitmapReplacement(AWidth, AHeight: integer; AColor: TBGRAPixel): TBGRABitmap;
 begin
   result := TBGRABitmap.Create(AWidth,AHeight, AColor);
@@ -1864,6 +1909,12 @@ procedure TLazPaintInstance.SetChooseColorTarget(const AValue: TColorTarget);
 begin
   if not Assigned(FChooseColor) then exit;
   FChooseColor.ColorTarget:= AValue;
+  if Assigned(FMain) then
+  begin
+    FMain.VectorialFill_Pen.IsTarget := AValue in [ctForeColorSolid..ctForeColorEndGrad];
+    FMain.VectorialFill_Back.IsTarget := AValue in [ctBackColorSolid..ctBackColorEndGrad];
+    FMain.VectorialFill_Outline.IsTarget := AValue in [ctOutlineColorSolid..ctOutlineColorEndGrad];
+  end;
   ColorToFChooseColor;
 end;
 

+ 1 - 26
lazpaint/lazpaintmainform.lfm

@@ -7,7 +7,6 @@ object FMain: TFMain
   Caption = 'LazPaint'
   ClientHeight = 572
   ClientWidth = 739
-  Color = clSkyBlue
   Constraints.MinWidth = 320
   Font.Height = -12
   KeyPreview = True
@@ -20,12 +19,6 @@ object FMain: TFMain
   OnHide = FormHide
   OnKeyDown = FormKeyDown
   OnKeyUp = FormKeyUp
-  OnMouseDown = FormMouseDown
-  OnMouseEnter = FormMouseEnter
-  OnMouseMove = FormMouseMove
-  OnMouseUp = FormMouseUp
-  OnMouseWheel = FormMouseWheel
-  OnPaint = FormPaint
   OnResize = FormResize
   OnShow = FormShow
   OnUTF8KeyPress = FormUTF8KeyPress
@@ -1524,9 +1517,7 @@ object FMain: TFMain
     Height = 104
     Top = 176
     Width = 106
-    ClientHeight = 104
-    ClientWidth = 106
-    Color = clBtnFace
+    BevelOuter = bvNone
     Font.Height = -12
     ParentColor = False
     ParentFont = False
@@ -2342,22 +2333,6 @@ object FMain: TFMain
       end
     end
   end
-  object PaintBox_Picture: TPaintBox
-    Left = 608
-    Height = 84
-    Top = 56
-    Width = 117
-    Anchors = [akTop, akLeft, akRight, akBottom]
-    Font.Height = -12
-    ParentFont = False
-    Visible = False
-    OnMouseDown = PaintBox_PictureMouseDown
-    OnMouseEnter = PaintBox_PictureMouseEnter
-    OnMouseMove = PaintBox_PictureMouseMove
-    OnMouseUp = PaintBox_PictureMouseUp
-    OnMouseWheel = PaintBox_PictureMouseWheel
-    OnPaint = PaintBox_PicturePaint
-  end
   object Panel_Brush: TPanel
     Left = 8
     Height = 36

+ 119 - 417
lazpaint/lazpaintmainform.pas

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit LazpaintMainForm;
 
 {$mode objfpc}{$H+}
 
 interface
 
-{$IFDEF DARWIN}
-  {$DEFINE USEPAINTBOXPICTURE}
-{$ENDIF}
-
 uses
   Classes, LMessages, SysUtils, LazFileUtils, LResources, Forms, Controls,
   Graphics, Dialogs, Menus, ExtDlgs, ComCtrls, ActnList, StdCtrls, ExtCtrls,
@@ -20,7 +17,7 @@ uses
   ubrowseimages, UToolPolygon, UToolVectorial, LCVectorRectShapes,
   LCVectorialFillControl, LCVectorialFill,
 
-  laztablet, udarktheme, UScriptType;
+  udarktheme, UScriptType;
 
 type
   { TFMain }
@@ -344,7 +341,6 @@ type
     Panel_Text: TPanel;
     ToolBar15: TToolBar;
     Tool_TextFont: TToolButton;
-    PaintBox_Picture: TPaintBox;
     PaintBox_PenPreview: TPaintBox;
     Panel_Embedded: TPanel;
     Panel_PenWidthPreview: TPanel;
@@ -479,7 +475,6 @@ type
     procedure FileUseImageBrowserUpdate(Sender: TObject);
     procedure ForgetDialogAnswersExecute(Sender: TObject);
     procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
-    procedure FormMouseLeave(Sender: TObject);
     procedure FormWindowStateChange(Sender: TObject);
     procedure ItemDockLayersAndColorsClick(Sender: TObject);
     procedure ItemFullscreenClick(Sender: TObject);
@@ -517,7 +512,6 @@ type
     procedure FileSaveSelectionAsUpdate(Sender: TObject);
     procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
     procedure FormKeyUp(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
-    procedure FormMouseEnter(Sender: TObject);
     procedure FormUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
     procedure ImageCropLayerUpdate(Sender: TObject);
     procedure ImageFlattenExecute(Sender: TObject);
@@ -532,7 +526,6 @@ type
     procedure LayerRotateExecute(Sender: TObject);
     procedure LayerRotateUpdate(Sender: TObject);
     procedure ItemDonateClick(Sender: TObject);
-    procedure PaintBox_PictureMouseEnter(Sender: TObject);
     procedure Perspective_TwoPlanesClick(Sender: TObject);
     procedure SpinEdit_ShapeAltitudeChange(Sender: TObject; AByUser: boolean);
     procedure SpinEdit_BrushSpacingChange(Sender: TObject; AByUser: boolean);
@@ -544,15 +537,6 @@ type
     procedure ToolButton_DonateClick(Sender: TObject);
     procedure VectorialFill_TextureClick(Sender: TObject);
     procedure PaintBox_PenPreviewPaint(Sender: TObject);
-    procedure PaintBox_PictureMouseDown(Sender: TObject; Button: TMouseButton;
-      Shift: TShiftState; X, Y: Integer);
-    procedure PaintBox_PictureMouseMove(Sender: TObject; Shift: TShiftState; X,
-      Y: Integer);
-    procedure PaintBox_PictureMouseUp(Sender: TObject; Button: TMouseButton;
-      Shift: TShiftState; X, Y: Integer);
-    procedure PaintBox_PictureMouseWheel(Sender: TObject; Shift: TShiftState;
-      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
-    procedure PaintBox_PicturePaint(Sender: TObject);
     procedure Panel_PenWidthMouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
       {%H-}Y: Integer);
     procedure Panel_ToolbarBackgroundMouseMove(Sender: TObject;
@@ -565,8 +549,6 @@ type
     procedure ToolAnyExecute(Sender: TObject);
     procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
     procedure FormHide(Sender: TObject);
-    procedure FormMouseWheel(Sender: TObject; {%H-}Shift: TShiftState;
-      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
     procedure HelpAboutExecute(Sender: TObject);
     procedure HelpIndexExecute(Sender: TObject);
     procedure ImageChangeCanvasSizeExecute(Sender: TObject);
@@ -632,12 +614,6 @@ type
     procedure FormResize(Sender: TObject);
     procedure ImageActionExecute(Sender: TObject);
     procedure FormCreate(Sender: TObject);
-    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
-      Shift: TShiftState; X, Y: Integer);
-    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
-    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
-      Shift: TShiftState; X, Y: Integer);
-    procedure FormPaint(Sender: TObject);
     procedure FormShow(Sender: TObject);
     procedure Image_SwapColorsMouseDown(Sender: TObject; {%H-}Button: TMouseButton;
       {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
@@ -687,8 +663,13 @@ type
     procedure ManagerToleranceChanged(Sender: TObject);
     procedure ManagerToolbarChanged(Sender: TObject);
     procedure Perspective_RepeatClick(Sender: TObject);
+    procedure PictureMouseBefore(Sender: TObject; AShift: TShiftState);
+    procedure PictureMouseMove(Sender: TObject; APosition: TPointF);
+    procedure PictureOnPaint(Sender: TObject);
+    procedure PictureToolbarUpdate(Sender: TObject);
     function ScriptShowColorDialog(AVars: TVariableSet): TScriptResult;
     procedure VectorialFill_Change(Sender: TObject);
+    procedure vectorialFill_ClickLabel(Sender: TObject);
     procedure VectorialFill_TypeChange(Sender: TObject);
     procedure VectorialFill_Resize(Sender: TObject);
     procedure VectorialFill_EditGradTexPoints(Sender: TObject);
@@ -710,9 +691,6 @@ type
     FBrowseBrushes: TFBrowseImages;
     FSaveImage: TFBrowseImages;
     FSaveSelection: TFBrowseImages;
-
-    FTablet: TLazTablet;
-
     FLoadInitialDir, FSaveInitialDir, FExportInitialDir: string;
     FSaveSelectionInitialFilename: string;
     FInFillChange, FInPenWidthChange, FInBrush, FInShapeRatio, FInEraserOption,
@@ -722,31 +700,21 @@ type
     FOnlineUpdater: TLazPaintCustomOnlineUpdater;
     FInitialized: boolean;
     FShouldArrange: boolean;
-    btnLeftDown, btnRightDown, btnMiddleDown: boolean;
     spacePressed, altPressed, snapPressed, shiftPressed: boolean;
-    FormMouseMovePos: TPoint;
-    InFormMouseMove: boolean;
-    InFormPaint: boolean;
     FirstPaint, LoadToolWindow: boolean;
-    CanCompressOrUpdateStack: boolean;
     FShowSelectionNormal: boolean;
     FLazPaintInstance: TLazPaintCustomInstance;
     Config: TLazPaintConfig;
     StartDirectory: string;
     previousToolImg: integer;
     currentToolLabel: string;
-    InShowNoPicture: boolean;
     FTopMostInfo: TTopMostInfo;
-    DelayedPaintPicture: boolean;
     Panel_LineCap_FullSize: integer;
     FCoordinatesCaption: string;
     FCoordinatesCaptionCount: NativeInt;
-    FImageView: TImageView;
-    FLastPaintDate: TDateTime;
-    FUpdateStackWhenIdle: boolean;
     FToolbarElementsInitDone: boolean;
+    FPenPlusMinus: integer;
 
-    function GetCurrentPressure: single;
     function GetDarkTheme: boolean;
     function GetImageAction: TImageActions;
     function GetUpdatingPopup: boolean;
@@ -782,10 +750,12 @@ type
     function TextSpinEditFocused: boolean;
     procedure UpdateBrush;
     procedure UpdateBrushList;
+    function CatchToolKeyDown(var AKey: Word): boolean;
+    function CatchToolKeyUp(var AKey: Word): boolean;
+    function CatchToolKeyPress(var AKey: TUTF8Char): boolean;
 
     procedure CreateMenuAndToolbar;
     function GetToolManager: TToolManager;
-    procedure LayoutPictureAreaChange({%H-}ASender: TObject; {%H-}ANewArea: TRect);
     function GetCurrentTool: TPaintToolType;
     procedure SwitchColors;
     function EditingColors: boolean;
@@ -793,7 +763,6 @@ type
     procedure OnLatestVersionUpdate(ANewVersion: string);
     procedure ManagerToolChanged({%H-}sender: TToolManager; {%H-}ANewTool: TPaintToolType);
     procedure OnQueryExitToolHandler({%H-}sender: TLazPaintImage);
-    procedure OnZoomChanged({%H-}sender: TZoom; {%H-}ANewZoom: single);
     procedure SetLazPaintInstance(const AValue: TLazPaintCustomInstance);
     procedure SetShowSelectionNormal(const AValue: boolean);
     procedure ToggleToolwindowsVisible;
@@ -809,20 +778,15 @@ type
     procedure HidePenPreview(ATimeMs: Integer = 300; AClearTime: boolean = false);
     procedure ShowFill(AFillControl: TLCVectorialFillControl; APanel: TPanel);
     procedure HideFill(ATimeMs: Integer = 300; AClearTime: boolean = false);
-    procedure OnPaintHandler;
     procedure OnImageChangedHandler({%H-}AEvent: TLazPaintImageObservationEvent);
     procedure OnImageRenderChanged({%H-}Sender: TObject);
     procedure LabelAutosize(ALabel: TLabel);
     procedure AskMergeSelection(ACaption: string);
-    procedure ReleaseMouseButtons(Shift: TShiftState);
     procedure UpdateSpecialKeys({%H-}Shift: TShiftState);
     procedure UpdateCurveModeToolbar;
     function ShowOpenTextureDialog(ATargetFill: TVectorialFill): boolean;
     procedure ShowNoPicture;
     procedure SetCurveMode(AMode: TToolSplineMode);
-    procedure IncreasePenSize;
-    procedure DecreasePenSize;
-    function PenSizeDelta(direction: integer): integer;
     procedure UpdatePenWidthFromSpinEdit;
     procedure UpdateWindowCaption;
     procedure ImageCurrentFilenameChanged({%H-}sender: TLazPaintImage);
@@ -860,15 +824,15 @@ type
 
   public
     { public declarations }
-    UpdateStackOnTimer: boolean;
     Zoom: TZoom;
 
     procedure PaintPictureNow;
+    procedure PaintPictureLater;
+    procedure NotifyImagePaint;
     procedure InvalidatePicture(AInvalidateAll: boolean = true);
     function TryOpenFileUTF8(filenameUTF8: string; AddToRecent: Boolean=True;
       ALoadedImage: PImageEntry = nil; ASkipDialogIfSingleImage: boolean = false;
       AAllowDuplicate: boolean = false; AEntryToLoad: integer = -1): Boolean;
-    function PictureCanvasOfs: TPoint;
     procedure UpdateLineCapBar;
     procedure UpdateFillToolbar(AUpdateColorDiff: boolean);
     procedure UpdateToolbar;
@@ -886,7 +850,6 @@ type
     property ToolManager: TToolManager read GetToolManager;
     property Layout: TMainFormLayout read FLayout;
     property UseImageBrowser: boolean read GetUseImageBrowser;
-    property CurrentPressure: single read GetCurrentPressure;
     property DarkTheme: boolean read GetDarkTheme write SetDarkTheme;
     property Initialized: boolean read FInitialized;
     property UpdatingPopup: boolean read GetUpdatingPopup write SetUpdatingPopup;
@@ -898,7 +861,8 @@ implementation
 uses LCLIntf, BGRAUTF8, ugraph, math, umac, uclipboard, ucursors,
    ufilters, ULoadImage, ULoading, UFileExtensions, UBrushType,
    ugeometricbrush, UPreviewDialog, UQuestion, BGRALayerOriginal,
-   BGRATransform, LCVectorPolyShapes, URaw, UFileSystem;
+   BGRATransform, LCVectorPolyShapes, URaw, UFileSystem,
+   UTranslation, UPython;
 
 const PenWidthFactor = 10;
 
@@ -910,17 +874,16 @@ procedure TFMain.FormCreate(Sender: TObject);
 begin
   FInitialized := false;
 
-  FLayout := TMainFormLayout.Create(self);
-  FImageView := nil;
+  Zoom := TZoom.Create(Label_CurrentZoom, Edit_Zoom);
+  FLayout := TMainFormLayout.Create(self, Zoom);
+  FLayout.OnPaintPicture:=@PictureOnPaint;
+  FLayout.OnToolbarUpdate:=@PictureToolbarUpdate;
+  FLayout.OnPictureMouseMove:=@PictureMouseMove;
+  FLayout.OnPictureMouseBefore:=@PictureMouseBefore;
 
   ScaleControl(Self,OriginalDPI);
   self.Color := clBtnFace; //toolbar color inherited on mac
 
-  {$IFDEF USEPAINTBOXPICTURE}
-  PaintBox_Picture.SetBounds(0,0,ClientWidth,ClientHeight);
-  PaintBox_Picture.Visible := True;
-  {$ENDIF}
-
   //mac interface
   CheckActions(ActionList1);
   CheckQuitMenu(ItemQuit,ItemQuitSeparator);
@@ -939,29 +902,13 @@ begin
   ExportPictureDialog.Filter := SavePictureDialog1.Filter;
   SaveSelectionDialog.Filter := SavePictureDialog1.Filter;
 
-  Zoom := TZoom.Create(Label_CurrentZoom,Edit_Zoom,FLayout);
-  Zoom.OnZoomChanged:= @OnZoomChanged;
   previousToolImg:= -1;
 
-  //mouse status
-  btnLeftDown := false;
-  btnRightDown := false;
-  btnMiddleDown:= false;
-  try
-    FTablet := TLazTablet.Create(self);
-  except
-    on ex: exception do
-      FTablet := nil;
-  end;
   spacePressed:= false;
   altPressed:= false;
   snapPressed:= false;
   shiftPressed:= false;
 
-  //recursive calls
-  InFormMouseMove:= false;
-  InFormPaint := false;
-
   {$IFDEF LINUX}
   ComboBox_BrushSelect.Top := ComboBox_BrushSelect.Top - 2;
   ComboBox_BrushSelect.Font.Height := -10;
@@ -973,7 +920,6 @@ begin
   ComboBox_ArrowEnd.Font.Height := ComboBox_BrushSelect.Font.Height;
   {$ENDIF}
 
-  FLayout.OnPictureAreaChange := @LayoutPictureAreaChange;
   FInitialized := true;
   FirstPaint := true;
 end;
@@ -1026,11 +972,8 @@ begin
     if ToolManager.OnFloodFillOptionChanged = @ManagerFloodFillOptionChanged then ToolManager.OnFloodFillOptionChanged := nil;
     if ToolManager.OnPerspectiveOptionChanged = @ManagerPerspectiveOptionChanged then ToolManager.OnPerspectiveOptionChanged := nil;
   end;
-  FreeAndNil(Zoom);
   FreeAndNil(FOnlineUpdater);
 
-  FreeAndNil(FTablet);
-
   FreeAndNil(FBrowseSelections);
   FreeAndNil(FBrowseImages);
   FreeAndNil(FBrowseTextures);
@@ -1045,8 +988,8 @@ begin
   FreeAndNil(FSaveImage);
   FreeAndNil(FSaveSelection);
 
-  FreeAndNil(FImageView);
   FreeAndNil(FLayout);
+  FreeAndNil(Zoom);
 end;
 
 procedure TFMain.SetLazPaintInstance(const AValue: TLazPaintCustomInstance);
@@ -1087,9 +1030,6 @@ begin
     ExportPictureDialog.FilterIndex:= 1;
   end;
 
-  FImageView := TImageView.Create(LazPaintInstance, Zoom,
-                {$IFDEF USEPAINTBOXPICTURE}PaintBox_Picture.Canvas{$ELSE}self.Canvas{$ENDIF});
-
   LazPaintInstance.EmbeddedResult := mrNone;
 
   Image.OnSelectedLayerIndexChanged:= @PictureSelectedLayerIndexChanged;
@@ -1169,6 +1109,7 @@ end;
 procedure TFMain.FormShow(Sender: TObject);
 var
   m: TMainFormMenu;
+  startFillControlWidth: LongInt;
 begin
   if FLayout.Menu = nil then
   begin
@@ -1220,8 +1161,10 @@ begin
   LazPaintInstance.ShowTopmost(FTopMostInfo);
   if Position = poDefault then LazPaintInstance.RestoreMainWindowPosition;
 
-  VectorialFill_Pen.Width := VectorialFill_Pen.PreferredSize.Width;
-  VectorialFill_Back.Width := VectorialFill_Back.PreferredSize.Width;
+  startFillControlWidth := VectorialFill_Pen.PreferredSize.Width;
+  VectorialFill_Pen.Width := startFillControlWidth;
+  VectorialFill_Back.Width := startFillControlWidth;
+  VectorialFill_Outline.Width := startFillControlWidth;
   ToolManager.UpdateContextualToolbars;
   UpdateToolImage;
   UpdateToolBar;
@@ -1263,137 +1206,6 @@ begin
   Scripting.RegisterScriptFunction('ShowColorDialog',@ScriptShowColorDialog,ARegister);
 end;
 
-procedure TFMain.FormMouseDown(Sender: TObject; Button: TMouseButton;
-  Shift: TShiftState; X, Y: Integer);
-begin
-  if not Assigned(FImageView) then exit;
-  ReleaseMouseButtons(Shift);
-  if not (Button in[mbLeft,mbRight,mbMiddle]) or not FImageView.PictureCoordsDefined then exit;
-  CanCompressOrUpdateStack := false;
-  if Assigned(LazPaintInstance) then LazPaintInstance.ExitColorEditor;
-  Image.OnImageChanged.DelayedStackUpdate := True;
-
-  if btnLeftDown or btnRightDown or btnMiddleDown then exit;
-
-  if Button = mbMiddle then
-  begin
-    btnMiddleDown:= true;
-    if not ToolManager.ToolSleeping and not (ssAlt in Shift) then ToolManager.ToolSleep;
-  end;
-
-  if FImageView.PictureCoordsDefined then
-  begin
-    if Button = mbLeft then
-      btnLeftDown := true else
-    if Button = mbRight then
-      btnRightDown := true;
-
-    if ToolManager.ToolDown(FImageView.FormToBitmap(X,Y),
-        btnRightDown{$IFDEF DARWIN} or (ssCtrl in Shift){$ENDIF},
-        CurrentPressure) then
-        PaintPictureNow;
-    UpdateToolbar;
-  end;
-end;
-
-procedure TFMain.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
-  Y: Integer);
-var BmpPos: TPointF;
-    updateForVSCursor: boolean;
-
-//var tickstart:DWord;
-begin
-  //tickstart := GetTickCount;
-  if not Assigned(FImageView) then exit;
-
-  ReleaseMouseButtons(Shift);
-  UpdateSpecialKeys(Shift);
-  HidePenPreview;
-  HideFill;
-  if LazPaintInstance.TopMostHasFocus then
-  begin
-    if LazPaintInstance.TopMostOkToUnfocus then
-      SafeSetFocus(self)
-    else
-      exit;
-  end;
-  if (CurrentTool in[ptText,ptEditShape]) and TextSpinEditFocused then VectorialFill_Pen.SetFocus;
-  Image.CurrentState.LayeredBitmap.EditorFocused := true;
-
-  FormMouseMovePos := Point(X,Y);
-  if InFormMouseMove then exit;
-  InFormMouseMove := True;
-  if not FImageView.PictureCoordsDefined then
-    Application.ProcessMessages; //empty message stack
-  if not FImageView.PictureCoordsDefined then
-  begin
-    InFormMouseMove:= false;
-    exit;
-  end;
-
-  BmpPos := FImageView.FormToBitmap(FormMouseMovePos);
-  FCoordinatesCaption := IntToStr(round(BmpPos.X))+','+IntToStr(round(BmpPos.Y));
-  Inc(FCoordinatesCaptionCount);
-  if FCoordinatesCaptionCount > 8 then
-  begin
-    FCoordinatesCaptionCount := 0;
-    Label_Coordinates.caption := FCoordinatesCaption;
-    Label_Coordinates.Update;
-    UpdateStatusText;
-  end;
-  updateForVSCursor:= false;
-  if ToolManager.ToolMove(BmpPos,CurrentPressure) then
-  begin
-    FImageView.UpdatePicture(PictureCanvasOfs, FLayout.WorkArea, self);
-  end else
-    updateForVSCursor := true;
-  UpdateToolbar;
-
-  if updateForVSCursor then
-    FImageView.UpdateCursor(X,Y, PictureCanvasOfs, FLayout.WorkArea,
-                            {$IFDEF USEPAINTBOXPICTURE}PaintBox_Picture{$ELSE}self{$ENDIF},
-                            Point(0,0), self);
-
-  if ToolManager.ToolSleeping and not spacePressed and not btnLeftDown and not btnRightDown
-    and not btnMiddleDown then
-    ToolManager.ToolWakeUp;
-
-  InFormMouseMove := False;
-  //Canvas.TextOut(FLayout.WorkArea.Left,FLayout.WorkArea.Top,inttostr(GetTickCount-tickstart)+'     ');
-end;
-
-procedure TFMain.FormMouseUp(Sender: TObject; Button: TMouseButton;
-  Shift: TShiftState; X, Y: Integer);
-var redraw: boolean;
-begin
-  if not Assigned(FImageView) then exit;
-
-  redraw := false;
-  if (btnLeftDown and (Button = mbLeft)) or (btnRightDown and (Button=mbRight))
-    or (btnMiddleDown and (Button = mbMiddle)) then
-  begin
-    if FImageView.PictureCoordsDefined then
-      redraw := ToolManager.ToolMove(FImageView.FormToBitmap(X,Y),CurrentPressure)
-      else redraw := false;
-    if ToolManager.ToolUp then redraw := true;
-    btnLeftDown := false;
-    btnRightDown := false;
-    btnMiddleDown:= false;
-  end;
-  if redraw then PaintPictureNow;
-  if FUpdateStackWhenIdle then
-  begin
-    UpdateStackOnTimer:= true;
-    FUpdateStackWhenIdle:= false;
-  end;
-  UpdateToolbar;
-  ReleaseMouseButtons(Shift);
-
-  if ToolManager.ToolSleeping and not spacePressed and not btnLeftDown and not btnRightDown
-   and not btnMiddleDown then
-    ToolManager.ToolWakeUp;
-end;
-
 function TFMain.ScriptFileOpen(AVars: TVariableSet): TScriptResult;
 var vFilename: TScriptVariableReference;
     topInfo: TTopMostInfo;
@@ -1959,17 +1771,16 @@ begin
   end;
 end;
 
-procedure TFMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
-  );
+procedure TFMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
 begin
   try
     if Key = VK_MENU then altPressed:= true
     else if (Key = VK_SNAP) or (Key = VK_SNAP2) then snapPressed:= true
     else if Key = VK_SHIFT then shiftPressed:= true;
     if Zoom.EditingZoom or EditingColors then exit;
-    if not ((CurrentTool = ptText) and TextSpinEditFocused and (Key = VK_BACK)) and ToolManager.ToolKeyDown(Key) then
+    if not ((CurrentTool = ptText) and TextSpinEditFocused and (Key = VK_BACK)) and CatchToolKeyDown(Key) then
     begin
-      DelayedPaintPicture := True;
+      PaintPictureLater;
     end else
     if Key = VK_F6 then
     begin
@@ -1980,7 +1791,7 @@ begin
     begin
       spacePressed:= true;
       Key := 0;
-      if not ToolManager.ToolSleeping and not btnLeftDown and not btnRightDown then ToolManager.ToolSleep;
+      if not ToolManager.ToolSleeping and ([ssLeft,ssRight] * FLayout.MouseButtonState = []) then ToolManager.ToolSleep;
     end else
     if LazPaintInstance.ImageListWindowVisible then
       LazPaintInstance.ImageListWindowVisibleKeyDown(Key,Shift);
@@ -2031,7 +1842,7 @@ begin
   Open3DObjectDialog.InitialDir := Config.Default3dObjectDirectory;
   if Open3DObjectDialog.InitialDir = '' then
   begin
-    dir3d := {$IFDEF WINDOWS}SysToUTF8({$ENDIF}ExtractFilePath(Application.ExeName){$IFDEF WINDOWS}){$ENDIF}+'models';
+    dir3d := GetResourcePath('models');
     if DirectoryExistsUTF8(dir3d) then
       Open3DObjectDialog.InitialDir := dir3d;
   end;
@@ -2387,24 +2198,20 @@ begin
   if Key = VK_MENU then altPressed:= false
   else if (Key = VK_SNAP) or (Key = VK_SNAP2) then snapPressed:= false
   else if Key = VK_SHIFT then shiftPressed:= false;
-  if ToolManager.ToolKeyUp(Key) then
+  if CatchToolKeyUp(Key) then
   begin
-    DelayedPaintPicture := True;
+    PaintPictureLater;
   end else
   If Key = VK_SPACE then
   begin
     spacePressed:= false;
-    if ToolManager.ToolSleeping and not spacePressed and not btnRightDown and not btnLeftDown then
+    if ToolManager.ToolSleeping and not spacePressed and
+       ([ssLeft,ssRight] * FLayout.MouseButtonState = []) then
       ToolManager.ToolWakeUp;
     Key := 0;
   end;
 end;
 
-procedure TFMain.FormMouseEnter(Sender: TObject);
-begin
-  Image.PrepareForRendering;
-end;
-
 procedure TFMain.FormUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
 var selectedTool: TPaintToolType;
   toolProcessKey: boolean;
@@ -2417,9 +2224,9 @@ begin
       if TextSpinEditFocused then
          toolProcessKey:= false;
     end;
-    if toolProcessKey and ToolManager.ToolKeyPress(UTF8Key) then
+    if toolProcessKey and CatchToolKeyPress(UTF8Key) then
     begin
-      DelayedPaintPicture := true;
+      PaintPictureLater;
       UpdateToolbar;
     end else
     if UTF8Key <> '' then
@@ -2461,11 +2268,6 @@ begin
   end;
 end;
 
-procedure TFMain.FormMouseLeave(Sender: TObject);
-begin
-  Cursor := crDefault;
-end;
-
 procedure TFMain.FormWindowStateChange(Sender: TObject);
 begin
   {$IFDEF LINUX}
@@ -2633,43 +2435,6 @@ begin
   LazPaintInstance.Donate;
 end;
 
-procedure TFMain.PaintBox_PictureMouseEnter(Sender: TObject);
-begin
-  FormMouseEnter(Sender);
-end;
-
-procedure TFMain.PaintBox_PictureMouseDown(Sender: TObject;
-  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
-begin
-  FormMouseDown(Sender,Button,Shift,X+PaintBox_Picture.Left,Y+PaintBox_Picture.Top);
-end;
-
-procedure TFMain.PaintBox_PictureMouseMove(Sender: TObject; Shift: TShiftState;
-  X, Y: Integer);
-begin
-  FormMouseMove(Sender,Shift,X+PaintBox_Picture.Left,Y+PaintBox_Picture.Top);
-end;
-
-procedure TFMain.PaintBox_PictureMouseUp(Sender: TObject; Button: TMouseButton;
-  Shift: TShiftState; X, Y: Integer);
-begin
-  FormMouseUp(Sender,Button,Shift,X+PaintBox_Picture.Left,Y+PaintBox_Picture.Top);
-end;
-
-procedure TFMain.PaintBox_PictureMouseWheel(Sender: TObject;
-  Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
-  var Handled: Boolean);
-begin
-  FormMouseWheel(Sender,Shift,WheelDelta,Point(MousePos.X+PaintBox_Picture.Left,MousePos.Y+PaintBox_Picture.Top),Handled);
-end;
-
-procedure TFMain.PaintBox_PicturePaint(Sender: TObject);
-begin
-  {$IFDEF USEPAINTBOXPICTURE}
-    OnPaintHandler;
-  {$ENDIF}
-end;
-
 procedure TFMain.FormCloseQuery(Sender: TObject; var CanClose: boolean);
 var topmostInfo: TTopMostInfo;
 begin
@@ -2723,24 +2488,6 @@ begin
   LazPaintInstance.SaveMainWindowPosition;
 end;
 
-procedure TFMain.FormMouseWheel(Sender: TObject; Shift: TShiftState;
-  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
-begin
-  if not Assigned(FImageView) or not FImageView.PictureCoordsDefined then exit;
-  if ssAlt in Shift then
-  begin
-    if WheelDelta > 0 then IncreasePenSize
-    else if WheelDelta < 0 then DecreasePenSize;
-  end else
-  begin
-    Zoom.SetPosition(FImageView.FormToBitmap(MousePos.X,MousePos.Y), MousePos);
-    if WheelDelta > 0 then Zoom.ZoomIn(ssSnap in Shift) else
-    if WheelDelta < 0 then Zoom.ZoomOut(ssSnap in Shift);
-    Zoom.ClearPosition;
-  end;
-  Handled := True;
-end;
-
 procedure TFMain.HelpAboutExecute(Sender: TObject);
 begin
   LazPaintInstance.ShowAboutDlg;
@@ -2835,9 +2582,11 @@ begin
 end;
 
 procedure TFMain.TimerUpdateTimer(Sender: TObject);
-const SelectionPaintDelay = 100/(1000*60*60*24);
 begin
   TimerUpdate.Enabled := false;
+  if ToolManager.ToolSleeping and not spacePressed and
+     ([ssLeft,ssRight,ssMiddle] * FLayout.MouseButtonState = []) then
+    ToolManager.ToolWakeUp;
   EditUndo.Update;
   EditRedo.Update;
   UpdateStatusText;
@@ -2847,22 +2596,7 @@ begin
     Label_Coordinates.Update;
     FCoordinatesCaptionCount := 0;
   end;
-  if CanCompressOrUpdateStack and UpdateStackOnTimer then
-  begin
-    LazPaintInstance.NotifyStackChange;
-    UpdateStackOnTimer := false;
-  end else
-  begin
-    if CanCompressOrUpdateStack then image.CompressUndo;
-  end;
-  if DelayedPaintPicture or ToolManager.ToolUpdateNeeded or
-   (Assigned(FImageView) and not FImageView.ShowSelection and
-    (Now > FLastPaintDate+SelectionPaintDelay) ) then
-  begin
-    if ToolManager.ToolUpdateNeeded then ToolManager.ToolUpdate;
-    if Assigned(FImageView) then FImageView.ShowSelection := true;
-    PaintPictureNow;
-  end;
+  FLayout.CheckDelayedUpdate;
   TimerUpdate.Enabled := true;
 end;
 
@@ -3015,14 +2749,6 @@ begin
   params.Free;
 end;
 
-procedure TFMain.LayoutPictureAreaChange(ASender: TObject; ANewArea: TRect);
-begin
-   {$IFDEF USEPAINTBOXPICTURE}
-   PaintBox_Picture.SetBounds(ANewArea.Left,ANewArea.Top,ANewArea.Right-ANewArea.Left,ANewArea.Bottom-ANewArea.Top);
-   {$ENDIF}
-   if Assigned(FImageView) then FImageView.InvalidatePicture(True, ANewArea, Point(0,0), self);
-end;
-
 procedure TFMain.ToggleGridVisible;
 begin
   LazPaintInstance.GridVisible := not LazPaintInstance.GridVisible;
@@ -3240,8 +2966,7 @@ begin
         ToolManager.ToolMove(texMapBounds.Right-0.5, texMapBounds.Bottom-0.5, 1);
         ToolManager.ToolUp;
       end;
-      if Assigned(FImageView) then
-        FImageView.FillSelectionHighlight := ToolManager.DisplayFilledSelection and not FShowSelectionNormal;
+      FLayout.FillSelectionHighlight := ToolManager.DisplayFilledSelection and not FShowSelectionNormal;
     except
       on ex:Exception do
       begin
@@ -3321,7 +3046,6 @@ begin
 
   if needUpdate then
   begin
-    FImageView.UpdatePicture(PictureCanvasOfs, FLayout.WorkArea, self);
     PaintPictureNow;
     UpdateToolbar;
   end;
@@ -3399,7 +3123,6 @@ begin
 
   if needUpdate then
   begin
-    FImageView.UpdatePicture(PictureCanvasOfs, FLayout.WorkArea, self);
     PaintPictureNow;
     UpdateToolbar;
   end;
@@ -3447,7 +3170,6 @@ begin
     end;
     if needUpdate then
     begin
-      FImageView.UpdatePicture(PictureCanvasOfs, FLayout.WorkArea, self);
       PaintPictureNow;
       UpdateToolbar;
     end;
@@ -3738,6 +3460,8 @@ procedure TFMain.FileRunScriptExecute(Sender: TObject);
 var
   dlg: TOpenDialog;
   tmi: TTopMostInfo;
+  title: String;
+  posSub: Integer;
 begin
   tmi := LazPaintInstance.HideTopmost;
   try
@@ -3750,7 +3474,10 @@ begin
       if dlg.Execute then
       begin
         Config.SetDefaultScriptDirectory(ExtractFilePath(dlg.FileName));
-        LazPaintInstance.RunScript(dlg.FileName);
+        title := GetScriptTitle(dlg.FileName);
+        posSub := title.LastIndexOf('>');
+        if posSub <> -1 then title := title.Substring(posSub+1);
+        LazPaintInstance.RunScript(dlg.FileName, title);
       end;
     except
       on ex:exception do
@@ -3889,7 +3616,7 @@ begin
   ItemViewDockToolbox.Checked := (Layout.ToolBoxDocking <> twWindow) and (Layout.ToolBoxDocking <> twNone);
   ItemDockLayersAndColors.Checked := LazPaintInstance.DockLayersAndColors;
   ItemFullscreen.Checked := LazPaintInstance.Fullscreen;
-  {$IFDEF LINUX}
+  {$IF defined(LINUX) or defined(DARWIN)}
   ItemFullscreen.Visible := false;
   {$ENDIF}
 end;
@@ -3946,30 +3673,6 @@ begin
   end;
 end;
 
-procedure TFMain.ReleaseMouseButtons(Shift: TShiftState);
-begin
-  if not (ssLeft in Shift) and btnLeftDown then
-  begin
-    btnLeftDown := false;
-    if ToolManager.ToolUp then PaintPictureNow;
-  end;
-  if not (ssRight in Shift) and btnRightDown then
-  begin
-    btnRightDown := false;
-    if ToolManager.ToolUp then PaintPictureNow;
-  end;
-  if not (ssMiddle in Shift) and btnMiddleDown then
-  begin
-    btnMiddleDown := false;
-    if ToolManager.ToolUp then PaintPictureNow;
-  end;
-  if not btnLeftDown and not btnRightDown then
-  begin
-    CanCompressOrUpdateStack := true;
-    Image.OnImageChanged.DelayedStackUpdate := False;
-  end;
-end;
-
 procedure TFMain.UpdateSpecialKeys(Shift: TShiftState);
   procedure UpdateKey(AShift: TShiftStateEnum; ACode: Word; var APressed: boolean);
   begin
@@ -4133,9 +3836,8 @@ end;
 
 procedure TFMain.ShowNoPicture;
 begin
-  InShowNoPicture := true;
-  PaintPictureNow;
-  InShowNoPicture:= false;
+  if Assigned(FLayout) then
+    FLayout.ShowNoPicture;
 end;
 
 procedure TFMain.UpdateWindowCaption;
@@ -4369,34 +4071,8 @@ end;
 
 {****************************** Picture ************************}
 
-procedure TFMain.OnPaintHandler;
-var
-  ac: TWinControl;
-begin
-  if FirstPaint then
-  begin
-    LoadToolwindow := True;
-    TimerLoadToolWin.Enabled := true;
-    FirstPaint := false;
-  end;
-  if InFormPaint then exit;
-  InFormPaint := true;
-
-  if Assigned(FImageView) then FImageView.DoPaint(PictureCanvasOfs, FLayout.WorkArea, InShowNoPicture);
-  DelayedPaintPicture:= false;
-
-  ac := ActiveControl;
-  if ac is TBCTrackbarUpdown then
-    TBCTrackbarUpdown(ac).DelayTimer;
-
-  InFormPaint := false;
-  FLastPaintDate := Now;
-end;
-
 procedure TFMain.OnImageChangedHandler(AEvent: TLazPaintImageObservationEvent);
 begin
-  InvalidatePicture(false);
-
   if (image.Width <> FLastWidth) or (image.Height <> FLastHeight)
    or (image.BPP <> FLastBPP) or (image.FrameIndex <> FLastFrameIndex) then
   begin
@@ -4411,7 +4087,6 @@ begin
     ChooseTool(ptHand);
     MessagePopup(rsToolOnInvisibleLayer,5000);
   end;
-  if AEvent.DelayedStackUpdate then FUpdateStackWhenIdle := true;
 end;
 
 procedure TFMain.OnImageRenderChanged(Sender: TObject);
@@ -4423,37 +4098,78 @@ procedure TFMain.UpdateEditPicture(ADelayed: boolean = false);
 begin
   if ToolManager.ToolUpdate then
   begin
-    if ADelayed then DelayedPaintPicture := True
+    if ADelayed then PaintPictureLater
     else
       PaintPictureNow;
   end;
 end;
 
-procedure TFMain.OnZoomChanged(sender: TZoom; ANewZoom: single);
+procedure TFMain.PaintPictureNow;
+begin
+  if not visible then exit;
+  if Assigned(LazPaintInstance) then LazPaintInstance.UpdateStackOnTimer := true;
+  if Assigned(FLayout) then FLayout.PaintPictureNow;
+end;
+
+procedure TFMain.PaintPictureLater;
 begin
-  if Assigned(FImageView) then
+  if Assigned(FLayout) then FLayout.DelayedPaintPicture := True;
+end;
+
+procedure TFMain.NotifyImagePaint;
+begin
+  if Assigned(FLayout) then
+    FLayout.DelayedPaintPicture:= false;
+end;
+
+procedure TFMain.PictureMouseBefore(Sender: TObject; AShift: TShiftState);
+begin
+  UpdateSpecialKeys(AShift);
+end;
+
+procedure TFMain.PictureMouseMove(Sender: TObject; APosition: TPointF);
+begin
+  HidePenPreview;
+  HideFill;
+
+  FCoordinatesCaption := IntToStr(round(APosition.X))+','+IntToStr(round(APosition.Y));
+  Inc(FCoordinatesCaptionCount);
+  if FCoordinatesCaptionCount > 8 then
+  begin
+    FCoordinatesCaptionCount := 0;
+    Label_Coordinates.caption := FCoordinatesCaption;
+    Label_Coordinates.Update;
+    UpdateStatusText;
+  end;
+
+  if LazPaintInstance.TopMostHasFocus then
   begin
-    if not Image.SelectionMaskEmpty then
-      FImageView.ShowSelection := false;
-    FImageView.OnZoomChanged(sender, ANewZoom, FLayout.WorkArea);
+    if LazPaintInstance.TopMostOkToUnfocus then
+      SafeSetFocus(self)
+    else
+      exit;
   end;
-  UpdateToolbar;
-  PaintPictureNow;
+  if (CurrentTool in[ptText,ptEditShape]) and TextSpinEditFocused then VectorialFill_Pen.SetFocus;
 end;
 
-procedure TFMain.PaintPictureNow;
+procedure TFMain.PictureOnPaint(Sender: TObject);
+var
+  ac: TWinControl;
 begin
-  if not visible then exit;
-  UpdateStackOnTimer := true;
-  Image.OnImageChanged.NotifyObservers;
-  {$IFDEF USEPAINTBOXPICTURE}PaintBox_Picture{$ELSE}self{$ENDIF}.Update;
+  if FirstPaint then
+  begin
+    LoadToolwindow := True;
+    TimerLoadToolWin.Enabled := true;
+    FirstPaint := false;
+  end;
+  ac := ActiveControl;
+  if ac is TBCTrackbarUpdown then
+    TBCTrackbarUpdown(ac).DelayTimer;
 end;
 
-procedure TFMain.FormPaint(Sender: TObject);
+procedure TFMain.PictureToolbarUpdate(Sender: TObject);
 begin
-  {$IFNDEF USEPAINTBOXPICTURE}
-  OnPaintHandler;
-  {$ENDIF}
+  UpdateToolbar;
 end;
 
 procedure TFMain.PictureSelectedLayerIndexChanged(sender: TLazPaintImage);
@@ -4475,8 +4191,8 @@ end;
 procedure TFMain.SetShowSelectionNormal(const AValue: boolean);
 begin
   FShowSelectionNormal := AValue;
-  if Assigned(FImageView) then
-    FImageView.FillSelectionHighlight := ToolManager.DisplayFilledSelection and not FShowSelectionNormal;
+  if Assigned(FLayout) then
+    FLayout.FillSelectionHighlight := ToolManager.DisplayFilledSelection and not FShowSelectionNormal;
 end;
 
 procedure TFMain.WMEraseBkgnd(var Message: TLMEraseBkgnd);
@@ -4610,8 +4326,8 @@ end;
 
 procedure TFMain.InvalidatePicture(AInvalidateAll: boolean = true);
 begin
-  if Assigned(FImageView) and Assigned(FLayout) then
-    FImageView.InvalidatePicture(AInvalidateAll, FLayout.WorkArea, Point(0,0), self);
+  if Assigned(FLayout) then
+    FLayout.InvalidatePicture(AInvalidateAll);
 end;
 
 function TFMain.GetUseImageBrowser: boolean;
@@ -4632,15 +4348,8 @@ end;
 
 procedure TFMain.SetUpdatingPopup(AValue: boolean);
 begin
-  FImageView.UpdatingPopup := AValue;
-end;
-
-function TFMain.GetCurrentPressure: single;
-begin
-  if Assigned(FTablet) and FTablet.Present and FTablet.Entering and (FTablet.Max > 0) then
-    result := FTablet.Pressure/FTablet.Max
-  else
-    result := 1;
+  if Assigned(FLayout) then
+    FLayout.UpdatingPopup := AValue;
 end;
 
 function TFMain.GetDarkTheme: boolean;
@@ -4656,7 +4365,9 @@ end;
 
 function TFMain.GetUpdatingPopup: boolean;
 begin
-  result := FImageView.UpdatingPopup;
+  if Assigned(FLayout) then
+    result := FLayout.UpdatingPopup
+    else result := false;
 end;
 
 function TFMain.GetScriptContext: TScriptContext;
@@ -4678,15 +4389,6 @@ begin
   end;
 end;
 
-function TFMain.PictureCanvasOfs: TPoint;
-begin
-  {$IFDEF USEPAINTBOXPICTURE}
-  result := Point(-PaintBox_Picture.Left,-PaintBox_Picture.Top);
-  {$ELSE}
-  result := Point(0,0);
-  {$ENDIF}
-end;
-
 {$R *.lfm}
 
 end.

+ 10 - 2
lazpaint/lazpainttype.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit LazPaintType;
 
 {$mode objfpc}{$H+}
@@ -10,7 +11,7 @@ uses
   {$IFDEF LINUX}, InterfaceBase{$ENDIF};
 
 const
-  LazPaintVersion = 7010300;
+  LazPaintVersion = 7010400;
 
   function LazPaintVersionStr: string;
 
@@ -180,6 +181,9 @@ type
     procedure SetBlackAndWhite(AValue: boolean); virtual;
     function GetZoomFactor: single; virtual;
 
+    function GetUpdateStackOnTimer: boolean; virtual; abstract;
+    procedure SetUpdateStackOnTimer(AValue: boolean); virtual; abstract;
+
     function GetChooseColorHeight: integer; virtual; abstract;
     function GetChooseColorWidth: integer; virtual; abstract;
     procedure SetChooseColorHeight(AValue: integer); virtual; abstract;
@@ -240,10 +244,11 @@ type
     procedure CancelRestart; virtual; abstract;
     procedure NotifyImageChange(RepaintNow: boolean; ARect: TRect); virtual; abstract;
     procedure NotifyImageChangeCompletely(RepaintNow: boolean); virtual; abstract;
+    procedure NotifyImagePaint; virtual; abstract;
     procedure NotifyStackChange; virtual; abstract;
     function TryOpenFileUTF8(filename: string; skipDialogIfSingleImage: boolean = false): boolean; virtual; abstract;
     function ExecuteFilter(filter: TPictureFilter; skipDialog: boolean = false): TScriptResult; virtual; abstract;
-    function RunScript(AFilename: string): boolean; virtual; abstract;
+    function RunScript(AFilename: string; ACaption: string = ''): boolean; virtual; abstract;
     procedure AdjustChooseColorHeight; virtual; abstract;
     procedure ColorFromFChooseColor; virtual; abstract;
     procedure ColorToFChooseColor; virtual; abstract;
@@ -293,6 +298,8 @@ type
     property BlackAndWhite: boolean read FBlackAndWhite write SetBlackAndWhite;
 
     procedure ScrollLayerStackOnItem(AIndex: integer; ADelayedUpdate: boolean = true); virtual; abstract;
+    procedure InvalidateLayerStack; virtual; abstract;
+    procedure UpdateLayerStackOnTimer; virtual; abstract;
     function MakeNewBitmapReplacement(AWidth, AHeight: integer; AColor: TBGRAPixel): TBGRABitmap; virtual; abstract;
     procedure ChooseTool(Tool : TPaintToolType); virtual; abstract;
     function GetOnlineUpdater: TLazPaintCustomOnlineUpdater; virtual;
@@ -339,6 +346,7 @@ type
     property Fullscreen: boolean read GetFullscreen write SetFullscreen;
     property RestartQuery: boolean read FRestartQuery;
     property DarkTheme: boolean read GetDarkTheme write SetDarkTheme;
+    property UpdateStackOnTimer: boolean read GetUpdateStackOnTimer write SetUpdateStackOnTimer;
 
     property Icons[ASize: integer]: TImageList read GetIcons;
   end;

+ 124 - 89
lazpaint/maintoolbar.inc

@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-3.0-only
 procedure TFMain.CreateToolbarElements;
 
   procedure InitVectorialFill(vf: TLCVectorialFillControl; grad: TBGRALayerGradientOriginal;
-      lbl: TLabel; pnl: TPanel; mouseMove: TMouseMoveEvent);
+      lbl: TLabel; pnl: TPanel; mouseMove: TMouseMoveEvent; mouseClick: TNotifyEvent; AIsTarget: boolean);
   begin
     vf.PopupMenu := nil;
     vf.VerticalPadding:= DoScaleY(6, OriginalDPI);
@@ -21,10 +22,15 @@ procedure TFMain.CreateToolbarElements;
       vf.GradRepetition:= Repetition;
       vf.GradInterpolation:= ColorInterpolation;
     end;
-    if Assigned(lbl) then lbl.OnMouseMove:= mouseMove;
+    if Assigned(lbl) then
+    begin
+      lbl.OnMouseMove:= mouseMove;
+      lbl.OnClick:= mouseClick;
+    end;
     pnl.PopupMenu := nil;
     pnl.OnMouseMove:= mouseMove;
     vf.OnMouseMove:= mouseMove;
+    vf.IsTarget:= AIsTarget;
   end;
 
 var
@@ -36,11 +42,17 @@ begin
   Panel_ToolbarBackground.PopupMenu := PopupToolbar;
   Perspective_Repeat.OnClick:=@Perspective_RepeatClick;
   Perspective_TwoPlanes.OnClick := @Perspective_TwoPlanesClick;
-  InitVectorialFill(VectorialFill_Pen, ToolManager.ForeLastGradient, Label_Pen, Panel_PenFill, @VectorialFill_ShowPenFill);
+  InitVectorialFill(VectorialFill_Pen, ToolManager.ForeLastGradient, Label_Pen, Panel_PenFill,
+    @VectorialFill_ShowPenFill, @vectorialFill_ClickLabel,
+    LazPaintInstance.ChooseColorTarget in[ctForeColorSolid..ctForeColorEndGrad]);
   VectorialFill_Pen.SolidColor := ToolManager.ForeColor;
-  InitVectorialFill(VectorialFill_Back, ToolManager.BackLastGradient, Label_Back, Panel_BackFill, @VectorialFill_ShowBackFill);
+  InitVectorialFill(VectorialFill_Back, ToolManager.BackLastGradient, Label_Back, Panel_BackFill,
+    @VectorialFill_ShowBackFill, @vectorialFill_ClickLabel,
+    LazPaintInstance.ChooseColorTarget in[ctBackColorSolid..ctBackColorEndGrad]);
   VectorialFill_Back.SolidColor := ToolManager.BackColor;
-  InitVectorialFill(VectorialFill_Outline, ToolManager.OutlineLastGradient, nil, Panel_OutlineFill, @VectorialFill_ShowOutlineFill);
+  InitVectorialFill(VectorialFill_Outline, ToolManager.OutlineLastGradient, nil, Panel_OutlineFill,
+    @VectorialFill_ShowOutlineFill, @vectorialFill_ClickLabel,
+    LazPaintInstance.ChooseColorTarget in[ctOutlineColorSolid..ctOutlineColorEndGrad]);
   VectorialFill_Outline.SolidColor := ToolManager.OutlineColor;
   Image_SwapColors.OnMouseDown := @Image_SwapColorsMouseDown;
   Tool_DrawShapeBorder.OnClick := @Tool_DrawShapeBorderClick;
@@ -83,6 +95,7 @@ begin
   PaintBox_PenPreview.OnMouseMove := @Panel_PenWidthMouseMove;
   PaintBox_PenPreview.OnMouseDown := @PaintBox_PenPreviewMouseDown;
   PaintBox_PenPreview.OnPaint := @PaintBox_PenPreviewPaint;
+  PaintBox_PenPreview.Align := alClient;
   Tool_PhongShapeRectangle.OnClick := @Tool_PhongShapeRectangleClick;
   Tool_PhongShapeRoundRect.OnClick := @Tool_PhongShapeRoundRectClick;
   Tool_PhongShapeSphere.OnClick := @Tool_PhongShapeSphereClick;
@@ -530,6 +543,7 @@ begin
   prevBackColor := VectorialFill_Back.AverageColor;
   VectorialFill_Pen.AssignFill(ToolManager.ForeFill);
   VectorialFill_Back.AssignFill(ToolManager.BackFill);
+  VectorialFill_Outline.AssignFill(ToolManager.OutlineFill);
   newPenColor := VectorialFill_Pen.AverageColor;
   newBackColor := VectorialFill_Back.AverageColor;
   FInFillChange:= false;
@@ -666,6 +680,27 @@ begin
   FInitialized := oldInit;
 end;
 
+function TFMain.CatchToolKeyDown(var AKey: Word): boolean;
+begin
+  if Assigned(FLayout) then
+    result := FLayout.CatchToolKeyDown(AKey)
+    else result := false;
+end;
+
+function TFMain.CatchToolKeyUp(var AKey: Word): boolean;
+begin
+  if Assigned(FLayout) then
+    result := FLayout.CatchToolKeyUp(AKey)
+    else result := false;
+end;
+
+function TFMain.CatchToolKeyPress(var AKey: TUTF8Char): boolean;
+begin
+  if Assigned(FLayout) then
+    result := FLayout.CatchToolKeyPress(AKey)
+    else result := false;
+end;
+
 procedure TFMain.SpinEdit_ShapeAltitudeChange(Sender: TObject; AByUser: boolean);
 begin
   if SpinEdit_ShapeAltitude.Value < 6 then
@@ -833,54 +868,38 @@ begin
 end;
 
 procedure TFMain.UpdateAllowedFillTypes;
-begin
-  if VectorialFill_Pen.AllowedFillTypes <> ToolManager.AllowedForeFillTypes then
+  procedure UpdateFor(AFillControl: TLCVectorialFillControl; AAllowedFillTypes: TVectorialFillTypes;
+      ANeedGradientProc: TProcedureOfObject);
   begin
-    if not (VectorialFill_Pen.FillType in ToolManager.AllowedForeFillTypes) then
+    if AFillControl.AllowedFillTypes <> AAllowedFillTypes then
     begin
-      if vftGradient in ToolManager.AllowedForeFillTypes then
-      begin
-        VectorialFill_Pen.AllowedFillTypes:= [VectorialFill_Pen.FillType] + ToolManager.AllowedForeFillTypes;
-        ToolManager.NeedForeGradient;
-      end else
-      if vftTexture in ToolManager.AllowedForeFillTypes then
-      begin
-        VectorialFill_Pen.AllowedFillTypes:= [VectorialFill_Pen.FillType] + ToolManager.AllowedForeFillTypes;
-        Vectorialfill_Pen.FillType := vftTexture;
-      end else
-      if vftSolid in ToolManager.AllowedForeFillTypes then
+      if not (AFillControl.FillType in AAllowedFillTypes) then
       begin
-        VectorialFill_Pen.AllowedFillTypes:= [VectorialFill_Pen.FillType] + ToolManager.AllowedForeFillTypes;
-        Vectorialfill_Pen.FillType := vftSolid;
+        if vftGradient in AAllowedFillTypes then
+        begin
+          AFillControl.AllowedFillTypes:= [AFillControl.FillType] + AAllowedFillTypes;
+          ANeedGradientProc();
+        end else
+        if vftTexture in AAllowedFillTypes then
+        begin
+          AFillControl.AllowedFillTypes:= [AFillControl.FillType] + AAllowedFillTypes;
+          AFillControl.FillType := vftTexture;
+        end else
+        if vftSolid in AAllowedFillTypes then
+        begin
+          AFillControl.AllowedFillTypes:= [AFillControl.FillType] + AAllowedFillTypes;
+          AFillControl.FillType := vftSolid;
+        end;
       end;
+      AFillControl.AllowedFillTypes:= AAllowedFillTypes;
+      AFillControl.Width := AFillControl.PreferredSize.cx;
     end;
-    VectorialFill_Pen.AllowedFillTypes:= ToolManager.AllowedForeFillTypes;
-    VectorialFill_Pen.Width := VectorialFill_Pen.PreferredSize.cx;
   end;
 
-  if VectorialFill_Back.AllowedFillTypes <> ToolManager.AllowedBackFillTypes then
-  begin
-    if not (VectorialFill_Back.FillType in ToolManager.AllowedBackFillTypes) then
-    begin
-      if vftGradient in ToolManager.AllowedBackFillTypes then
-      begin
-        VectorialFill_Back.AllowedFillTypes:= [VectorialFill_Back.FillType] + ToolManager.AllowedBackFillTypes;
-        ToolManager.NeedBackGradient;
-      end else
-      if vftTexture in ToolManager.AllowedBackFillTypes then
-      begin
-        VectorialFill_Back.AllowedFillTypes:= [VectorialFill_Back.FillType] + ToolManager.AllowedBackFillTypes;
-        Vectorialfill_Back.FillType := vftTexture;
-      end else
-      if vftSolid in ToolManager.AllowedBackFillTypes then
-      begin
-        VectorialFill_Back.AllowedFillTypes:= [VectorialFill_Back.FillType] + ToolManager.AllowedBackFillTypes;
-        Vectorialfill_Back.FillType := vftSolid;
-      end;
-    end;
-    VectorialFill_Back.AllowedFillTypes:= ToolManager.AllowedBackFillTypes;
-    VectorialFill_Back.Width := VectorialFill_Back.PreferredSize.cx;
-  end;
+begin
+  UpdateFor(VectorialFill_Pen, ToolManager.AllowedForeFillTypes, @ToolManager.NeedForeGradient);
+  UpdateFor(VectorialFill_Back, ToolManager.AllowedBackFillTypes, @ToolManager.NeedBackGradient);
+  UpdateFor(VectorialFill_Outline, ToolManager.AllowedOutlineFillTypes, @ToolManager.NeedOutlineGradient);
 
   Perspective_Repeat.Visible := (CurrentTool = ptLayerMapping);
 end;
@@ -942,6 +961,32 @@ begin
   FInFillChange:= false;
 end;
 
+procedure TFMain.vectorialFill_ClickLabel(Sender: TObject);
+  procedure CheckFor(ALabel: TLabel; ASolid, AStart, AEnd: TColorTarget;
+      AControl: TLCVectorialFillControl);
+  begin
+    if Sender = ALabel then
+    begin
+      if LazPaintInstance.ChooseColorTarget = ASolid then exit;
+      if LazPaintInstance.ChooseColorTarget = AStart then
+        LazPaintInstance.ChooseColorTarget := AEnd
+      else if LazPaintInstance.ChooseColorTarget = AEnd then
+        LazPaintInstance.ChooseColorTarget := AStart
+      else
+        begin
+          case AControl.FillType of
+            vftSolid: LazPaintInstance.ChooseColorTarget:= ASolid;
+            vftGradient: LazPaintInstance.ChooseColorTarget:= AStart;
+          end;
+        end;
+    end;
+  end;
+
+begin
+  CheckFor(Label_Pen, ctForeColorSolid, ctForeColorStartGrad, ctForeColorEndGrad, VectorialFill_Pen);
+  CheckFor(Label_Back, ctBackColorSolid, ctBackColorStartGrad, ctBackColorEndGrad, VectorialFill_Back);
+end;
+
 procedure TFMain.VectorialFill_Resize(Sender: TObject);
 begin
   QueryArrange;
@@ -1520,39 +1565,13 @@ begin
   if SpinEdit_PenWidth.Value < MinPenWidth*PenWidthFactor then SpinEdit_PenWidth.Value := MinPenWidth*PenWidthFactor;
 end;
 
-procedure TFMain.IncreasePenSize;
-begin
-  SpinEdit_PenWidth.Value := max(SpinEdit_PenWidth.Value+PenSizeDelta(1),MinPenWidth*PenWidthFactor);
-  UpdatePenWidthFromSpinEdit;
-end;
-
-procedure TFMain.DecreasePenSize;
-begin
-  SpinEdit_PenWidth.Value := max(SpinEdit_PenWidth.Value-PenSizeDelta(-1),MinPenWidth*PenWidthFactor);
-  UpdatePenWidthFromSpinEdit;
-end;
-
-function TFMain.PenSizeDelta(direction: integer): integer;
-var v: integer;
-begin
-  v := SpinEdit_PenWidth.Value;
-  if direction < 0 then dec(v);
-  if v < 100 then result := 10 else
-  if v < 200 then result := 20 else
-  if v < 500 then result := 50 else
-  if v < 1000 then result := 100 else
-  if v < 2000 then result := 200 else
-  if v < 5000 then result := 500 else
-    result := 1000;
-end;
-
 procedure TFMain.PaintBox_PenPreviewMouseDown(Sender: TObject;
   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 var t: integer;
 begin
-  t := ImageList16.Width;
-  if (X < t) and (Y < t) then DecreasePenSize else
-  if (X >= PaintBox_PenPreview.Width-t) and (Y < t) then IncreasePenSize;
+  t := FPenPlusMinus;
+  if (X < t) and (Y < t) then ToolManager.StepPenSize(True) else
+  if (X >= PaintBox_PenPreview.Width-t) and (Y < t) then ToolManager.StepPenSize(False);
   ShowPenPreview(False);
 end;
 
@@ -1585,17 +1604,22 @@ end;
 
 procedure TFMain.PaintBox_PenPreviewPaint(Sender: TObject);
 var bmp: TBGRABitmap;
-    x,y,t: integer;
+    x,y,t,margin: integer;
     c: TBGRAPixel;
     m: single;
     bi: TLazPaintBrush;
     visualSize: single;
+    scaling: Double;
 begin
-  bmp := TBGRABitmap.Create(PaintBox_PenPreview.Width,PaintBox_PenPreview.Height,Panel_PenWidthPreview.Color);
+  scaling := PaintBox_PenPreview.GetCanvasScaleFactor;
+  bmp := TBGRABitmap.Create(round(PaintBox_PenPreview.Width*scaling),
+    round(PaintBox_PenPreview.Height*scaling), Panel_PenWidthPreview.Color);
+  bmp.ClipRect := rect(1,1,bmp.Width-1,bmp.Height-1);
   if DarkTheme then c := clLightText else c := clBtnText;
-  x := round(PaintBox_PenPreview.Width/2);
-  y := round(PaintBox_PenPreview.Height/2);
+  x := round(bmp.Width/2);
+  y := round(bmp.Height/2);
   if Assigned(Zoom) then visualSize := ToolManager.PenWidth * Zoom.Factor else visualSize := ToolManager.PenWidth;
+  visualSize *= scaling;
   if (CurrentTool in[ptBrush,ptClone]) and (visualSize <= 2*bmp.width) and (visualSize <= 2*bmp.Height) then
   begin
     bi := ToolManager.BrushInfo;
@@ -1607,17 +1631,28 @@ begin
       end;
   end else
     bmp.FillEllipseAntialias(x,y,visualSize/2,visualSize/2,c);
-  t := ImageList16.Width;
+  t := round(ImageList16.Width*scaling);
+  margin := DoScaleX(round(4*scaling),OriginalDPI);
+  FPenPlusMinus := round((t+margin)/scaling);
   m := t/10;
-  x := 0;
-  bmp.EllipseAntialias(x+(t-1)/2,(t-1)/2,t/2-m,t/2-m,BGRABlack,m,BGRAWhite);
-  bmp.DrawLineAntialias(x+m*2.6,(t-1)/2,x+t-1-m*2.6,(t-1)/2,BGRABlack,m);
-  x := bmp.Width-t;
-  bmp.EllipseAntialias(x+(t-1)/2,(t-1)/2,t/2-m,t/2-m,BGRABlack,m,BGRAWhite);
-  bmp.DrawLineAntialias(x+(t-1)/2,m*2.6,x+(t-1)/2,t-1-m*2.6,BGRABlack,m);
-  bmp.DrawLineAntialias(x+m*2.6,(t-1)/2,x+t-1-m*2.6,(t-1)/2,BGRABlack,m);
-
-  bmp.Draw(PaintBox_PenPreview.Canvas,0,0);
+  x := margin;
+  y := margin;
+  bmp.EllipseAntialias(x+(t-1)/2, y+(t-1)/2, t/2-m, t/2-m, BGRABlack,m,BGRAWhite);
+  bmp.DrawLineAntialias(x+m*2.6, y+(t-1)/2, x+t-1-m*2.6, y+(t-1)/2, BGRABlack,m);
+  x := bmp.Width-t-margin;
+  y := margin;
+  bmp.EllipseAntialias(x+(t-1)/2, y+(t-1)/2, t/2-m, t/2-m, BGRABlack,m,BGRAWhite);
+  bmp.DrawLineAntialias(x+(t-1)/2, y+m*2.6, x+(t-1)/2, y+t-1-m*2.6, BGRABlack,m);
+  bmp.DrawLineAntialias(x+m*2.6, y+(t-1)/2, x+t-1-m*2.6, y+(t-1)/2, BGRABlack,m);
+
+  bmp.NoClip;
+  bmp.HorizLine(0,0,bmp.Width-1, ApplyLightnessFast(Panel_PenWidthPreview.Color, 48000));
+  bmp.VertLine(0,0,bmp.Height-1, ApplyLightnessFast(Panel_PenWidthPreview.Color, 48000));
+  bmp.HorizLine(0,bmp.Height-1,bmp.Width-1, ApplyLightnessFast(Panel_PenWidthPreview.Color, 16000));
+  bmp.VertLine(bmp.Width-1,0,bmp.Height-1, ApplyLightnessFast(Panel_PenWidthPreview.Color, 16000));
+
+  bmp.Draw(PaintBox_PenPreview.Canvas,
+    rect(0, 0, PaintBox_PenPreview.Width, PaintBox_PenPreview.Height));
   bmp.Free;
 end;
 

+ 1 - 0
lazpaint/quote.inc

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 function ScriptUnquote(const S: string): string;
 var errors: TInterpretationErrors;
 begin

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

@@ -3174,6 +3174,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "طبقات"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "طبقة"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3144,6 +3144,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Слоеве"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "слой"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3184,6 +3184,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Vrstvy"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Vrstva"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3188,6 +3188,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Ebenen"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Ebene"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3175,6 +3175,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Capas"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Capa"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3163,6 +3163,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Kerrokset"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Kerros"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3185,6 +3185,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Calques"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Calque"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3171,7 +3171,12 @@ msgstr ""
 #: uresourcestrings.rslayers
 msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
-msgstr ""
+msgstr "レイヤー"
+
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "層"
 
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"

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

@@ -3171,6 +3171,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Tissiyin"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Tissi"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3187,6 +3187,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Slaņi"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Slaņim"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3203,6 +3203,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Lagen"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Laag"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3164,6 +3164,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr ""
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr ""
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3189,6 +3189,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Camadas"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Camada"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3168,6 +3168,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Слои"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Слой"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3157,6 +3157,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "Lager"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "Lager"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

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

@@ -3174,6 +3174,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgstr "图层"
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "层"
+
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"

+ 0 - 213
lazpaint/release/changelog

@@ -1,213 +0,0 @@
-lazpaint (6.4.1) stable; urgency=low
-
-  * added brush tool and clone tool
-  * added palette toolbar
-  * docking of toolbox
-  * choice of quality when saving PNG/JPG/BMP files
-  * rain rendering
-  * improved 3d object importation (texture, vertex normals)
-
--- circular <[email protected]>  Sat, 4 Jul 2015 10:29:00 +0100
-
-lazpaint (7.0.1) unstable; urgency=low
-
-  * support for ICO/CUR, GIF frames, SVG, TIFF Lab, LRS and RES containers
-  * improve drawing tool (transformations of shapes)
-  * added zoom layer tool and non-destructive layer transform
-
--- circular <[email protected]>  Fri, 5 Jul 2019 12:49:00 +0100
-
-lazpaint (7.0.2) unstable; urgency=low
-
-  * bug fixes with tools and undo
-  * better drive detection
-  * improvements on layer stack interface
-  * layers can be rasterized and their bounds are shown when transforming them
-  * text tool stable word warp, unicode arabic ligatures and non-spacing marks
-  * polyline/curve tool is now vectorial
-  * faster rendering in draft mode (when editing)
-
--- circular <[email protected]>  Sat, 27 Jul 2019 22:23:00 +0100
-
-lazpaint (7.0.3) unstable; urgency=low
-
-  * (Tools) edit shape tool
-  * copy/paste shape
-  * align shape horizontally/vertically
-  * bring shape to front/send to back
-  * shape count limit
-  * rotation lock on 90 degrees unless Shift is pressed
-  * add wave displacement filter
-  * add aliased mode for eraser
-  * (Interface) selection pen shortcut changed to "O" letter key
-  * fix update on move image
-  * minor toolbar adjustments
-  * less space used by upper toolbar, nicer comboboxes
-  * faster draft gradient rendering
-  * dark theme option
-  * fix undo/redo with originals
-  * (Optimize) optimize selection rendering
-  * less memory usage by selection
-  * update highlight when rotating
-
--- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
-
-lazpaint (7.0.4) unstable; urgency=low
-
-  * adjusting font size for windows
-  * fix screen update on move image
-  * duplicate vector original
-
--- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
-
-lazpaint (7.0.5) stable; urgency=low
-
-  * added convert shape to curve
-  * adjust pixel-centered coordinates
-  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
-  * dutch translation
-  * filling of workarea with maximum zoom
-  * paste vector shape on empty layer
-  * alignment of vector shapes to pixels with CTRL
-  * return key to finish polygon shape
-  * reset counter of popups on "forget dialogs"
-  * fix TIFF loading error on some systems
-
--- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
-
-lazpaint (7.0.6) stable; urgency=low
-
-  * fix merge bitmap layer
-  * fix mouse scroll on MacOS
-  * clipboard image format with transparency
-  * allow undo when creating shape
-  * fix texture panel
-  * merging empty layer simply deletes it
-  * fix layer offset after undoing merge layer
-
--- circular <[email protected]>  Wed, 11 Sep 2019 18:20:00 +0100
-
-lazpaint (7.0.7) stable; urgency=low
-
-  * polygon: clicking first point closes the polygon, holding Shift while inserting new point will align it on segment
-  * rectangular shape: right-clicking on border will rotate/shear the shape as with Alt key  * clipboard image format with transparency
-  * merging vector layers will make a vector layer if possible
-  * merging a vector with a raster layer will convert the latter to a vector shape
-  * transform texture when modifying rectangular shape
-  * select vector shape even if clicking a bit aside
-  * allow Space key when editing text object
-  * update contextual toolbar when selecting shape with edit shape tool
-  * context menu of toolbar in the upper toolbar background
-  * handling case when saving current file that has been renamed/deleted
-  * faster saving of layers with vectors
-  * fix bug with undo of deleted vector layer
-  * fix transform when copying shapes between layers
-  * fix crop layer with layer offset
-  * clear layer when deleting it in shape editor
-  * duplicate entry in GIF or TIFF
-
--- circular <[email protected]>  Wed, 10 Oct 2019 17:37:00 +0100
-
-lazpaint (7.0.8) unstable; urgency=low
-
-  * rendering optimizations to reduce slowdown with big images
-  * read support for Portable Any Map (PBM, PGM, PPM)
-  * read/write support for WebP images using libwebp
-  * read support for RAW images using dcraw
-  * fix loading PDN images
-  * show progress of loading/saving/actions on layered images
-  * scripting in Python
-  * scripts provided: color overlay, drop shadow, split/merge channels...
-  * vectorial tools: gradient and texture fill for vectorial shapes
-  * paste vector shapes within visible bounds
-  * tools: align to pixels when image is not zoomed
-  * tools: grouping of items in toolbar
-  * added polyline and opened curve tool
-  * pen tool: SHIFT click to retrieve color, ALT+wheel to change width
-  * selection pen tool: add antialiasing option
-  * color picker: SHIFT click to retrieve color of flattened image
-  * eraser tool: added lighten, darken and sharpen modes
-  * floodfill tool: makes vector original on an empty layer
-  * edit shape tool: show shape information
-  * polygon tool: highlight hovered point, arrows to move points
-  * palette: indicate last added color in palette
-  * palette: fix scroll bug
-  * color window resizable
-  * color and layer windows dockable to main window
-  * adjust more windows to system DPI
-  * adjust curves: show source histograms
-  * filter function: optimize, add Lab colorspace, add min/max/avg
-  * blend operations: add Saturation (HSL) and Mask blend operation
-  * added Kabyle language
-  * updated Swedish translation
-  * fixes for image browser
-  * command line: parenthesis optional to make it Linux-friendly 
-
--- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
-
-lazpaint (7.0.9) unstable; urgency=low
-
-  * interface: less flickering during action progress
-  * interface: minor scaling improvements
-  * interface: ensure toolwindows in front when restoring app
-  * interface: dark theme for status bar
-  * interface: add Donate tool button
-  * interface: add Python download button if missing
-  * interface: separate color for background and outline
-  * interface: don't undock windows when going fullscreen
-  * interface: fix remember save file extension
-  * translation: added Latvian
-  * translation: completed Kabyle and Bulgarian
-  * tool: fix updating transparent colors
-  * tool: fix release of middle mouse button
-  * tool: optimize layer transform
-  * tool: added font aliasing option
-  * tool: replace layer by gradient if it is opaque
-  * tool: floodfill using vector if possible
-  * tool: fix gradient undo/redo
-  * tool: multiselection of shapes
-  * tool: fix text editor handling of keys
-  * script: sort in menus
-  * script: added inner shadow/light
-  * script: added version function
-
--- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
-
-lazpaint (7.1) stable; urgency=low
-
-  * tool: fix update of pen style from shape
-  * interface: fix file extension mask when opening image browser
-  * interface: fix selection of file after changing folder
-  * interface: show progress when changing canvas size
-  * interface: show popup when downsampling opened big image
-  * interface: fix update of popup on Windows
-  * interface: allow to select outside color circle of color window
-  * interface: added shortcuts / and * to shrink and use original zoom
-
--- circular <[email protected]>  Fri, 10 Apr 2020 12:07:00 +0100
-
-lazpaint (7.1.2) stable; urgency=low
-
-  * installer: add scripts on Windows
-  * installer: add new extensions on Windows (oXo, cur, jpeg, tif, tga, webp, xpm)
-  * rendering: phong shape undo
-  * rendering: vector layer with selection and transform
-  * rendering: add font kerning for text shape
-  * file browser: load thumbnails in separate thread to prevent freeze
-  * file browser: generate less file extensions to avoid slowdown
-  * crash fixes: skip when matrix transform is invalid
-  * crash fixes: catch tablet initialization error
-
--- circular <[email protected]>  Fri, 24 Apr 2020 14:19:00 +0100
-
-lazpaint (7.1.3) stable; urgency=low
-
-  * clipboard: fix pasting image in 24-bit with transparent color
-  * selection mask: Fix undo of complex selection mask
-  * text tool: better handling of character groups
-  * curve tool: assign line cap, fix bounds for square cap
-  * interface: fix context menu on fill controls
-  * translation: update Czech translation
-
--- circular <[email protected]>  Thu, 14 May 2020 11:28:00 +0100
-

+ 3 - 3
lazpaint/release/debian/linux32/usr/share/applications/lazpaint.desktop → lazpaint/release/debian/applications/lazpaint.desktop

@@ -3,9 +3,9 @@ Encoding=UTF-8
 Name=LazPaint
 Name[fr]=LazPaint
 Comment=LazPaint
-¢omment[fr]=LazPaint
-Icon=/usr/share/pixmaps/lazpaint.png
-Exec=/usr/share/lazpaint/lazpaint
+Comment[fr]=LazPaint
+Icon=lazpaint
+Exec=lazpaint
 Terminal=false
 Type=Application
 Categories=Graphics

+ 184 - 152
lazpaint/release/debian/linux64/DEBIAN/changelog → lazpaint/release/debian/debian/changelog

@@ -1,112 +1,100 @@
-lazpaint (6.4.1) stable; urgency=low
-
-  * added brush tool and clone tool
-  * added palette toolbar
-  * docking of toolbox
-  * choice of quality when saving PNG/JPG/BMP files
-  * rain rendering
-  * improved 3d object importation (texture, vertex normals)
-
--- circular <[email protected]>  Sat, 4 Jul 2015 10:29:00 +0100
-
-lazpaint (7.0.1) unstable; urgency=low
-
-  * support for ICO/CUR, GIF frames, SVG, TIFF Lab, LRS and RES containers
-  * improve drawing tool (transformations of shapes)
-  * added zoom layer tool and non-destructive layer transform
-
--- circular <[email protected]>  Fri, 5 Jul 2019 12:49:00 +0100
-
-lazpaint (7.0.2) unstable; urgency=low
-
-  * bug fixes with tools and undo
-  * better drive detection
-  * improvements on layer stack interface
-  * layers can be rasterized and their bounds are shown when transforming them
-  * text tool stable word warp, unicode arabic ligatures and non-spacing marks
-  * polyline/curve tool is now vectorial
-  * faster rendering in draft mode (when editing)
-
--- circular <[email protected]>  Sat, 27 Jul 2019 22:23:00 +0100
-
-lazpaint (7.0.3) unstable; urgency=low
-
-  * (Tools) edit shape tool
-  * copy/paste shape
-  * align shape horizontally/vertically
-  * bring shape to front/send to back
-  * shape count limit
-  * rotation lock on 90 degrees unless Shift is pressed
-  * add wave displacement filter
-  * add aliased mode for eraser
-  * (Interface) selection pen shortcut changed to "O" letter key
-  * fix update on move image
-  * minor toolbar adjustments
-  * less space used by upper toolbar, nicer comboboxes
-  * faster draft gradient rendering
-  * dark theme option
-  * fix undo/redo with originals
-  * (Optimize) optimize selection rendering
-  * less memory usage by selection
-  * update highlight when rotating
-
--- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
+lazpaint (7.1.4) stable; urgency=low
+
+  * add --help command line
+  * fix potential crashes
+  * minor interface fixes
+  * fix outline fill update
+  * catch loading errors of layer originals
+  * macOS: fix multiselection
+  * macOS: handle retina display
+  * macOS: optimize tools rendering
+  * macOS: remove fullscreen menu (can be done with OS window menu)
+  * tools: draw editor outside of image
+  * choose color: display target name, highlight fill preview
+  * palette: using CTRL to select gradient colors
+  * raster selection: fix update area
+  * clone tool: don't exit when changing layer
+  * clone tool: shift-click to clone from flattened image
+  * hand tool / edit shape tool: select non empty layer with shift-click
+  * magic wand: implement progressive option
+  * deformation grid: fix bug when changing grid size
+  * text tool: optimize multiline text
+  * print: show message and count
+  * print: don't print empty image
+  * curve adjustments: keep within limits when adding points
+  * curve adjustments: fix toolbar position
+  * gradient: don't link when duplicating layer
+  * multiselection: remove hitboxes to allow selecting within
+  * refactoring of debian package
+  * translations of scripts
+
+ -- circular <[email protected]>  Mon, 28 Sep 2020 10:35:00 +0100
 
-lazpaint (7.0.4) unstable; urgency=low
+lazpaint (7.1.3) stable; urgency=low
 
-  * adjusting font size for windows
-  * fix screen update on move image
-  * duplicate vector original
+  * clipboard: fix pasting image in 24-bit with transparent color
+  * selection mask: Fix undo of complex selection mask
+  * text tool: better handling of character groups
+  * curve tool: assign line cap, fix bounds for square cap
+  * interface: fix context menu on fill controls
+  * translation: update Czech translation
 
--- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
+ -- circular <[email protected]>  Thu, 14 May 2020 11:28:00 +0100
 
-lazpaint (7.0.5) stable; urgency=low
+lazpaint (7.1.2) stable; urgency=low
 
-  * added convert shape to curve
-  * adjust pixel-centered coordinates
-  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
-  * dutch translation
-  * filling of workarea with maximum zoom
-  * paste vector shape on empty layer
-  * alignment of vector shapes to pixels with CTRL
-  * return key to finish polygon shape
-  * reset counter of popups on "forget dialogs"
-  * fix TIFF loading error on some systems
+  * installer: add scripts on Windows
+  * installer: add new extensions on Windows (oXo, cur, jpeg, tif, tga, webp, xpm)
+  * rendering: phong shape undo
+  * rendering: vector layer with selection and transform
+  * rendering: add font kerning for text shape
+  * file browser: load thumbnails in separate thread to prevent freeze
+  * file browser: generate less file extensions to avoid slowdown
+  * crash fixes: skip when matrix transform is invalid
+  * crash fixes: catch tablet initialization error
 
--- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
+ -- circular <[email protected]>  Fri, 24 Apr 2020 14:19:00 +0100
 
-lazpaint (7.0.6) stable; urgency=low
+lazpaint (7.1) stable; urgency=low
 
-  * fix merge bitmap layer
-  * fix mouse scroll on MacOS
-  * clipboard image format with transparency
-  * allow undo when creating shape
-  * fix texture panel
-  * merging empty layer simply deletes it
-  * fix layer offset after undoing merge layer
+  * tool: fix update of pen style from shape
+  * interface: fix file extension mask when opening image browser
+  * interface: fix selection of file after changing folder
+  * interface: show progress when changing canvas size
+  * interface: show popup when downsampling opened big image
+  * interface: fix update of popup on Windows
+  * interface: allow to select outside color circle of color window
+  * interface: added shortcuts / and * to shrink and use original zoom
 
--- circular <[email protected]>  Wed, 11 Sep 2019 18:20:00 +0100
+ -- circular <[email protected]>  Fri, 10 Apr 2020 12:07:00 +0100
 
-lazpaint (7.0.7) stable; urgency=low
+lazpaint (7.0.9) unstable; urgency=low
 
-  * polygon: clicking first point closes the polygon, holding Shift while inserting new point will align it on segment
-  * rectangular shape: right-clicking on border will rotate/shear the shape as with Alt key  * clipboard image format with transparency
-  * merging vector layers will make a vector layer if possible
-  * merging a vector with a raster layer will convert the latter to a vector shape
-  * transform texture when modifying rectangular shape
-  * select vector shape even if clicking a bit aside
-  * allow Space key when editing text object
-  * update contextual toolbar when selecting shape with edit shape tool
-  * context menu of toolbar in the upper toolbar background
-  * handling case when saving current file that has been renamed/deleted
-  * faster saving of layers with vectors
-  * fix bug with undo of deleted vector layer
-  * fix transform when copying shapes between layers
-  * fix crop layer with layer offset
-  * clear layer when deleting it in shape editor
-  * duplicate entry in GIF or TIFF
+  * interface: less flickering during action progress
+  * interface: minor scaling improvements
+  * interface: ensure toolwindows in front when restoring app
+  * interface: dark theme for status bar
+  * interface: add Donate tool button
+  * interface: add Python download button if missing
+  * interface: separate color for background and outline
+  * interface: don't undock windows when going fullscreen
+  * interface: fix remember save file extension
+  * translation: added Latvian
+  * translation: completed Kabyle and Bulgarian
+  * tool: fix updating transparent colors
+  * tool: fix release of middle mouse button
+  * tool: optimize layer transform
+  * tool: added font aliasing option
+  * tool: replace layer by gradient if it is opaque
+  * tool: floodfill using vector if possible
+  * tool: fix gradient undo/redo
+  * tool: multiselection of shapes
+  * tool: fix text editor handling of keys
+  * script: sort in menus
+  * script: added inner shadow/light
+  * script: added version function
 
--- circular <[email protected]>  Wed, 10 Oct 2019 17:37:00 +0100
+ -- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
 
 lazpaint (7.0.8) unstable; urgency=low
 
@@ -143,71 +131,115 @@ lazpaint (7.0.8) unstable; urgency=low
   * fixes for image browser
   * command line: parenthesis optional to make it Linux-friendly 
 
--- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
+ -- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
 
-lazpaint (7.0.9) unstable; urgency=low
+lazpaint (7.0.7) stable; urgency=low
 
-  * interface: less flickering during action progress
-  * interface: minor scaling improvements
-  * interface: ensure toolwindows in front when restoring app
-  * interface: dark theme for status bar
-  * interface: add Donate tool button
-  * interface: add Python download button if missing
-  * interface: separate color for background and outline
-  * interface: don't undock windows when going fullscreen
-  * interface: fix remember save file extension
-  * translation: added Latvian
-  * translation: completed Kabyle and Bulgarian
-  * tool: fix updating transparent colors
-  * tool: fix release of middle mouse button
-  * tool: optimize layer transform
-  * tool: added font aliasing option
-  * tool: replace layer by gradient if it is opaque
-  * tool: floodfill using vector if possible
-  * tool: fix gradient undo/redo
-  * tool: multiselection of shapes
-  * tool: fix text editor handling of keys
-  * script: sort in menus
-  * script: added inner shadow/light
-  * script: added version function
+  * polygon: clicking first point closes the polygon, holding Shift while inserting new point will align it on segment
+  * rectangular shape: right-clicking on border will rotate/shear the shape as with Alt key  * clipboard image format with transparency
+  * merging vector layers will make a vector layer if possible
+  * merging a vector with a raster layer will convert the latter to a vector shape
+  * transform texture when modifying rectangular shape
+  * select vector shape even if clicking a bit aside
+  * allow Space key when editing text object
+  * update contextual toolbar when selecting shape with edit shape tool
+  * context menu of toolbar in the upper toolbar background
+  * handling case when saving current file that has been renamed/deleted
+  * faster saving of layers with vectors
+  * fix bug with undo of deleted vector layer
+  * fix transform when copying shapes between layers
+  * fix crop layer with layer offset
+  * clear layer when deleting it in shape editor
+  * duplicate entry in GIF or TIFF
 
--- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
+ -- circular <[email protected]>  Wed, 10 Oct 2019 17:37:00 +0100
 
-lazpaint (7.1) stable; urgency=low
+lazpaint (7.0.6) stable; urgency=low
 
-  * tool: fix update of pen style from shape
-  * interface: fix file extension mask when opening image browser
-  * interface: fix selection of file after changing folder
-  * interface: show progress when changing canvas size
-  * interface: show popup when downsampling opened big image
-  * interface: fix update of popup on Windows
-  * interface: allow to select outside color circle of color window
-  * interface: added shortcuts / and * to shrink and use original zoom
+  * fix merge bitmap layer
+  * fix mouse scroll on MacOS
+  * clipboard image format with transparency
+  * allow undo when creating shape
+  * fix texture panel
+  * merging empty layer simply deletes it
+  * fix layer offset after undoing merge layer
 
--- circular <[email protected]>  Fri, 10 Apr 2020 12:07:00 +0100
+ -- circular <[email protected]>  Wed, 11 Sep 2019 18:20:00 +0100
 
-lazpaint (7.1.2) stable; urgency=low
+lazpaint (7.0.5) stable; urgency=low
 
-  * installer: add scripts on Windows
-  * installer: add new extensions on Windows (oXo, cur, jpeg, tif, tga, webp, xpm)
-  * rendering: phong shape undo
-  * rendering: vector layer with selection and transform
-  * rendering: add font kerning for text shape
-  * file browser: load thumbnails in separate thread to prevent freeze
-  * file browser: generate less file extensions to avoid slowdown
-  * crash fixes: skip when matrix transform is invalid
-  * crash fixes: catch tablet initialization error
+  * added convert shape to curve
+  * adjust pixel-centered coordinates
+  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
+  * dutch translation
+  * filling of workarea with maximum zoom
+  * paste vector shape on empty layer
+  * alignment of vector shapes to pixels with CTRL
+  * return key to finish polygon shape
+  * reset counter of popups on "forget dialogs"
+  * fix TIFF loading error on some systems
 
--- circular <[email protected]>  Fri, 24 Apr 2020 14:19:00 +0100
+ -- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
 
-lazpaint (7.1.3) stable; urgency=low
+lazpaint (7.0.4) unstable; urgency=low
 
-  * clipboard: fix pasting image in 24-bit with transparent color
-  * selection mask: Fix undo of complex selection mask
-  * text tool: better handling of character groups
-  * curve tool: assign line cap, fix bounds for square cap
-  * interface: fix context menu on fill controls
-  * translation: update Czech translation
+  * adjusting font size for windows
+  * fix screen update on move image
+  * duplicate vector original
+
+ -- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
+
+lazpaint (7.0.3) unstable; urgency=low
+
+  * (Tools) edit shape tool
+  * copy/paste shape
+  * align shape horizontally/vertically
+  * bring shape to front/send to back
+  * shape count limit
+  * rotation lock on 90 degrees unless Shift is pressed
+  * add wave displacement filter
+  * add aliased mode for eraser
+  * (Interface) selection pen shortcut changed to "O" letter key
+  * fix update on move image
+  * minor toolbar adjustments
+  * less space used by upper toolbar, nicer comboboxes
+  * faster draft gradient rendering
+  * dark theme option
+  * fix undo/redo with originals
+  * (Optimize) optimize selection rendering
+  * less memory usage by selection
+  * update highlight when rotating
+
+ -- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
+
+lazpaint (7.0.2) unstable; urgency=low
+
+  * bug fixes with tools and undo
+  * better drive detection
+  * improvements on layer stack interface
+  * layers can be rasterized and their bounds are shown when transforming them
+  * text tool stable word warp, unicode arabic ligatures and non-spacing marks
+  * polyline/curve tool is now vectorial
+  * faster rendering in draft mode (when editing)
+
+ -- circular <[email protected]>  Sat, 27 Jul 2019 22:23:00 +0100
+
+lazpaint (7.0.1) unstable; urgency=low
+
+  * support for ICO/CUR, GIF frames, SVG, TIFF Lab, LRS and RES containers
+  * improve drawing tool (transformations of shapes)
+  * added zoom layer tool and non-destructive layer transform
+
+ -- circular <[email protected]>  Fri, 5 Jul 2019 12:49:00 +0100
+
+lazpaint (6.4.1) stable; urgency=low
+
+  * added brush tool and clone tool
+  * added palette toolbar
+  * docking of toolbox
+  * choice of quality when saving PNG/JPG/BMP files
+  * rain rendering
+  * improved 3d object importation (texture, vertex normals)
 
--- circular <[email protected]>  Thu, 14 May 2020 11:28:00 +0100
+ -- circular <[email protected]>  Sat, 4 Jul 2015 10:29:00 +0100
 

+ 15 - 0
lazpaint/release/debian/debian/control

@@ -0,0 +1,15 @@
+Source: lazpaint
+Section: graphics
+Priority: optional
+Maintainer: circular <[email protected]>
+Build-Depends: lazarus-project (>= 2.0.2), dpkg-dev (>= 7)
+Homepage: https://wiki.freepascal.org/LazPaint
+Package: lazpaint
+Architecture: any
+Version: 7.1.4
+Depends: ${shlibs:Depends}
+Description: Graphics viewer and editor. 
+ Can read layered files (lzp, ora, pdn, oXo), multi-images (gif, ico, tiff), 
+ flat files (bmp, jpeg, pcx, png, tga, xpm, xwd), vectorial (svg), 3D (obj).
+ Has drawing tools, phong shading, curve adjustments,
+ filters and render some textures.

+ 0 - 0
lazpaint/release/debian/linux32/DEBIAN/copyright → lazpaint/release/debian/debian/copyright


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

@@ -1,213 +0,0 @@
-lazpaint (6.4.1) stable; urgency=low
-
-  * added brush tool and clone tool
-  * added palette toolbar
-  * docking of toolbox
-  * choice of quality when saving PNG/JPG/BMP files
-  * rain rendering
-  * improved 3d object importation (texture, vertex normals)
-
--- circular <[email protected]>  Sat, 4 Jul 2015 10:29:00 +0100
-
-lazpaint (7.0.1) unstable; urgency=low
-
-  * support for ICO/CUR, GIF frames, SVG, TIFF Lab, LRS and RES containers
-  * improve drawing tool (transformations of shapes)
-  * added zoom layer tool and non-destructive layer transform
-
--- circular <[email protected]>  Fri, 5 Jul 2019 12:49:00 +0100
-
-lazpaint (7.0.2) unstable; urgency=low
-
-  * bug fixes with tools and undo
-  * better drive detection
-  * improvements on layer stack interface
-  * layers can be rasterized and their bounds are shown when transforming them
-  * text tool stable word warp, unicode arabic ligatures and non-spacing marks
-  * polyline/curve tool is now vectorial
-  * faster rendering in draft mode (when editing)
-
--- circular <[email protected]>  Sat, 27 Jul 2019 22:23:00 +0100
-
-lazpaint (7.0.3) unstable; urgency=low
-
-  * (Tools) edit shape tool
-  * copy/paste shape
-  * align shape horizontally/vertically
-  * bring shape to front/send to back
-  * shape count limit
-  * rotation lock on 90 degrees unless Shift is pressed
-  * add wave displacement filter
-  * add aliased mode for eraser
-  * (Interface) selection pen shortcut changed to "O" letter key
-  * fix update on move image
-  * minor toolbar adjustments
-  * less space used by upper toolbar, nicer comboboxes
-  * faster draft gradient rendering
-  * dark theme option
-  * fix undo/redo with originals
-  * (Optimize) optimize selection rendering
-  * less memory usage by selection
-  * update highlight when rotating
-
--- circular <[email protected]>  Sat, 17 Aug 2019 12:16:00 +0100
-
-lazpaint (7.0.4) unstable; urgency=low
-
-  * adjusting font size for windows
-  * fix screen update on move image
-  * duplicate vector original
-
--- circular <[email protected]>  Sun, 18 Aug 2019 22:07:00 +0100
-
-lazpaint (7.0.5) stable; urgency=low
-
-  * added convert shape to curve
-  * adjust pixel-centered coordinates
-  * shortcuts for colorpicker is "C", for curve move point "Z", for curve insert point "I" as well of Insert
-  * dutch translation
-  * filling of workarea with maximum zoom
-  * paste vector shape on empty layer
-  * alignment of vector shapes to pixels with CTRL
-  * return key to finish polygon shape
-  * reset counter of popups on "forget dialogs"
-  * fix TIFF loading error on some systems
-
--- circular <[email protected]>  Sun, 24 Aug 2019 11:46:00 +0100
-
-lazpaint (7.0.6) stable; urgency=low
-
-  * fix merge bitmap layer
-  * fix mouse scroll on MacOS
-  * clipboard image format with transparency
-  * allow undo when creating shape
-  * fix texture panel
-  * merging empty layer simply deletes it
-  * fix layer offset after undoing merge layer
-
--- circular <[email protected]>  Wed, 11 Sep 2019 18:20:00 +0100
-
-lazpaint (7.0.7) stable; urgency=low
-
-  * polygon: clicking first point closes the polygon, holding Shift while inserting new point will align it on segment
-  * rectangular shape: right-clicking on border will rotate/shear the shape as with Alt key  * clipboard image format with transparency
-  * merging vector layers will make a vector layer if possible
-  * merging a vector with a raster layer will convert the latter to a vector shape
-  * transform texture when modifying rectangular shape
-  * select vector shape even if clicking a bit aside
-  * allow Space key when editing text object
-  * update contextual toolbar when selecting shape with edit shape tool
-  * context menu of toolbar in the upper toolbar background
-  * handling case when saving current file that has been renamed/deleted
-  * faster saving of layers with vectors
-  * fix bug with undo of deleted vector layer
-  * fix transform when copying shapes between layers
-  * fix crop layer with layer offset
-  * clear layer when deleting it in shape editor
-  * duplicate entry in GIF or TIFF
-
--- circular <[email protected]>  Wed, 10 Oct 2019 17:37:00 +0100
-
-lazpaint (7.0.8) unstable; urgency=low
-
-  * rendering optimizations to reduce slowdown with big images
-  * read support for Portable Any Map (PBM, PGM, PPM)
-  * read/write support for WebP images using libwebp
-  * read support for RAW images using dcraw
-  * fix loading PDN images
-  * show progress of loading/saving/actions on layered images
-  * scripting in Python
-  * scripts provided: color overlay, drop shadow, split/merge channels...
-  * vectorial tools: gradient and texture fill for vectorial shapes
-  * paste vector shapes within visible bounds
-  * tools: align to pixels when image is not zoomed
-  * tools: grouping of items in toolbar
-  * added polyline and opened curve tool
-  * pen tool: SHIFT click to retrieve color, ALT+wheel to change width
-  * selection pen tool: add antialiasing option
-  * color picker: SHIFT click to retrieve color of flattened image
-  * eraser tool: added lighten, darken and sharpen modes
-  * floodfill tool: makes vector original on an empty layer
-  * edit shape tool: show shape information
-  * polygon tool: highlight hovered point, arrows to move points
-  * palette: indicate last added color in palette
-  * palette: fix scroll bug
-  * color window resizable
-  * color and layer windows dockable to main window
-  * adjust more windows to system DPI
-  * adjust curves: show source histograms
-  * filter function: optimize, add Lab colorspace, add min/max/avg
-  * blend operations: add Saturation (HSL) and Mask blend operation
-  * added Kabyle language
-  * updated Swedish translation
-  * fixes for image browser
-  * command line: parenthesis optional to make it Linux-friendly 
-
--- circular <[email protected]>  Fri, 6 Mar 2020 18:32:00 +0100
-
-lazpaint (7.0.9) unstable; urgency=low
-
-  * interface: less flickering during action progress
-  * interface: minor scaling improvements
-  * interface: ensure toolwindows in front when restoring app
-  * interface: dark theme for status bar
-  * interface: add Donate tool button
-  * interface: add Python download button if missing
-  * interface: separate color for background and outline
-  * interface: don't undock windows when going fullscreen
-  * interface: fix remember save file extension
-  * translation: added Latvian
-  * translation: completed Kabyle and Bulgarian
-  * tool: fix updating transparent colors
-  * tool: fix release of middle mouse button
-  * tool: optimize layer transform
-  * tool: added font aliasing option
-  * tool: replace layer by gradient if it is opaque
-  * tool: floodfill using vector if possible
-  * tool: fix gradient undo/redo
-  * tool: multiselection of shapes
-  * tool: fix text editor handling of keys
-  * script: sort in menus
-  * script: added inner shadow/light
-  * script: added version function
-
--- circular <[email protected]>  Fri, 3 Apr 2020 12:40:00 +0100
-
-lazpaint (7.1) stable; urgency=low
-
-  * tool: fix update of pen style from shape
-  * interface: fix file extension mask when opening image browser
-  * interface: fix selection of file after changing folder
-  * interface: show progress when changing canvas size
-  * interface: show popup when downsampling opened big image
-  * interface: fix update of popup on Windows
-  * interface: allow to select outside color circle of color window
-  * interface: added shortcuts / and * to shrink and use original zoom
-
--- circular <[email protected]>  Fri, 10 Apr 2020 12:07:00 +0100
-
-lazpaint (7.1.2) stable; urgency=low
-
-  * installer: add scripts on Windows
-  * installer: add new extensions on Windows (oXo, cur, jpeg, tif, tga, webp, xpm)
-  * rendering: phong shape undo
-  * rendering: vector layer with selection and transform
-  * rendering: add font kerning for text shape
-  * file browser: load thumbnails in separate thread to prevent freeze
-  * file browser: generate less file extensions to avoid slowdown
-  * crash fixes: skip when matrix transform is invalid
-  * crash fixes: catch tablet initialization error
-
--- circular <[email protected]>  Fri, 24 Apr 2020 14:19:00 +0100
-
-lazpaint (7.1.3) stable; urgency=low
-
-  * clipboard: fix pasting image in 24-bit with transparent color
-  * selection mask: Fix undo of complex selection mask
-  * text tool: better handling of character groups
-  * curve tool: assign line cap, fix bounds for square cap
-  * interface: fix context menu on fill controls
-  * translation: update Czech translation
-
--- circular <[email protected]>  Thu, 14 May 2020 11:28:00 +0100
-

+ 0 - 12
lazpaint/release/debian/linux32/DEBIAN/control

@@ -1,12 +0,0 @@
-Package: lazpaint
-Version: 7.1.3
-Section: base
-Priority: optional
-Architecture: i386
-Depends: 
-Maintainer: circular <[email protected]>
-Homepage: https://wiki.freepascal.org/LazPaint
-Description: LazPaint
- Graphics viewer and editor.
- Can read layered files (lzp, ora, pdn, oXo), multi-images (gif, ico, tiff), flat files (bmp, jpeg, pcx, png, tga, xpm, xwd), vectorial (svg), 3D (obj)
- Has drawing tools, phong shading, curve adjustments, filters and render some textures.

+ 0 - 6
lazpaint/release/debian/linux32/usr/bin/lazpaint

@@ -1,6 +0,0 @@
-#!/bin/bash
-# launcher for lazpaint by Bruno 2015-06-04
-
-cd /usr/share/lazpaint
-
-./lazpaint "$@"

+ 0 - 0
lazpaint/release/debian/linux32/usr/share/lazpaint/delete.me


BIN=BIN
lazpaint/release/debian/linux32/usr/share/pixmaps/lazpaint.png


+ 0 - 12
lazpaint/release/debian/linux64/DEBIAN/control

@@ -1,12 +0,0 @@
-Package: lazpaint
-Version: 7.1.3
-Section: base
-Priority: optional
-Architecture: amd64
-Depends: 
-Maintainer: circular <[email protected]>
-Homepage: https://wiki.freepascal.org/LazPaint
-Description: LazPaint
- Graphics viewer and editor.
- Can read layered files (lzp, ora, pdn, oXo), multi-images (gif, ico, tiff), flat files (bmp, jpeg, pcx, png, tga, xpm, xwd), vectorial (svg), 3D (obj)
- Has drawing tools, phong shading, curve adjustments, filters and render some textures.

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

@@ -1,28 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: lazpaint
-Upstream-Contact: circular <[email protected]>
-Source: https://github.com/bgrabitmap/lazpaint/releases
-
-Files: *
-Copyright: 2011-2019 circular <[email protected]>
-License: GPL-3+
-
-License: GPL-3+
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version. 
- .
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- .
- On Debian systems, the full text of the GNU General Public
- License version 3 can be found in the file
- '/usr/share/common-licenses/GPL-3'.
-

+ 0 - 6
lazpaint/release/debian/linux64/usr/bin/lazpaint

@@ -1,6 +0,0 @@
-#!/bin/bash
-# launcher for lazpaint by Bruno 2015-06-04
-
-cd /usr/share/lazpaint
-
-./lazpaint "$@"

+ 0 - 12
lazpaint/release/debian/linux64/usr/share/applications/lazpaint.desktop

@@ -1,12 +0,0 @@
-[Desktop Entry]
-Encoding=UTF-8
-Name=LazPaint
-Name[fr]=LazPaint
-Comment=LazPaint
-¢omment[fr]=LazPaint
-Icon=/usr/share/pixmaps/lazpaint.png
-Exec=/usr/share/lazpaint/lazpaint
-Terminal=false
-Type=Application
-Categories=Graphics
-GenericName=LazPaint

+ 0 - 0
lazpaint/release/debian/linux64/usr/share/lazpaint/delete.me


+ 52 - 30
lazpaint/release/debian/makedeb.sh

@@ -1,46 +1,68 @@
 #!/bin/bash
-STAGING_DIR="./staging"
-BIN_DIR="${STAGING_DIR}/usr/share/lazpaint"
-SCRIPT_DIR="${BIN_DIR}/scripts"
-SOURCE_SCRIPT_DIR="../../../scripts"
+STAGING_RELATIVEDIR="./staging"
+STAGING_DIR=$(readlink --canonicalize "${STAGING_RELATIVEDIR}")
+USER_DIR="${STAGING_DIR}/usr"
+BIN_DIR="${USER_DIR}/bin"
+SHARE_DIR="${USER_DIR}/share"
+RESOURCE_DIR="${SHARE_DIR}/lazpaint"
+DOC_PARENT_DIR="${SHARE_DIR}/doc"
+DOC_DIR="${DOC_PARENT_DIR}/lazpaint"
 SOURCE_BIN="../bin"
+TARGET_ARCHITECTURE="$(dpkg --print-architecture)"
+VERSION="$(sed -n 's/^Version: //p' debian/control)"
 
-rm -rf "${STAGING_DIR}"
-if [ $(arch) = "x86_64" ]; then
-  echo Creating 64-bit package...
-  cp -r linux64 "${STAGING_DIR}"
-  TARGET_OS="linux64"
+if [ ${TARGET_ARCHITECTURE} = "amd64" ]; then
+  OS_NAME="linux64"
+elif [ ${TARGET_ARCHITECTURE} = "i386" ]; then
+  OS_NAME="linux32"
 else
-  echo Creating 32-bit package...
-  cp -r linux32 "${STAGING_DIR}"
-  TARGET_OS="linux32"
+  OS_NAME="${TARGET_ARCHITECTURE}"
 fi
+PACKAGE_NAME="lazpaint${VERSION}_${OS_NAME}"
+
+echo "Version is $VERSION"
+echo "Target OS is ${OS_NAME}"
 
-VERSION="$(sed -n 's/^Version: //p' $STAGING_DIR/DEBIAN/control)"
-echo Version is $VERSION
-PACKAGE_NAME="lazpaint${VERSION}_${TARGET_OS}"
+if [ ! -f "${SOURCE_BIN}/lazpaint" ]; then
+  echo "Cannot find binary file."  
+  exit 1
+fi
 
-rm "${BIN_DIR}/delete.me"
-cp "${SOURCE_BIN}/lazpaint" "${BIN_DIR}"
-cp "${SOURCE_BIN}/lazpaint_simplified.ini" "${BIN_DIR}"
-cp "${SOURCE_BIN}/readme.txt" "${BIN_DIR}"
+echo "Creating package..."
 
-mkdir "${BIN_DIR}/i18n"
-find "${SOURCE_BIN}/i18n" -maxdepth 1 -name *.po -exec cp {} "${BIN_DIR}/i18n" \;
+rm -rf "${STAGING_DIR}"
+mkdir "${STAGING_DIR}"
+pushd ../../..
+make install prefix=/usr "DESTDIR=$STAGING_DIR"
+popd
 
-cp -r "${SOURCE_BIN}/models" "${BIN_DIR}/models"
+mkdir "${STAGING_DIR}/DEBIAN"
+cp "debian/control" "${STAGING_DIR}/DEBIAN"
+sed -i -e "s/Architecture: any/Architecture: ${TARGET_ARCHITECTURE}/" "${STAGING_DIR}/DEBIAN/control"
 
-mkdir "${SCRIPT_DIR}"
-find "${SOURCE_SCRIPT_DIR}" -maxdepth 1 -name *.py -exec cp {} "${SCRIPT_DIR}" \;
-mkdir "${SCRIPT_DIR}/lazpaint" 
-find "${SOURCE_SCRIPT_DIR}/lazpaint" -maxdepth 1 -name *.py -exec cp {} "${SCRIPT_DIR}/lazpaint" \;
+echo "Determining dependencies..."
+dpkg-shlibdeps "${BIN_DIR}/lazpaint"
+DEPENDENCIES="$(sed -n 's/^shlibs:Depends=//p' debian/substvars)"
+sed -i -e "s/\\\${shlibs:Depends}/${DEPENDENCIES}/" "${STAGING_DIR}/DEBIAN/control"
+rm "debian/substvars"
+echo "Done determining dependencies."
+
+SIZE_IN_KB="$(du -s ${STAGING_DIR} | awk '{print $1;}')"
+echo "Installed-Size: ${SIZE_IN_KB}" >> "${STAGING_DIR}/DEBIAN/control"
+find "${STAGING_DIR}" -type d -exec chmod 0755 {} \;
+find "${STAGING_DIR}" -type f -exec chmod 0644 {} \;
+chmod 0755 "${BIN_DIR}/lazpaint"
+
+fakeroot dpkg-deb --build "${STAGING_DIR}" "${PACKAGE_NAME}.deb"
 
-dpkg-deb --build "${STAGING_DIR}" "${PACKAGE_NAME}.deb"
 NO_INSTALL_ARCHIVE="${PACKAGE_NAME}_no_install.tar.gz"
+
 echo "Making ${NO_INSTALL_ARCHIVE}..."
-cd "$BIN_DIR"
-cd ..
+mv "${BIN_DIR}/lazpaint" "${RESOURCE_DIR}/lazpaint"
+mv "${DOC_DIR}/copyright" "${RESOURCE_DIR}/copyright"
+mv "${DOC_DIR}/README" "${RESOURCE_DIR}/README"
+pushd ${SHARE_DIR}
 tar -czf "../../../${NO_INSTALL_ARCHIVE}" "lazpaint"
-cd ../../..
+popd
 rm -rf "${STAGING_DIR}"
 

+ 88 - 0
lazpaint/release/debian/man/man1/lazpaint.1

@@ -0,0 +1,88 @@
+.TH LazPaint 1 "18 May 2020" "" LazPaint
+.SH NAME
+LazPaint - Image editor
+.SH SYNOPSIS
+.B lazpaint
+[INPUT FILE] [OUTPUT FILE]
+.br
+.B lazpaint
+[INPUT FILE] [ACTION]... [OUTPUT FILE]
+.SH DESCRIPTION
+Graphics viewer and editor. 
+.PP
+Can read layered files (lzp, ora, pdn, oXo), multi-images (gif, ico, tiff), flat files (bmp, jpeg, pcx, png, tga, xpm, xwd), vectorial (svg), 3D (obj). Has drawing tools, phong shading, curve adjustments, filters and render some 
+textures.
+.SH OPTIONS
+If supplied, the INPUT FILE is loaded. If the OUTPUT FILE is supplied, the image is saved and the program ends. Otherwise, the GUI of the program is displayed.
+.PP
+.B -scriptbasedir
+DIRECTORY
+.RS
+set the directory where Python scripts for LazPaint are located.
+
+.RE
+.B -script
+FILENAME
+.RS
+runs the specified Python script. It must have a ".py" extension.
+.RE
+
+.B -new
+WIDTH,HEIGHT
+.RS
+creates an empty image of size WIDTH x HEIGHT.
+.RE
+
+.B -resample
+WIDTH,HEIGHT
+.RS
+resamples the image to the size WIDTH x HEIGHT.
+.RE
+
+.B -opacity
+ALPHA
+.RS
+applies the opacity to the image. ALPHA is between 0 and 255.
+.RE
+
+.B -gradient
+R1,G1,B1,A1,R2,G2,B2,A2,TYPE,X1,Y1,X2,Y2
+.RS
+renders a gradient from point X1,Y1 to point X2,Y2. TYPE can be linear, reflected, diamond, radial or angular. The starting color is (R1,G1,B1,A1) and final color is (R2,G2,B2,A2).
+.RE
+
+.B -horizontalflip
+.RS
+flips selection or image horizontally.
+.RE
+
+.B -verticalflip
+.RS
+flips selection or image vertically.
+.RE
+
+.B -swapredblue
+.RS
+swap red and blue channels.
+.RE
+
+.B -smartzoom3
+.RS
+resample the image 3 times bigger with smart detection of borders.
+.RE
+
+.B -rotatecw
+.RS
+rotates the image clockwise.
+.RE
+
+.B -rotateccw
+.RS
+rotates the image counter-clockwise.
+.RE
+
+.B -quit
+.RS
+quits the program even if no output file was provided. Can be useful when only running scripts.
+.RE
+

+ 0 - 0
lazpaint/release/debian/linux64/usr/share/pixmaps/lazpaint.png → lazpaint/release/debian/pixmaps/lazpaint.png


+ 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.3</string>
+    <string>7.1.4</string>
     <key>CFBundleVersion</key>
-    <string>7.1.3</string>
+    <string>7.1.4</string>
     <key>CSResourcesFileMapped</key>
     <true/>
     <key>CFBundleDocumentTypes</key>

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

@@ -12,7 +12,7 @@ fi
 
 
 appname=LazPaint
-appversion=7.1.3
+appversion=7.1.4
 pkgversion=0
 appnamenospaces=lazpaint
 appbundle="$appname.app"
@@ -23,7 +23,7 @@ DMG_TMP="${VOL_NAME}-temp.dmg"
 DMG_FINAL="${VOL_NAME}.dmg"         
 STAGING_DIR="./staging"             # we copy all our stuff into this dir
 SOURCE_DIR="$(cd ../bin; pwd)"
-SCRIPT_DIR="$(cd ../../../scripts; pwd)"
+SCRIPT_DIR="$(cd ../../../resources/scripts; pwd)"
 
 # Check the background image DPI and convert it if it isn't 72x72
 _BACKGROUND_IMAGE_DPI_H=`sips -g dpiHeight ${DMG_BACKGROUND_IMG} | grep -Eo '[0-9]+\.[0-9]+'`

+ 1 - 1
lazpaint/release/stable/latest.txt

@@ -1,2 +1,2 @@
-7.1.2
+7.1.3
 lang_update=

+ 7 - 7
lazpaint/release/stable/pad_file.xml

@@ -34,9 +34,9 @@
 	</Company_Info>
 	<Program_Info>
 		<Program_Name>LazPaint</Program_Name>
-		<Program_Version>7.1.2</Program_Version>
-		<Program_Release_Month>04/Program_Release_Month>
-		<Program_Release_Day>24</Program_Release_Day>
+		<Program_Version>7.1.3</Program_Version>
+		<Program_Release_Month>05/Program_Release_Month>
+		<Program_Release_Day>16</Program_Release_Day>
 		<Program_Release_Year>2020</Program_Release_Year>
 		<Program_Cost_Dollars />
 		<Program_Cost_Other_Code />
@@ -51,9 +51,9 @@
 		<Program_Category_Class>Graphic Apps::Editors</Program_Category_Class>
 		<Program_System_Requirements>Pentium, 32-bit processor, 200 Mbytes RAM</Program_System_Requirements>
 		<File_Info>
-			<File_Size_Bytes>6891512</File_Size_Bytes>
-			<File_Size_K>6730</File_Size_K>
-			<File_Size_MB>6.57</File_Size_MB>
+			<File_Size_Bytes>6742204</File_Size_Bytes>
+			<File_Size_K>6584</File_Size_K>
+			<File_Size_MB>6.43</File_Size_MB>
 		</File_Info>
 		<Expire_Info>
 			<Has_Expire_Info>N</Has_Expire_Info>
@@ -116,7 +116,7 @@
 			<Application_XML_File_URL>https://gitcdn.link/repo/bgrabitmap/lazpaint/master/lazpaint/release/stable/pad_file.xml</Application_XML_File_URL>
 		</Application_URLs>
 		<Download_URLs>
-			<Primary_Download_URL>https://github.com/bgrabitmap/lazpaint/releases/download/v7.1.2/lazpaint7.1.2_setup_win32_win64.exe</Primary_Download_URL>
+			<Primary_Download_URL>https://github.com/bgrabitmap/lazpaint/releases/download/v7.1.3/lazpaint7.1.3_setup_win32_win64.exe</Primary_Download_URL>
 			<Secondary_Download_URL />
 			<Additional_Download_URL_1 />
 			<Additional_Download_URL_2 />

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

@@ -1,14 +1,14 @@
 #define MyAppName "LazPaint"
 #define MyAppOutputName "lazpaint"
 #define MyInstallerSuffix "_setup_win32_win64"
-#define MyAppVersion "7.1.3"
+#define MyAppVersion "7.1.4"
 #define MyAppPublisher "Circular, Fabien Wang, Lainz and others"
 #define MyAppURL "http://sourceforge.net/projects/lazpaint/"
 #define MyAppExeName "lazpaint.exe"
 #define DCRawExeName "dcraw.exe"
 #define LibWebPDllName "libwebp.dll"
 #define ReleaseDir "..\bin\"
-#define ScriptsDir "..\..\..\scripts\"
+#define ScriptsDir "..\..\..\resources\scripts\"
 
 [Setup]
 AppId={{A177F82E-B44A-4348-A265-3D1C089D6304}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio