Browse Source

Merge pull request #195 from bgrabitmap/dev-lazpaint

Dev lazpaint 7.1.4
circular17 5 years ago
parent
commit
1769fb4e72
100 changed files with 2939 additions and 1590 deletions
  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
      lazpaint/fpc-res.obj
  42. 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
      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/lazpaint32.*
 lazpaint/release/bin/i18n/lazpaint_x64.*
 lazpaint/release/bin/i18n/lazpaint_x64.*
 /lazpaint/dialog/color/backup
 /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
 package lazpaintembeddedpack.lpk
 const lazpainttype.pas LazPaintVersion
 const lazpainttype.pas LazPaintVersion
 text release/windows/lazpaint.iss "#define MyAppVersion ""$(Version)"""
 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)"
 text release/macOS/makedmg.sh "appversion=$(Version)"
 bundle release/macOS/LazPaint.app
 bundle release/macOS/LazPaint.app
 copy ../resources/icon/lazpaint.icns release/macOS/LazPaint.app/Contents/Resources/lazpaint.icns
 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'
       'Alpha'
     )
     )
     Align = alClient
     Align = alClient
+    Anchors = [akLeft, akTop, akRight, akBottom]
     TabOrder = 0
     TabOrder = 0
     object vsChart: TBGRAVirtualScreen
     object vsChart: TBGRAVirtualScreen
       Left = 2
       Left = 2
@@ -64,7 +65,7 @@ object FAdjustCurves: TFAdjustCurves
         Top = 0
         Top = 0
         Width = 90
         Width = 90
         Align = alNone
         Align = alNone
-        Anchors = [akTop, akRight]
+        Anchors = [akTop, akLeft]
         EdgeBorders = []
         EdgeBorders = []
         Images = FMain.ImageList16
         Images = FMain.ImageList16
         ParentShowHint = False
         ParentShowHint = False

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

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

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

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

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

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

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

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

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UEmboss;
 unit UEmboss;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -145,23 +146,27 @@ var bmp: TBGRABitmap;
     x1,y1,x2,y2: single;
     x1,y1,x2,y2: single;
     dx,dy,t: single;
     dx,dy,t: single;
     c: TBGRAPixel;
     c: TBGRAPixel;
+    scaling: Double;
 begin
 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;
 end;
 
 
 procedure TFEmboss.TrackBar_StrengthChange(Sender: TObject);
 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;
 unit UFilterFunction;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}

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

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UFormRain;
 unit UFormRain;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -161,7 +162,7 @@ var bmp: TBGRABitmap;
 begin
 begin
     if wind = 0 then exit;
     if wind = 0 then exit;
     bmp := TBGRABitmap.Create(PaintBox_Wind.Width,PaintBox_Wind.Height);
     bmp := TBGRABitmap.Create(PaintBox_Wind.Width,PaintBox_Wind.Height);
-    bmp.Fill(ColorToRGB(clBtnFace));
+    bmp.Fill(clForm);
     c := ColorToBGRA(ColorToRGB(clWindowText));
     c := ColorToBGRA(ColorToRGB(clWindowText));
     if wind < 0 then angle := 180 else angle := 0;
     if wind < 0 then angle := 180 else angle := 0;
     t := PaintBox_Wind.Width/2*abs(wind);
     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;
 unit UMotionBlur;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -101,31 +102,36 @@ var bmp: TBGRABitmap;
     x0,y0,x1,y1,x2,y2: single;
     x0,y0,x1,y1,x2,y2: single;
     dx,dy,t: single;
     dx,dy,t: single;
     c: TBGRAPixel;
     c: TBGRAPixel;
+    scaling: Double;
 begin
 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;
 end;
 
 
 procedure TFMotionBlur.SpinEdit_DistanceChange(Sender: TObject);
 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;
 unit unoisefilter;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 3 - 2
