1 // SPDX-License-Identifier: GPL-3.0-only
2 unit UImageDiff;
3 
4 {$mode objfpc}
5 
6 interface
7 
8 uses
9   Classes, SysUtils, UStateType, BGRABitmap, BGRABitmapTypes, BGRALayers,
10   BGRALayerOriginal, LCVectorOriginal, UImageState;
11 
IsInverseImageDiffnull12 function IsInverseImageDiff(ADiff1, ADiff2: TCustomImageDifference): boolean;
TryCombineImageDiffnull13 function TryCombineImageDiff(ANewDiff, APrevDiff: TCustomImageDifference): boolean;
14 
15 type
16   { TInversibleStateDifference }
17 
18   TInversibleStateDifference = class(TCustomImageDifference)
19   private
20     FAction: TInversibleAction;
21     FLayerIndex: integer;
22   public
23     constructor Create(AState: TState; AAction: TInversibleAction; ALayerIndex : integer = -1);
24     procedure ApplyTo(AState: TState); override;
25     procedure UnApplyTo(AState: TState); override;
26     procedure ApplyAction(AState: TState; AAction: TInversibleAction; AInverse: boolean);
ToStringnull27     function ToString: ansistring; override;
28     property Action: TInversibleAction read FAction write FAction;
29     property LayerIndex: integer read FLayerIndex;
30   end;
31 
32   { TSelectCurrentLayer }
33 
34   TSelectCurrentLayer = class(TCustomImageDifference)
35   private
36     FPrevLayerIndex, FNewLayerIndex: integer;
37   protected
GetImageDifferenceKindnull38     function GetImageDifferenceKind: TImageDifferenceKind; override;
39   public
40     constructor Create(AState: TState; ANewLayerIndex: integer);
41     procedure ApplyTo(AState: TState); override;
42     procedure UnApplyTo(AState: TState); override;
ToStringnull43     function ToString: ansistring; override;
44   end;
45 
46 type
47   { TImageLayerStateDifference }
48 
49   TImageLayerStateDifference = class(TCustomImageDifference)
50   private
GetChangeImageLayernull51     function GetChangeImageLayer: boolean;
GetChangeSelectionLayernull52     function GetChangeSelectionLayer: boolean;
GetChangeSelectionMasknull53     function GetChangeSelectionMask: boolean;
54   protected
GetImageDifferenceKindnull55     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull56     function GetIsIdentity: boolean; override;
GetChangingBoundsDefinednull57     function GetChangingBoundsDefined: boolean; override;
GetChangingBoundsnull58     function GetChangingBounds: TRect; override;
GetLayerRectnull59     function GetLayerRect(AState: TImageState; AIndex: integer): TRect;
60     procedure EnsureLayerRect(AState: TImageState; AIndex: integer);
61     procedure Init(AToState: TState; APreviousImage: TBGRABitmap; APreviousImageChangeRect: TRect;
62         APreviousSelection: TBGRABitmap; APreviousSelectionChangeRect: TRect;
63         APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerChangeRect: TRect);
64   public
65     layerId: integer;
66     layerRect: TRect;
67     imageDiff, selectionLayerDiff: TImageDiff;
68     selectionMaskDiff: TImageDiff;
TryCompressnull69     function TryCompress: boolean; override;
70     procedure ApplyTo(AState: TState); override;
71     procedure UnapplyTo(AState: TState); override;
UsedMemorynull72     function UsedMemory: int64; override;
73     constructor Create(AFromState, AToState: TState);
74     constructor Create(AToState: TState; APreviousImage: TBGRABitmap; APreviousImageDefined: boolean;
75         APreviousSelection: TBGRABitmap; APreviousSelectionDefined: boolean;
76         APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerDefined: boolean); overload;
77     constructor Create(AToState: TState; APreviousImage: TBGRABitmap; APreviousImageChangeRect: TRect;
78         APreviousSelection: TBGRABitmap; APreviousSelectionChangeRect: TRect;
79         APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerChangeRect: TRect); overload;
ToStringnull80     function ToString: ansistring; override;
81     destructor Destroy; override;
82     property ChangeImageLayer: boolean read GetChangeImageLayer;
83     property ChangeSelectionMask: boolean read GetChangeSelectionMask;
84     property ChangeSelectionLayer: boolean read GetChangeSelectionLayer;
85   end;
86 
87   { TSetLayerNameStateDifference }
88 
89   TSetLayerNameStateDifference = class(TCustomImageDifference)
90   private
91     previousName,nextName: ansistring;
92     layerId: integer;
93   protected
GetImageDifferenceKindnull94     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull95     function GetIsIdentity: boolean; override;
96   public
97     constructor Create(ADestination: TState; ALayerId: integer; ANewName: ansistring);
98     procedure ApplyTo(AState: TState); override;
99     procedure UnapplyTo(AState: TState); override;
ToStringnull100     function ToString: ansistring; override;
101   end;
102 
103   { TSetLayerOpacityStateDifference }
104 
105   TSetLayerOpacityStateDifference = class(TCustomImageDifference)
106   private
107     previousOpacity,nextOpacity: byte;
108     layerId: integer;
109     layerBounds: TRect;
110   protected
GetImageDifferenceKindnull111     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetChangingBoundsnull112     function GetChangingBounds: TRect; override;
GetChangingBoundsDefinednull113     function GetChangingBoundsDefined: boolean; override;
GetIsIdentitynull114     function GetIsIdentity: boolean; override;
115   public
116     constructor Create(ADestination: TState; ALayerId: integer; ANewOpacity: byte);
117     procedure ApplyTo(AState: TState); override;
118     procedure UnapplyTo(AState: TState); override;
119   end;
120 
121   { TSetLayerOffsetStateDifference }
122 
123   TSetLayerOffsetStateDifference = class(TCustomImageDifference)
124   private
125     previousOffset,nextOffset: TPoint;
126     layerId: integer;
127   protected
GetImageDifferenceKindnull128     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull129     function GetIsIdentity: boolean; override;
130   public
131     constructor Create(ADestination: TState; ALayerId: integer; ANewOffset: TPoint);
132     procedure ApplyTo(AState: TState); override;
133     procedure UnapplyTo(AState: TState); override;
134   end;
135 
136   { TSetLayerMatrixDifference }
137 
138   TSetLayerMatrixDifference = class(TCustomImageDifference)
139   private
140     previousMatrix,nextMatrix: TAffineMatrix;
141     layerId: integer;
142   protected
GetImageDifferenceKindnull143     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull144     function GetIsIdentity: boolean; override;
145   public
146     constructor Create({%H-}ADestination: TState; ALayerId: integer; APreviousMatrix, ANextMatrix: TAffineMatrix);
147     procedure ApplyTo(AState: TState); override;
148     procedure UnapplyTo(AState: TState); override;
149   end;
150 
151   { TSetLayerRegistryDifference }
152 
153   TSetLayerRegistryDifference = class(TCustomImageDifference)
154   private
155     identifier: string;
156     previousValue,nextValue: RawByteString;
157     layerId: integer;
158   protected
GetImageDifferenceKindnull159     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull160     function GetIsIdentity: boolean; override;
GetCostnull161     function GetCost: integer; override;
162   public
163     constructor Create(ADestination: TState; ALayerId: integer; AIdentifier: string; ANewValue: RawByteString; AApplyNow: boolean);
164     procedure ApplyTo(AState: TState); override;
165     procedure UnapplyTo(AState: TState); override;
166   end;
167 
168   { TSetImageRegistryDifference }
169 
170   TSetImageRegistryDifference = class(TCustomImageDifference)
171   private
172     identifier: string;
173     previousValue,nextValue: RawByteString;
174   protected
GetImageDifferenceKindnull175     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull176     function GetIsIdentity: boolean; override;
GetCostnull177     function GetCost: integer; override;
178   public
179     constructor Create(ADestination: TState; AIdentifier: string; ANewValue: RawByteString; AApplyNow: boolean);
180     procedure ApplyTo(AState: TState); override;
181     procedure UnapplyTo(AState: TState); override;
182   end;
183 
184   { TSetSelectionTransformDifference }
185 
186   TSetSelectionTransformDifference = class(TCustomImageDifference)
187   private
188     previousMatrix,nextMatrix: TAffineMatrix;
189   protected
GetImageDifferenceKindnull190     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull191     function GetIsIdentity: boolean; override;
192   public
193     constructor Create({%H-}ADestination: TState; ANextMatrix: TAffineMatrix);
194     procedure ApplyTo(AState: TState); override;
195     procedure UnapplyTo(AState: TState); override;
196   end;
197 
198   { TApplyLayerOffsetStateDifference }
199 
200   TApplyLayerOffsetStateDifference = class(TCustomImageDifference)
201   private
202     previousBounds,nextBounds,unchangedBounds: TRect;
203     clippedData: TMemoryStream;
204     useOriginal: boolean;
205     previousOriginalRenderStatus: TOriginalRenderStatus;
206     layerId: integer;
207     previousLayerOffset: TPoint;
208   protected
GetImageDifferenceKindnull209     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull210     function GetIsIdentity: boolean; override;
GetChangingBoundsDefinednull211     function GetChangingBoundsDefined: boolean; override;
GetChangingBoundsnull212     function GetChangingBounds: TRect; override;
213   public
214     constructor Create(ADestination: TState; ALayerId: integer; AOffsetX, AOffsetY: integer; AApplyNow: boolean);
215     destructor Destroy; override;
216     procedure ApplyTo(AState: TState); override;
217     procedure UnapplyTo(AState: TState); override;
218   end;
219 
220   { TSelectionTransformDifference }
221 
222   TSelectionTransformDifference = class(TCustomImageDifference)
223     FPrevTransform: TAffineMatrix;
224     FPrevSelectionMask, FPrevSelectionLayer: TStoredImage;
225   protected
GetImageDifferenceKindnull226     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetIsIdentitynull227     function GetIsIdentity: boolean; override;
228   public
229     constructor Create(ADestination: TState; AApplyNow: boolean);
TryCompressnull230     function TryCompress: boolean; override;
231     destructor Destroy; override;
232     procedure ApplyTo(AState: TState); override;
233     procedure UnapplyTo(AState: TState); override;
234   end;
235 
236   { TSetLayerVisibleStateDifference }
237 
238   TSetLayerVisibleStateDifference = class(TCustomImageDifference)
239   private
240     previousVisible,nextVisible: boolean;
241     layerId: integer;
242     layerBounds: TRect;
243   protected
GetImageDifferenceKindnull244     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetChangingBoundsnull245     function GetChangingBounds: TRect; override;
GetChangingBoundsDefinednull246     function GetChangingBoundsDefined: boolean; override;
GetIsIdentitynull247     function GetIsIdentity: boolean; override;
248   public
249     constructor Create(ADestination: TState; ALayerId: integer; ANewVisible: boolean);
250     procedure ApplyTo(AState: TState); override;
251     procedure UnapplyTo(AState: TState); override;
252   end;
253 
254   { TSetLayerBlendOpStateDifference }
255 
256   TSetLayerBlendOpStateDifference = class(TCustomImageDifference)
257   private
258     previousBlendOp,nextBlendOp: TBlendOperation;
259     layerId: integer;
260     layerBounds: TRect;
261   protected
GetImageDifferenceKindnull262     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetChangingBoundsnull263     function GetChangingBounds: TRect; override;
GetChangingBoundsDefinednull264     function GetChangingBoundsDefined: boolean; override;
GetIsIdentitynull265     function GetIsIdentity: boolean; override;
266   public
267     constructor Create(ADestination: TState; ALayerId: integer; ANewBlendOp: TBlendOperation);
268     procedure ApplyTo(AState: TState); override;
269     procedure UnapplyTo(AState: TState); override;
270   end;
271 
272   { TAddLayerStateDifference }
273 
274   TAddLayerStateDifference = class(TCustomImageDifference)
275   protected
GetImageDifferenceKindnull276     function GetImageDifferenceKind: TImageDifferenceKind; override;
277   public
278     layerId: integer;
279     content: TStoredImage;
280     previousActiveLayerId: integer;
281     name: ansistring;
282     offset: TPoint;
283     blendOp: TBlendOperation;
284     opacity: byte;
UsedMemorynull285     function UsedMemory: int64; override;
TryCompressnull286     function TryCompress: boolean; override;
287     procedure ApplyTo(AState: TState); override;
288     procedure UnapplyTo(AState: TState); override;
289     constructor Create(ADestination: TState; AContent: TBGRABitmap; AName: ansistring;
290         AOffset: TPoint; ABlendOp: TBlendOperation; AOpacity: byte);
291     destructor Destroy; override;
292   end;
293 
294   { TAddLayerFromOwnedOriginalStateDifference }
295 
296   TAddLayerFromOwnedOriginalStateDifference = class(TCustomImageDifference)
297   protected
GetImageDifferenceKindnull298     function GetImageDifferenceKind: TImageDifferenceKind; override;
299     procedure Uncompress;
300   public
301     layerId: integer;
302     originalData: TStream;
303     compressedData: TStream;
304     previousActiveLayerId: integer;
305     name: ansistring;
306     blendOp: TBlendOperation;
307     opacity: byte;
308     matrix: TAffineMatrix;
UsedMemorynull309     function UsedMemory: int64; override;
TryCompressnull310     function TryCompress: boolean; override;
311     procedure ApplyTo(AState: TState); override;
312     procedure UnapplyTo(AState: TState); override;
313     constructor Create(ADestination: TState; AOriginal: TBGRALayerCustomOriginal;
314         AName: ansistring; ABlendOp: TBlendOperation; AMatrix: TAffineMatrix; AOpacity: Byte = 255);
315     destructor Destroy; override;
316   end;
317 
318   { TRemoveLayerStateDifference }
319 
320   TRemoveLayerStateDifference = class(TCustomImageDifference)
321   protected
322     FContent: TStoredLayer;
323     FNextActiveLayerId: integer;
GetImageDifferenceKindnull324     function GetImageDifferenceKind: TImageDifferenceKind; override;
325   public
UsedMemorynull326     function UsedMemory: int64; override;
TryCompressnull327     function TryCompress: boolean; override;
328     procedure ApplyTo(AState: TState); override;
329     procedure UnapplyTo(AState: TState); override;
330     constructor Create(AState: TState; AApplyNow: boolean);
331     destructor Destroy; override;
332     property nextActiveLayerId: integer read FNextActiveLayerId write FNextActiveLayerId;
333   end;
334 
335   { TReplaceLayerByOriginalDifference }
336 
337   TReplaceLayerByOriginalDifference = class(TCustomImageDifference)
338   private
GetLayerIdnull339     function GetLayerId: integer;
340   protected
341     FPreviousLayerContent: TStoredLayer;
342     FPrevMatrix,FNextMatrix: TAffineMatrix;
343     FSourceBounds: TRect;
344     FSourceLayerId: integer;
345     FOriginalGuid: TGUID;
GetImageDifferenceKindnull346     function GetImageDifferenceKind: TImageDifferenceKind; override;
CreateOriginalnull347     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; virtual; abstract;
ShouldRenderOriginalnull348     function ShouldRenderOriginal: boolean; virtual;
349     procedure StorePreviousLayer(AImgState: TImageState; ALayerIndex: integer;
350       AAlwaysStoreBitmap: boolean); virtual;
351     procedure CustomUnapplyto(AState: TState);
352   public
353     constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
UsedMemorynull354     function UsedMemory: int64; override;
TryCompressnull355     function TryCompress: boolean; override;
356     procedure ApplyTo(AState: TState); override;
357     procedure UnapplyTo(AState: TState); override;
358     property LayerId: integer read GetLayerId;
359     property prevMatrix: TAffineMatrix read FPrevMatrix;
360     property nextMatrix: TAffineMatrix read FNextMatrix write FNextMatrix;
361     destructor Destroy; override;
362   end;
363 
364   { TDiscardOriginalDifference }
365 
366   TDiscardOriginalDifference = class(TCustomImageDifference)
367   private
GetLayerIdnull368     function GetLayerId: integer;
369   protected
370     FPreviousOriginalData: TStream;
371     FPreviousOriginalGuid: TGuid;
372     FOriginalUsedInOtherLayer: boolean;
373     FPreviousOriginalMatrix: TAffineMatrix;
374     FPreviousOriginalRenderStatus: TOriginalRenderStatus;
375     FLayerId: integer;
GetImageDifferenceKindnull376     function GetImageDifferenceKind: TImageDifferenceKind; override;
377   public
378     constructor Create(AFromState: TState; AIndex: integer; AApplyNow: boolean);
UsedMemorynull379     function UsedMemory: int64; override;
TryCompressnull380     function TryCompress: boolean; override;
381     procedure ApplyTo(AState: TState); override;
382     procedure UnapplyTo(AState: TState); override;
383     property LayerId: integer read GetLayerId;
384     destructor Destroy; override;
385   end;
386 
387   { TReplaceLayerByImageOriginalDifference }
388 
389   TReplaceLayerByImageOriginalDifference = class(TReplaceLayerByOriginalDifference)
390   protected
391     FSourceStoredInOriginal: boolean;
392     procedure StorePreviousLayer(AImgState: TImageState; ALayerIndex: integer;
393       AAlwaysStoreBitmap: boolean); override;
CreateOriginalnull394     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; override;
395   public
UsedMemorynull396     function UsedMemory: int64; override;
TryCompressnull397     function TryCompress: boolean; override;
398     procedure UnapplyTo(AState: TState); override;
399   end;
400 
401   { TReplaceLayerByVectorOriginalDifference }
402 
403   TReplaceLayerByVectorOriginalDifference = class(TReplaceLayerByOriginalDifference)
404   protected
405     FShouldRenderOriginal: boolean;
ShouldRenderOriginalnull406     function ShouldRenderOriginal: boolean; override;
CreateOriginalnull407     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; override;
408   public
409     constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
410   end;
411 
412   { TReplaceLayerByCustomOriginalDifference }
413 
414   TReplaceLayerByCustomOriginalDifference = class(TReplaceLayerByOriginalDifference)
415   protected
416     FOriginal: TBGRALayerCustomOriginal;
CreateOriginalnull417     function CreateOriginal({%H-}AState: TState; {%H-}ALayerIndex: integer): TBGRALayerCustomOriginal; override;
ShouldRenderOriginalnull418     function ShouldRenderOriginal: boolean; override;
419   public
420     constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean; AOriginal: TBGRALayerCustomOriginal);
421     destructor Destroy; override;
422   end;
423 
424   { TAddShapeToVectorOriginalDifference }
425 
426   TAddShapeToVectorOriginalDifference = class(TCustomImageDifference)
427   private
428     FShapeIndex, FShapeId: integer;
429     FLayerId: integer;
430     FShapeCopy: TVectorShape;
431     FShapeBounds: TRect;
432   protected
GetImageDifferenceKindnull433     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetChangingBoundsnull434     function GetChangingBounds: TRect; override;
GetChangingBoundsDefinednull435     function GetChangingBoundsDefined: boolean; override;
436   public
437     constructor Create(ADestination: TState; ALayerId: integer; AShape: TVectorShape; AShapeIndex: integer = -1);
438     destructor Destroy; override;
439     procedure ApplyTo(AState: TState); override;
440     procedure UnapplyTo(AState: TState); override;
441   end;
442 
443   { TVectorOriginalEmbeddedDifference }
444 
445   TVectorOriginalEmbeddedDifference = class(TCustomImageDifference)
446   private
447     FDate: TDateTime;
448     FOriginalGuid: TGuid;
449     FDiff: TBGRAOriginalDiff;
450     FBounds: TRect;
451   protected
GetImageDifferenceKindnull452     function GetImageDifferenceKind: TImageDifferenceKind; override;
GetChangingBoundsnull453     function GetChangingBounds: TRect; override;
GetChangingBoundsDefinednull454     function GetChangingBoundsDefined: boolean; override;
GetIsIdentitynull455     function GetIsIdentity: boolean; override;
456   public
457     constructor Create({%H-}ADestination: TState; AOriginalGuid: TGuid; ADiff: TBGRAOriginalDiff; ABounds: TRect);
458     destructor Destroy; override;
459     procedure ApplyTo(AState: TState); override;
460     procedure UnapplyTo(AState: TState); override;
461   end;
462 
463   { TDiscardOriginalStateDifference }
464 
465   TDiscardOriginalStateDifference = class(TCustomImageDifference)
466   protected
467     origData: TStream;
468     origMatrix: TAffineMatrix;
469     origRenderStatus: TOriginalRenderStatus;
470     layerId: integer;
GetImageDifferenceKindnull471     function GetImageDifferenceKind: TImageDifferenceKind; override;
472   public
UsedMemorynull473     function UsedMemory: int64; override;
TryCompressnull474     function TryCompress: boolean; override;
475     procedure ApplyTo(AState: TState); override;
476     procedure UnapplyTo(AState: TState); override;
477     constructor Create(AState: TState; AIndex: integer);
478     destructor Destroy; override;
479   end;
480 
481   { TAssignStateDifference }
482 
483   TAssignStateDifference = class(TCustomImageDifference)
484   protected
485     FStreamBefore, FStreamAfter: TMemoryStream;
486     FSelectionDiff,FSelectionLayerDiff: TImageDiff;
487     procedure Init(AState: TState; AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer);
488   public
489     constructor Create(AState: TState; AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer);
490     constructor Create(AState: TState; AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer; ACurrentSelection: TBGRABitmap; ASelectionLayer: TBGRABitmap);
UsedMemorynull491     function UsedMemory: int64; override;
TryCompressnull492     function TryCompress: boolean; override;
493     procedure ApplyTo(AState: TState); override;
494     procedure UnApplyTo(AState: TState); override;
495     destructor Destroy; override;
496   end;
497 
498   { TAssignStateDifferenceAfter }
499 
500   TAssignStateDifferenceAfter = class(TAssignStateDifference)
501   public
502     constructor Create(AState: TState; ABackup: TState);
503   end;
504 
505   { TDuplicateLayerStateDifference }
506 
507   TDuplicateLayerStateDifference = class(TCustomImageDifference)
508   protected
GetImageDifferenceKindnull509     function GetImageDifferenceKind: TImageDifferenceKind; override;
510   public
511     sourceLayerId: integer;
512     duplicateId: integer;
513     useOriginal: boolean;
514     duplicateOriginal: boolean;
515     duplicateGuid: TGuid;
516     procedure ApplyTo(AState: TState); override;
517     procedure UnapplyTo(AState: TState); override;
518     constructor Create(ADestination: TState; AUseOriginal: boolean);
519   end;
520 
521   { TMoveLayerStateDifference }
522 
523   TMoveLayerStateDifference = class(TCustomImageDifference)
524   protected
GetIsIdentitynull525     function GetIsIdentity: boolean; override;
GetImageDifferenceKindnull526     function GetImageDifferenceKind: TImageDifferenceKind; override;
527   public
528     sourceIndex,destIndex: integer;
529     procedure ApplyTo(AState: TState); override;
530     procedure UnapplyTo(AState: TState); override;
531     constructor Create(ADestination: TState; AFromIndex, AToIndex: integer);
532   end;
533 
534   { TMergeLayerOverStateDifference }
535 
536   TMergeLayerOverStateDifference = class(TCustomImageDifference)
537   protected
GetImageDifferenceKindnull538     function GetImageDifferenceKind: TImageDifferenceKind; override;
539   public
540     previousActiveLayerId: integer;
541     layerOverIndex: integer;
542     layerOverCompressedBackup: TStoredLayer;
543     layerUnderCompressedBackup: TStoredLayer;
544     mergeVectorial: boolean;
545     mergeVectorialGuid: TGuid;
546     constructor Create(ADestination: TState; ALayerOverIndex: integer);
UsedMemorynull547     function UsedMemory: int64; override;
TryCompressnull548     function TryCompress: boolean; override;
549     procedure ApplyTo(AState: TState); override;
550     procedure UnapplyTo(AState: TState); override;
551     destructor Destroy; override;
552   end;
553 
554 implementation
555 
556 uses BGRAWriteLzp, BGRAReadLzp, BGRAStreamLayers, BGRALzpCommon, ugraph, Types,
557   BGRATransform, zstream, LCVectorRectShapes, BGRAPen, LCVectorialFill,
558   BGRAGradientOriginal;
559 
IsInverseImageDiffnull560 function IsInverseImageDiff(ADiff1, ADiff2: TCustomImageDifference): boolean;
561 begin
562   if (ADiff1 is TInversibleStateDifference) and (ADiff2 is TInversibleStateDifference) then
563     result := ((ADiff1 as TInversibleStateDifference).Action = GetInverseAction( (ADiff2 as TInversibleStateDifference).Action ))
564           and ((ADiff1 as TInversibleStateDifference).LayerIndex = (ADiff2 as TInversibleStateDifference).LayerIndex)
565   else
566   if (ADiff1 is TSetLayerNameStateDifference) and (ADiff2 is TSetLayerNameStateDifference) then
567   begin
568     result := ((ADiff1 as TSetLayerNameStateDifference).nextName = (ADiff2 as TSetLayerNameStateDifference).previousName) and
569       ((ADiff1 as TSetLayerNameStateDifference).previousName = (ADiff2 as TSetLayerNameStateDifference).nextName);
570   end
571   else
572   if (ADiff1 is TSetLayerVisibleStateDifference) and (ADiff2 is TSetLayerVisibleStateDifference) then
573   begin
574     result := ((ADiff1 as TSetLayerVisibleStateDifference).nextVisible = (ADiff2 as TSetLayerVisibleStateDifference).previousVisible) and
575       ((ADiff1 as TSetLayerVisibleStateDifference).previousVisible = (ADiff2 as TSetLayerVisibleStateDifference).nextVisible);
576   end
577   else
578   if (ADiff1 is TSetLayerOpacityStateDifference) and (ADiff2 is TSetLayerOpacityStateDifference) then
579   begin
580     result := ((ADiff1 as TSetLayerOpacityStateDifference).nextOpacity = (ADiff2 as TSetLayerOpacityStateDifference).previousOpacity) and
581       ((ADiff1 as TSetLayerOpacityStateDifference).previousOpacity = (ADiff2 as TSetLayerOpacityStateDifference).nextOpacity);
582   end
583   else
584   if (ADiff1 is TSetLayerBlendOpStateDifference) and (ADiff2 is TSetLayerBlendOpStateDifference) then
585   begin
586     result := ((ADiff1 as TSetLayerBlendOpStateDifference).nextBlendOp = (ADiff2 as TSetLayerBlendOpStateDifference).previousBlendOp) and
587       ((ADiff1 as TSetLayerBlendOpStateDifference).previousBlendOp = (ADiff2 as TSetLayerBlendOpStateDifference).nextBlendOp);
588   end
589   else
590     result := false;
591 end;
592 
TryCombineImageDiffnull593 function TryCombineImageDiff(ANewDiff, APrevDiff: TCustomImageDifference): boolean;
594 const VectorDiffMinTime = 2000/(1000*60*60*24);
595 var
596   combined: TInversibleAction;
597 begin
598   if (APrevDiff is TInversibleStateDifference) and (ANewDiff is TInversibleStateDifference) then
599   begin
600     if CanCombineInversibleAction((APrevDiff as TInversibleStateDifference).Action, (ANewDiff as TInversibleStateDifference).Action, combined) then
601     begin
602       (APrevDiff as TInversibleStateDifference).Action := combined;
603       result := true;
604     end
605     else result := false;
606   end
607   else
608   if (APrevDiff is TSetLayerNameStateDifference) and (ANewDiff is TSetLayerNameStateDifference) then
609   begin
610     if (APrevDiff as TSetLayerNameStateDifference).nextName = (ANewDiff as TSetLayerNameStateDifference).previousName then
611     begin
612       (APrevDiff as TSetLayerNameStateDifference).nextName := (ANewDiff as TSetLayerNameStateDifference).nextName;
613       result := true;
614     end
615     else result := false;
616   end
617   else
618   if (APrevDiff is TSetLayerOpacityStateDifference) and (ANewDiff is TSetLayerOpacityStateDifference) then
619   begin
620     if (APrevDiff as TSetLayerOpacityStateDifference).nextOpacity = (ANewDiff as TSetLayerOpacityStateDifference).previousOpacity then
621     begin
622       (APrevDiff as TSetLayerOpacityStateDifference).nextOpacity := (ANewDiff as TSetLayerOpacityStateDifference).nextOpacity;
623       result := true;
624     end
625     else result := false;
626   end
627   else
628   if (APrevDiff is TSetLayerOffsetStateDifference) and (ANewDiff is TSetLayerOffsetStateDifference) then
629   begin
630     if ((APrevDiff as TSetLayerOffsetStateDifference).nextOffset.x = (ANewDiff as TSetLayerOffsetStateDifference).previousOffset.x)
631     and ((APrevDiff as TSetLayerOffsetStateDifference).nextOffset.y = (ANewDiff as TSetLayerOffsetStateDifference).previousOffset.y) then
632     begin
633       (APrevDiff as TSetLayerOffsetStateDifference).nextOffset := (ANewDiff as TSetLayerOffsetStateDifference).nextOffset;
634       result := true;
635     end
636     else result := false;
637   end
638   else
639   if (APrevDiff is TSetLayerMatrixDifference) and (ANewDiff is TSetLayerMatrixDifference) then
640   begin
641     if (APrevDiff as TSetLayerMatrixDifference).nextMatrix = (ANewDiff as TSetLayerMatrixDifference).previousMatrix then
642     begin
643       (APrevDiff as TSetLayerMatrixDifference).nextMatrix := (ANewDiff as TSetLayerMatrixDifference).nextMatrix;
644       result := true;
645     end
646     else result := false;
647   end
648   else
649   if (APrevDiff is TReplaceLayerByOriginalDifference) and (ANewDiff is TSetLayerMatrixDifference) then
650   begin
651     if (APrevDiff as TReplaceLayerByOriginalDifference).nextMatrix = (ANewDiff as TSetLayerMatrixDifference).previousMatrix then
652     begin
653       (APrevDiff as TReplaceLayerByOriginalDifference).nextMatrix := (ANewDiff as TSetLayerMatrixDifference).nextMatrix;
654       result := true;
655     end
656     else result := false;
657   end
658   else
659   if (APrevDiff is TSetSelectionTransformDifference) and (ANewDiff is TSetSelectionTransformDifference) then
660   begin
661     if (APrevDiff as TSetSelectionTransformDifference).nextMatrix = (ANewDiff as TSetSelectionTransformDifference).previousMatrix then
662     begin
663       (APrevDiff as TSetSelectionTransformDifference).nextMatrix := (ANewDiff as TSetSelectionTransformDifference).nextMatrix;
664       result := true;
665     end
666     else result := false;
667   end
668   else
669   if (APrevDiff is TSetLayerBlendOpStateDifference) and (ANewDiff is TSetLayerBlendOpStateDifference) then
670   begin
671     if (APrevDiff as TSetLayerBlendOpStateDifference).nextBlendOp = (ANewDiff as TSetLayerBlendOpStateDifference).previousBlendOp then
672     begin
673       (APrevDiff as TSetLayerBlendOpStateDifference).nextBlendOp := (ANewDiff as TSetLayerBlendOpStateDifference).nextBlendOp;
674       result := true;
675     end
676     else result := false;
677   end
678   else
679   if (APrevDiff is TVectorOriginalEmbeddedDifference) and (ANewDiff is TVectorOriginalEmbeddedDifference) then
680   begin
681     if (TVectorOriginalEmbeddedDifference(ANewDiff).FDate <
682        TVectorOriginalEmbeddedDifference(APrevDiff).FDate+VectorDiffMinTime) and
683       TVectorOriginalEmbeddedDifference(APrevDiff).FDiff.CanAppend(
684       TVectorOriginalEmbeddedDifference(ANewDiff).FDiff) then
685     begin
686       TVectorOriginalEmbeddedDifference(APrevDiff).FDiff.Append(
687         TVectorOriginalEmbeddedDifference(ANewDiff).FDiff);
688       result := true;
689     end else
690       result := false;
691   end else
692     result := false;
693 end;
694 
695 { TSetImageRegistryDifference }
696 
GetImageDifferenceKindnull697 function TSetImageRegistryDifference.GetImageDifferenceKind: TImageDifferenceKind;
698 begin
699   Result:= idkChangeStack;
700 end;
701 
GetIsIdentitynull702 function TSetImageRegistryDifference.GetIsIdentity: boolean;
703 begin
704   Result:= previousValue = nextValue;
705 end;
706 
GetCostnull707 function TSetImageRegistryDifference.GetCost: integer;
708 begin
709   Result:= 0;
710 end;
711 
712 constructor TSetImageRegistryDifference.Create(ADestination: TState;
713   AIdentifier: string; ANewValue: RawByteString; AApplyNow: boolean);
714 var
715   imgState: TImageState;
716 begin
717   inherited Create(ADestination);
718   identifier := AIdentifier;
719   nextValue := ANewValue;
720   imgState := ADestination as TImageState;
721   previousValue:= imgState.LayeredBitmap.GetGlobalRegistry(identifier);
722   if AApplyNow then ApplyTo(ADestination);
723 end;
724 
725 procedure TSetImageRegistryDifference.ApplyTo(AState: TState);
726 var
727   imgState: TImageState;
728 begin
729   inherited ApplyTo(AState);
730   imgState := AState as TImageState;
731   imgState.LayeredBitmap.SetGlobalRegistry(identifier, nextValue);
732 end;
733 
734 procedure TSetImageRegistryDifference.UnapplyTo(AState: TState);
735 var
736   imgState: TImageState;
737 begin
738   inherited UnapplyTo(AState);
739   imgState := AState as TImageState;
740   imgState.LayeredBitmap.SetGlobalRegistry(identifier, previousValue);
741 end;
742 
743 { TSetLayerRegistryDifference }
744 
GetImageDifferenceKindnull745 function TSetLayerRegistryDifference.GetImageDifferenceKind: TImageDifferenceKind;
746 begin
747   Result:= idkChangeStack;
748 end;
749 
GetIsIdentitynull750 function TSetLayerRegistryDifference.GetIsIdentity: boolean;
751 begin
752   Result:= previousValue = nextValue;
753 end;
754 
TSetLayerRegistryDifference.GetCostnull755 function TSetLayerRegistryDifference.GetCost: integer;
756 begin
757   Result:= 0;
758 end;
759 
760 constructor TSetLayerRegistryDifference.Create(ADestination: TState;
761   ALayerId: integer; AIdentifier: string; ANewValue: RawByteString;
762   AApplyNow: boolean);
763 var
764   imgState: TImageState;
765 begin
766   inherited Create(ADestination);
767   layerId := ALayerId;
768   identifier := AIdentifier;
769   nextValue := ANewValue;
770   imgState := ADestination as TImageState;
771   previousValue:= imgState.LayeredBitmap.GetLayerRegistry(imgState.LayeredBitmap.GetLayerIndexFromId(layerId), identifier);
772   if AApplyNow then ApplyTo(ADestination);
773 end;
774 
775 procedure TSetLayerRegistryDifference.ApplyTo(AState: TState);
776 var
777   imgState: TImageState;
778 begin
779   inherited ApplyTo(AState);
780   imgState := AState as TImageState;
781   imgState.LayeredBitmap.SetLayerRegistry(imgState.LayeredBitmap.GetLayerIndexFromId(layerId), identifier, nextValue);
782 end;
783 
784 procedure TSetLayerRegistryDifference.UnapplyTo(AState: TState);
785 var
786   imgState: TImageState;
787 begin
788   inherited UnapplyTo(AState);
789   imgState := AState as TImageState;
790   imgState.LayeredBitmap.SetLayerRegistry(imgState.LayeredBitmap.GetLayerIndexFromId(layerId), identifier, previousValue);
791 end;
792 
793 { TReplaceLayerByCustomOriginalDifference }
794 
TReplaceLayerByCustomOriginalDifference.CreateOriginalnull795 function TReplaceLayerByCustomOriginalDifference.CreateOriginal(AState: TState;
796   ALayerIndex: integer): TBGRALayerCustomOriginal;
797 begin
798   result := FOriginal.Duplicate;
799 end;
800 
ShouldRenderOriginalnull801 function TReplaceLayerByCustomOriginalDifference.ShouldRenderOriginal: boolean;
802 begin
803   result := true;
804 end;
805 
806 constructor TReplaceLayerByCustomOriginalDifference.Create(AFromState: TState;
807   AIndex: integer; AAlwaysStoreBitmap: boolean; AOriginal: TBGRALayerCustomOriginal);
808 begin
809   FOriginal := AOriginal;
810   inherited Create(AFromState,AIndex,AAlwaysStoreBitmap);
811 end;
812 
813 destructor TReplaceLayerByCustomOriginalDifference.Destroy;
814 begin
815   FOriginal.Free;
816   inherited Destroy;
817 end;
818 
819 { TVectorOriginalEmbeddedDifference }
820 
GetImageDifferenceKindnull821 function TVectorOriginalEmbeddedDifference.GetImageDifferenceKind: TImageDifferenceKind;
822 begin
823   Result:= idkChangeImage;
824 end;
825 
TVectorOriginalEmbeddedDifference.GetChangingBoundsnull826 function TVectorOriginalEmbeddedDifference.GetChangingBounds: TRect;
827 begin
828   Result:= FBounds;
829 end;
830 
GetChangingBoundsDefinednull831 function TVectorOriginalEmbeddedDifference.GetChangingBoundsDefined: boolean;
832 begin
833   Result:= true;
834 end;
835 
GetIsIdentitynull836 function TVectorOriginalEmbeddedDifference.GetIsIdentity: boolean;
837 begin
838   Result:= FDiff.IsIdentity;
839 end;
840 
841 constructor TVectorOriginalEmbeddedDifference.Create(ADestination: TState;
842   AOriginalGuid: TGuid; ADiff: TBGRAOriginalDiff; ABounds: TRect);
843 begin
844   FDate := Now;
845   FOriginalGuid:= AOriginalGuid;
846   FDiff := ADiff;
847   FBounds := ABounds;
848 end;
849 
850 destructor TVectorOriginalEmbeddedDifference.Destroy;
851 begin
852   FDiff.Free;
853   inherited Destroy;
854 end;
855 
856 procedure TVectorOriginalEmbeddedDifference.ApplyTo(AState: TState);
857 var
858   img: TImageState;
859   idxOrig: Integer;
860 begin
861   inherited ApplyTo(AState);
862   img := AState as TImageState;
863   idxOrig := img.LayeredBitmap.IndexOfOriginal(FOriginalGuid);
864   if idxOrig<>-1 then
865     FDiff.Apply(img.LayeredBitmap.Original[idxOrig])
866   else
867     raise exception.Create('Cannot find original');
868 end;
869 
870 procedure TVectorOriginalEmbeddedDifference.UnapplyTo(AState: TState);
871 var
872   img: TImageState;
873   idxOrig: Integer;
874 begin
875   inherited UnapplyTo(AState);
876   img := AState as TImageState;
877   idxOrig := img.LayeredBitmap.IndexOfOriginal(FOriginalGuid);
878   if idxOrig<>-1 then
879     FDiff.Unapply(img.LayeredBitmap.Original[idxOrig])
880   else
881     raise exception.Create('Cannot find original');
882 end;
883 
884 { TDiscardOriginalDifference }
885 
TDiscardOriginalDifference.GetLayerIdnull886 function TDiscardOriginalDifference.GetLayerId: integer;
887 begin
888   result := FLayerId;
889 end;
890 
TDiscardOriginalDifference.GetImageDifferenceKindnull891 function TDiscardOriginalDifference.GetImageDifferenceKind: TImageDifferenceKind;
892 begin
893   Result:= idkChangeStack;
894 end;
895 
896 constructor TDiscardOriginalDifference.Create(AFromState: TState;
897   AIndex: integer; AApplyNow: boolean);
898 var
899   imgState: TImageState;
900   i: Integer;
901 begin
902   imgState := AFromState as TImageState;
903   FLayerId := imgState.LayerId[AIndex];
904   if not imgState.LayerOriginalDefined[AIndex] then
905     raise exception.Create('Layer original is not defined');
906   FPreviousOriginalGuid := imgState.LayeredBitmap.LayerOriginalGuid[AIndex];
907   FOriginalUsedInOtherLayer := false;
908   for i := 0 to imgState.NbLayers-1 do
909     if (i <> AIndex) and (imgState.LayeredBitmap.LayerOriginalGuid[i] = FPreviousOriginalGuid) then
910     begin
911       FOriginalUsedInOtherLayer:= true;
912       break;
913     end;
914   if not FOriginalUsedInOtherLayer then
915   begin
916     FPreviousOriginalData := TMemoryStream.Create;
917     imgState.LayeredBitmap.SaveOriginalToStream(
918       imgState.LayeredBitmap.LayerOriginalGuid[AIndex],
919       FPreviousOriginalData);
920   end;
921   FPreviousOriginalMatrix := imgState.LayerOriginalMatrix[AIndex];
922   FPreviousOriginalRenderStatus:= imgState.layeredBitmap.LayerOriginalRenderStatus[AIndex];
923   if AApplyNow then ApplyTo(AFromState)
924 end;
925 
UsedMemorynull926 function TDiscardOriginalDifference.UsedMemory: int64;
927 begin
928   if Assigned(FPreviousOriginalData) then
929     Result:= FPreviousOriginalData.Size
930   else
931     result:= 0;
932 end;
933 
TryCompressnull934 function TDiscardOriginalDifference.TryCompress: boolean;
935 begin
936   Result:= false;
937 end;
938 
939 procedure TDiscardOriginalDifference.ApplyTo(AState: TState);
940 var
941   imgState: TImageState;
942   layerIdx: Integer;
943 begin
944   imgState := AState as TImageState;
945   layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FLayerId);
946   imgState.LayeredBitmap.LayerOriginalGuid[layerIdx] := GUID_NULL;
947   imgState.LayeredBitmap.LayerOriginalMatrix[layerIdx] := AffineMatrixIdentity;
948   if not FOriginalUsedInOtherLayer then
949     imgState.LayeredBitmap.RemoveUnusedOriginals;
950   inherited ApplyTo(AState);
951 end;
952 
953 procedure TDiscardOriginalDifference.UnapplyTo(AState: TState);
954 var
955   imgState: TImageState;
956   layerIdx, origIdx: Integer;
957 begin
958   imgState := AState as TImageState;
959   layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FLayerId);
960   if FOriginalUsedInOtherLayer then
961   begin
962     imgState.LayeredBitmap.LayerOriginalGuid[layerIdx] := FPreviousOriginalGuid;
963   end else
964   begin
965     FPreviousOriginalData.Position := 0;
966     origIdx := imgState.LayeredBitmap.AddOriginalFromStream(FPreviousOriginalData, FPreviousOriginalGuid, true);
967     imgState.LayeredBitmap.LayerOriginalGuid[layerIdx] := imgState.LayeredBitmap.OriginalGuid[origIdx];
968   end;
969   imgState.LayeredBitmap.LayerOriginalMatrix[layerIdx] := FPreviousOriginalMatrix;
970   imgState.LayeredBitmap.LayerOriginalRenderStatus[layerIdx] := FPreviousOriginalRenderStatus;
971   inherited UnapplyTo(AState);
972 end;
973 
974 destructor TDiscardOriginalDifference.Destroy;
975 begin
976   FPreviousOriginalData.Free;
977   inherited Destroy;
978 end;
979 
980 { TAddShapeToVectorOriginalDifference }
981 
GetImageDifferenceKindnull982 function TAddShapeToVectorOriginalDifference.GetImageDifferenceKind: TImageDifferenceKind;
983 begin
984   Result:= idkChangeImage;
985 end;
986 
GetChangingBoundsnull987 function TAddShapeToVectorOriginalDifference.GetChangingBounds: TRect;
988 begin
989   Result:= FShapeBounds;
990 end;
991 
GetChangingBoundsDefinednull992 function TAddShapeToVectorOriginalDifference.GetChangingBoundsDefined: boolean;
993 begin
994   Result:= true;
995 end;
996 
997 constructor TAddShapeToVectorOriginalDifference.Create(ADestination: TState;
998   ALayerId: integer; AShape: TVectorShape; AShapeIndex: integer);
999 var
1000   imgState: TImageState;
1001   layerIdx: Integer;
1002   orig: TBGRALayerCustomOriginal;
1003 begin
1004   FLayerId := ALayerId;
1005   imgState := ADestination as TImageState;
1006   layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FLayerId);
1007   orig := imgState.LayerOriginal[layerIdx];
1008   if not (orig is TVectorOriginal) then
1009   begin
1010     AShape.Free;
1011     raise exception.Create('Vector original expected');
1012   end;
1013   if AShapeIndex = -1 then AShapeIndex := TVectorOriginal(orig).ShapeCount;
1014   FShapeIndex:= AShapeIndex;
1015   FShapeCopy := AShape.Duplicate;
1016 
1017   inherited ApplyTo(ADestination);
1018   TVectorOriginal(orig).InsertShape(AShape, FShapeIndex);
1019   FShapeId := TVectorOriginal(orig).Shape[FShapeIndex].Id;
1020   TVectorOriginal(orig).SelectShape(FShapeIndex);
1021   FShapeBounds := imgState.LayeredBitmap.RenderOriginalIfNecessary(orig.Guid);
1022 end;
1023 
1024 destructor TAddShapeToVectorOriginalDifference.Destroy;
1025 begin
1026   FShapeCopy.Free;
1027   inherited Destroy;
1028 end;
1029 
1030 procedure TAddShapeToVectorOriginalDifference.ApplyTo(AState: TState);
1031 var
1032   imgState: TImageState;
1033   layerIdx: Integer;
1034   orig: TBGRALayerCustomOriginal;
1035   shape: TVectorShape;
1036 begin
1037   inherited ApplyTo(AState);
1038   imgState := AState as TImageState;
1039   layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FLayerId);
1040   orig := imgState.LayerOriginal[layerIdx];
1041   if not (orig is TVectorOriginal) then
1042     raise exception.Create('Vector original expected');
1043 
1044   shape := FShapeCopy.Duplicate;
1045   TVectorOriginal(orig).InsertShape(shape, FShapeIndex);
1046   TVectorOriginal(orig).Shape[FShapeIndex].Id := FShapeId;
1047   TVectorOriginal(orig).SelectShape(FShapeIndex);
1048   imgState.LayeredBitmap.RenderLayerFromOriginal(layerIdx);
1049 end;
1050 
1051 procedure TAddShapeToVectorOriginalDifference.UnapplyTo(AState: TState);
1052 var
1053   imgState: TImageState;
1054   layerIdx: Integer;
1055   orig: TBGRALayerCustomOriginal;
1056 begin
1057   inherited UnapplyTo(AState);
1058   imgState := AState as TImageState;
1059   layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FLayerId);
1060   orig := imgState.LayerOriginal[layerIdx];
1061   if not (orig is TVectorOriginal) then
1062     raise exception.Create('Vector original expected');
1063   TVectorOriginal(orig).RemoveShape(TVectorOriginal(orig).Shape[FShapeIndex]);
1064 end;
1065 
1066 { TReplaceLayerByVectorOriginalDifference }
1067 
TReplaceLayerByVectorOriginalDifference.ShouldRenderOriginalnull1068 function TReplaceLayerByVectorOriginalDifference.ShouldRenderOriginal: boolean;
1069 begin
1070   Result:= FShouldRenderOriginal;
1071 end;
1072 
CreateOriginalnull1073 function TReplaceLayerByVectorOriginalDifference.CreateOriginal(AState: TState;
1074   ALayerIndex: integer): TBGRALayerCustomOriginal;
1075 var
1076   source: TBGRABitmap;
1077   temp: TBGRABitmap;
1078   imgState: TImageState;
1079   orig: TVectorOriginal;
1080   shape: TRectShape;
1081 begin
1082   imgState := TImageState(AState);
1083   orig := TVectorOriginal.Create;
1084   if imgState.LayeredBitmap.LayerOriginalClass[ALayerIndex]=TBGRALayerGradientOriginal then
1085   begin
1086     shape := TRectShape.Create(orig);
1087     shape.QuickDefine(PointF(-0.5,-0.5),PointF(FSourceBounds.Width-0.5,FSourceBounds.Height-0.5));
1088     shape.PenStyle := ClearPenStyle;
1089     shape.BackFill.SetGradient(
1090       imgState.LayeredBitmap.LayerOriginal[ALayerIndex] as TBGRALayerGradientOriginal,false);
1091     shape.BackFill.Transform(imgState.LayeredBitmap.LayerOriginalMatrix[ALayerIndex]);
1092     orig.AddShape(shape);
1093   end else
1094   if imgState.LayeredBitmap.LayerOriginalClass[ALayerIndex]=TBGRALayerImageOriginal then
1095   begin
1096     temp := (imgState.LayeredBitmap.LayerOriginal[ALayerIndex] as TBGRALayerImageOriginal).GetImageCopy;
1097     if temp <> nil then
1098     begin
1099       if not temp.Empty then
1100       begin
1101         shape := TRectShape.Create(orig);
1102         shape.QuickDefine(PointF(-0.5,-0.5),PointF(temp.Width-0.5,temp.Height-0.5));
1103         shape.PenStyle := ClearPenStyle;
1104         if temp.Equals(temp.GetPixel(0,0)) then
1105           shape.BackFill.SetSolid(temp.GetPixel(0,0))
1106           else shape.BackFill.SetTexture(temp,AffineMatrixIdentity,255,trNone);
1107         shape.Transform(imgState.LayeredBitmap.LayerOriginalMatrix[ALayerIndex]);
1108         with imgState.LayeredBitmap.LayerOffset[ALayerIndex] do
1109           shape.Transform(AffineMatrixTranslation(-X-FSourceBounds.Left,-Y-FSourceBounds.Top));
1110         orig.AddShape(shape);
1111       end;
1112       temp.FreeReference;
1113     end;
1114   end else
1115   begin
1116     source := imgState.LayeredBitmap.LayerBitmap[ALayerIndex];
1117     if not source.Empty and not FSourceBounds.IsEmpty then
1118     begin
1119       temp := source.GetPart(FSourceBounds) as TBGRABitmap;
1120       shape := TRectShape.Create(orig);
1121       shape.QuickDefine(PointF(-0.5,-0.5),PointF(FSourceBounds.Width-0.5,FSourceBounds.Height-0.5));
1122       shape.PenStyle := ClearPenStyle;
1123       if temp.Equals(temp.GetPixel(0,0)) then
1124         shape.BackFill.SetSolid(temp.GetPixel(0,0))
1125         else shape.BackFill.SetTexture(temp,AffineMatrixIdentity,255,trNone);
1126       orig.AddShape(shape);
1127       temp.FreeReference;
1128     end;
1129   end;
1130   result := orig;
1131 end;
1132 
1133 constructor TReplaceLayerByVectorOriginalDifference.Create(AFromState: TState;
1134   AIndex: integer; AAlwaysStoreBitmap: boolean);
1135 var
1136   imgState: TImageState;
1137 begin
1138   imgState := AFromState as TImageState;
1139   FShouldRenderOriginal:= imgState.LayeredBitmap.LayerOriginalClass[AIndex]=TBGRALayerGradientOriginal;
1140   inherited Create(AFromState, AIndex, AAlwaysStoreBitmap);
1141 end;
1142 
1143 { TReplaceLayerByImageOriginalDifference }
1144 
1145 procedure TReplaceLayerByImageOriginalDifference.StorePreviousLayer(
1146   AImgState: TImageState; ALayerIndex: integer; AAlwaysStoreBitmap: boolean);
1147 begin
1148   if not AImgState.LayerOriginalDefined[ALayerIndex] then
1149     FSourceStoredInOriginal:= true
1150   else
1151     inherited StorePreviousLayer(AImgState, ALayerIndex, AAlwaysStoreBitmap);
1152 end;
1153 
TReplaceLayerByImageOriginalDifference.CreateOriginalnull1154 function TReplaceLayerByImageOriginalDifference.CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal;
1155 var
1156   source: TBGRABitmap;
1157   temp: TBGRACustomBitmap;
1158   imgState: TImageState;
1159   orig: TBGRALayerImageOriginal;
1160 begin
1161   imgState := TImageState(AState);
1162   orig := TBGRALayerImageOriginal.Create;
1163   source := imgState.LayeredBitmap.LayerBitmap[ALayerIndex];
1164   if (FSourceBounds.Width <> source.Width) or (FSourceBounds.Height <> source.Height) then
1165   begin
1166     temp := source.GetPart(FSourceBounds);
1167     orig.AssignImage(temp);
1168     temp.Free;
1169   end else
1170     orig.AssignImage(source);
1171   result := orig;
1172 end;
1173 
UsedMemorynull1174 function TReplaceLayerByImageOriginalDifference.UsedMemory: int64;
1175 begin
1176   if FSourceStoredInOriginal then
1177     result := 0
1178   else
1179     Result:=inherited UsedMemory;
1180 end;
1181 
TReplaceLayerByImageOriginalDifference.TryCompressnull1182 function TReplaceLayerByImageOriginalDifference.TryCompress: boolean;
1183 begin
1184   if FSourceStoredInOriginal then
1185     result := false
1186   else Result:=inherited TryCompress;
1187 end;
1188 
1189 procedure TReplaceLayerByImageOriginalDifference.UnapplyTo(AState: TState);
1190 var
1191   imgState: TImageState;
1192   layerIdx: Integer;
1193   bmp: TBGRABitmap;
1194 begin
1195   if FSourceStoredInOriginal then
1196   begin
1197     CustomUnapplyto(AState);
1198     imgState := AState as TImageState;
1199     layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(LayerId);
1200     bmp := (imgState.LayeredBitmap.LayerOriginal[layerIdx] as TBGRALayerImageOriginal).GetImageCopy;
1201     imgState.LayeredBitmap.SetLayerBitmap(layerIdx, bmp, True);
1202     imgState.LayeredBitmap.LayerOffset[layerIdx] := Point(round(FPrevMatrix[1,3]), round(FPrevMatrix[2,3]));
1203     imgState.LayeredBitmap.RemoveUnusedOriginals;
1204   end else
1205     inherited UnapplyTo(AState);
1206 end;
1207 
1208 { TSelectionTransformDifference }
1209 
GetImageDifferenceKindnull1210 function TSelectionTransformDifference.GetImageDifferenceKind: TImageDifferenceKind;
1211 begin
1212   if Assigned(FPrevSelectionMask) then
1213   begin
1214     if Assigned(FPrevSelectionLayer) then
1215       Result:= idkChangeImageAndSelection
1216     else
1217       Result:= idkChangeSelection;
1218   end else
1219     if Assigned(FPrevSelectionLayer) then
1220       Result:= idkChangeImage;
1221 end;
1222 
GetIsIdentitynull1223 function TSelectionTransformDifference.GetIsIdentity: boolean;
1224 begin
1225   Result:= IsAffineMatrixIdentity(FPrevTransform);
1226 end;
1227 
TSelectionTransformDifference.TryCompressnull1228 function TSelectionTransformDifference.TryCompress: boolean;
1229 begin
1230   Result:= (Assigned(FPrevSelectionMask) and FPrevSelectionMask.Compress) or
1231            (Assigned(FPrevSelectionLayer) and FPrevSelectionLayer.Compress);
1232 end;
1233 
1234 constructor TSelectionTransformDifference.Create(ADestination: TState;
1235   AApplyNow: boolean);
1236 var
1237   ImgState: TImageState;
1238 begin
1239   inherited Create(ADestination);
1240   ImgState := ADestination as TImageState;
1241   FPrevTransform := ImgState.SelectionTransform;
1242   if not ImgState.SelectionMaskEmpty then
1243     FPrevSelectionMask := TStoredImage.Create(ImgState.SelectionMask, True)
1244     else FPrevSelectionMask := nil;
1245   if not ImgState.SelectionLayerEmpty then
1246     FPrevSelectionLayer := TStoredImage.Create(ImgState.SelectionLayer, False)
1247     else FPrevSelectionLayer := nil;
1248   if AApplyNow then ApplyTo(ADestination);
1249 end;
1250 
1251 destructor TSelectionTransformDifference.Destroy;
1252 begin
1253   FPrevSelectionMask.Free;
1254   FPrevSelectionLayer.Free;
1255   inherited Destroy;
1256 end;
1257 
1258 procedure TSelectionTransformDifference.ApplyTo(AState: TState);
1259 var
1260   ImgState: TImageState;
1261   newBmp: TBGRABitmap;
1262   newLeft, newTop: integer;
1263   r: TRect;
1264 begin
1265   inherited ApplyTo(AState);
1266   if not IsIdentity then
1267   begin
1268     ImgState := AState as TImageState;
1269     if not ImgState.SelectionMaskEmpty then
1270     begin
1271       ImgState.ComputeTransformedSelectionMask(newBmp,newLeft,newTop);
1272       r := ImgState.GetSelectionMaskBounds;
1273       ImgState.SelectionMask.FillRect(r, BGRABlack, dmSet);
1274       ImgState.SelectionMask.PutImage(newLeft,newTop,newBmp,dmSet);
1275       newBmp.Free;
1276     end;
1277     if not ImgState.SelectionLayerEmpty then
1278     begin
1279       ImgState.ComputeTransformedSelectionLayer(newBmp,newLeft,newTop);
1280       r := ImgState.GetSelectionLayerBounds;
1281       ImgState.SelectionLayer.FillRect(r, BGRAPixelTransparent, dmSet);
1282       ImgState.SelectionLayer.PutImage(newLeft,newTop,newBmp,dmSet);
1283       newBmp.Free;
1284     end;
1285     ImgState.SelectionTransform := AffineMatrixIdentity;
1286     ImgState.DiscardSelectionMaskBoundsCompletely;
1287     ImgState.DiscardSelectionLayerBoundsCompletely;
1288   end;
1289 end;
1290 
1291 procedure TSelectionTransformDifference.UnapplyTo(AState: TState);
1292 var
1293   ImgState: TImageState;
1294   prevMask, prevSelectionLayer: TBGRABitmap;
1295 begin
1296   if not IsIdentity then
1297   begin
1298     ImgState := AState as TImageState;
1299     if Assigned(FPrevSelectionMask) then prevMask := FPrevSelectionMask.GetBitmap else prevMask := nil;
1300     if Assigned(FPrevSelectionLayer) then prevSelectionLayer := FPrevSelectionLayer.GetBitmap else prevSelectionLayer := nil;
1301     ImgState.ReplaceSelection(prevMask, prevSelectionLayer);
1302     ImgState.DiscardSelectionMaskBoundsCompletely;
1303     ImgState.DiscardSelectionLayerBoundsCompletely;
1304     ImgState.SelectionTransform := FPrevTransform;
1305   end;
1306   inherited UnapplyTo(AState);
1307 end;
1308 
1309 { TReplaceLayerByOriginalDifference }
1310 
GetLayerIdnull1311 function TReplaceLayerByOriginalDifference.GetLayerId: integer;
1312 begin
1313   result := FSourceLayerId;
1314 end;
1315 
TReplaceLayerByOriginalDifference.GetImageDifferenceKindnull1316 function TReplaceLayerByOriginalDifference.GetImageDifferenceKind: TImageDifferenceKind;
1317 begin
1318   Result:= idkChangeImage;
1319 end;
1320 
ShouldRenderOriginalnull1321 function TReplaceLayerByOriginalDifference.ShouldRenderOriginal: boolean;
1322 begin
1323   result := false;
1324 end;
1325 
1326 procedure TReplaceLayerByOriginalDifference.StorePreviousLayer(
1327   AImgState: TImageState; ALayerIndex: integer; AAlwaysStoreBitmap: boolean);
1328 begin
1329   FPreviousLayerContent := TStoredLayer.Create(AImgState.LayeredBitmap, ALayerIndex, AAlwaysStoreBitmap);
1330 end;
1331 
1332 procedure TReplaceLayerByOriginalDifference.CustomUnapplyto(AState: TState);
1333 begin
1334   inherited UnapplyTo(AState);
1335 end;
1336 
1337 constructor TReplaceLayerByOriginalDifference.Create(
1338   AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
1339 var
1340   imgState: TImageState;
1341 begin
1342   inherited Create(AFromState);
1343   imgState := AFromState as TImageState;
1344   FSourceBounds := imgState.LayeredBitmap.LayerBitmap[AIndex].GetImageBounds;
1345   FSourceLayerId := imgState.LayeredBitmap.LayerUniqueId[AIndex];
1346   with imgState.LayeredBitmap.LayerOffset[AIndex] do FPrevMatrix := AffineMatrixTranslation(x+FSourceBounds.Left,y+FSourceBounds.Top);
1347   StorePreviousLayer(imgState, AIndex, AAlwaysStoreBitmap);
1348   FNextMatrix := FPrevMatrix;
1349   ApplyTo(imgState);
1350 end;
1351 
TReplaceLayerByOriginalDifference.UsedMemorynull1352 function TReplaceLayerByOriginalDifference.UsedMemory: int64;
1353 begin
1354   Result:= FPreviousLayerContent.UsedMemory;
1355 end;
1356 
TryCompressnull1357 function TReplaceLayerByOriginalDifference.TryCompress: boolean;
1358 begin
1359   Result:= FPreviousLayerContent.Compress;
1360 end;
1361 
1362 procedure TReplaceLayerByOriginalDifference.ApplyTo(AState: TState);
1363 var
1364   imgState: TImageState;
1365   orig: TBGRALayerCustomOriginal;
1366   origIndex,layerIdx: Integer;
1367 begin
1368   inherited ApplyTo(AState);
1369   imgState := AState as TImageState;
1370   layerIdx := imgState.LayeredBitmap.GetLayerIndexFromId(FSourceLayerId);
1371   orig := CreateOriginal(imgState, layerIdx);
1372   if FOriginalGuid <> GUID_NULL then orig.Guid := FOriginalGuid;
1373   origIndex := imgState.LayeredBitmap.AddOriginal(orig, true);
1374   if FOriginalGuid = GUID_NULL then FOriginalGuid := orig.Guid;
1375   imgState.LayeredBitmap.LayerOriginalGuid[layerIdx] := imgState.LayeredBitmap.OriginalGuid[origIndex];
1376   imgState.LayeredBitmap.LayerOriginalMatrix[layerIdx] := FNextMatrix;
1377   if (FNextMatrix = FPrevMatrix) and not ShouldRenderOriginal then
1378     imgState.LayeredBitmap.LayerOriginalRenderStatus[layerIdx] := orsProof
1379   else
1380   begin
1381     imgState.LayeredBitmap.LayerOriginalRenderStatus[layerIdx] := orsNone;
1382     imgState.LayeredBitmap.RenderLayerFromOriginal(layerIdx);
1383   end;
1384   imgState.LayeredBitmap.RemoveUnusedOriginals;
1385 end;
1386 
1387 procedure TReplaceLayerByOriginalDifference.UnapplyTo(AState: TState);
1388 var
1389   imgState: TImageState;
1390 begin
1391   CustomUnapplyto(AState);
1392   imgState := AState as TImageState;
1393   FPreviousLayerContent.Replace(imgState.LayeredBitmap);
1394 end;
1395 
1396 destructor TReplaceLayerByOriginalDifference.Destroy;
1397 begin
1398   FPreviousLayerContent.Free;
1399   inherited Destroy;
1400 end;
1401 
1402 { TSetSelectionTransformDifference }
1403 
TSetSelectionTransformDifference.GetImageDifferenceKindnull1404 function TSetSelectionTransformDifference.GetImageDifferenceKind: TImageDifferenceKind;
1405 begin
1406   Result:= idkChangeImageAndSelection;
1407 end;
1408 
GetIsIdentitynull1409 function TSetSelectionTransformDifference.GetIsIdentity: boolean;
1410 begin
1411   Result:= previousMatrix = nextMatrix;
1412 end;
1413 
1414 constructor TSetSelectionTransformDifference.Create(ADestination: TState;
1415   ANextMatrix: TAffineMatrix);
1416 var
1417   imgState: TImageState;
1418 begin
1419   imgState := ADestination as TImageState;
1420   previousMatrix := imgState.SelectionTransform;
1421   nextMatrix := ANextMatrix;
1422 end;
1423 
1424 procedure TSetSelectionTransformDifference.ApplyTo(AState: TState);
1425 var
1426   imgState: TImageState;
1427 begin
1428   inherited ApplyTo(AState);
1429   imgState := AState as TImageState;
1430   imgState.SelectionTransform := nextMatrix;
1431 end;
1432 
1433 procedure TSetSelectionTransformDifference.UnapplyTo(AState: TState);
1434 var
1435   imgState: TImageState;
1436 begin
1437   inherited UnapplyTo(AState);
1438   imgState := AState as TImageState;
1439   imgState.SelectionTransform := previousMatrix;
1440 end;
1441 
1442 { TDiscardOriginalStateDifference }
1443 
TDiscardOriginalStateDifference.GetImageDifferenceKindnull1444 function TDiscardOriginalStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1445 begin
1446   Result:= idkChangeStack;
1447 end;
1448 
UsedMemorynull1449 function TDiscardOriginalStateDifference.UsedMemory: int64;
1450 begin
1451   if Assigned(origData) then
1452     result := origData.Size
1453   else
1454     result := 0;
1455 end;
1456 
TDiscardOriginalStateDifference.TryCompressnull1457 function TDiscardOriginalStateDifference.TryCompress: boolean;
1458 begin
1459   Result:= false;
1460 end;
1461 
1462 procedure TDiscardOriginalStateDifference.ApplyTo(AState: TState);
1463 var
1464   imgState: TImageState;
1465   idx: Integer;
1466 begin
1467   imgState := AState as TImageState;
1468   idx := imgState.LayeredBitmap.GetLayerIndexFromId(layerId);
1469   imgState.LayeredBitmap.LayerOriginalGuid[idx] := GUID_NULL;
1470   imgState.LayeredBitmap.LayerOriginalMatrix[idx] := AffineMatrixIdentity;
1471   imgState.LayeredBitmap.RemoveUnusedOriginals;
1472 end;
1473 
1474 procedure TDiscardOriginalStateDifference.UnapplyTo(AState: TState);
1475 var
1476   imgState: TImageState;
1477   idx, idxOrig: Integer;
1478 begin
1479   imgState := AState as TImageState;
1480   idx := imgState.LayeredBitmap.GetLayerIndexFromId(layerId);
1481   if Assigned(origData) then
1482   begin
1483     origData.Position:= 0;
1484     idxOrig := imgState.LayeredBitmap.AddOriginalFromStream(origData, true);
1485     imgState.LayeredBitmap.LayerOriginalGuid[idx] := imgState.LayeredBitmap.OriginalGuid[idxOrig];
1486     imgState.LayeredBitmap.LayerOriginalMatrix[idx] := origMatrix;
1487     imgState.LayeredBitmap.LayerOriginalRenderStatus[idx] := origRenderStatus;
1488   end;
1489 end;
1490 
1491 constructor TDiscardOriginalStateDifference.Create(AState: TState; AIndex: integer);
1492 var
1493   imgState: TImageState;
1494 begin
1495   inherited Create(AState);
1496   imgState := AState as TImageState;
1497   if imgState.LayeredBitmap = nil then
1498     raise exception.Create('Layered bitmap not created');
1499   AIndex := AIndex;
1500   if AIndex = -1 then raise exception.Create('No layer selected');
1501   layerId:= imgState.LayerId[AIndex];
1502   if imgState.LayerOriginalDefined[AIndex] then
1503   begin
1504     origData := TMemoryStream.Create;
1505     imgState.LayeredBitmap.SaveOriginalToStream(imgState.LayeredBitmap.LayerOriginalGuid[AIndex], origData);
1506     origMatrix := imgState.LayeredBitmap.LayerOriginalMatrix[AIndex];
1507     origRenderStatus:= imgState.LayeredBitmap.LayerOriginalRenderStatus[AIndex];
1508   end else
1509   begin
1510     origData := nil;
1511     origMatrix := AffineMatrixIdentity;
1512     origRenderStatus:= orsNone;
1513   end;
1514 end;
1515 
1516 destructor TDiscardOriginalStateDifference.Destroy;
1517 begin
1518   origData.Free;
1519   inherited Destroy;
1520 end;
1521 
1522 { TSetLayerMatrixDifference }
1523 
TSetLayerMatrixDifference.GetImageDifferenceKindnull1524 function TSetLayerMatrixDifference.GetImageDifferenceKind: TImageDifferenceKind;
1525 begin
1526   Result:= idkChangeImage;
1527 end;
1528 
GetIsIdentitynull1529 function TSetLayerMatrixDifference.GetIsIdentity: boolean;
1530 begin
1531   Result:= nextMatrix = previousMatrix;
1532 end;
1533 
1534 constructor TSetLayerMatrixDifference.Create(ADestination: TState;
1535   ALayerId: integer; APreviousMatrix, ANextMatrix: TAffineMatrix);
1536 begin
1537   layerId:= ALayerId;
1538   previousMatrix := APreviousMatrix;
1539   nextMatrix := ANextMatrix;
1540 end;
1541 
1542 procedure TSetLayerMatrixDifference.ApplyTo(AState: TState);
1543 var
1544   idx: Integer;
1545 begin
1546   inherited ApplyTo(AState);
1547   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1548   if idx =-1 then raise exception.Create('Layer not found');
1549   TImageState(AState).LayeredBitmap.LayerOriginalMatrix[idx] := nextMatrix;
1550   TImageState(AState).LayeredBitmap.RenderLayerFromOriginal(idx);
1551 end;
1552 
1553 procedure TSetLayerMatrixDifference.UnapplyTo(AState: TState);
1554 var
1555   idx: Integer;
1556 begin
1557   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1558   if idx =-1 then raise exception.Create('Layer not found');
1559   TImageState(AState).LayeredBitmap.LayerOriginalMatrix[idx] := previousMatrix;
1560   TImageState(AState).LayeredBitmap.RenderLayerFromOriginal(idx);
1561 end;
1562 
1563 { TSelectCurrentLayer }
1564 
TSelectCurrentLayer.GetImageDifferenceKindnull1565 function TSelectCurrentLayer.GetImageDifferenceKind: TImageDifferenceKind;
1566 begin
1567   Result:= idkChangeImage; //selection layer can affect image
1568 end;
1569 
1570 constructor TSelectCurrentLayer.Create(AState: TState; ANewLayerIndex: integer);
1571 begin
1572   inherited Create(AState.saved, AState.saved);
1573   FPrevLayerIndex:= (AState as TImageState).SelectedImageLayerIndex;
1574   FNewLayerIndex:= ANewLayerIndex;
1575 end;
1576 
1577 procedure TSelectCurrentLayer.ApplyTo(AState: TState);
1578 begin
1579   (AState as TImageState).SelectedImageLayerIndex:= FNewLayerIndex;
1580 end;
1581 
1582 procedure TSelectCurrentLayer.UnApplyTo(AState: TState);
1583 begin
1584   (AState as TImageState).SelectedImageLayerIndex:= FPrevLayerIndex;
1585 end;
1586 
TSelectCurrentLayer.ToStringnull1587 function TSelectCurrentLayer.ToString: ansistring;
1588 begin
1589   Result:= ClassName+'('+IntToStr(FPrevLayerIndex)+' to '+IntToStr(FNewLayerIndex)+')';
1590 end;
1591 
1592 { TAddLayerFromOwnedOriginalStateDifference }
1593 
TAddLayerFromOwnedOriginalStateDifference.GetImageDifferenceKindnull1594 function TAddLayerFromOwnedOriginalStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1595 begin
1596   Result:= idkChangeImage;
1597 end;
1598 
1599 procedure TAddLayerFromOwnedOriginalStateDifference.Uncompress;
1600 var
1601   decompression: Tdecompressionstream;
1602   uncompressedSize: Int64;
1603 begin
1604   if Assigned(compressedData) and not Assigned(originalData) then
1605   begin
1606     originalData:= TMemoryStream.Create;
1607     compressedData.Position := 0;
1608     uncompressedSize:= 0;
1609     compressedData.ReadBuffer(uncompressedSize, sizeof(uncompressedSize));
1610     decompression := Tdecompressionstream.Create(compressedData, true);
1611     originalData.CopyFrom(decompression, uncompressedSize);
1612     decompression.Free;
1613     FreeAndNil(compressedData);
1614   end
1615 end;
1616 
TAddLayerFromOwnedOriginalStateDifference.UsedMemorynull1617 function TAddLayerFromOwnedOriginalStateDifference.UsedMemory: int64;
1618 begin
1619   if Assigned(originalData) then
1620     result := originalData.Size
1621   else
1622   if Assigned(compressedData) then
1623     result := compressedData.Size
1624   else
1625     result := 0;
1626 end;
1627 
TryCompressnull1628 function TAddLayerFromOwnedOriginalStateDifference.TryCompress: boolean;
1629 var
1630   compression: Tcompressionstream;
1631   uncompressedSize: Int64;
1632 begin
1633   if Assigned(originalData) and not Assigned(compressedData) then
1634   begin
1635     compressedData:= TMemoryStream.Create;
1636     uncompressedSize := originalData.Size;
1637     compressedData.WriteBuffer(uncompressedSize, sizeof(uncompressedSize));
1638     compression := Tcompressionstream.Create(cldefault, compressedData, true);
1639     originalData.Position:= 0;
1640     compression.CopyFrom(originalData, originalData.Size);
1641     compression.Free;
1642     FreeAndNil(originalData);
1643     result := true;
1644   end
1645   else
1646     result := false;
1647 end;
1648 
1649 procedure TAddLayerFromOwnedOriginalStateDifference.ApplyTo(AState: TState);
1650 var idx, origIdx: integer;
1651 begin
1652   inherited ApplyTo(AState);
1653   Uncompress;
1654   if not Assigned(originalData) then
1655     raise exception.Create('Original data missing');
1656 
1657   with AState as TImageState do
1658   begin
1659     originalData.Position:= 0;
1660     origIdx:= LayeredBitmap.AddOriginalFromStream(originalData);
1661     idx := LayeredBitmap.AddLayerFromOriginal(LayeredBitmap.Original[origIdx].Guid, self.blendOp, self.opacity);
1662     LayeredBitmap.LayerUniqueId[idx] := self.layerId;
1663     LayeredBitmap.LayerName[idx] := name;
1664     LayeredBitmap.LayerOriginalMatrix[idx] := matrix;
1665     LayeredBitmap.RenderLayerFromOriginal(idx);
1666     SelectedImageLayerIndex := idx;
1667   end;
1668 end;
1669 
1670 procedure TAddLayerFromOwnedOriginalStateDifference.UnapplyTo(AState: TState);
1671 var idx: integer;
1672 begin
1673   inherited UnapplyTo(AState);
1674   with AState as TImageState do
1675   begin
1676     idx := LayeredBitmap.GetLayerIndexFromId(self.layerId);
1677     LayeredBitmap.RemoveLayer(idx);
1678     SelectedImageLayerIndex := LayeredBitmap.GetLayerIndexFromId(self.previousActiveLayerId);
1679   end;
1680 end;
1681 
1682 constructor TAddLayerFromOwnedOriginalStateDifference.Create(ADestination: TState;
1683   AOriginal: TBGRALayerCustomOriginal; AName: ansistring;
1684   ABlendOp: TBlendOperation; AMatrix: TAffineMatrix; AOpacity: Byte);
1685 var idx: integer;
1686   imgDest: TImageState;
1687 begin
1688   inherited Create(ADestination);
1689   imgDest := ADestination as TImageState;
1690   if imgDest.LayeredBitmap = nil then
1691     raise exception.Create('Layered bitmap not created');
1692 
1693   self.originalData := TMemoryStream.Create;
1694   AOriginal.SaveToStream(originalData);
1695 
1696   self.name := AName;
1697   self.blendOp:= AblendOp;
1698   self.matrix := AMatrix;
1699   self.previousActiveLayerId := imgDest.LayeredBitmap.LayerUniqueId[imgDest.SelectedImageLayerIndex];
1700   idx := imgDest.LayeredBitmap.AddLayerFromOwnedOriginal(AOriginal, ABlendOp, AOpacity);
1701   imgDest.LayeredBitmap.LayerName[idx] := name;
1702   imgDest.LayeredBitmap.LayerOriginalMatrix[idx] := matrix;
1703   self.layerId := imgDest.LayeredBitmap.LayerUniqueId[idx];
1704   imgDest.LayeredBitmap.RenderLayerFromOriginal(idx);
1705   imgDest.SelectedImageLayerIndex := idx;
1706 end;
1707 
1708 destructor TAddLayerFromOwnedOriginalStateDifference.Destroy;
1709 begin
1710   originalData.Free;
1711   compressedData.Free;
1712   inherited Destroy;
1713 end;
1714 
1715 { TApplyLayerOffsetStateDifference }
1716 
GetImageDifferenceKindnull1717 function TApplyLayerOffsetStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1718 begin
1719   Result:= idkChangeImage;
1720 end;
1721 
GetIsIdentitynull1722 function TApplyLayerOffsetStateDifference.GetIsIdentity: boolean;
1723 begin
1724   Result:= (previousBounds.Left = nextBounds.Left) and (previousBounds.Top = nextBounds.Top) and
1725      (previousBounds.right = nextBounds.Right) and (previousBounds.bottom = nextBounds.Bottom);
1726 end;
1727 
GetChangingBoundsDefinednull1728 function TApplyLayerOffsetStateDifference.GetChangingBoundsDefined: boolean;
1729 begin
1730   Result:= true;
1731 end;
1732 
GetChangingBoundsnull1733 function TApplyLayerOffsetStateDifference.GetChangingBounds: TRect;
1734 begin
1735   Result:= EmptyRect;
1736 end;
1737 
1738 constructor TApplyLayerOffsetStateDifference.Create(ADestination: TState;
1739   ALayerId: integer; AOffsetX, AOffsetY: integer; AApplyNow: boolean);
1740 var idx: integer;
1741   layers: TBGRALayeredBitmap;
1742   clippedImage: TBGRABitmap;
1743 begin
1744   inherited Create(ADestination);
1745   layerId:= ALayerId;
1746   layers := (ADestination as TImageState).LayeredBitmap;
1747   idx := layers.GetLayerIndexFromId(ALayerId);
1748   if idx = -1 then raise exception.Create('Invalid layer Id');
1749   nextBounds := rect(0,0,layers.Width,layers.Height);
1750   previousBounds.Left := AOffsetX;
1751   previousBounds.Top := AOffsetY;
1752   previousBounds.Right := previousBounds.Left+layers.LayerBitmap[idx].Width;
1753   previousBounds.Bottom := previousBounds.Top+layers.LayerBitmap[idx].Height;
1754   previousLayerOffset := layers.LayerOffset[idx];
1755   if IsIdentity then
1756   begin
1757     clippedData := nil;
1758     useOriginal := false;
1759     unchangedBounds := previousBounds;
1760   end else
1761   begin
1762     unchangedBounds := previousBounds;
1763     IntersectRect(unchangedBounds, unchangedBounds, nextBounds);
1764     OffsetRect(unchangedBounds, -AOffsetX, -AOffsetY);
1765     useOriginal:= layers.LayerOriginalGuid[idx]<>GUID_NULL;
1766     previousOriginalRenderStatus:= layers.LayerOriginalRenderStatus[idx];
1767 
1768     clippedImage := layers.LayerBitmap[idx].Duplicate as TBGRABitmap;
1769     clippedImage.FillRect(unchangedBounds,BGRAPixelTransparent,dmSet);
1770     clippedData := TMemoryStream.Create;
1771     TBGRAWriterLazPaint.WriteRLEImage(clippedData, clippedImage);
1772     clippedImage.Free;
1773   end;
1774   if AApplyNow then ApplyTo(ADestination);
1775 end;
1776 
1777 destructor TApplyLayerOffsetStateDifference.Destroy;
1778 begin
1779   FreeAndNil(clippedData);
1780   inherited Destroy;
1781 end;
1782 
1783 procedure TApplyLayerOffsetStateDifference.ApplyTo(AState: TState);
1784 var idx: integer;
1785 begin
1786   inherited ApplyTo(AState);
1787   if IsIdentity then exit;
1788   idx := (AState as TImageState).LayeredBitmap.GetLayerIndexFromId(layerId);
1789   if idx =-1 then raise exception.Create('Layer not found');
1790   (AState as TImageState).LayeredBitmap.ApplyLayerOffset(idx, true);
1791 end;
1792 
1793 procedure TApplyLayerOffsetStateDifference.UnapplyTo(AState: TState);
1794 var idx: integer;
1795   newContent: TBGRABitmap;
1796   layers: TBGRALayeredBitmap;
1797   shifted: TRect;
1798   dummyCaption: ansistring;
1799   guid: TGuid;
1800   m: TAffineMatrix;
1801 begin
1802   inherited ApplyTo(AState);
1803   if IsIdentity then exit;
1804   layers := (AState as TImageState).LayeredBitmap;
1805   idx := layers.GetLayerIndexFromId(layerId);
1806   if idx =-1 then
1807     raise exception.Create('Layer not found');
1808 
1809   newContent := TBGRABitmap.Create;
1810   clippedData.Position:= 0;
1811   TBGRAReaderLazPaint.LoadRLEImage(clippedData,newContent,dummyCaption);
1812   shifted := unchangedBounds;
1813   OffsetRect(shifted, previousBounds.left-nextBounds.left,previousBounds.top-nextBounds.top);
1814   newContent.PutImagePart(unchangedBounds.Left,unchangedBounds.Top, layers.LayerBitmap[idx],shifted, dmSet);
1815   guid := layers.LayerOriginalGuid[idx];
1816   m := layers.LayerOriginalMatrix[idx];
1817   layers.SetLayerBitmap(idx,newContent,True);
1818   layers.LayerOffset[idx] := previousLayerOffset;
1819   if useOriginal then
1820   begin
1821     layers.LayerOriginalGuid[idx] := guid;
1822     layers.LayerOriginalMatrix[idx] := m;
1823     layers.LayerOriginalRenderStatus[idx] := previousOriginalRenderStatus;
1824   end;
1825 end;
1826 
1827 { TSetLayerOffsetStateDifference }
1828 
GetImageDifferenceKindnull1829 function TSetLayerOffsetStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1830 begin
1831   Result:= idkChangeImage;
1832 end;
1833 
GetIsIdentitynull1834 function TSetLayerOffsetStateDifference.GetIsIdentity: boolean;
1835 begin
1836   Result:=(previousOffset.x = nextOffset.x) and (previousOffset.y = nextOffset.y);
1837 end;
1838 
1839 constructor TSetLayerOffsetStateDifference.Create(ADestination: TState;
1840   ALayerId: integer; ANewOffset: TPoint);
1841 var idx: integer;
1842   imgDest: TImageState;
1843 begin
1844   inherited Create(Adestination);
1845   imgDest := ADestination as TImageState;
1846   layerId:= ALayerId;
1847   nextOffset:= ANewOffset;
1848   idx := imgDest.LayeredBitmap.GetLayerIndexFromId(ALayerId);
1849   if idx =-1 then
1850     raise exception.Create('Layer not found');
1851   previousOffset:= imgDest.LayerOffset[idx];
1852   ApplyTo(imgDest);
1853 end;
1854 
1855 procedure TSetLayerOffsetStateDifference.ApplyTo(AState: TState);
1856 var idx: integer;
1857 begin
1858   inherited ApplyTo(AState);
1859   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1860   if idx =-1 then
1861     raise exception.Create('Layer not found');
1862   TImageState(AState).LayeredBitmap.LayerOffset[idx] := nextOffset;
1863 end;
1864 
1865 procedure TSetLayerOffsetStateDifference.UnapplyTo(AState: TState);
1866 var idx: integer;
1867 begin
1868   inherited UnapplyTo(AState);
1869   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1870   if idx =-1 then
1871     raise exception.Create('Layer not found');
1872   TImageState(AState).LayeredBitmap.LayerOffset[idx] := previousOffset;
1873 end;
1874 
1875 { TSetLayerBlendOpStateDifference }
1876 
GetImageDifferenceKindnull1877 function TSetLayerBlendOpStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1878 begin
1879   Result:= idkChangeImage;
1880 end;
1881 
TSetLayerBlendOpStateDifference.GetChangingBoundsnull1882 function TSetLayerBlendOpStateDifference.GetChangingBounds: TRect;
1883 begin
1884   Result:= layerBounds;
1885 end;
1886 
GetChangingBoundsDefinednull1887 function TSetLayerBlendOpStateDifference.GetChangingBoundsDefined: boolean;
1888 begin
1889   Result:= true;
1890 end;
1891 
GetIsIdentitynull1892 function TSetLayerBlendOpStateDifference.GetIsIdentity: boolean;
1893 begin
1894   Result:=previousBlendOp = nextBlendOp;
1895 end;
1896 
1897 constructor TSetLayerBlendOpStateDifference.Create(ADestination: TState;
1898   ALayerId: integer; ANewBlendOp: TBlendOperation);
1899 var idx: integer;
1900   imgDest: TImageState;
1901 begin
1902   inherited Create(Adestination);
1903   imgDest := ADestination as TImageState;
1904   layerId:= ALayerId;
1905   nextBlendOp:= ANewBlendOp;
1906   idx := imgDest.LayeredBitmap.GetLayerIndexFromId(ALayerId);
1907   if idx =-1 then
1908     raise exception.Create('Layer not found');
1909   previousBlendOp:= imgDest.BlendOperation[idx];
1910   layerBounds := imgDest.LayerBitmap[idx].GetImageBounds;
1911   with imgDest.LayerOffset[idx] do layerBounds.Offset(x,y);
1912   ApplyTo(imgDest);
1913 end;
1914 
1915 procedure TSetLayerBlendOpStateDifference.ApplyTo(AState: TState);
1916 var idx: integer;
1917 begin
1918   inherited ApplyTo(AState);
1919   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1920   if idx =-1 then
1921     raise exception.Create('Layer not found');
1922   TImageState(AState).LayeredBitmap.BlendOperation[idx] := nextBlendOp;
1923 end;
1924 
1925 procedure TSetLayerBlendOpStateDifference.UnapplyTo(AState: TState);
1926 var idx: integer;
1927 begin
1928   inherited UnapplyTo(AState);
1929   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1930   if idx =-1 then
1931     raise exception.Create('Layer not found');
1932   TImageState(AState).LayeredBitmap.BlendOperation[idx] := previousBlendOp;
1933 end;
1934 
1935 { TSetLayerVisibleStateDifference }
1936 
GetImageDifferenceKindnull1937 function TSetLayerVisibleStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1938 begin
1939   Result:= idkChangeImage;
1940 end;
1941 
TSetLayerVisibleStateDifference.GetChangingBoundsnull1942 function TSetLayerVisibleStateDifference.GetChangingBounds: TRect;
1943 begin
1944   Result:= layerBounds;
1945 end;
1946 
GetChangingBoundsDefinednull1947 function TSetLayerVisibleStateDifference.GetChangingBoundsDefined: boolean;
1948 begin
1949   Result:= true;
1950 end;
1951 
GetIsIdentitynull1952 function TSetLayerVisibleStateDifference.GetIsIdentity: boolean;
1953 begin
1954   Result:= previousVisible=nextVisible;
1955 end;
1956 
1957 constructor TSetLayerVisibleStateDifference.Create(ADestination: TState;
1958   ALayerId: integer; ANewVisible: boolean);
1959 var idx: integer;
1960   imgDest: TImageState;
1961 begin
1962   inherited Create(Adestination);
1963   imgDest := ADestination as TImageState;
1964   layerId:= ALayerId;
1965   nextVisible:= ANewVisible;
1966   idx := imgDest.LayeredBitmap.GetLayerIndexFromId(ALayerId);
1967   if idx =-1 then
1968     raise exception.Create('Layer not found');
1969   previousVisible:= imgDest.LayerVisible[idx];
1970   layerBounds := imgDest.LayerBitmap[idx].GetImageBounds;
1971   with imgDest.LayerOffset[idx] do layerBounds.Offset(x,y);
1972   ApplyTo(imgDest);
1973 end;
1974 
1975 procedure TSetLayerVisibleStateDifference.ApplyTo(AState: TState);
1976 var idx: integer;
1977 begin
1978   inherited ApplyTo(AState);
1979   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1980   if idx =-1 then
1981     raise exception.Create('Layer not found');
1982   TImageState(AState).LayeredBitmap.LayerVisible[idx] := nextVisible;
1983 end;
1984 
1985 procedure TSetLayerVisibleStateDifference.UnapplyTo(AState: TState);
1986 var idx: integer;
1987 begin
1988   inherited UnapplyTo(AState);
1989   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
1990   if idx =-1 then
1991     raise exception.Create('Layer not found');
1992   TImageState(AState).LayeredBitmap.LayerVisible[idx] := previousVisible;
1993 end;
1994 
1995 { TSetLayerOpacityStateDifference }
1996 
TSetLayerOpacityStateDifference.GetImageDifferenceKindnull1997 function TSetLayerOpacityStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
1998 begin
1999   Result:= idkChangeImage;
2000 end;
2001 
TSetLayerOpacityStateDifference.GetChangingBoundsnull2002 function TSetLayerOpacityStateDifference.GetChangingBounds: TRect;
2003 begin
2004   Result:= layerBounds;
2005 end;
2006 
GetChangingBoundsDefinednull2007 function TSetLayerOpacityStateDifference.GetChangingBoundsDefined: boolean;
2008 begin
2009   Result:= true;
2010 end;
2011 
GetIsIdentitynull2012 function TSetLayerOpacityStateDifference.GetIsIdentity: boolean;
2013 begin
2014   Result:= (previousOpacity=nextOpacity);
2015 end;
2016 
2017 constructor TSetLayerOpacityStateDifference.Create(ADestination: TState;
2018   ALayerId: integer; ANewOpacity: byte);
2019 var idx: integer;
2020   imgDest: TImageState;
2021 begin
2022   inherited Create(Adestination);
2023   imgDest := ADestination as TImageState;
2024   layerId:= ALayerId;
2025   nextOpacity:= ANewOpacity;
2026   idx := imgDest.LayeredBitmap.GetLayerIndexFromId(ALayerId);
2027   if idx =-1 then
2028     raise exception.Create('Layer not found');
2029   previousOpacity:= imgDest.LayerOpacity[idx];
2030   layerBounds := imgDest.LayerBitmap[idx].GetImageBounds;
2031   with imgDest.LayerOffset[idx] do layerBounds.Offset(x,y);
2032   ApplyTo(imgDest);
2033 end;
2034 
2035 procedure TSetLayerOpacityStateDifference.ApplyTo(AState: TState);
2036 var idx: integer;
2037 begin
2038   inherited ApplyTo(AState);
2039   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
2040   if idx =-1 then
2041     raise exception.Create('Layer not found');
2042   TImageState(AState).LayeredBitmap.LayerOpacity[idx] := nextOpacity;
2043 end;
2044 
2045 procedure TSetLayerOpacityStateDifference.UnapplyTo(AState: TState);
2046 var idx: integer;
2047 begin
2048   inherited UnapplyTo(AState);
2049   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
2050   if idx =-1 then
2051     raise exception.Create('Layer not found');
2052   TImageState(AState).LayeredBitmap.LayerOpacity[idx] := previousOpacity;
2053 end;
2054 
2055 { TSetLayerNameStateDifference }
2056 
TSetLayerNameStateDifference.GetImageDifferenceKindnull2057 function TSetLayerNameStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2058 begin
2059   Result:= idkChangeStack;
2060 end;
2061 
GetIsIdentitynull2062 function TSetLayerNameStateDifference.GetIsIdentity: boolean;
2063 begin
2064   Result:= (previousName=nextName);
2065 end;
2066 
2067 constructor TSetLayerNameStateDifference.Create(ADestination: TState;
2068   ALayerId: integer; ANewName: ansistring);
2069 var idx: integer;
2070   imgDest: TImageState;
2071 begin
2072   inherited Create(Adestination);
2073   imgDest := ADestination as TImageState;
2074   layerId:= ALayerId;
2075   nextName:= ANewName;
2076   idx := imgDest.LayeredBitmap.GetLayerIndexFromId(ALayerId);
2077   if idx =-1 then
2078     raise exception.Create('Layer not found');
2079   previousName:= imgDest.LayerName[idx];
2080   ApplyTo(imgDest);
2081 end;
2082 
2083 procedure TSetLayerNameStateDifference.ApplyTo(AState: TState);
2084 var idx: integer;
2085 begin
2086   inherited ApplyTo(AState);
2087   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
2088   if idx =-1 then
2089     raise exception.Create('Layer not found');
2090   TImageState(AState).LayeredBitmap.LayerName[idx] := nextName;
2091 end;
2092 
2093 procedure TSetLayerNameStateDifference.UnapplyTo(AState: TState);
2094 var idx: integer;
2095 begin
2096   inherited ApplyTo(AState);
2097   idx := TImageState(AState).LayeredBitmap.GetLayerIndexFromId(layerId);
2098   if idx =-1 then
2099     raise exception.Create('Layer not found');
2100   TImageState(AState).LayeredBitmap.LayerName[idx] := previousName;
2101 end;
2102 
TSetLayerNameStateDifference.ToStringnull2103 function TSetLayerNameStateDifference.ToString: ansistring;
2104 begin
2105   Result:=ClassName+'('+QuotedStr(previousName)+' to '+QuotedStr(nextName)+')';
2106 end;
2107 
2108 { TAssignStateDifferenceAfter }
2109 
2110 constructor TAssignStateDifferenceAfter.Create(AState: TState; ABackup: TState);
2111 var imgState,imgBackup: TImageState;
2112 begin
2113   imgState := AState as TImageState;
2114   imgBackup := ABackup as TImageState;
2115   FSavedBefore := imgState.saved;
2116   FSavedAfter := False;
2117   FStreamBefore := TMemoryStream.Create;
2118   SaveLayersToStream(FStreamBefore,imgBackup.LayeredBitmap,imgBackup.SelectedImageLayerIndex,lzpRLE);
2119   FStreamAfter := TMemoryStream.Create;
2120   SaveLayersToStream(FStreamAfter,imgState.LayeredBitmap,imgState.SelectedImageLayerIndex,lzpRLE);
2121   FSelectionDiff := TImageDiff.Create(imgBackup.SelectionMask, imgState.SelectionMask, True);
2122   FSelectionLayerDiff := TImageDiff.Create(imgBackup.SelectionLayer, imgState.SelectionLayer, False);
2123 end;
2124 
2125 { TAssignStateDifference }
2126 
2127 procedure TAssignStateDifference.Init(AState: TState; AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer);
2128 begin
2129   with AState as TImageState do
2130   begin
2131     FStreamBefore := TMemoryStream.Create;
2132     SaveLayersToStream(FStreamBefore,LayeredBitmap,SelectedImageLayerIndex,lzpRLE);
2133     FStreamAfter := TMemoryStream.Create;
2134     SaveLayersToStream(FStreamAfter,AValue,ASelectedLayerIndex,lzpRLE);
2135     Assign(AValue, AOwned);
2136     SelectedImageLayerIndex := ASelectedLayerIndex;
2137   end;
2138   FSelectionDiff := nil;
2139   FSelectionLayerDiff := nil;
2140 end;
2141 
2142 constructor TAssignStateDifference.Create(AState: TState;
2143   AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer);
2144 begin
2145   inherited Create(AState);
2146   Init(AState, AValue, AOwned, ASelectedLayerIndex);
2147 end;
2148 
2149 constructor TAssignStateDifference.Create(AState: TState;
2150   AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer;
2151   ACurrentSelection: TBGRABitmap; ASelectionLayer: TBGRABitmap);
2152 begin
2153   inherited Create(AState);
2154   Init(AState, AValue, AOwned, ASelectedLayerIndex);
2155   FSelectionDiff := TImageDiff.Create((AState as TImageState).SelectionMask, ACurrentSelection, True);
2156   FSelectionLayerDiff := TImageDiff.Create((AState as TImageState).SelectionLayer, ASelectionLayer, False);
2157   (AState as TImageState).ReplaceSelection(ACurrentSelection, ASelectionLayer);
2158 end;
2159 
TAssignStateDifference.UsedMemorynull2160 function TAssignStateDifference.UsedMemory: int64;
2161 begin
2162   Result:= 0;
2163   if Assigned(FStreamBefore) then result += FStreamBefore.Size;
2164   if Assigned(FStreamAfter) then result += FStreamAfter.Size;
2165   if Assigned(FSelectionDiff) then result += FSelectionDiff.UsedMemory;
2166   if Assigned(FSelectionLayerDiff) then result += FSelectionLayerDiff.UsedMemory;
2167 end;
2168 
TryCompressnull2169 function TAssignStateDifference.TryCompress: boolean;
2170 begin
2171   result := false;
2172   if Assigned(FSelectionDiff) then result := result or FSelectionDiff.Compress;
2173   if not result and Assigned(FSelectionLayerDiff) then result := result or FSelectionLayerDiff.Compress;
2174 end;
2175 
2176 procedure TAssignStateDifference.ApplyTo(AState: TState);
2177 var temp: TBGRALayeredBitmap;
2178   index: integer;
2179 begin
2180   inherited ApplyTo(AState);
2181   FStreamAfter.Position:= 0;
2182   temp := LoadLayersFromStream(FStreamAfter, index, True);
2183   (AState as TImageState).Assign(temp, True);
2184   (AState as TImageState).SelectedImageLayerIndex := index;
2185   (AState as TImageState).ReplaceSelection( FSelectionDiff.ApplyCanCreateNew((AState as TImageState).SelectionMask, False, True),
2186                                             FSelectionLayerDiff.ApplyCanCreateNew((AState as TImageState).SelectionLayer, False, True) );
2187 end;
2188 
2189 procedure TAssignStateDifference.UnApplyTo(AState: TState);
2190 var temp: TBGRALayeredBitmap;
2191   index: integer;
2192 begin
2193   inherited UnapplyTo(AState);
2194   FStreamBefore.Position:= 0;
2195   temp := LoadLayersFromStream(FStreamBefore, index, True);
2196   (AState as TImageState).Assign(temp, True);
2197   (AState as TImageState).SelectedImageLayerIndex := index;
2198   (AState as TImageState).ReplaceSelection( FSelectionDiff.ApplyCanCreateNew((AState as TImageState).SelectionMask, True, True),
2199                                             FSelectionLayerDiff.ApplyCanCreateNew((AState as TImageState).SelectionLayer, True, True) );
2200 end;
2201 
2202 destructor TAssignStateDifference.Destroy;
2203 begin
2204   FStreamBefore.Free;
2205   FStreamAfter.Free;
2206   FSelectionDiff.Free;
2207   FSelectionLayerDiff.Free;
2208   inherited Destroy;
2209 end;
2210 
2211 { TInversibleStateDifference }
2212 
2213 constructor TInversibleStateDifference.Create(AState: TState;
2214   AAction: TInversibleAction; ALayerIndex : integer = -1);
2215 begin
2216   inherited Create(AState);
2217   FAction := AAction;
2218   FLayerIndex:= ALayerIndex;
2219   ApplyTo(AState);
2220 end;
2221 
2222 procedure TInversibleStateDifference.ApplyTo(AState: TState);
2223 begin
2224   inherited ApplyTo(AState);
2225   ApplyAction(AState as TImageState, FAction, False);
2226 end;
2227 
2228 procedure TInversibleStateDifference.UnApplyTo(AState: TState);
2229 begin
2230   inherited UnapplyTo(AState);
2231   ApplyAction(AState as TImageState, FAction, True);
2232 end;
2233 
2234 procedure TInversibleStateDifference.ApplyAction(AState: TState;
2235   AAction: TInversibleAction; AInverse: boolean);
2236 var i: integer;
2237   imgState: TImageState;
2238   newSelectionMask, newSelectionLayer: TBGRABitmap;
2239 begin
2240   imgState := AState as TImageState;
2241   if AInverse then AAction := GetInverseAction(AAction);
2242   case AAction of
2243   iaSwapRedBlue,iaLinearNegative:
2244     begin
2245       for i := 0 to imgState.NbLayers-1 do
2246         if imgState.LayerOriginalDefined[i] then
2247           raise exception.Create('Cannot do an inversible raster action with layer originals');
2248       case AAction of
2249         iaSwapRedBlue: begin
2250                          imgState.LayeredBitmap.Unfreeze;
2251                          for i := 0 to imgState.NbLayers-1 do imgState.LayerBitmap[i].SwapRedBlue;
2252                        end;
2253         iaLinearNegative:
2254            begin
2255              imgState.LayeredBitmap.Unfreeze;
2256              for i := 0 to imgState.NbLayers-1 do imgState.LayerBitmap[i].LinearNegative;
2257            end
2258       else
2259         raise exception.Create('Unhandled case');
2260       end;
2261     end;
2262   iaHorizontalFlip: imgState.LayeredBitmap.HorizontalFlip;
2263   iaHorizontalFlipLayer: imgState.LayeredBitmap.HorizontalFlip(FLayerIndex);
2264   iaVerticalFlip: imgState.LayeredBitmap.VerticalFlip;
2265   iaVerticalFlipLayer: imgState.LayeredBitmap.VerticalFlip(FLayerIndex);
2266   iaRotate180: begin
2267       imgState.LayeredBitmap.HorizontalFlip;
2268       imgState.LayeredBitmap.VerticalFlip;
2269     end;
2270   iaRotateCW: begin
2271       imgState.LayeredBitmap.RotateCW;
2272       if imgState.SelectionMask <> nil then newSelectionMask := imgState.SelectionMask.RotateCW as TBGRABitmap else newSelectionMask := nil;
2273       if imgState.SelectionLayer <> nil then newSelectionLayer := imgState.SelectionLayer.RotateCW as TBGRABitmap else newSelectionLayer := nil;
2274       imgState.ReplaceSelection(newSelectionMask, newSelectionLayer);
2275       if (imgState.Width <> imgState.Height) then imgState.NotifySizeChanged;
2276     end;
2277   iaRotateCCW: begin
2278       imgState.LayeredBitmap.RotateCCW;
2279       if imgState.SelectionMask <> nil then newSelectionMask := imgState.SelectionMask.RotateCCW as TBGRABitmap else newSelectionMask := nil;
2280       if imgState.SelectionLayer <> nil then newSelectionLayer := imgState.SelectionLayer.RotateCCW as TBGRABitmap else newSelectionLayer := nil;
2281       imgState.ReplaceSelection(newSelectionMask, newSelectionLayer);
2282       if (imgState.Width <> imgState.Height) then imgState.NotifySizeChanged;
2283     end;
2284   end;
2285 end;
2286 
TInversibleStateDifference.ToStringnull2287 function TInversibleStateDifference.ToString: ansistring;
2288 begin
2289   Result:= ClassName+'('+InversibleActionStr[FAction];
2290   if FLayerIndex <> -1 then result += ', '+inttostr(FLayerIndex);
2291   result += ')';
2292 end;
2293 
2294 { TRemoveLayerStateDifference }
2295 
GetImageDifferenceKindnull2296 function TRemoveLayerStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2297 begin
2298   Result:=idkChangeImage;
2299 end;
2300 
UsedMemorynull2301 function TRemoveLayerStateDifference.UsedMemory: int64;
2302 begin
2303   if Assigned(FContent) then
2304     result := FContent.UsedMemory
2305   else
2306     result := 0;
2307 end;
2308 
TryCompressnull2309 function TRemoveLayerStateDifference.TryCompress: boolean;
2310 begin
2311   Result:= FContent.Compress;
2312 end;
2313 
2314 procedure TRemoveLayerStateDifference.ApplyTo(AState: TState);
2315 var idx: integer;
2316 begin
2317   inherited ApplyTo(AState);
2318   with AState as TImageState do
2319   begin
2320     idx := LayeredBitmap.GetLayerIndexFromId(FContent.LayerId);
2321     LayeredBitmap.RemoveLayer(idx);
2322     LayeredBitmap.RemoveUnusedOriginals;
2323     SelectedImageLayerIndex := LayeredBitmap.GetLayerIndexFromId(self.FNextActiveLayerId);
2324   end;
2325 end;
2326 
2327 procedure TRemoveLayerStateDifference.UnapplyTo(AState: TState);
2328 begin
2329   inherited UnapplyTo(AState);
2330   with AState as TImageState do
2331   begin
2332     FContent.Restore(LayeredBitmap);
2333     SelectedImageLayerIndex := FContent.LayerIndex;
2334   end;
2335 end;
2336 
2337 constructor TRemoveLayerStateDifference.Create(AState: TState; AApplyNow: boolean);
2338 var idx,nextIdx: integer;
2339   imgState: TImageState;
2340 begin
2341   inherited Create(AState);
2342   imgState := AState as TImageState;
2343   if imgState.LayeredBitmap = nil then
2344     raise exception.Create('Layered bitmap not created');
2345   if imgState.NbLayers = 1 then
2346     raise exception.Create('Impossible to remove last layer');
2347   idx := imgState.SelectedImageLayerIndex;
2348   if idx = -1 then
2349     raise exception.Create('No layer selected');
2350   self.FContent := TStoredLayer.Create(imgState.LayeredBitmap, idx);
2351   if idx+1 < imgState.NbLayers then
2352     nextIdx := idx+1 else nextIdx := idx-1;
2353   self.FNextActiveLayerId := imgState.LayeredBitmap.LayerUniqueId[nextIdx];
2354   if AApplyNow then ApplyTo(AState);
2355 end;
2356 
2357 destructor TRemoveLayerStateDifference.Destroy;
2358 begin
2359   self.FContent.Free;
2360   inherited Destroy;
2361 end;
2362 
2363 { TMergeLayerOverStateDifference }
2364 
GetImageDifferenceKindnull2365 function TMergeLayerOverStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2366 begin
2367   Result:= idkChangeImage; //includes stack
2368 end;
2369 
2370 constructor TMergeLayerOverStateDifference.Create(ADestination: TState;
2371   ALayerOverIndex: integer);
2372 var
2373   imgDest: TImageState;
2374   totalCost: Integer;
2375 begin
2376   inherited Create(ADestination);
2377   imgDest := ADestination as TImageState;
2378   if (ALayerOverIndex < 0) or (ALayerOverIndex >= imgDest.NbLayers) then
2379     raise exception.Create('Index out of bounds');
2380   if ALayerOverIndex = 0 then
2381     raise exception.Create('First layer cannot be merged over');
2382 
2383   mergeVectorial := false;
2384   mergeVectorialGuid := GUID_NULL;
2385   layerOverIndex := ALayerOverIndex;
2386   with imgDest.LayeredBitmap do
2387   begin
2388     previousActiveLayerId:= LayerUniqueId[imgDest.SelectedImageLayerIndex];
2389     layerOverCompressedBackup := TStoredLayer.Create(imgDest.LayeredBitmap, ALayerOverIndex, true);
2390     layerUnderCompressedBackup := TStoredLayer.Create(imgDest.LayeredBitmap, ALayerOverIndex-1, true);
2391     if ((LayerOriginalClass[ALayerOverIndex] = TVectorOriginal) or
2392        (LayerOriginalClass[ALayerOverIndex-1] = TVectorOriginal) or
2393        (LayerOriginalClass[ALayerOverIndex] = TBGRALayerGradientOriginal) or
2394        (LayerOriginalClass[ALayerOverIndex-1] = TBGRALayerGradientOriginal)) and
2395        (BlendOperation[ALayerOverIndex] = boTransparent) and
2396        (BlendOperation[ALayerOverIndex-1] = boTransparent) then
2397     begin
2398       totalCost := 0;
2399       if LayerOriginalClass[ALayerOverIndex] = TVectorOriginal then
2400         inc(totalCost, TVectorOriginal(LayerOriginal[ALayerOverIndex]).GetShapesCost)
2401       else inc(totalCost, 10);
2402       if LayerOriginalClass[ALayerOverIndex-1] = TVectorOriginal then
2403         inc(totalCost, TVectorOriginal(LayerOriginal[ALayerOverIndex-1]).GetShapesCost)
2404       else inc(totalCost, 10);
2405       if totalCost <= MediumShapeCost then mergeVectorial := true;
2406     end;
2407   end;
2408 
2409   //select layer under and merge
2410   ApplyTo(imgDest);
2411 end;
2412 
UsedMemorynull2413 function TMergeLayerOverStateDifference.UsedMemory: int64;
2414 begin
2415   Result:=0;
2416   if Assigned(layerOverCompressedBackup) then result += layerOverCompressedBackup.UsedMemory;
2417   if Assigned(layerUnderCompressedBackup) then result += layerUnderCompressedBackup.UsedMemory;
2418 end;
2419 
TryCompressnull2420 function TMergeLayerOverStateDifference.TryCompress: boolean;
2421 begin
2422   result := layerOverCompressedBackup.Compress or layerUnderCompressedBackup.Compress;
2423 end;
2424 
2425 procedure TMergeLayerOverStateDifference.ApplyTo(AState: TState);
2426 var
2427   merged: TBGRABitmap;
2428   mergedOriginal: TVectorOriginal;
2429 
2430   procedure AppendToMergedOriginal(ALayeredBitmap: TBGRALayeredBitmap; ALayerIndex: integer);
2431   var
2432     vectOrig: TVectorOriginal;
2433     m: TAffineMatrix;
2434     i: Integer;
2435     s: TVectorShape;
2436     temp: TBGRABitmap;
2437     b: TRect;
2438     c: TBGRALayerOriginalAny;
2439   begin
2440     c := ALayeredBitmap.LayerOriginalClass[ALayerIndex];
2441     m := ALayeredBitmap.LayerOriginalMatrix[ALayerIndex];
2442     if c = TVectorOriginal then
2443     begin
2444       vectOrig := ALayeredBitmap.LayerOriginal[ALayerIndex] as TVectorOriginal;
2445       for i := 0 to vectOrig.ShapeCount-1 do
2446       begin
2447         s := vectOrig.Shape[i].Duplicate;
2448         s.Transform(m);
2449         mergedOriginal.AddShape(s);
2450       end;
2451     end else
2452     if c = TBGRALayerGradientOriginal then
2453     begin
2454       s := TRectShape.Create(mergedOriginal);
2455       s.PenStyle := ClearPenStyle;
2456       s.BackFill.SetGradient(ALayeredBitmap.LayerOriginal[ALayerIndex] as TBGRALayerGradientOriginal, false);
2457       s.BackFill.Transform(m);
2458       s.QuickDefine(PointF(-0.5,-0.5), PointF(ALayeredBitmap.width-0.5,ALayeredBitmap.Height-0.5));
2459       mergedOriginal.AddShape(s);
2460     end else
2461     if c = TBGRALayerImageOriginal then
2462     begin
2463       temp := (ALayeredBitmap.LayerOriginal[ALayerIndex] as TBGRALayerImageOriginal).GetImageCopy;
2464       if Assigned(temp) then
2465       begin
2466         if not temp.Empty then
2467         begin
2468           s := TRectShape.Create(mergedOriginal);
2469           s.PenStyle := ClearPenStyle;
2470           if temp.Equals(temp.GetPixel(0,0)) then
2471             s.BackFill.SetSolid(temp.GetPixel(0,0))
2472             else s.BackFill.SetTexture(temp, AffineMatrixIdentity, 255, trNone);
2473           s.QuickDefine(PointF(-0.5,-0.5), PointF(temp.width-0.5,temp.Height-0.5));
2474           s.Transform(m);
2475           mergedOriginal.AddShape(s);
2476         end;
2477         temp.FreeReference;
2478       end;
2479     end else
2480     begin
2481       if Assigned(ALayeredBitmap.LayerBitmap[ALayerIndex]) then
2482       begin
2483         b := ALayeredBitmap.LayerBitmap[ALayerIndex].GetImageBounds;
2484         if not b.IsEmpty then
2485         begin
2486           temp := ALayeredBitmap.LayerBitmap[ALayerIndex].GetPart(b) as TBGRABitmap;
2487           s := TRectShape.Create(mergedOriginal);
2488           s.PenStyle := ClearPenStyle;
2489           if temp.Equals(temp.GetPixel(0,0)) then
2490             s.BackFill.SetSolid(temp.GetPixel(0,0))
2491             else s.BackFill.SetTexture(temp, AffineMatrixIdentity, 255, trNone);
2492           s.QuickDefine(PointF(-0.5,-0.5), PointF(temp.width-0.5,temp.Height-0.5));
2493           with ALayeredBitmap.LayerOffset[ALayerIndex] do
2494             s.Transform(AffineMatrixTranslation(b.Left+X,b.Top+Y));
2495           mergedOriginal.AddShape(s);
2496           temp.FreeReference;
2497         end;
2498       end;
2499     end;
2500   end;
2501 
2502 begin
2503   inherited ApplyTo(AState);
2504   with AState as TImageState do
2505   begin
2506     if layerOverIndex >= NbLayers then exit;
2507 
2508      SelectedImageLayerIndex := layerOverIndex-1;
2509      if mergeVectorial then
2510      begin
2511        mergedOriginal := TVectorOriginal.Create;
2512        mergedOriginal.Guid := mergeVectorialGuid;
2513        AppendToMergedOriginal(LayeredBitmap, layerOverIndex-1);
2514        AppendToMergedOriginal(LayeredBitmap, layerOverIndex);
2515        LayeredBitmap.AddOriginal(mergedOriginal);
2516        mergeVectorialGuid := mergedOriginal.Guid;
2517        LayeredBitmap.LayerOriginalGuid[layerOverIndex-1] := mergedOriginal.Guid;
2518        LayeredBitmap.LayerOriginalMatrix[layerOverIndex-1] := AffineMatrixIdentity;
2519        LayeredBitmap.RenderLayerFromOriginal(layerOverIndex-1);
2520      end else
2521      if (LayerBitmap[layerOverIndex-1].Width <> Width) or
2522         (LayerBitmap[layerOverIndex-1].Height <> Height) or
2523         (LayerOffset[layerOverIndex-1].X <> 0) or
2524         (LayerOffset[layerOverIndex-1].Y <> 0) then
2525      begin
2526        merged := TBGRABitmap.Create(Width,Height);
2527        merged.PutImage(LayerOffset[layerOverIndex-1].X,LayerOffset[layerOverIndex-1].Y,LayerBitmap[layerOverIndex-1],dmSet);
2528        merged.BlendImageOver(LayerOffset[layerOverIndex].X,LayerOffset[layerOverIndex].Y,LayerBitmap[layerOverIndex],
2529                              BlendOperation[layerOverIndex],LayerOpacity[layerOverIndex],LinearBlend);
2530        LayeredBitmap.SetLayerBitmap(layerOverIndex-1, merged,true);
2531        LayeredBitmap.LayerOffset[layerOverIndex-1] := Point(0,0);
2532      end else
2533      begin
2534        LayeredBitmap.LayerOriginalGuid[layerOverIndex-1] := GUID_NULL;
2535        LayeredBitmap.LayerOriginalMatrix[layerOverIndex-1] := AffineMatrixIdentity;
2536        LayerBitmap[layerOverIndex-1].BlendImageOver(LayerOffset[layerOverIndex].X,LayerOffset[layerOverIndex].Y,LayerBitmap[layerOverIndex],
2537                              BlendOperation[layerOverIndex],LayerOpacity[layerOverIndex],LinearBlend);
2538      end;
2539      LayeredBitmap.RemoveLayer(layerOverIndex);
2540      LayeredBitmap.RemoveUnusedOriginals;
2541   end;
2542 end;
2543 
2544 procedure TMergeLayerOverStateDifference.UnapplyTo(AState: TState);
2545 begin
2546   inherited UnapplyTo(AState);
2547   with AState as TImageState do
2548   begin
2549     layerOverCompressedBackup.Restore(LayeredBitmap);
2550     layerUnderCompressedBackup.Replace(LayeredBitmap);
2551 
2552     //select previous layer
2553     SelectedImageLayerIndex := LayeredBitmap.GetLayerIndexFromId(Self.previousActiveLayerId);
2554   end;
2555 end;
2556 
2557 destructor TMergeLayerOverStateDifference.Destroy;
2558 begin
2559   layerOverCompressedBackup.Free;
2560   layerUnderCompressedBackup.Free;
2561   inherited Destroy;
2562 end;
2563 
2564 { TMoveLayerStateDifference }
2565 
GetIsIdentitynull2566 function TMoveLayerStateDifference.GetIsIdentity: boolean;
2567 begin
2568   Result:= (sourceIndex = destIndex);
2569 end;
2570 
TMoveLayerStateDifference.GetImageDifferenceKindnull2571 function TMoveLayerStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2572 begin
2573   Result:=idkChangeImage; //includes stack
2574 end;
2575 
2576 procedure TMoveLayerStateDifference.ApplyTo(AState: TState);
2577 begin
2578   inherited ApplyTo(AState);
2579   with AState as TImageState do
2580     LayeredBitmap.InsertLayer(destIndex, sourceIndex);
2581 end;
2582 
2583 procedure TMoveLayerStateDifference.UnapplyTo(AState: TState);
2584 begin
2585   inherited UnapplyTo(AState);
2586   with AState as TImageState do
2587     LayeredBitmap.InsertLayer(sourceIndex, destIndex);
2588 end;
2589 
2590 constructor TMoveLayerStateDifference.Create(ADestination: TState;
2591   AFromIndex, AToIndex: integer);
2592 begin
2593   inherited Create(ADestination);
2594   self.sourceIndex := AFromIndex;
2595   self.destIndex := AToIndex;
2596   ApplyTo(ADestination);
2597 end;
2598 
2599 { TDuplicateLayerStateDifference }
2600 
GetImageDifferenceKindnull2601 function TDuplicateLayerStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2602 begin
2603   Result:=idkChangeImage;
2604 end;
2605 
2606 procedure TDuplicateLayerStateDifference.ApplyTo(AState: TState);
2607 var sourceLayerIndex,duplicateIndex: integer;
2608   copy: integer;
2609   stream: TMemoryStream;
2610 begin
2611   inherited ApplyTo(AState);
2612   with AState as TImageState do
2613   begin
2614     sourceLayerIndex := LayeredBitmap.GetLayerIndexFromId(self.sourceLayerId);
2615     duplicateIndex := sourceLayerIndex+1;
2616     with LayeredBitmap do
2617     begin
2618       copy := AddLayer(LayerBitmap[sourceLayerIndex],BlendOperation[sourceLayerIndex],LayerOpacity[sourceLayerIndex]);
2619       LayerName[copy] := LayerName[sourceLayerIndex];
2620       LayerOffset[copy] := LayerOffset[sourceLayerIndex];
2621       LayerVisible[copy] := LayerVisible[sourceLayerIndex];
2622       if useOriginal then
2623       begin
2624         if duplicateOriginal then
2625         begin
2626           stream:= TMemoryStream.Create;
2627           SaveOriginalToStream(LayerOriginalGuid[sourceLayerIndex], stream);
2628           stream.Position:= 0;
2629           AddOriginalFromStream(stream, duplicateGuid, true);
2630           stream.Free;
2631           LayerOriginalGuid[copy] := duplicateGuid;
2632         end else
2633           LayerOriginalGuid[copy] := LayerOriginalGuid[sourceLayerIndex];
2634         LayerOriginalMatrix[copy] := LayerOriginalMatrix[sourceLayerIndex];
2635         LayerOriginalRenderStatus[copy] := LayerOriginalRenderStatus[sourceLayerIndex];
2636       end;
2637       LayerUniqueId[copy] := duplicateId;
2638       InsertLayer(duplicateIndex, copy);
2639     end;
2640     SelectedImageLayerIndex := duplicateIndex;
2641   end;
2642 end;
2643 
2644 procedure TDuplicateLayerStateDifference.UnapplyTo(AState: TState);
2645 var sourceLayerIndex,duplicateIndex: integer;
2646 begin
2647   inherited UnapplyTo(AState);
2648   with AState as TImageState do
2649   begin
2650     sourceLayerIndex := LayeredBitmap.GetLayerIndexFromId(self.sourceLayerId);
2651     duplicateIndex := LayeredBitmap.GetLayerIndexFromId(self.duplicateId);
2652     LayeredBitmap.RemoveLayer(duplicateIndex);
2653     SelectedImageLayerIndex := sourceLayerIndex;
2654     if duplicateOriginal then LayeredBitmap.RemoveUnusedOriginals;
2655   end;
2656 end;
2657 
2658 constructor TDuplicateLayerStateDifference.Create(ADestination: TState;
2659   AUseOriginal: boolean);
2660 var imgDest: TImageState;
2661 begin
2662   inherited Create(ADestination);
2663   imgDest := ADestination as TImageState;
2664   useOriginal:= AUseOriginal;
2665   with imgDest do
2666   begin
2667     self.sourceLayerId := LayeredBitmap.LayerUniqueId[SelectedImageLayerIndex];
2668     self.duplicateId := LayeredBitmap.ProduceLayerUniqueId;
2669     self.duplicateOriginal := useOriginal and
2670       ((LayeredBitmap.LayerOriginalClass[SelectedImageLayerIndex]=TVectorOriginal) or
2671        (LayeredBitmap.LayerOriginalClass[SelectedImageLayerIndex]=TBGRALayerGradientOriginal));
2672     if self.duplicateOriginal then
2673       CreateGUID(duplicateGuid);
2674   end;
2675   ApplyTo(imgDest);
2676 end;
2677 
2678 { TAddLayerStateDifference }
2679 
GetImageDifferenceKindnull2680 function TAddLayerStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2681 begin
2682   Result:= idkChangeImage;
2683 end;
2684 
UsedMemorynull2685 function TAddLayerStateDifference.UsedMemory: int64;
2686 begin
2687   if Assigned(content) then
2688     result := content.UsedMemory
2689   else
2690     result := 0;
2691 end;
2692 
TryCompressnull2693 function TAddLayerStateDifference.TryCompress: boolean;
2694 begin
2695   if Assigned(content) then
2696     Result := content.Compress
2697   else
2698     result := false;
2699 end;
2700 
2701 procedure TAddLayerStateDifference.ApplyTo(AState: TState);
2702 var idx: integer;
2703   bmp: TBGRABitmap;
2704 begin
2705   inherited ApplyTo(AState);
2706   with AState as TImageState do
2707   begin
2708     bmp := content.GetBitmap;
2709     if bmp = nil then
2710       raise exception.Create('Bitmap not found');
2711     idx := LayeredBitmap.AddOwnedLayer(bmp, self.offset, self.blendOp, self.opacity);
2712     LayeredBitmap.LayerUniqueId[idx] := self.layerId;
2713     LayeredBitmap.LayerName[idx] := name;
2714     SelectedImageLayerIndex := idx;
2715   end;
2716 end;
2717 
2718 procedure TAddLayerStateDifference.UnapplyTo(AState: TState);
2719 var idx: integer;
2720 begin
2721   inherited UnapplyTo(AState);
2722   with AState as TImageState do
2723   begin
2724     idx := LayeredBitmap.GetLayerIndexFromId(self.layerId);
2725     LayeredBitmap.RemoveLayer(idx);
2726     SelectedImageLayerIndex := LayeredBitmap.GetLayerIndexFromId(self.previousActiveLayerId);
2727   end;
2728 end;
2729 
2730 constructor TAddLayerStateDifference.Create(ADestination: TState;
2731   AContent: TBGRABitmap; AName: ansistring; AOffset: TPoint;
2732   ABlendOp: TBlendOperation; AOpacity: byte);
2733 var idx: integer;
2734   imgDest: TImageState;
2735 begin
2736   inherited Create(ADestination);
2737   imgDest := ADestination as TImageState;
2738   if imgDest.LayeredBitmap = nil then
2739     raise exception.Create('Layered bitmap not created');
2740   self.content := TStoredImage.Create(AContent, False);
2741   self.name := AName;
2742   self.offset := AOffset;
2743   self.blendOp:= AblendOp;
2744   self.opacity:= AOpacity;
2745   self.previousActiveLayerId := imgDest.LayeredBitmap.LayerUniqueId[imgDest.SelectedImageLayerIndex];
2746   idx := imgDest.LayeredBitmap.AddLayer(AContent, AOffset, ABlendOp, AOpacity);
2747   imgDest.LayeredBitmap.LayerName[idx] := name;
2748   self.layerId := imgDest.LayeredBitmap.LayerUniqueId[idx];
2749   imgDest.SelectedImageLayerIndex := idx;
2750 end;
2751 
2752 destructor TAddLayerStateDifference.Destroy;
2753 begin
2754   self.content.Free;
2755   inherited Destroy;
2756 end;
2757 
2758 { TImageLayerStateDifference }
2759 
TImageLayerStateDifference.GetChangeImageLayernull2760 function TImageLayerStateDifference.GetChangeImageLayer: boolean;
2761 begin
2762   result := (imageDiff <> nil) and not imageDiff.IsIdentity;
2763 end;
2764 
GetChangeSelectionLayernull2765 function TImageLayerStateDifference.GetChangeSelectionLayer: boolean;
2766 begin
2767   result := (selectionLayerDiff <> nil) and not selectionLayerDiff.IsIdentity;
2768 end;
2769 
GetChangeSelectionMasknull2770 function TImageLayerStateDifference.GetChangeSelectionMask: boolean;
2771 begin
2772   result := (selectionMaskDiff <> nil) and not selectionMaskDiff.IsIdentity;
2773 end;
2774 
TImageLayerStateDifference.GetImageDifferenceKindnull2775 function TImageLayerStateDifference.GetImageDifferenceKind: TImageDifferenceKind;
2776 begin
2777   if ChangeImageLayer or ChangeSelectionLayer then
2778   begin
2779     if ChangeSelectionMask then
2780       result := idkChangeImageAndSelection
2781     else if ChangeSelectionLayer then
2782       result := idkChangeImage
2783     else
2784       result := idkChangeImage;
2785   end
2786   else if ChangeSelectionMask then
2787     result := idkChangeSelection
2788   else
2789     result := idkChangeStack; //some default value
2790 end;
2791 
GetIsIdentitynull2792 function TImageLayerStateDifference.GetIsIdentity: boolean;
2793 begin
2794   Result:= not ChangeImageLayer and
2795           not ChangeSelectionMask and
2796           not ChangeSelectionLayer;
2797 end;
2798 
GetChangingBoundsDefinednull2799 function TImageLayerStateDifference.GetChangingBoundsDefined: boolean;
2800 begin
2801   Result:= true;
2802 end;
2803 
GetChangingBoundsnull2804 function TImageLayerStateDifference.GetChangingBounds: TRect;
2805 var
2806   r: TRect;
2807 begin
2808   result := EmptyRect;
2809   if ChangeImageLayer then
2810   begin
2811     r := imageDiff.ChangeRect;
2812     OffsetRect(r, layerRect.Left, layerRect.Top);
2813     result := RectUnion(result, r);
2814   end;
2815   if ChangeSelectionLayer then result := RectUnion(result, selectionLayerDiff.ChangeRect);
2816   if ChangeSelectionMask then result := RectUnion(result, selectionMaskDiff.ChangeRect);
2817 end;
2818 
TImageLayerStateDifference.GetLayerRectnull2819 function TImageLayerStateDifference.GetLayerRect(AState: TImageState;
2820   AIndex: integer): TRect;
2821 begin
2822   result.TopLeft := AState.LayerOffset[AIndex];
2823   result.Width:= AState.LayerBitmap[AIndex].Width;
2824   result.Height:= AState.LayerBitmap[AIndex].Height;
2825 end;
2826 
2827 procedure TImageLayerStateDifference.EnsureLayerRect(AState: TImageState;
2828   AIndex: integer);
2829 var
2830   curRect: TRect;
2831   newBmp: TBGRABitmap;
2832 begin
2833   curRect := GetLayerRect(AState, AIndex);
2834   if (layerRect.Left<>curRect.Left) or
2835      (layerRect.Top<>curRect.Top) or
2836      (layerRect.Width<>curRect.Width) or
2837      (layerRect.Height<>curRect.Height) then
2838   begin
2839     newBmp := TBGRABitmap.Create(layerRect.Width,layerRect.Height);
2840     newBmp.PutImage(curRect.Left-layerRect.Left,curRect.Top-layerRect.Top,
2841       AState.LayerBitmap[AIndex], dmSet);
2842     AState.SetLayerBitmap(AIndex, newBmp, true);
2843     AState.LayeredBitmap.LayerOffset[AIndex] := layerRect.TopLeft;
2844   end;
2845 end;
2846 
2847 procedure TImageLayerStateDifference.Init(AToState: TState; APreviousImage: TBGRABitmap; APreviousImageChangeRect: TRect;
2848         APreviousSelection: TBGRABitmap; APreviousSelectionChangeRect: TRect;
2849         APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerChangeRect: TRect);
2850 var
2851   next: TImageState;
2852   curIdx: integer;
2853 begin
2854   inherited Create((AToState as TImageState).saved,false);
2855   layerId := -1;
2856   imageDiff := nil;
2857   layerRect := EmptyRect;
2858   selectionMaskDiff := nil;
2859   selectionLayerDiff := nil;
2860 
2861   next := AToState as TImageState;
2862   layerId := next.selectedLayerId;
2863   curIdx := next.LayeredBitmap.GetLayerIndexFromId(LayerId);
2864   if curIdx = -1 then
2865     raise exception.Create('Layer not found')
2866   else
2867   begin
2868     if not IsRectEmpty(APreviousImageChangeRect) then
2869     begin
2870       imageDiff := TImageDiff.Create(APreviousImage, next.LayerBitmap[curIdx],
2871                                      False, APreviousImageChangeRect);
2872       layerRect := GetLayerRect(next,curIdx);
2873     end;
2874     if not IsRectEmpty(APreviousSelectionChangeRect) then
2875       selectionMaskDiff := TImageDiff.Create(APreviousSelection, next.SelectionMask,
2876                            True, APreviousSelectionChangeRect);
2877     if not IsRectEmpty(APreviousSelectionLayerChangeRect) then
2878       selectionLayerDiff := TImageDiff.Create(APreviousSelectionLayer, next.SelectionLayer,
2879                             False, APreviousSelectionLayerChangeRect);
2880   end;
2881 end;
2882 
TryCompressnull2883 function TImageLayerStateDifference.TryCompress: boolean;
2884 begin
2885   result := false;
2886   if Assigned(imageDiff) then result := result or imageDiff.Compress;
2887   if Assigned(selectionMaskDiff) then result := result or selectionMaskDiff.Compress;
2888   if Assigned(selectionLayerDiff) then result := result or selectionLayerDiff.Compress;
2889 end;
2890 
2891 procedure TImageLayerStateDifference.ApplyTo(AState: TState);
2892 var
2893   idx: integer;
2894   lState: TImageState;
2895   newSelectionMask, newSelectionLayer: TBGRABitmap;
2896 begin
2897   inherited ApplyTo(AState);
2898   lState := AState as TImageState;
2899   if layerId <> -1 then
2900   begin
2901     idx := lState.LayeredBitmap.GetLayerIndexFromId(layerId);
2902     if idx = -1 then raise exception.Create('Layer not found');
2903     lState.LayeredBitmap.Unfreeze(idx);
2904     if ChangeImageLayer and (lState.LayeredBitmap.LayerOriginalGuid[idx] <> GUID_NULL) then raise exception.Create('Does not apply to originals');
2905     if ChangeImageLayer then
2906     begin
2907       EnsureLayerRect(lState,idx);
2908       lState.LayeredBitmap.SetLayerBitmap(idx,
2909         imageDiff.ApplyCanCreateNew(lState.LayerBitmap[idx], False, True), True);
2910     end;
2911     if ChangeSelectionMask then
2912       newSelectionMask := selectionMaskDiff.ApplyCanCreateNew(lState.SelectionMask, False, True)
2913       else newSelectionMask := lState.SelectionMask;
2914     if ChangeSelectionLayer then
2915       newSelectionLayer := selectionLayerDiff.ApplyCanCreateNew(lState.SelectionLayer, False, True)
2916        else newSelectionLayer := lState.SelectionLayer;
2917     lState.ReplaceSelection(newSelectionMask, newSelectionLayer);
2918   end;
2919 end;
2920 
2921 procedure TImageLayerStateDifference.UnapplyTo(AState: TState);
2922 var
2923   idx: integer;
2924   lState: TImageState;
2925   newSelectionMask, newSelectionLayer: TBGRABitmap;
2926 begin
2927   inherited UnapplyTo(AState);
2928   lState := AState as TImageState;
2929   if layerId <> -1 then
2930   begin
2931     idx := lState.LayeredBitmap.GetLayerIndexFromId(layerId);
2932     if idx = -1 then raise exception.Create('Layer not found');
2933     lState.LayeredBitmap.Unfreeze(idx);
2934     if ChangeImageLayer and (lState.LayeredBitmap.LayerOriginalGuid[idx] <> GUID_NULL) then raise exception.Create('Does not apply to originals');
2935     if ChangeImageLayer then
2936     begin
2937       EnsureLayerRect(lState,idx);
2938       lState.LayeredBitmap.SetLayerBitmap(idx,
2939         imageDiff.ApplyCanCreateNew(lState.LayerBitmap[idx], True, True), True);
2940     end;
2941     if ChangeSelectionMask then
2942       newSelectionMask := selectionMaskDiff.ApplyCanCreateNew(lState.SelectionMask, True, True)
2943       else newSelectionMask := lState.SelectionMask;
2944     if ChangeSelectionLayer then
2945       newSelectionLayer := selectionLayerDiff.ApplyCanCreateNew(lState.SelectionLayer, True, True)
2946       else newSelectionLayer := lState.SelectionLayer;
2947     lState.ReplaceSelection(newSelectionMask, newSelectionLayer);
2948   end;
2949 end;
2950 
UsedMemorynull2951 function TImageLayerStateDifference.UsedMemory: int64;
2952 begin
2953   Result:= 0;
2954   if Assigned(imageDiff) then result += imageDiff.UsedMemory;
2955   if Assigned(selectionMaskDiff) then result += selectionMaskDiff.UsedMemory;
2956   if Assigned(selectionLayerDiff) then result += selectionLayerDiff.UsedMemory;
2957 end;
2958 
2959 constructor TImageLayerStateDifference.Create(AFromState, AToState: TState);
2960 var
2961   prev,next: TImageState;
2962   prevIdx,curIdx: integer;
2963 begin
2964   inherited Create(AFromState,AToState);
2965   layerId := -1;
2966   imageDiff := nil;
2967   layerRect := EmptyRect;
2968   selectionMaskDiff := nil;
2969   selectionLayerDiff := nil;
2970 
2971   prev := AFromState as TImageState;
2972   next := AToState as TImageState;
2973   layerId := next.selectedLayerId;
2974   if layerId <> prev.selectedLayerId then
2975     raise exception.Create('Inconsistent layer id');
2976   prevIdx := prev.LayeredBitmap.GetLayerIndexFromId(LayerId);
2977   curIdx := next.LayeredBitmap.GetLayerIndexFromId(LayerId);
2978   if (curIdx = -1) or (prevIdx = -1) then
2979     raise exception.Create('Layer not found')
2980   else
2981   begin
2982     imageDiff := TImageDiff.Create(prev.LayerBitmap[prevIdx], next.LayerBitmap[curIdx], False);
2983     layerRect := GetLayerRect(next, curIdx);
2984     selectionMaskDiff := TImageDiff.Create(prev.SelectionMask, next.SelectionMask, True);
2985     selectionLayerDiff := TImageDiff.Create(prev.SelectionLayer, next.SelectionLayer, False);
2986   end;
2987 end;
2988 
2989 constructor TImageLayerStateDifference.Create(AToState: TState;
2990   APreviousImage: TBGRABitmap; APreviousImageDefined: boolean;
2991   APreviousSelection: TBGRABitmap; APreviousSelectionDefined: boolean;
2992   APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerDefined: boolean);
2993 var
2994   r1,r2,r3: TRect;
2995   w,h: integer;
2996 begin
2997   w := (AToState as TImageState).Width;
2998   h := (AToState as TImageState).Height;
2999   if APreviousImageDefined then r1 := rect(0,0,w,h) else r1 := EmptyRect;
3000   if APreviousSelectionDefined then r2 := rect(0,0,w,h) else r2 := EmptyRect;
3001   if APreviousSelectionLayerDefined then r3 := rect(0,0,w,h) else r3 := EmptyRect;
3002   Init(AToState,APreviousImage,r1,APreviousSelection,r2,APreviousSelectionLayer,r3);
3003 end;
3004 
3005 constructor TImageLayerStateDifference.Create(AToState: TState;
3006   APreviousImage: TBGRABitmap; APreviousImageChangeRect: TRect;
3007   APreviousSelection: TBGRABitmap; APreviousSelectionChangeRect: TRect;
3008   APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerChangeRect: TRect);
3009 begin
3010   Init(AToState, APreviousImage, APreviousImageChangeRect, APreviousSelection,
3011     APreviousSelectionChangeRect, APreviousSelectionLayer, APreviousSelectionLayerChangeRect);
3012 end;
3013 
TImageLayerStateDifference.ToStringnull3014 function TImageLayerStateDifference.ToString: ansistring;
3015 begin
3016   Result:= ClassName+'(';
3017   If ChangeImageLayer then
3018   begin
3019     if (imageDiff.SizeBefore.cx = 0) or (imageDiff.SizeBefore.cy = 0) then
3020       result += 'Create'
3021     else
3022     if (imageDiff.SizeAfter.cx = 0) or (imageDiff.SizeAfter.cy = 0) then
3023       result += 'Remove'
3024     else
3025       result += 'Change';
3026 
3027     result += 'ImageLayer ';
3028   end;
3029   If ChangeSelectionMask then
3030   begin
3031     if (selectionMaskDiff.SizeBefore.cx = 0) or (selectionMaskDiff.SizeBefore.cy = 0) then
3032       result += 'Create'
3033     else
3034     if (selectionMaskDiff.SizeAfter.cx = 0) or (selectionMaskDiff.SizeAfter.cy = 0) then
3035       result += 'Remove'
3036     else
3037       result += 'Change';
3038 
3039     result += 'SelectionMask ';
3040   end;
3041   If ChangeSelectionLayer then
3042   begin
3043     if (selectionLayerDiff.SizeBefore.cx = 0) or (selectionLayerDiff.SizeBefore.cy = 0) then
3044       result += 'Create'
3045     else
3046     if (selectionLayerDiff.SizeAfter.cx = 0) or (selectionLayerDiff.SizeAfter.cy = 0) then
3047       result += 'Remove'
3048     else
3049       result += 'Change';
3050 
3051     result += 'SelectionLayer ';
3052   end;
3053   result := trim(Result)+')';
3054 end;
3055 
3056 destructor TImageLayerStateDifference.Destroy;
3057 begin
3058   imageDiff.Free;
3059   selectionMaskDiff.Free;
3060   selectionLayerDiff.Free;
3061   inherited Destroy;
3062 end;
3063 
3064 end.
3065 
3066