|
@@ -5,18 +5,27 @@ unit ULayerAction;
|
|
|
interface
|
|
|
|
|
|
uses
|
|
|
- Classes, SysUtils, UImage, BGRABitmap, BGRABitmapTypes, UImageType;
|
|
|
+ Classes, SysUtils, BGRABitmap, BGRABitmapTypes, UImageType,
|
|
|
+ UStateType, UImageState;
|
|
|
|
|
|
type
|
|
|
+ TNotifyChangeEvent = procedure(ASender: TObject; ALayer: TBGRABitmap; ARect: TRect) of object;
|
|
|
+ TNotifyUndoEvent = procedure(ASender: TObject; AUndo: TCustomImageDifference; var Owned: boolean) of object;
|
|
|
+
|
|
|
{ TLayerAction }
|
|
|
|
|
|
TLayerAction = class(TCustomLayerAction)
|
|
|
private
|
|
|
- FAllChangesNotified: boolean;
|
|
|
- FImage: TLazPaintImage;
|
|
|
+ FChangeBoundsNotified: boolean;
|
|
|
+ FImageState: TImageState;
|
|
|
+ FOnDestroy: TNotifyEvent;
|
|
|
+ FOnNotifyChange: TNotifyChangeEvent;
|
|
|
+ FOnNotifyUndo: TNotifyUndoEvent;
|
|
|
+ FPrediff: TComposedImageDifference;
|
|
|
FBackupSelectedLayer, FBackupSelectionLayer, FBackupSelection: TBGRABitmap;
|
|
|
- FBackupSelectedLayerDefined, FBackupSelectionLayerDefined, FBackupSelectionDefined: boolean;
|
|
|
- FSelectedLayerChangedArea, FSelectionLayerChangedArea, FSelectionChangedArea: TRect;
|
|
|
+ FBackupSelectedLayerDefined, FBackupSelectionLayerDefined, FBackupSelectionMaskDefined: boolean;
|
|
|
+ FBackupSelectionTransform: TAffineMatrix;
|
|
|
+ FSelectedImageLayerChangedArea, FSelectionLayerChangedArea, FSelectionMaskChangedArea: TRect;
|
|
|
FDone: boolean;
|
|
|
FOnTryStop: TOnTryStopEventHandler;
|
|
|
function GetBackupDrawingLayer: TBGRABitmap;
|
|
@@ -24,18 +33,23 @@ type
|
|
|
function GetBackupSelection: TBGRABitmap;
|
|
|
function GetBackupSelectionLayer: TBGRABitmap;
|
|
|
function GetCurrentSelection: TBGRABitmap;
|
|
|
+ function GetCurrentState: TImageState;
|
|
|
function GetSelectedImageLayer: TBGRABitmap;
|
|
|
function GetDrawingLayer: TBGRABitmap;
|
|
|
function GetSelectedImageLayerOffset: TPoint;
|
|
|
+ function GetSelectionLayerBounds: TRect;
|
|
|
+ function GetSelectionTransform: TAffineMatrix;
|
|
|
+ procedure SetOnDestroy(AValue: TNotifyEvent);
|
|
|
+ procedure SetOnNotifyChange(AValue: TNotifyChangeEvent);
|
|
|
+ procedure SetOnNotifyUndo(AValue: TNotifyUndoEvent);
|
|
|
protected
|
|
|
procedure Cancel;
|
|
|
- procedure NeedSelectionBackup;
|
|
|
+ procedure NeedSelectionMaskBackup;
|
|
|
procedure NeedSelectedLayerBackup;
|
|
|
procedure NeedSelectionLayerBackup;
|
|
|
- function GetSelectionTransform: TAffineMatrix;
|
|
|
- procedure SetSelectionTransform(AValue: TAffineMatrix);
|
|
|
+ property CurrentState: TImageState read GetCurrentState;
|
|
|
public
|
|
|
- constructor Create(AImage: TLazPaintImage);
|
|
|
+ constructor Create(AState: TImageState; AApplyOfsBefore: boolean = false);
|
|
|
procedure Validate;
|
|
|
procedure PartialValidate(ADiscardBackup: boolean = false);
|
|
|
procedure PartialCancel;
|
|
@@ -44,18 +58,17 @@ type
|
|
|
procedure QuerySelection;
|
|
|
procedure RemoveSelection;
|
|
|
procedure EraseSelectionInBitmap;
|
|
|
+ procedure MergeWithSelection(AApplyMask: boolean = true);
|
|
|
procedure ReleaseSelection;
|
|
|
procedure RetrieveSelection;
|
|
|
function RetrieveSelectionIfLayerEmpty(removeFromBitmap: boolean = false): boolean;
|
|
|
procedure ApplySelectionTransform(ApplyToMask: boolean= true);
|
|
|
procedure ApplySelectionMask;
|
|
|
|
|
|
- procedure ReplaceSelectedLayer(AValue: TBGRABitmap; AOwned: boolean);
|
|
|
procedure ReplaceSelectionLayer(bmp: TBGRABitmap; AOwned: boolean);
|
|
|
- procedure ReplaceDrawingLayer(bmp: TBGRABitmap; AOwned: boolean);
|
|
|
procedure ReplaceCurrentSelection(AValue: TBGRABitmap);
|
|
|
procedure NotifyChange(ADest: TBGRABitmap; ARect: TRect);
|
|
|
- procedure RestoreSelection;
|
|
|
+ procedure RestoreSelectionMask;
|
|
|
procedure RestoreDrawingLayer;
|
|
|
procedure RestoreSelectedLayer;
|
|
|
procedure RestoreSelectionLayer;
|
|
@@ -73,27 +86,38 @@ type
|
|
|
property BackupSelectedLayer: TBGRABitmap read GetBackupSelectedLayer;
|
|
|
property BackupDrawingLayer: TBGRABitmap read GetBackupDrawingLayer;
|
|
|
property OnTryStop: TOnTryStopEventHandler read FOnTryStop write FOnTryStop;
|
|
|
- property SelectionTransform: TAffineMatrix read GetSelectionTransform write SetSelectionTransform;
|
|
|
property Done: boolean read FDone;
|
|
|
- property AllChangesNotified: boolean read FAllChangesNotified write FAllChangesNotified;
|
|
|
+ property ChangeBoundsNotified: boolean read FChangeBoundsNotified write FChangeBoundsNotified;
|
|
|
+ property SelectionTransform: TAffineMatrix read GetSelectionTransform;
|
|
|
+ property SelectionLayerBounds: TRect read GetSelectionLayerBounds;
|
|
|
+ property OnNotifyChange: TNotifyChangeEvent read FOnNotifyChange write SetOnNotifyChange;
|
|
|
+ property OnNotifyUndo: TNotifyUndoEvent read FOnNotifyUndo write SetOnNotifyUndo;
|
|
|
+ property OnDestroy: TNotifyEvent read FOnDestroy write SetOnDestroy;
|
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-uses UResourceStrings, UGraph, Types, Dialogs;
|
|
|
+uses UResourceStrings, UGraph, Types, Dialogs, BGRATransform, BGRALayerOriginal, UImageDiff;
|
|
|
|
|
|
{ TLayerAction }
|
|
|
|
|
|
function TLayerAction.GetSelectedImageLayer: TBGRABitmap;
|
|
|
begin
|
|
|
+ result := CurrentState.SelectedImageLayer;
|
|
|
+ if not Assigned(result) then
|
|
|
+ raise exception.Create('No image layer selected');
|
|
|
NeedSelectedLayerBackup;
|
|
|
- result := FImage.GetSelectedImageLayer;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetCurrentSelection: TBGRABitmap;
|
|
|
begin
|
|
|
- NeedSelectionBackup;
|
|
|
- result := fImage.currentSelection;
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
+ result := CurrentState.SelectionMask;
|
|
|
+end;
|
|
|
+
|
|
|
+function TLayerAction.GetCurrentState: TImageState;
|
|
|
+begin
|
|
|
+ result := FImageState;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetBackupSelectedLayer: TBGRABitmap;
|
|
@@ -104,13 +128,13 @@ end;
|
|
|
|
|
|
function TLayerAction.GetBackupDrawingLayer: TBGRABitmap;
|
|
|
begin
|
|
|
- if FImage.SelectionEmpty then result := BackupSelectedLayer else
|
|
|
+ if CurrentState.SelectionMaskEmpty then result := BackupSelectedLayer else
|
|
|
result := BackupSelectionLayer;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetBackupSelection: TBGRABitmap;
|
|
|
begin
|
|
|
- NeedSelectionBackup;
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
result := FBackupSelection;
|
|
|
end;
|
|
|
|
|
@@ -122,23 +146,41 @@ end;
|
|
|
|
|
|
function TLayerAction.GetDrawingLayer: TBGRABitmap;
|
|
|
begin
|
|
|
- if FImage.SelectionEmpty then result := GetSelectedImageLayer else
|
|
|
+ if CurrentState.SelectionMaskEmpty then result := GetSelectedImageLayer else
|
|
|
result := GetOrCreateSelectionLayer;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetSelectedImageLayerOffset: TPoint;
|
|
|
begin
|
|
|
- result := FImage.LayerOffset[FImage.currentImageLayerIndex];
|
|
|
+ result := CurrentState.LayerOffset[CurrentState.SelectedImageLayerIndex];
|
|
|
+end;
|
|
|
+
|
|
|
+function TLayerAction.GetSelectionLayerBounds: TRect;
|
|
|
+begin
|
|
|
+ result := CurrentState.GetSelectionLayerBounds;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetSelectionTransform: TAffineMatrix;
|
|
|
begin
|
|
|
- result := FImage.SelectionTransform;
|
|
|
+ result:= CurrentState.SelectionTransform;
|
|
|
end;
|
|
|
|
|
|
-procedure TLayerAction.SetSelectionTransform(AValue: TAffineMatrix);
|
|
|
+procedure TLayerAction.SetOnDestroy(AValue: TNotifyEvent);
|
|
|
begin
|
|
|
- FImage.SelectionTransform := AValue;
|
|
|
+ if FOnDestroy=AValue then Exit;
|
|
|
+ FOnDestroy:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TLayerAction.SetOnNotifyChange(AValue: TNotifyChangeEvent);
|
|
|
+begin
|
|
|
+ if FOnNotifyChange=AValue then Exit;
|
|
|
+ FOnNotifyChange:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TLayerAction.SetOnNotifyUndo(AValue: TNotifyUndoEvent);
|
|
|
+begin
|
|
|
+ if FOnNotifyUndo=AValue then Exit;
|
|
|
+ FOnNotifyUndo:=AValue;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.Cancel;
|
|
@@ -146,16 +188,22 @@ begin
|
|
|
if FDone then raise Exception.Create('Already done');
|
|
|
RestoreSelectedLayer;
|
|
|
RestoreSelectionLayer;
|
|
|
- RestoreSelection;
|
|
|
+ RestoreSelectionMask;
|
|
|
+ CurrentState.SelectionTransform := FBackupSelectionTransform;
|
|
|
+ if Assigned(FPrediff) then
|
|
|
+ begin
|
|
|
+ FPrediff.UnapplyTo(CurrentState);
|
|
|
+ FreeAndNil(FPrediff);
|
|
|
+ end;
|
|
|
FDone := true;
|
|
|
end;
|
|
|
|
|
|
-procedure TLayerAction.NeedSelectionBackup;
|
|
|
+procedure TLayerAction.NeedSelectionMaskBackup;
|
|
|
begin
|
|
|
- if not FBackupSelectionDefined then
|
|
|
+ if not FBackupSelectionMaskDefined then
|
|
|
begin
|
|
|
- FBackupSelection := DuplicateBitmap(FImage.currentSelection);
|
|
|
- FBackupSelectionDefined := true;
|
|
|
+ FBackupSelection := DuplicateBitmap(CurrentState.SelectionMask);
|
|
|
+ FBackupSelectionMaskDefined := true;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -163,7 +211,7 @@ procedure TLayerAction.NeedSelectedLayerBackup;
|
|
|
begin
|
|
|
if not FBackupSelectedLayerDefined then
|
|
|
begin
|
|
|
- FBackupSelectedLayer := DuplicateBitmap(FImage.GetSelectedImageLayer);
|
|
|
+ FBackupSelectedLayer := DuplicateBitmap(CurrentState.SelectedImageLayer);
|
|
|
FBackupSelectedLayerDefined := true;
|
|
|
end;
|
|
|
end;
|
|
@@ -172,30 +220,40 @@ procedure TLayerAction.NeedSelectionLayerBackup;
|
|
|
begin
|
|
|
if not FBackupSelectionLayerDefined then
|
|
|
begin
|
|
|
- FBackupSelectionLayer := DuplicateBitmap(FImage.GetSelectionLayerIfExists);
|
|
|
+ FBackupSelectionLayer := DuplicateBitmap(CurrentState.SelectionLayer);
|
|
|
FBackupSelectionLayerDefined := true;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-constructor TLayerAction.Create(AImage: TLazPaintImage);
|
|
|
+constructor TLayerAction.Create(AState: TImageState; AApplyOfsBefore: boolean);
|
|
|
+var
|
|
|
+ layerOfsDiff: TCustomImageDifference;
|
|
|
begin
|
|
|
- if AImage <> nil then
|
|
|
- begin
|
|
|
- if not AImage.CheckNoAction(True) then
|
|
|
- raise exception.Create(rsConflictingActions);
|
|
|
- end;
|
|
|
- FImage := AImage;
|
|
|
- FImage.ActionInProgress := self;
|
|
|
+ FImageState := AState;
|
|
|
FBackupSelectedLayer := nil;
|
|
|
FBackupSelection := nil;
|
|
|
FBackupSelectionLayer := nil;
|
|
|
FBackupSelectedLayerDefined := false;
|
|
|
- FBackupSelectionDefined := false;
|
|
|
+ FBackupSelectionMaskDefined := false;
|
|
|
FBackupSelectionLayerDefined := false;
|
|
|
- FSelectedLayerChangedArea := EmptyRect;
|
|
|
+ FBackupSelectionTransform := CurrentState.SelectionTransform;
|
|
|
+ FSelectedImageLayerChangedArea := EmptyRect;
|
|
|
FSelectionLayerChangedArea := EmptyRect;
|
|
|
- FSelectionChangedArea := EmptyRect;
|
|
|
+ FSelectionMaskChangedArea := EmptyRect;
|
|
|
FDone := false;
|
|
|
+ FPrediff := TComposedImageDifference.Create;
|
|
|
+ if AApplyOfsBefore then
|
|
|
+ begin
|
|
|
+ with CurrentState.LayerOffset[CurrentState.SelectedImageLayerIndex] do
|
|
|
+ layerOfsDiff := CurrentState.ComputeLayerOffsetDifference(X,Y);
|
|
|
+ if layerOfsDiff.IsIdentity then FreeAndNil(layerOfsDiff)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ layerOfsDiff.ApplyTo(CurrentState);
|
|
|
+ FPrediff.Add(layerOfsDiff);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if FPrediff.Count = 0 then FreeAndNil(FPrediff);
|
|
|
end;
|
|
|
|
|
|
destructor TLayerAction.Destroy;
|
|
@@ -204,67 +262,66 @@ begin
|
|
|
FBackupSelectedLayer.Free;
|
|
|
FBackupSelection.Free;
|
|
|
FBackupSelectionLayer.Free;
|
|
|
- if FImage <> nil then
|
|
|
- begin
|
|
|
- if FImage.ActionInProgress = self then
|
|
|
- FImage.ActionInProgress := nil;
|
|
|
- end;
|
|
|
+ if Assigned(FOnDestroy) then FOnDestroy(self);
|
|
|
inherited Destroy;
|
|
|
end;
|
|
|
|
|
|
-procedure TLayerAction.ReplaceDrawingLayer(bmp: TBGRABitmap; AOwned: boolean);
|
|
|
-begin
|
|
|
- FImage.ReplaceDrawingLayer(bmp,AOwned);
|
|
|
-end;
|
|
|
-
|
|
|
procedure TLayerAction.ReplaceCurrentSelection(AValue: TBGRABitmap);
|
|
|
begin
|
|
|
- NeedSelectionBackup;
|
|
|
- if (AValue.Width = FImage.CurrentSelection.Width) and
|
|
|
- (AValue.Height = FImage.CurrentSelection.Height) then
|
|
|
- NotifyChange(FImage.CurrentSelection, AValue.GetDifferenceBounds(FImage.CurrentSelection))
|
|
|
+ if AValue = CurrentState.SelectionMask then exit;
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
+ if Assigned(AValue) and Assigned(CurrentState.SelectionMask) and
|
|
|
+ (AValue.Width = CurrentState.SelectionMask.Width) and
|
|
|
+ (AValue.Height = CurrentState.SelectionMask.Height) then
|
|
|
+ NotifyChange(CurrentState.SelectionMask, AValue.GetDifferenceBounds(CurrentState.SelectionMask))
|
|
|
else
|
|
|
begin
|
|
|
- NotifyChange(FImage.CurrentSelection, rect(0,0,FImage.CurrentSelection.Width,FImage.CurrentSelection.Height));
|
|
|
- NotifyChange(AValue, rect(0,0,AValue.Width,AValue.Height));
|
|
|
+ if Assigned(CurrentState.SelectionMask) then
|
|
|
+ NotifyChange(CurrentState.SelectionMask, rect(0,0,CurrentState.SelectionMask.Width,CurrentState.SelectionMask.Height));
|
|
|
+ if Assigned(AValue) then
|
|
|
+ NotifyChange(AValue, rect(0,0,AValue.Width,AValue.Height));
|
|
|
end;
|
|
|
- FImage.ReplaceCurrentSelection(AValue);
|
|
|
+ CurrentState.SelectionMask.Free;
|
|
|
+ CurrentState.SelectionMask := AValue
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.NotifyChange(ADest: TBGRABitmap; ARect: TRect);
|
|
|
begin
|
|
|
if ADest = nil then exit;
|
|
|
- if not IntersectRect(ARect, ARect, rect(0,0,FImage.Width,FImage.Height)) then exit;
|
|
|
- if ADest = FImage.CurrentSelection then
|
|
|
- FSelectionChangedArea := RectUnion(FSelectionChangedArea, ARect)
|
|
|
- else if ADest = FImage.GetSelectedImageLayer then
|
|
|
- FSelectedLayerChangedArea := RectUnion(FSelectedLayerChangedArea, ARect)
|
|
|
- else if ADest = FImage.GetSelectionLayerIfExists then
|
|
|
+ if not IntersectRect(ARect, ARect, rect(0,0,CurrentState.Width,CurrentState.Height)) then exit;
|
|
|
+ if ADest = CurrentState.SelectionMask then
|
|
|
+ FSelectionMaskChangedArea := RectUnion(FSelectionMaskChangedArea, ARect)
|
|
|
+ else if ADest = CurrentState.SelectedImageLayer then
|
|
|
+ FSelectedImageLayerChangedArea := RectUnion(FSelectedImageLayerChangedArea, ARect)
|
|
|
+ else if ADest = CurrentState.SelectionLayer then
|
|
|
FSelectionLayerChangedArea := RectUnion(FSelectionLayerChangedArea, ARect);
|
|
|
+ if Assigned(FOnNotifyChange) then
|
|
|
+ FOnNotifyChange(self, ADest, ARect);
|
|
|
end;
|
|
|
|
|
|
-procedure TLayerAction.RestoreSelection;
|
|
|
+procedure TLayerAction.RestoreSelectionMask;
|
|
|
var prevClip: TRect;
|
|
|
begin
|
|
|
- if FBackupSelectionDefined then
|
|
|
+ if FBackupSelectionMaskDefined then
|
|
|
begin
|
|
|
- if not AllChangesNotified then FSelectionChangedArea := rect(0,0,FImage.Width,FImage.Height);
|
|
|
- if IsRectEmpty(FSelectionChangedArea) then exit;
|
|
|
- prevClip := FImage.CurrentSelection.ClipRect;
|
|
|
- FImage.CurrentSelection.ClipRect := FSelectionChangedArea;
|
|
|
+ if not ChangeBoundsNotified then FSelectionMaskChangedArea := rect(0,0,CurrentState.Width,CurrentState.Height);
|
|
|
+ if IsRectEmpty(FSelectionMaskChangedArea) then exit;
|
|
|
+ prevClip := CurrentState.SelectionMask.ClipRect;
|
|
|
+ CurrentState.SelectionMask.ClipRect := FSelectionMaskChangedArea;
|
|
|
if Assigned(FBackupSelection) then
|
|
|
- FImage.CurrentSelection.PutImage(0,0,FBackupSelection,dmSet)
|
|
|
+ CurrentState.SelectionMask.PutImage(0,0,FBackupSelection,dmSet)
|
|
|
else
|
|
|
- FImage.CurrentSelection.FillRect(0,0,FImage.Width,FImage.Height,BGRABlack,dmSet);
|
|
|
- FImage.CurrentSelection.ClipRect := prevClip;
|
|
|
- FImage.SelectionMayChange(FSelectionChangedArea);
|
|
|
- FSelectionChangedArea := EmptyRect;
|
|
|
+ CurrentState.SelectionMask.FillRect(0,0,CurrentState.Width,CurrentState.Height,BGRABlack,dmSet);
|
|
|
+ CurrentState.SelectionMask.ClipRect := prevClip;
|
|
|
+ If Assigned(FOnNotifyChange) then
|
|
|
+ FOnNotifyChange(self, CurrentState.SelectionMask, FSelectionMaskChangedArea);
|
|
|
+ FSelectionMaskChangedArea := EmptyRect;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.RestoreDrawingLayer;
|
|
|
begin
|
|
|
- if FImage.SelectionEmpty then RestoreSelectedLayer
|
|
|
+ if CurrentState.SelectionMaskEmpty then RestoreSelectedLayer
|
|
|
else RestoreSelectionLayer;
|
|
|
end;
|
|
|
|
|
@@ -273,35 +330,37 @@ var prevClip: TRect;
|
|
|
begin
|
|
|
if FBackupSelectedLayerDefined then
|
|
|
begin
|
|
|
- if not AllChangesNotified then FSelectedLayerChangedArea := rect(0,0,FImage.Width,FImage.Height);
|
|
|
- if IsRectEmpty(FSelectedLayerChangedArea) then exit;
|
|
|
- prevClip := FImage.GetSelectedImageLayer.ClipRect;
|
|
|
- FImage.GetSelectedImageLayer.ClipRect := FSelectedLayerChangedArea;
|
|
|
+ if not ChangeBoundsNotified then FSelectedImageLayerChangedArea := rect(0,0,CurrentState.Width,CurrentState.Height);
|
|
|
+ if IsRectEmpty(FSelectedImageLayerChangedArea) then exit;
|
|
|
+ prevClip := CurrentState.SelectedImageLayer.ClipRect;
|
|
|
+ CurrentState.SelectedImageLayer.ClipRect := FSelectedImageLayerChangedArea;
|
|
|
if Assigned(FBackupSelectedLayer) then
|
|
|
- FImage.GetSelectedImageLayer.PutImage(0,0,FBackupSelectedLayer,dmSet)
|
|
|
+ CurrentState.SelectedImageLayer.PutImage(0,0,FBackupSelectedLayer,dmSet)
|
|
|
else
|
|
|
- FImage.GetSelectedImageLayer.FillRect(0,0,FImage.Width,FImage.Height,BGRAPixelTransparent,dmSet);
|
|
|
- FImage.GetSelectedImageLayer.ClipRect := prevClip;
|
|
|
- FImage.LayerMayChange(FImage.GetSelectedImageLayer,FSelectedLayerChangedArea);
|
|
|
- FSelectedLayerChangedArea := EmptyRect;
|
|
|
+ CurrentState.SelectedImageLayer.FillRect(0,0,CurrentState.Width,CurrentState.Height,BGRAPixelTransparent,dmSet);
|
|
|
+ CurrentState.SelectedImageLayer.ClipRect := prevClip;
|
|
|
+ If Assigned(FOnNotifyChange) then
|
|
|
+ FOnNotifyChange(self, CurrentState.SelectedImageLayer, FSelectedImageLayerChangedArea);
|
|
|
+ FSelectedImageLayerChangedArea := EmptyRect;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.RestoreSelectionLayer;
|
|
|
var prevClip: TRect;
|
|
|
begin
|
|
|
- if FBackupSelectionLayerDefined and (GetSelectionLayerIfExists <> nil) then
|
|
|
+ if FBackupSelectionLayerDefined and (CurrentState.SelectionLayer <> nil) then
|
|
|
begin
|
|
|
- if not AllChangesNotified then FSelectionLayerChangedArea := rect(0,0,FImage.Width,FImage.Height);
|
|
|
+ if not ChangeBoundsNotified then FSelectionLayerChangedArea := rect(0,0,CurrentState.Width,CurrentState.Height);
|
|
|
if IsRectEmpty(FSelectionLayerChangedArea) then exit;
|
|
|
- prevClip := FImage.GetSelectionLayerIfExists.ClipRect;
|
|
|
- FImage.GetSelectionLayerIfExists.ClipRect := FSelectionLayerChangedArea;
|
|
|
+ prevClip := CurrentState.SelectionLayer.ClipRect;
|
|
|
+ CurrentState.SelectionLayer.ClipRect := FSelectionLayerChangedArea;
|
|
|
if Assigned(FBackupSelectionLayer) then
|
|
|
- FImage.GetSelectionLayerIfExists.PutImage(0,0,FBackupSelectionLayer,dmSet)
|
|
|
+ CurrentState.SelectionLayer.PutImage(0,0,FBackupSelectionLayer,dmSet)
|
|
|
else
|
|
|
- FImage.GetSelectionLayerIfExists.FillRect(0,0,FImage.Width,FImage.Height,BGRAPixelTransparent,dmSet);
|
|
|
- FImage.GetSelectionLayerIfExists.ClipRect := prevClip;
|
|
|
- FImage.LayerMayChange(FImage.GetSelectionLayerIfExists,FSelectionLayerChangedArea);
|
|
|
+ CurrentState.SelectionLayer.FillRect(0,0,CurrentState.Width,CurrentState.Height,BGRAPixelTransparent,dmSet);
|
|
|
+ CurrentState.SelectionLayer.ClipRect := prevClip;
|
|
|
+ If Assigned(FOnNotifyChange) then
|
|
|
+ FOnNotifyChange(self, CurrentState.SelectionLayer, FSelectionLayerChangedArea);
|
|
|
FSelectionLayerChangedArea := EmptyRect;
|
|
|
end;
|
|
|
end;
|
|
@@ -314,76 +373,131 @@ end;
|
|
|
|
|
|
procedure TLayerAction.QuerySelection;
|
|
|
begin
|
|
|
- NeedSelectionBackup;
|
|
|
- FImage.QuerySelection;
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
+ CurrentState.QuerySelectionMask;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.RemoveSelection;
|
|
|
+var bounds: TRect;
|
|
|
begin
|
|
|
- if not FImage.SelectionEmpty or (FImage.GetSelectionLayerIfExists <> nil) then
|
|
|
+ if not CurrentState.SelectionMaskEmpty or (CurrentState.SelectionLayer <> nil) then
|
|
|
begin
|
|
|
- NeedSelectionBackup;
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
NeedSelectionLayerBackup;
|
|
|
- FImage.RemoveSelection;
|
|
|
+ bounds := CurrentState.GetTransformedSelectionMaskBounds;
|
|
|
+ NotifyChange(CurrentState.SelectionLayer, bounds);
|
|
|
+ CurrentState.RemoveSelection;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.EraseSelectionInBitmap;
|
|
|
+var offs: TPoint;
|
|
|
+ r: TRect;
|
|
|
begin
|
|
|
- if not FImage.SelectionEmpty then
|
|
|
+ if not CurrentState.SelectionMaskEmpty then
|
|
|
begin
|
|
|
NeedSelectedLayerBackup;
|
|
|
- FImage.EraseSelectionInBitmap;
|
|
|
+ offs := CurrentState.LayerOffset[CurrentState.SelectedImageLayerIndex];
|
|
|
+ r := CurrentState.GetSelectionMaskBounds;
|
|
|
+ SubstractMask(GetSelectedImageLayer,-offs.X+r.left,-offs.Y+r.top,CurrentState.SelectionMask,r);
|
|
|
+ OffsetRect(r,-offs.x,-offs.y);
|
|
|
+ NotifyChange(GetSelectedImageLayer,r);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TLayerAction.MergeWithSelection(AApplyMask: boolean);
|
|
|
+var offs: TPoint;
|
|
|
+ sourceRect,destRect: TRect;
|
|
|
+begin
|
|
|
+ if not CurrentState.SelectionLayerEmpty and not (AApplyMask and CurrentState.SelectionMaskEmpty) then
|
|
|
+ begin
|
|
|
+ sourceRect := CurrentState.GetSelectionLayerBounds;
|
|
|
+ if AApplyMask then
|
|
|
+ begin
|
|
|
+ CurrentState.SelectionLayer.ApplyMask(CurrentState.SelectionMask,CurrentState.GetSelectionLayerBounds);
|
|
|
+ IntersectRect(sourceRect,sourceRect,CurrentState.GetSelectionMaskBounds);
|
|
|
+ NotifyChange(CurrentState.SelectionLayer,CurrentState.GetSelectionLayerBounds);
|
|
|
+ end;
|
|
|
+ offs := CurrentState.LayerOffset[CurrentState.SelectedImageLayerIndex];
|
|
|
+ destRect := sourceRect;
|
|
|
+ OffsetRect(destRect, -offs.x,-offs.y);
|
|
|
+ GetSelectedImageLayer.PutImagePart(destRect.left,destRect.top,CurrentState.SelectionLayer,sourceRect,dmDrawWithTransparency);
|
|
|
+ NotifyChange(GetSelectedImageLayer,destRect);
|
|
|
+ CurrentState.ReplaceSelectionLayer(nil,true);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.ReleaseSelection;
|
|
|
var bounds: TRect;
|
|
|
begin
|
|
|
- if not FImage.SelectionEmpty then
|
|
|
+ if not CurrentState.SelectionMaskEmpty then
|
|
|
begin
|
|
|
- bounds := FImage.SelectionBounds;
|
|
|
- NeedSelectionBackup;
|
|
|
- NotifyChange(FImage.CurrentSelection, bounds);
|
|
|
- if FImage.GetSelectionLayerIfExists <> nil then
|
|
|
+ bounds := CurrentState.GetSelectionMaskBounds;
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
+ NotifyChange(CurrentState.SelectionMask, bounds);
|
|
|
+ if CurrentState.SelectionLayer <> nil then
|
|
|
begin
|
|
|
NeedSelectedLayerBackup;
|
|
|
- NotifyChange(FImage.GetSelectedImageLayer, bounds);
|
|
|
+ NotifyChange(CurrentState.SelectedImageLayer, bounds);
|
|
|
NeedSelectionLayerBackup;
|
|
|
- NotifyChange(FImage.GetSelectionLayerIfExists, bounds);
|
|
|
+ NotifyChange(CurrentState.SelectionLayer, bounds);
|
|
|
end;
|
|
|
- FImage.ReleaseSelection;
|
|
|
+
|
|
|
+ ApplySelectionMask;
|
|
|
+ CurrentState.SelectionMask.Free;
|
|
|
+ CurrentState.SelectionMask := nil;
|
|
|
+ ApplySelectionTransform(False);
|
|
|
+ MergeWithSelection(False);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.RetrieveSelection;
|
|
|
+var temp : TBGRABitmap;
|
|
|
+ offs: TPoint;
|
|
|
+ r, maskBounds: TRect;
|
|
|
begin
|
|
|
- if not FImage.SelectionEmpty then
|
|
|
+ if not CurrentState.SelectionMaskEmpty then
|
|
|
begin
|
|
|
NeedSelectedLayerBackup;
|
|
|
NeedSelectionLayerBackup;
|
|
|
- FImage.RetrieveSelection;
|
|
|
+ ApplySelectionTransform;
|
|
|
+ MergeWithSelection;
|
|
|
+ offs := CurrentState.LayerOffset[CurrentState.SelectedImageLayerIndex];
|
|
|
+ maskBounds := CurrentState.GetSelectionMaskBounds;
|
|
|
+ r := maskBounds;
|
|
|
+ OffsetRect(r, -offs.x, -offs.y);
|
|
|
+ IntersectRect(r, r, rect(0,0,GetSelectedImageLayer.Width,GetSelectedImageLayer.Height));
|
|
|
+ temp := TBGRABitmap.Create(CurrentState.Width,CurrentState.Height);
|
|
|
+ temp.PutImagePart(r.left+offs.x,r.top+offs.y,GetSelectedImageLayer,r,dmSet);
|
|
|
+ temp.ApplyMask(CurrentState.SelectionMask,maskBounds);
|
|
|
+ BGRAReplace(CurrentState.SelectionLayer,temp);
|
|
|
+ NotifyChange(CurrentState.SelectionLayer,maskBounds);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-function TLayerAction.RetrieveSelectionIfLayerEmpty(removeFromBitmap: boolean
|
|
|
- ): boolean;
|
|
|
+function TLayerAction.RetrieveSelectionIfLayerEmpty(removeFromBitmap: boolean): boolean;
|
|
|
begin
|
|
|
NeedSelectedLayerBackup;
|
|
|
NeedSelectionLayerBackup;
|
|
|
- result := FImage.RetrieveSelectionIfLayerEmpty(removeFromBitmap);
|
|
|
+ if CurrentState.SelectionLayerEmpty then
|
|
|
+ begin
|
|
|
+ RetrieveSelection;
|
|
|
+ if removeFromBitmap then EraseSelectionInBitmap;
|
|
|
+ result := true;
|
|
|
+ end
|
|
|
+ else result := false;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetOrCreateSelectionLayer: TBGRABitmap;
|
|
|
begin
|
|
|
NeedSelectionLayerBackup;
|
|
|
- result := FImage.GetOrCreateSelectionLayer;
|
|
|
+ result := CurrentState.GetOrCreateSelectionLayer;
|
|
|
end;
|
|
|
|
|
|
function TLayerAction.GetSelectionLayerIfExists: TBGRABitmap;
|
|
|
begin
|
|
|
NeedSelectionLayerBackup;
|
|
|
- result := FImage.GetSelectionLayerIfExists;
|
|
|
+ result := CurrentState.SelectionLayer;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.ReplaceSelectionLayer(bmp: TBGRABitmap; AOwned: boolean);
|
|
@@ -396,38 +510,61 @@ begin
|
|
|
NotifyChange(dest, bmp.GetDifferenceBounds(dest))
|
|
|
else
|
|
|
begin
|
|
|
- if dest <> nil then NotifyChange(dest, rect(0,0,dest.Width,dest.Height));
|
|
|
- if bmp <> nil then NotifyChange(bmp, rect(0,0,bmp.Width,bmp.Height));
|
|
|
+ if dest <> nil then NotifyChange(dest, dest.GetImageBounds);
|
|
|
+ if bmp <> nil then NotifyChange(bmp, bmp.GetImageBounds);
|
|
|
end;
|
|
|
- FImage.ReplaceSelectionLayer(bmp,AOwned);
|
|
|
+ CurrentState.ReplaceSelectionLayer(bmp,AOwned);
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.ApplySelectionTransform(ApplyToMask: boolean);
|
|
|
+var
|
|
|
+ newBmp: TBGRABitmap;
|
|
|
+ newLeft, newTop: integer;
|
|
|
+ r: TRect;
|
|
|
begin
|
|
|
- NeedSelectionLayerBackup;
|
|
|
- FImage.ApplySelectionTransform(ApplyToMask);
|
|
|
+ if not IsAffineMatrixIdentity(CurrentState.SelectionTransform) then
|
|
|
+ begin
|
|
|
+ if ApplyToMask and not CurrentState.SelectionMaskEmpty then
|
|
|
+ begin
|
|
|
+ NeedSelectionMaskBackup;
|
|
|
+ CurrentState.ComputeTransformedSelectionMask(newBmp,newLeft,newTop);
|
|
|
+ r := CurrentState.GetSelectionMaskBounds;
|
|
|
+ CurrentState.SelectionMask.FillRect(r, BGRABlack, dmSet);
|
|
|
+ NotifyChange(CurrentState.SelectionMask, r);
|
|
|
+ CurrentState.SelectionMask.PutImage(newLeft,newTop,newBmp,dmSet);
|
|
|
+ newBmp.Free;
|
|
|
+ CurrentState.DiscardSelectionMaskBounds;
|
|
|
+ end;
|
|
|
+ if not CurrentState.SelectionLayerEmpty then
|
|
|
+ begin
|
|
|
+ NeedSelectionLayerBackup;
|
|
|
+ CurrentState.ComputeTransformedSelectionLayer(newBmp,newLeft,newTop);
|
|
|
+ r := CurrentState.GetSelectionLayerBounds;
|
|
|
+ CurrentState.SelectionLayer.FillRect(r, BGRAPixelTransparent, dmSet);
|
|
|
+ NotifyChange(CurrentState.SelectionLayer, r);
|
|
|
+ CurrentState.SelectionLayer.PutImage(newLeft,newTop,newBmp,dmSet);
|
|
|
+ newBmp.Free;
|
|
|
+ CurrentState.DiscardSelectionLayerBounds;
|
|
|
+ end;
|
|
|
+ CurrentState.SelectionTransform := AffineMatrixIdentity;
|
|
|
+ NotifyChange(CurrentState.SelectionMask, CurrentState.GetSelectionMaskBounds);
|
|
|
+ NotifyChange(CurrentState.SelectionLayer, CurrentState.GetSelectionLayerBounds);
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.ApplySelectionMask;
|
|
|
+var r: TRect;
|
|
|
begin
|
|
|
NeedSelectionLayerBackup;
|
|
|
- FImage.ApplySelectionMask;
|
|
|
-end;
|
|
|
-
|
|
|
-procedure TLayerAction.ReplaceSelectedLayer(AValue: TBGRABitmap; AOwned: boolean);
|
|
|
-var dest: TBGRABitmap;
|
|
|
-begin
|
|
|
- NeedSelectedLayerBackup;
|
|
|
- dest := GetSelectedImageLayer;
|
|
|
- if (dest <> nil) and (AValue.Width = dest.Width) and
|
|
|
- (AValue.Height = dest.Height) then
|
|
|
- NotifyChange(dest, AValue.GetDifferenceBounds(dest))
|
|
|
- else
|
|
|
+ if (CurrentState.SelectionMask <> nil) and (CurrentState.SelectionLayer <> nil) then
|
|
|
begin
|
|
|
- if dest <> nil then NotifyChange(dest, rect(0,0,dest.Width,dest.Height));
|
|
|
- NotifyChange(AValue, rect(0,0,AValue.Width,AValue.Height));
|
|
|
+ r := GetSelectionLayerBounds;
|
|
|
+ if not IsRectEmpty(r) then
|
|
|
+ begin
|
|
|
+ GetOrCreateSelectionLayer.ApplyMask(CurrentState.SelectionMask,r);
|
|
|
+ NotifyChange(CurrentState.GetOrCreateSelectionLayer,r);
|
|
|
+ end;
|
|
|
end;
|
|
|
- FImage.ReplaceSelectedLayer(AValue, AOwned);
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.Validate;
|
|
@@ -441,41 +578,63 @@ procedure TLayerAction.PartialCancel;
|
|
|
begin
|
|
|
RestoreSelectedLayer;
|
|
|
RestoreSelectionLayer;
|
|
|
- RestoreSelection;
|
|
|
+ RestoreSelectionMask;
|
|
|
end;
|
|
|
|
|
|
procedure TLayerAction.PartialValidate(ADiscardBackup: boolean = false);
|
|
|
-begin
|
|
|
- if FBackupSelectedLayerDefined or FBackupSelectionDefined or FBackupSelectionLayerDefined then
|
|
|
+var
|
|
|
+ prevLayerOriginalMatrix: TAffineMatrix;
|
|
|
+ prevLayerOriginaData: TStream;
|
|
|
+ imgDiff: TImageLayerStateDifference;
|
|
|
+ composedDiff: TComposedImageDifference;
|
|
|
+ ofs: TPoint;
|
|
|
+ applyOfs: TCustomImageDifference;
|
|
|
+ appendOfs, owned: boolean;
|
|
|
+begin
|
|
|
+ if FBackupSelectedLayerDefined or FBackupSelectionMaskDefined or FBackupSelectionLayerDefined then
|
|
|
begin
|
|
|
- if AllChangesNotified then
|
|
|
- if IsRectEmpty(FSelectedLayerChangedArea) and IsRectEmpty(FSelectionChangedArea) and
|
|
|
+ if ChangeBoundsNotified then
|
|
|
+ if IsRectEmpty(FSelectedImageLayerChangedArea) and IsRectEmpty(FSelectionMaskChangedArea) and
|
|
|
IsRectEmpty(FSelectionLayerChangedArea) then exit;
|
|
|
if FBackupSelectionLayerDefined then
|
|
|
begin
|
|
|
- FImage.DiscardSelectionLayerBounds;
|
|
|
- if FImage.SelectionLayerIsEmpty then
|
|
|
- FImage.ReplaceSelectionLayer(nil,True);
|
|
|
+ CurrentState.DiscardSelectionLayerBounds;
|
|
|
+ if CurrentState.SelectionLayerEmpty then
|
|
|
+ CurrentState.ReplaceSelectionLayer(nil,True);
|
|
|
end;
|
|
|
- if FBackupSelectionDefined then
|
|
|
+ if FBackupSelectionMaskDefined then
|
|
|
begin
|
|
|
- FImage.DiscardSelectionBounds;
|
|
|
- if FImage.SelectionEmpty then
|
|
|
- begin
|
|
|
- FImage.ReplaceSelectionLayer(nil,true);
|
|
|
- FImage.ReplaceCurrentSelection(nil);
|
|
|
- end;
|
|
|
+ CurrentState.DiscardSelectionMaskBounds;
|
|
|
+ if CurrentState.SelectionMaskEmpty then
|
|
|
+ CurrentState.RemoveSelection;
|
|
|
+ end;
|
|
|
+ //original will be backed up if there are changes in the raster image of the selected layer
|
|
|
+ if CurrentState.LayerOriginalDefined[CurrentState.SelectedImageLayerIndex] and
|
|
|
+ (FBackupSelectedLayerDefined or not IsRectEmpty(FSelectedImageLayerChangedArea)) then
|
|
|
+ begin
|
|
|
+ prevLayerOriginaData:= TMemoryStream.Create;
|
|
|
+ CurrentState.SaveOriginalToStream(prevLayerOriginaData);
|
|
|
+ prevLayerOriginalMatrix:= CurrentState.LayerOriginalMatrix[CurrentState.SelectedImageLayerIndex];
|
|
|
+ CurrentState.DiscardOriginal(false);
|
|
|
+ end else
|
|
|
+ begin
|
|
|
+ prevLayerOriginaData := nil;
|
|
|
+ prevLayerOriginalMatrix:= AffineMatrixIdentity;
|
|
|
end;
|
|
|
- if AllChangesNotified then
|
|
|
- FImage.AddLayerUndo(FBackupSelectedLayer, FSelectedLayerChangedArea,
|
|
|
- FBackupSelection, FSelectionChangedArea,
|
|
|
- FBackupSelectionLayer, FSelectionLayerChangedArea)
|
|
|
- else
|
|
|
- FImage.AddLayerUndo(FBackupSelectedLayer, FBackupSelectedLayerDefined,
|
|
|
- FBackupSelection, FBackupSelectionDefined,
|
|
|
- FBackupSelectionLayer, FBackupSelectionLayerDefined);
|
|
|
|
|
|
- FImage.OnImageChanged.NotifyObservers;
|
|
|
+ if ChangeBoundsNotified then
|
|
|
+ imgDiff := CurrentState.ComputeLayerDifference(FBackupSelectedLayer, FSelectedImageLayerChangedArea,
|
|
|
+ FBackupSelection, FSelectionMaskChangedArea,
|
|
|
+ FBackupSelectionLayer, FSelectionLayerChangedArea,
|
|
|
+ FBackupSelectionTransform,
|
|
|
+ prevLayerOriginaData, prevLayerOriginalMatrix) as TImageLayerStateDifference
|
|
|
+ else
|
|
|
+ imgDiff := CurrentState.ComputeLayerDifference(FBackupSelectedLayer, FBackupSelectedLayerDefined,
|
|
|
+ FBackupSelection, FBackupSelectionMaskDefined,
|
|
|
+ FBackupSelectionLayer, FBackupSelectionLayerDefined,
|
|
|
+ FBackupSelectionTransform,
|
|
|
+ prevLayerOriginaData, prevLayerOriginalMatrix) as TImageLayerStateDifference;
|
|
|
+ if imgDiff.IsIdentity then FreeAndNil(imgDiff);
|
|
|
|
|
|
if ADiscardBackup then
|
|
|
begin
|
|
@@ -484,55 +643,112 @@ begin
|
|
|
FreeAndNil(FBackupSelection);
|
|
|
FBackupSelectedLayerDefined := false;
|
|
|
FBackupSelectedLayerDefined := false;
|
|
|
- FBackupSelectionDefined := false;
|
|
|
+ FBackupSelectionMaskDefined := false;
|
|
|
+
|
|
|
+ appendOfs:= Assigned(imgDiff) and imgDiff.ChangeImageLayer;
|
|
|
end else
|
|
|
begin
|
|
|
if FBackupSelectionLayerDefined then
|
|
|
begin
|
|
|
- if (FBackupSelectionLayer = nil) and (FImage.GetSelectionLayerIfExists <> nil) then
|
|
|
+ if (FBackupSelectionLayer = nil) and (CurrentState.SelectionLayer <> nil) then
|
|
|
begin
|
|
|
- if not FImage.SelectionLayerIsEmpty then
|
|
|
- FBackupSelectionLayer := Fimage.GetSelectionLayerIfExists.Duplicate as TBGRABitmap;
|
|
|
+ if not CurrentState.SelectionLayerEmpty then
|
|
|
+ FBackupSelectionLayer := CurrentState.SelectionLayer.Duplicate as TBGRABitmap;
|
|
|
end else
|
|
|
if Assigned(FBackupSelectionLayer) then
|
|
|
begin
|
|
|
- if AllChangesNotified then FBackupSelectionLayer.ClipRect := FSelectionLayerChangedArea;
|
|
|
- if Assigned(FImage.GetSelectionLayerIfExists) then
|
|
|
- FBackupSelectionLayer.PutImage(0,0,FImage.GetSelectionLayerIfExists,dmSet)
|
|
|
+ if ChangeBoundsNotified then FBackupSelectionLayer.ClipRect := FSelectionLayerChangedArea;
|
|
|
+ if Assigned(CurrentState.SelectionLayer) then
|
|
|
+ FBackupSelectionLayer.PutImage(0,0,CurrentState.SelectionLayer,dmSet)
|
|
|
else
|
|
|
- FBackupSelectionLayer.FillRect(0,0,FImage.Width,FImage.Height,BGRAPixelTransparent,dmSet);
|
|
|
+ FBackupSelectionLayer.FillRect(0,0,CurrentState.Width,CurrentState.Height,BGRAPixelTransparent,dmSet);
|
|
|
FBackupSelectionLayer.NoClip;
|
|
|
end;
|
|
|
FSelectionLayerChangedArea := EmptyRect;
|
|
|
end;
|
|
|
if FBackupSelectedLayerDefined then
|
|
|
begin
|
|
|
- if AllChangesNotified then FBackupSelectedLayer.ClipRect := FSelectedLayerChangedArea;
|
|
|
- if Assigned(FImage.GetSelectedImageLayer) then
|
|
|
- FBackupSelectedLayer.PutImage(0,0,FImage.GetSelectedImageLayer,dmSet)
|
|
|
+ if ChangeBoundsNotified then FBackupSelectedLayer.ClipRect := FSelectedImageLayerChangedArea;
|
|
|
+ if Assigned(CurrentState.SelectedImageLayer) then
|
|
|
+ FBackupSelectedLayer.PutImage(0,0,CurrentState.SelectedImageLayer,dmSet)
|
|
|
else
|
|
|
- FBackupSelectedLayer.FillRect(0,0,FImage.Width,FImage.Height,BGRAPixelTransparent,dmSet);
|
|
|
+ FBackupSelectedLayer.FillRect(0,0,CurrentState.Width,CurrentState.Height,BGRAPixelTransparent,dmSet);
|
|
|
FBackupSelectedLayer.NoClip;
|
|
|
- FSelectedLayerChangedArea := EmptyRect;
|
|
|
+ FSelectedImageLayerChangedArea := EmptyRect;
|
|
|
end;
|
|
|
- if FBackupSelectionDefined then
|
|
|
+ if FBackupSelectionMaskDefined then
|
|
|
begin
|
|
|
- if (FBackupSelection = nil) and (FImage.CurrentSelection <> nil) then
|
|
|
+ if (FBackupSelection = nil) and (CurrentState.SelectionMask <> nil) then
|
|
|
begin
|
|
|
- if not FImage.SelectionEmpty then
|
|
|
- FBackupSelection := Fimage.CurrentSelection.Duplicate as TBGRABitmap;
|
|
|
+ if not CurrentState.SelectionMaskEmpty then
|
|
|
+ FBackupSelection := CurrentState.SelectionMask.Duplicate as TBGRABitmap;
|
|
|
end else
|
|
|
if (FBackupSelection <> nil) then
|
|
|
begin
|
|
|
- if AllChangesNotified then FBackupSelection.ClipRect := FSelectionChangedArea;
|
|
|
- if Assigned(FImage.CurrentSelection) then
|
|
|
- FBackupSelection.PutImage(0,0,FImage.CurrentSelection,dmSet)
|
|
|
+ if ChangeBoundsNotified then FBackupSelection.ClipRect := FSelectionMaskChangedArea;
|
|
|
+ if Assigned(CurrentState.SelectionMask) then
|
|
|
+ FBackupSelection.PutImage(0,0,CurrentState.SelectionMask,dmSet)
|
|
|
else
|
|
|
- FBackupSelection.FillRect(0,0,FImage.Width,FImage.Height,BGRABlack,dmSet);
|
|
|
+ FBackupSelection.FillRect(0,0,CurrentState.Width,CurrentState.Height,BGRABlack,dmSet);
|
|
|
FBackupSelection.NoClip;
|
|
|
end;
|
|
|
- FSelectionChangedArea := EmptyRect;
|
|
|
+ FSelectionMaskChangedArea := EmptyRect;
|
|
|
+ end;
|
|
|
+
|
|
|
+ appendOfs := false;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if assigned(imgDiff) then
|
|
|
+ begin
|
|
|
+ if appendOfs or Assigned(FPrediff) then
|
|
|
+ begin
|
|
|
+ composedDiff := TComposedImageDifference.Create;
|
|
|
+ if Assigned(FPrediff) then
|
|
|
+ begin
|
|
|
+ composedDiff.AddRange(FPrediff);
|
|
|
+ FPrediff := nil;
|
|
|
+ end;
|
|
|
+ composedDiff.Add(imgDiff);
|
|
|
+ if appendOfs then
|
|
|
+ begin
|
|
|
+ ofs := CurrentState.LayerOffset[CurrentState.SelectedImageLayerIndex];
|
|
|
+ applyOfs:= CurrentState.ComputeLayerOffsetDifference(ofs.x, ofs.y);
|
|
|
+ if not applyOfs.IsIdentity then
|
|
|
+ begin
|
|
|
+ composedDiff.Add(applyOfs);
|
|
|
+ applyOfs.ApplyTo(CurrentState);
|
|
|
+ end else
|
|
|
+ applyOfs.Free;
|
|
|
+ end;
|
|
|
+ if Assigned(FOnNotifyUndo) then
|
|
|
+ begin
|
|
|
+ owned := false;
|
|
|
+ FOnNotifyUndo(self, composedDiff, owned);
|
|
|
+ if not owned then composedDiff.Free;
|
|
|
+ end;
|
|
|
+ end else
|
|
|
+ begin
|
|
|
+ if Assigned(FOnNotifyUndo) then
|
|
|
+ begin
|
|
|
+ owned := false;
|
|
|
+ FOnNotifyUndo(self, imgDiff, owned);
|
|
|
+ if not owned then imgDiff.Free;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ FBackupSelectionTransform := CurrentState.SelectionTransform;
|
|
|
+ end else
|
|
|
+ begin
|
|
|
+ if Assigned(FPrediff) then
|
|
|
+ begin
|
|
|
+ if Assigned(FOnNotifyUndo) then
|
|
|
+ begin
|
|
|
+ owned := false;
|
|
|
+ FOnNotifyUndo(self, FPrediff, owned);
|
|
|
+ if not owned then FPrediff.Free;
|
|
|
end;
|
|
|
+ FPrediff := nil;
|
|
|
end;
|
|
|
end;
|
|
|
end;
|