lazpaint/dialog/uabout.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UAbout;
 unit UAbout;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -90,12 +91,12 @@ var bmp: TBGRABitmap;
 begin
 begin
   shader.LightPosition := Point(round((cos(angle)+1)/2*Image_Title.Width),round((sin(angle)+1)*Image_Title.height));
   shader.LightPosition := Point(round((cos(angle)+1)/2*Image_Title.Width),round((sin(angle)+1)*Image_Title.height));
   inc(frameNumber);
   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 = -1 then xTxt := bmp.Width;
   if xTxt > bmp.Width div 2 then dec(xTxt);
   if xTxt > bmp.Width div 2 then dec(xTxt);
   fx.DrawShaded(bmp,xTxt,0, shader, 1,
   fx.DrawShaded(bmp,xTxt,0, shader, 1,
-    MergeBGRA(ColorToBGRA(ColorToRGB(clBtnFace)),ColorToBGRA(ColorToRGB(clWindowText))),
+    MergeBGRA(ColorToBGRA(clForm),ColorToBGRA(clWindowText)),
     taCenter, false);
     taCenter, false);
 
 
   bmp.Draw(Image_Title.Picture.Bitmap.Canvas,0,0,true);
   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;
 unit UBlendOp;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -92,6 +93,7 @@ begin
       exit;
       exit;
     end;
     end;
   end;
   end;
+  BGRAThumbnail.CheckersScale:= GetCanvasScaleFactor;
   if APattern = 'Under' then
   if APattern = 'Under' then
   begin
   begin
     result := GetBitmapThumbnail(PatternUnder,AWidth,AHeight,BGRAPixelTransparent,ACheckers) as TBGRABitmap;
     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);
       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));
     BGRAReplace(result,GetBitmapThumbnail(result,AWidth,AHeight,BGRAPixelTransparent,false));
   end;
   end;
+  BGRAThumbnail.CheckersScale:= 1;
   setlength(FPatterns,length(FPatterns)+1);
   setlength(FPatterns,length(FPatterns)+1);
   FPatterns[high(FPatterns)].name := fullPatternName;
   FPatterns[high(FPatterns)].name := fullPatternName;
   FPatterns[high(FPatterns)].bmp := result;
   FPatterns[high(FPatterns)].bmp := result;
@@ -148,12 +151,15 @@ end;
 
 
 procedure TFBlendOp.DrawPattern(ACanvas: TCanvas; ARect: TRect; APattern: string; State: TOwnerDrawState);
 procedure TFBlendOp.DrawPattern(ACanvas: TCanvas; ARect: TRect; APattern: string; State: TOwnerDrawState);
 var bmp: TBGRABitmap;
 var bmp: TBGRABitmap;
+  scaling: Double;
 begin
 begin
   if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
   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);
   if odSelected in State then DrawPatternHighlight(bmp);
-  bmp.Draw(ACanvas,ARect.Left,ARect.Top,false);
+  bmp.Draw(ACanvas,ARect,false);
   bmp.Free;
   bmp.Free;
 end;
 end;
 
 
@@ -355,9 +361,10 @@ procedure TFBlendOp.ListBox_DrawBlendItem(Control: TWinControl; Index: Integer;
   ARect: TRect; State: TOwnerDrawState);
   ARect: TRect; State: TOwnerDrawState);
 var
 var
   background,preview,over: TBGRABitmap;
   background,preview,over: TBGRABitmap;
-  w,h: integer;
+  w,h, checkerSize: integer;
   BlendStr: string;
   BlendStr: string;
   fx: TBGRATextEffect;
   fx: TBGRATextEffect;
+  scaling: Double;
 begin
 begin
   {$IFDEF LINUX}
   {$IFDEF LINUX}
   ARect.Right := ARect.Left+Control.Width-FListBoxInternalMargin;
   ARect.Right := ARect.Left+Control.Width-FListBoxInternalMargin;
@@ -368,22 +375,24 @@ begin
   begin
   begin
     if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
     if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
     BlendStr := (Control as TListBox).Items[Index];
     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 := 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;
     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);
     over := GetPattern(w,h,ListBox_PatternOver.Items[ListBox_PatternOver.ItemIndex],False);
     preview.BlendImageOver(0,0,over,StrToBlendOperation(BlendStr));
     preview.BlendImageOver(0,0,over,StrToBlendOperation(BlendStr));
     background.PutImage(0,0,preview,dmDrawWithTransparency);
     background.PutImage(0,0,preview,dmDrawWithTransparency);
     preview.Free;
     preview.Free;
     if odSelected in State then DrawPatternHighlight(background);
     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.DrawOutline(background,1,1,BGRABlack);
     fx.Draw(background,1,1,BGRAWhite);
     fx.Draw(background,1,1,BGRAWhite);
     fx.Free;
     fx.Free;
     background.FontName := 'Arial';
     background.FontName := 'Arial';
-    background.Draw((Control as TListBox).Canvas,ARect.Left,ARect.Top,True);
+    background.Draw((Control as TListBox).Canvas,ARect,True);
     background.Free;
     background.Free;
   end;
   end;
 end;
 end;

+ 14 - 0
lazpaint/dialog/ubrowseimages.pas

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

+ 1 - 1
lazpaint/dialog/ucanvassize.lfm

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

+ 17 - 12
lazpaint/dialog/ucanvassize.pas

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

+ 304 - 203
lazpaint/dialog/uchoosecolorinterface.pas

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

+ 1 - 0
lazpaint/dialog/ugeometricbrush.pas

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

+ 29 - 14
lazpaint/dialog/ulayerstackinterface.pas

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

+ 1 - 0
lazpaint/dialog/umultiimage.pas

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

+ 1 - 1
lazpaint/dialog/unewimage.lfm

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

+ 16 - 6
lazpaint/dialog/unewimage.pas

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

+ 4 - 2
lazpaint/dialog/uobject3d.pas

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

+ 56 - 17
lazpaint/dialog/uprint.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit uprint;
 unit uprint;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
@@ -78,6 +79,8 @@ type
     FPrevMousePos: TPoint;
     FPrevMousePos: TPoint;
     FDpiAspectRatio,FAspectRatio: single;
     FDpiAspectRatio,FAspectRatio: single;
     invZoom: TPointF;
     invZoom: TPointF;
+    FLabelCount: TLabel;
+    FPrintCount: integer;
     property RotatedSpinTop: TSpinEdit read GetRotatedSpinTop;
     property RotatedSpinTop: TSpinEdit read GetRotatedSpinTop;
     property RotatedSpinLeft: TSpinEdit read GetRotatedSpinLeft;
     property RotatedSpinLeft: TSpinEdit read GetRotatedSpinLeft;
     property RotatedSpinRight: TSpinEdit read GetRotatedSpinRight;
     property RotatedSpinRight: TSpinEdit read GetRotatedSpinRight;
@@ -95,7 +98,7 @@ type
 
 
 implementation
 implementation
 
 
-uses printers, UResourceStrings, Types, LCScaleDPI, umac;
+uses printers, UResourceStrings, Types, LCScaleDPI, umac, ULoading;
 
 
 var
 var
   marginLeft, marginRight, marginTop, marginBottom: integer;
   marginLeft, marginRight, marginTop, marginBottom: integer;
@@ -392,19 +395,50 @@ begin
   if (unrotatedTotalMarginInPoints.x >= paperSizeInPoints.x) or
   if (unrotatedTotalMarginInPoints.x >= paperSizeInPoints.x) or
     (unrotatedTotalMarginInPoints.y >= paperSizeInPoints.y) then exit;
     (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;
 end;
 
 
 procedure TFPrint.Button_ZoomFitClick(Sender: TObject);
 procedure TFPrint.Button_ZoomFitClick(Sender: TObject);
@@ -458,7 +492,7 @@ end;
 procedure TFPrint.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap
 procedure TFPrint.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap
   );
   );
 var
 var
-  ratio: single;
+  ratio, scaling: single;
   x,y,w,h: integer;
   x,y,w,h: integer;
   marTopLeft,marBottomRight,
   marTopLeft,marBottomRight,
   imgTopLeft,imgBottomRight: TPointF;
   imgTopLeft,imgBottomRight: TPointF;
@@ -466,6 +500,7 @@ var
   zoom: TPointF;
   zoom: TPointF;
 begin
 begin
   if (printer.PaperSize.Height = 0) or (printer.PaperSize.Width = 0) then exit;
   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;
   ratio := printer.PaperSize.Width/printer.PaperSize.Height;
   if Bitmap.Height * ratio > Bitmap.Width then
   if Bitmap.Height * ratio > Bitmap.Width then
     begin
     begin
@@ -498,7 +533,8 @@ begin
   marTopLeft := FPreviewTransform*unrotatedMarginTopLeftInPoints;
   marTopLeft := FPreviewTransform*unrotatedMarginTopLeftInPoints;
   marBottomRight := FPreviewTransform*(paperSizeInPoints - unrotatedMarginBottomRightInPoints);
   marBottomRight := FPreviewTransform*(paperSizeInPoints - unrotatedMarginBottomRightInPoints);
   area := rect(round(marTopLeft.x),round(marTopLeft.y),round(marBottomRight.x),round(marBottomRight.y));
   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
   if IntersectRect(area,area,Bitmap.ClipRect) then
   begin
   begin
     Bitmap.ClipRect := area;
     Bitmap.ClipRect := area;
@@ -517,7 +553,8 @@ begin
     InflateRect(bounds,1,1);
     InflateRect(bounds,1,1);
     IntersectRect(imgRect, imgRect,bounds);
     IntersectRect(imgRect, imgRect,bounds);
     Bitmap.DrawPolyLineAntialias([imgRect.TopLeft,Point(imgRect.Right-1,imgRect.Top),Point(imgRect.Right-1, imgRect.Bottom-1),
     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;
   end;
   Bitmap.NoClip;
   Bitmap.NoClip;
 end;
 end;
@@ -589,6 +626,8 @@ end;
 procedure TFPrint.FormCreate(Sender: TObject);
 procedure TFPrint.FormCreate(Sender: TObject);
 begin
 begin
   ScaleControl(Self,OriginalDPI);
   ScaleControl(Self,OriginalDPI);
+  BGRAVirtualScreen1.BitmapAutoScale:= false;
+  BGRAVirtualScreen1.Color := clDkGray;
 
 
   CheckSpinEdit(SpinEdit_DpiY);
   CheckSpinEdit(SpinEdit_DpiY);
   CheckSpinEdit(SpinEdit_DpiX);
   CheckSpinEdit(SpinEdit_DpiX);

+ 1 - 0
lazpaint/dialog/uquestion.pas

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

+ 1 - 1
lazpaint/dialog/uresample.lfm

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

+ 21 - 12
lazpaint/dialog/uresample.pas

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

+ 1 - 0
lazpaint/dialog/usaveoption.pas

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

BIN
lazpaint/fpc-res.obj


BIN
lazpaint/fpc-res.res


+ 30 - 0
lazpaint/image/uimage.pas

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

+ 4 - 1
lazpaint/image/uimagediff.pas

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0-only
 unit UImageDiff;
 unit UImageDiff;
 
 
 {$mode objfpc}
 {$mode objfpc}
@@ -2663,7 +2664,9 @@ begin
   begin
   begin
     self.sourceLayerId := LayeredBitmap.LayerUniqueId[SelectedImageLayerIndex];
     self.sourceLayerId := LayeredBitmap.LayerUniqueId[SelectedImageLayerIndex];
     self.duplicateId := LayeredBitmap.ProduceLayerUniqueId;
     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
     if self.duplicateOriginal then
       CreateGUID(duplicateGuid);
       CreateGUID(duplicateGuid);
   end;
   end;

+ 1 - 0
lazpaint/image/uimageobservation.pas

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

+ 48 - 2
lazpaint/image/uimagestate.pas

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

+ 1 - 0
lazpaint/image/uimagetype.pas

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

+ 1 - 0
lazpaint/image/ulayeraction.pas

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

+ 1 - 0
lazpaint/image/ustatetype.pas

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

+ 6 - 6
lazpaint/lazpaint.lpi

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

+ 28 - 8
lazpaint/lazpaint.lpr

@@ -133,14 +133,18 @@ begin
       Report += 'Exception class: ' + E.ClassName + LineEnding;
       Report += 'Exception class: ' + E.ClassName + LineEnding;
     Report += 'Message: ' + E.Message + LineEnding;
     Report += 'Message: ' + E.Message + LineEnding;
   end;
   end;
+  {$IFDEF DEBUG}
   Report += 'Stacktrace:' + LineEnding;
   Report += 'Stacktrace:' + LineEnding;
   Report := Report + '  ' + BackTraceStrFunc(ExceptAddr) + LineEnding;
   Report := Report + '  ' + BackTraceStrFunc(ExceptAddr) + LineEnding;
   Frames := ExceptFrames;
   Frames := ExceptFrames;
   for I := 0 to ExceptFrameCount - 1 do
   for I := 0 to ExceptFrameCount - 1 do
     Report := Report + '  ' + BackTraceStrFunc(Frames[I]) + LineEnding;
     Report := Report + '  ' + BackTraceStrFunc(Frames[I]) + LineEnding;
+  {$ELSE}
+  Report += 'To get more information, use the debug version.' + LineEnding;
+  {$ENDIF}
   Report += LineEnding;
   Report += LineEnding;
   if Initialized then
   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
   else
     Report += 'Application will now close.';
     Report += 'Application will now close.';
   ShowError(rsLazPaint, Report);
   ShowError(rsLazPaint, Report);
@@ -151,23 +155,39 @@ end;
 {$R *.res}
 {$R *.res}
 
 
 {$IFDEF DARWIN}{$IFDEF DEBUG}
 {$IFDEF DARWIN}{$IFDEF DEBUG}
+const
+  ConsoleOutputFile = '/dev/ttys000';
 var
 var
   OldOutput: TextFile;
   OldOutput: TextFile;
+  HasTerminalOutput: boolean;
 
 
   procedure InitOutput;
   procedure InitOutput;
+  var TerminalOutput: TextFile;
   begin
   begin
+    //on MacOS, you need to open the terminal before running LazPaint to get debug information
     OldOutput := Output;
     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;
   end;
 
 
   procedure DoneOutput;
   procedure DoneOutput;
   begin
   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;
   end;
 {$ENDIF}{$ENDIF}
 {$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;
 procedure TLazPaintInstance.ShowPrintDlg;
 var f: TFPrint;
 var f: TFPrint;
     wasVisible: boolean;
     wasVisible: boolean;
@@ -123,6 +124,12 @@ begin
   result := srOk;
   result := srOk;
 end;
 end;
 
 
+function TLazPaintInstance.ScriptGetName(AVars: TVariableSet): TScriptResult;
+begin
+  AVars.Strings['Result'] := FScriptName;
+  result := srOk;
+end;
+
 function TLazPaintInstance.ScriptImageCanvasSize(AVars: TVariableSet): TScriptResult;
 function TLazPaintInstance.ScriptImageCanvasSize(AVars: TVariableSet): TScriptResult;
 var
 var
   w, h: Int64;
   w, h: Int64;
@@ -229,6 +236,30 @@ begin
     result := srCancelledByUser;
     result := srCancelledByUser;
 end;
 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;
 function TLazPaintInstance.ShowResampleDialog(AParameters: TVariableSet): boolean;
 begin
 begin
   FormsNeeded;
   FormsNeeded;

+ 1 - 1
lazpaint/lazpaintembeddedpack.lpk

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

+ 59 - 8
lazpaint/lazpaintinstance.pas

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

+ 1 - 26
lazpaint/lazpaintmainform.lfm

@@ -7,7 +7,6 @@ object FMain: TFMain
   Caption = 'LazPaint'
   Caption = 'LazPaint'
   ClientHeight = 572
   ClientHeight = 572
   ClientWidth = 739
   ClientWidth = 739
-  Color = clSkyBlue
   Constraints.MinWidth = 320
   Constraints.MinWidth = 320
   Font.Height = -12
   Font.Height = -12
   KeyPreview = True
   KeyPreview = True
@@ -20,12 +19,6 @@ object FMain: TFMain
   OnHide = FormHide
   OnHide = FormHide
   OnKeyDown = FormKeyDown
   OnKeyDown = FormKeyDown
   OnKeyUp = FormKeyUp
   OnKeyUp = FormKeyUp
-  OnMouseDown = FormMouseDown
-  OnMouseEnter = FormMouseEnter
-  OnMouseMove = FormMouseMove
-  OnMouseUp = FormMouseUp
-  OnMouseWheel = FormMouseWheel
-  OnPaint = FormPaint
   OnResize = FormResize
   OnResize = FormResize
   OnShow = FormShow
   OnShow = FormShow
   OnUTF8KeyPress = FormUTF8KeyPress
   OnUTF8KeyPress = FormUTF8KeyPress
@@ -1524,9 +1517,7 @@ object FMain: TFMain
     Height = 104
     Height = 104
     Top = 176
     Top = 176
     Width = 106
     Width = 106
-    ClientHeight = 104
-    ClientWidth = 106
-    Color = clBtnFace
+    BevelOuter = bvNone
     Font.Height = -12
     Font.Height = -12
     ParentColor = False
     ParentColor = False
     ParentFont = False
     ParentFont = False
@@ -2342,22 +2333,6 @@ object FMain: TFMain
       end
       end
     end
     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
   object Panel_Brush: TPanel
     Left = 8
     Left = 8
     Height = 36
     Height = 36

+ 119 - 417
lazpaint/lazpaintmainform.pas

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

+ 10 - 2
lazpaint/lazpainttype.pas

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

+ 124 - 89
lazpaint/maintoolbar.inc

@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-3.0-only
 procedure TFMain.CreateToolbarElements;
 procedure TFMain.CreateToolbarElements;
 
 
   procedure InitVectorialFill(vf: TLCVectorialFillControl; grad: TBGRALayerGradientOriginal;
   procedure InitVectorialFill(vf: TLCVectorialFillControl; grad: TBGRALayerGradientOriginal;
-      lbl: TLabel; pnl: TPanel; mouseMove: TMouseMoveEvent);
+      lbl: TLabel; pnl: TPanel; mouseMove: TMouseMoveEvent; mouseClick: TNotifyEvent; AIsTarget: boolean);
   begin
   begin
     vf.PopupMenu := nil;
     vf.PopupMenu := nil;
     vf.VerticalPadding:= DoScaleY(6, OriginalDPI);
     vf.VerticalPadding:= DoScaleY(6, OriginalDPI);
@@ -21,10 +22,15 @@ procedure TFMain.CreateToolbarElements;
       vf.GradRepetition:= Repetition;
       vf.GradRepetition:= Repetition;
       vf.GradInterpolation:= ColorInterpolation;
       vf.GradInterpolation:= ColorInterpolation;
     end;
     end;
-    if Assigned(lbl) then lbl.OnMouseMove:= mouseMove;
+    if Assigned(lbl) then
+    begin
+      lbl.OnMouseMove:= mouseMove;
+      lbl.OnClick:= mouseClick;
+    end;
     pnl.PopupMenu := nil;
     pnl.PopupMenu := nil;
     pnl.OnMouseMove:= mouseMove;
     pnl.OnMouseMove:= mouseMove;
     vf.OnMouseMove:= mouseMove;
     vf.OnMouseMove:= mouseMove;
+    vf.IsTarget:= AIsTarget;
   end;
   end;
 
 
 var
 var
@@ -36,11 +42,17 @@ begin
   Panel_ToolbarBackground.PopupMenu := PopupToolbar;
   Panel_ToolbarBackground.PopupMenu := PopupToolbar;
   Perspective_Repeat.OnClick:=@Perspective_RepeatClick;
   Perspective_Repeat.OnClick:=@Perspective_RepeatClick;
   Perspective_TwoPlanes.OnClick := @Perspective_TwoPlanesClick;
   Perspective_TwoPlanes.OnClick := @Perspective_TwoPlanesClick;
-  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;
   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;
   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;
   VectorialFill_Outline.SolidColor := ToolManager.OutlineColor;
   Image_SwapColors.OnMouseDown := @Image_SwapColorsMouseDown;
   Image_SwapColors.OnMouseDown := @Image_SwapColorsMouseDown;
   Tool_DrawShapeBorder.OnClick := @Tool_DrawShapeBorderClick;
   Tool_DrawShapeBorder.OnClick := @Tool_DrawShapeBorderClick;
@@ -83,6 +95,7 @@ begin
   PaintBox_PenPreview.OnMouseMove := @Panel_PenWidthMouseMove;
   PaintBox_PenPreview.OnMouseMove := @Panel_PenWidthMouseMove;
   PaintBox_PenPreview.OnMouseDown := @PaintBox_PenPreviewMouseDown;
   PaintBox_PenPreview.OnMouseDown := @PaintBox_PenPreviewMouseDown;
   PaintBox_PenPreview.OnPaint := @PaintBox_PenPreviewPaint;
   PaintBox_PenPreview.OnPaint := @PaintBox_PenPreviewPaint;
+  PaintBox_PenPreview.Align := alClient;
   Tool_PhongShapeRectangle.OnClick := @Tool_PhongShapeRectangleClick;
   Tool_PhongShapeRectangle.OnClick := @Tool_PhongShapeRectangleClick;
   Tool_PhongShapeRoundRect.OnClick := @Tool_PhongShapeRoundRectClick;
   Tool_PhongShapeRoundRect.OnClick := @Tool_PhongShapeRoundRectClick;
   Tool_PhongShapeSphere.OnClick := @Tool_PhongShapeSphereClick;
   Tool_PhongShapeSphere.OnClick := @Tool_PhongShapeSphereClick;
@@ -530,6 +543,7 @@ begin
   prevBackColor := VectorialFill_Back.AverageColor;
   prevBackColor := VectorialFill_Back.AverageColor;
   VectorialFill_Pen.AssignFill(ToolManager.ForeFill);
   VectorialFill_Pen.AssignFill(ToolManager.ForeFill);
   VectorialFill_Back.AssignFill(ToolManager.BackFill);
   VectorialFill_Back.AssignFill(ToolManager.BackFill);
+  VectorialFill_Outline.AssignFill(ToolManager.OutlineFill);
   newPenColor := VectorialFill_Pen.AverageColor;
   newPenColor := VectorialFill_Pen.AverageColor;
   newBackColor := VectorialFill_Back.AverageColor;
   newBackColor := VectorialFill_Back.AverageColor;
   FInFillChange:= false;
   FInFillChange:= false;
@@ -666,6 +680,27 @@ begin
   FInitialized := oldInit;
   FInitialized := oldInit;
 end;
 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);
 procedure TFMain.SpinEdit_ShapeAltitudeChange(Sender: TObject; AByUser: boolean);
 begin
 begin
   if SpinEdit_ShapeAltitude.Value < 6 then
   if SpinEdit_ShapeAltitude.Value < 6 then
@@ -833,54 +868,38 @@ begin
 end;
 end;
 
 
 procedure TFMain.UpdateAllowedFillTypes;
 procedure TFMain.UpdateAllowedFillTypes;
-begin
-  if VectorialFill_Pen.AllowedFillTypes <> ToolManager.AllowedForeFillTypes then
+  procedure UpdateFor(AFillControl: TLCVectorialFillControl; AAllowedFillTypes: TVectorialFillTypes;
+      ANeedGradientProc: TProcedureOfObject);
   begin
   begin
-    if not (VectorialFill_Pen.FillType in ToolManager.AllowedForeFillTypes) then
+    if AFillControl.AllowedFillTypes <> AAllowedFillTypes then
     begin
     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
       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;
       end;
+      AFillControl.AllowedFillTypes:= AAllowedFillTypes;
+      AFillControl.Width := AFillControl.PreferredSize.cx;
     end;
     end;
-    VectorialFill_Pen.AllowedFillTypes:= ToolManager.AllowedForeFillTypes;
-    VectorialFill_Pen.Width := VectorialFill_Pen.PreferredSize.cx;
   end;
   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);
   Perspective_Repeat.Visible := (CurrentTool = ptLayerMapping);
 end;
 end;
@@ -942,6 +961,32 @@ begin
   FInFillChange:= false;
   FInFillChange:= false;
 end;
 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);
 procedure TFMain.VectorialFill_Resize(Sender: TObject);
 begin
 begin
   QueryArrange;
   QueryArrange;
@@ -1520,39 +1565,13 @@ begin
   if SpinEdit_PenWidth.Value < MinPenWidth*PenWidthFactor then SpinEdit_PenWidth.Value := MinPenWidth*PenWidthFactor;
   if SpinEdit_PenWidth.Value < MinPenWidth*PenWidthFactor then SpinEdit_PenWidth.Value := MinPenWidth*PenWidthFactor;
 end;
 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;
 procedure TFMain.PaintBox_PenPreviewMouseDown(Sender: TObject;
   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 var t: integer;
 var t: integer;
 begin
 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);
   ShowPenPreview(False);
 end;
 end;
 
 
@@ -1585,17 +1604,22 @@ end;
 
 
 procedure TFMain.PaintBox_PenPreviewPaint(Sender: TObject);
 procedure TFMain.PaintBox_PenPreviewPaint(Sender: TObject);
 var bmp: TBGRABitmap;
 var bmp: TBGRABitmap;
-    x,y,t: integer;
+    x,y,t,margin: integer;
     c: TBGRAPixel;
     c: TBGRAPixel;
     m: single;
     m: single;
     bi: TLazPaintBrush;
     bi: TLazPaintBrush;
     visualSize: single;
     visualSize: single;
+    scaling: Double;
 begin
 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;
   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;
   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
   if (CurrentTool in[ptBrush,ptClone]) and (visualSize <= 2*bmp.width) and (visualSize <= 2*bmp.Height) then
   begin
   begin
     bi := ToolManager.BrushInfo;
     bi := ToolManager.BrushInfo;
@@ -1607,17 +1631,28 @@ begin
       end;
       end;
   end else
   end else
     bmp.FillEllipseAntialias(x,y,visualSize/2,visualSize/2,c);
     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;
   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;
   bmp.Free;
 end;
 end;
 
 

+ 1 - 0
lazpaint/quote.inc

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -3174,6 +3174,11 @@ msgctxt "uresourcestrings.rslayers"
 msgid "Layers"
 msgid "Layers"
 msgstr "图层"
 msgstr "图层"
 
 
+#: uresourcestrings.rslayer
+msgctxt "uresourcestrings.rslayer"
+msgid "Layer"
+msgstr "层"
+
 #: uresourcestrings.rslazpaint
 #: uresourcestrings.rslazpaint
 msgctxt "uresourcestrings.rslazpaint"
 msgctxt "uresourcestrings.rslazpaint"
 msgid "LazPaint"
 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=LazPaint
 Name[fr]=LazPaint
 Name[fr]=LazPaint
 Comment=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
 Terminal=false
 Type=Application
 Type=Application
 Categories=Graphics
 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
 lazpaint (7.0.8) unstable; urgency=low
 
 
@@ -143,71 +131,115 @@ lazpaint (7.0.8) unstable; urgency=low
   * fixes for image browser
   * fixes for image browser
   * command line: parenthesis optional to make it Linux-friendly 
   * 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
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
 #!/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"
 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
 else
-  echo Creating 32-bit package...
-  cp -r linux32 "${STAGING_DIR}"
-  TARGET_OS="linux32"
+  OS_NAME="${TARGET_ARCHITECTURE}"
 fi
 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"
 NO_INSTALL_ARCHIVE="${PACKAGE_NAME}_no_install.tar.gz"
+
 echo "Making ${NO_INSTALL_ARCHIVE}..."
 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"
 tar -czf "../../../${NO_INSTALL_ARCHIVE}" "lazpaint"
-cd ../../..
+popd
 rm -rf "${STAGING_DIR}"
 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>
     <key>CFBundleSignature</key>
     <string>lazp</string>
     <string>lazp</string>
     <key>CFBundleShortVersionString</key>
     <key>CFBundleShortVersionString</key>
-    <string>7.1.3</string>
+    <string>7.1.4</string>
     <key>CFBundleVersion</key>
     <key>CFBundleVersion</key>
-    <string>7.1.3</string>
+    <string>7.1.4</string>
     <key>CSResourcesFileMapped</key>
     <key>CSResourcesFileMapped</key>
     <true/>
     <true/>
     <key>CFBundleDocumentTypes</key>
     <key>CFBundleDocumentTypes</key>

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

@@ -12,7 +12,7 @@ fi
 
 
 
 
 appname=LazPaint
 appname=LazPaint
-appversion=7.1.3
+appversion=7.1.4
 pkgversion=0
 pkgversion=0
 appnamenospaces=lazpaint
 appnamenospaces=lazpaint
 appbundle="$appname.app"
 appbundle="$appname.app"
@@ -23,7 +23,7 @@ DMG_TMP="${VOL_NAME}-temp.dmg"
 DMG_FINAL="${VOL_NAME}.dmg"         
 DMG_FINAL="${VOL_NAME}.dmg"         
 STAGING_DIR="./staging"             # we copy all our stuff into this dir
 STAGING_DIR="./staging"             # we copy all our stuff into this dir
 SOURCE_DIR="$(cd ../bin; pwd)"
 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
 # 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]+'`
 _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=
 lang_update=

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

@@ -34,9 +34,9 @@
 	</Company_Info>
 	</Company_Info>
 	<Program_Info>
 	<Program_Info>
 		<Program_Name>LazPaint</Program_Name>
 		<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_Release_Year>2020</Program_Release_Year>
 		<Program_Cost_Dollars />
 		<Program_Cost_Dollars />
 		<Program_Cost_Other_Code />
 		<Program_Cost_Other_Code />
@@ -51,9 +51,9 @@
 		<Program_Category_Class>Graphic Apps::Editors</Program_Category_Class>
 		<Program_Category_Class>Graphic Apps::Editors</Program_Category_Class>
 		<Program_System_Requirements>Pentium, 32-bit processor, 200 Mbytes RAM</Program_System_Requirements>
 		<Program_System_Requirements>Pentium, 32-bit processor, 200 Mbytes RAM</Program_System_Requirements>
 		<File_Info>
 		<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>
 		</File_Info>
 		<Expire_Info>
 		<Expire_Info>
 			<Has_Expire_Info>N</Has_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_XML_File_URL>https://gitcdn.link/repo/bgrabitmap/lazpaint/master/lazpaint/release/stable/pad_file.xml</Application_XML_File_URL>
 		</Application_URLs>
 		</Application_URLs>
 		<Download_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 />
 			<Secondary_Download_URL />
 			<Additional_Download_URL_1 />
 			<Additional_Download_URL_1 />
 			<Additional_Download_URL_2 />
 			<Additional_Download_URL_2 />

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

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

Some files were not shown because too many files changed in this diff