Browse Source

use gradient original when possible, no dithering otherwise

Johann 6 years ago
parent
commit
384cd47392

+ 77 - 8
lazpaint/image/uimagediff.pas

@@ -294,6 +294,7 @@ type
     FOriginalGuid: TGUID;
     function GetImageDifferenceKind: TImageDifferenceKind; override;
     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; virtual; abstract;
+    function ShouldRenderOriginal: boolean; virtual;
   public
     constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
     function UsedMemory: int64; override;
@@ -340,7 +341,22 @@ type
 
   TReplaceLayerByVectorOriginalDifference = class(TReplaceLayerByOriginalDifference)
   protected
+    FShouldRenderOriginal: boolean;
+    function ShouldRenderOriginal: boolean; override;
     function CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal; override;
+  public
+    constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
+  end;
+
+  { TReplaceLayerByCustomOriginalDifference }
+
+  TReplaceLayerByCustomOriginalDifference = class(TReplaceLayerByOriginalDifference)
+  protected
+    FOriginal: TBGRALayerCustomOriginal;
+    function CreateOriginal({%H-}AState: TState; {%H-}ALayerIndex: integer): TBGRALayerCustomOriginal; override;
+    function ShouldRenderOriginal: boolean; override;
+  public
+    constructor Create(AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean; AOriginal: TBGRALayerCustomOriginal);
   end;
 
   { TAddShapeToVectorOriginalDifference }
@@ -472,7 +488,8 @@ type
 implementation
 
 uses BGRAWriteLzp, BGRAReadLzp, UImageState, BGRAStreamLayers, BGRALzpCommon, ugraph, Types,
-  BGRATransform, zstream, LCVectorRectShapes, BGRAPen, LCVectorialFill;
+  BGRATransform, zstream, LCVectorRectShapes, BGRAPen, LCVectorialFill,
+  BGRAGradientOriginal;
 
 function IsInverseImageDiff(ADiff1, ADiff2: TCustomImageDifference): boolean;
 begin
@@ -609,6 +626,26 @@ begin
     result := false;
 end;
 
+{ TReplaceLayerByCustomOriginalDifference }
+
+function TReplaceLayerByCustomOriginalDifference.CreateOriginal(AState: TState;
+  ALayerIndex: integer): TBGRALayerCustomOriginal;
+begin
+  result := FOriginal.Duplicate;
+end;
+
+function TReplaceLayerByCustomOriginalDifference.ShouldRenderOriginal: boolean;
+begin
+  result := true;
+end;
+
+constructor TReplaceLayerByCustomOriginalDifference.Create(AFromState: TState;
+  AIndex: integer; AAlwaysStoreBitmap: boolean; AOriginal: TBGRALayerCustomOriginal);
+begin
+  FOriginal := AOriginal;
+  inherited Create(AFromState,AIndex,AAlwaysStoreBitmap);
+end;
+
 { TVectorOriginalEmbeddedDifference }
 
 function TVectorOriginalEmbeddedDifference.GetImageDifferenceKind: TImageDifferenceKind;
@@ -854,6 +891,11 @@ end;
 
 { TReplaceLayerByVectorOriginalDifference }
 
+function TReplaceLayerByVectorOriginalDifference.ShouldRenderOriginal: boolean;
+begin
+  Result:= FShouldRenderOriginal;
+end;
+
 function TReplaceLayerByVectorOriginalDifference.CreateOriginal(AState: TState;
   ALayerIndex: integer): TBGRALayerCustomOriginal;
 var
@@ -865,20 +907,42 @@ var
 begin
   imgState := TImageState(AState);
   orig := TVectorOriginal.Create;
-  source := imgState.LayeredBitmap.LayerBitmap[ALayerIndex];
-  if not source.Empty then
+  if imgState.LayeredBitmap.LayerOriginalClass[ALayerIndex]=TBGRALayerGradientOriginal then
   begin
     shape := TRectShape.Create(orig);
-    shape.QuickDefine(PointF(0,0),PointF(FSourceBounds.Width,FSourceBounds.Height));
+    shape.QuickDefine(PointF(-0.5,-0.5),PointF(FSourceBounds.Width-0.5,FSourceBounds.Height-0.5));
     shape.PenStyle := ClearPenStyle;
-    temp := source.GetPart(FSourceBounds) as TBGRABitmap;
-    shape.BackFill.SetTexture(temp,AffineMatrixIdentity,255,trNone);
-    temp.FreeReference;
+    shape.BackFill.SetGradient(
+      imgState.LayeredBitmap.LayerOriginal[ALayerIndex] as TBGRALayerGradientOriginal,false);
+    shape.BackFill.Transform(imgState.LayeredBitmap.LayerOriginalMatrix[ALayerIndex]);
     orig.AddShape(shape);
+  end else
+  begin
+    source := imgState.LayeredBitmap.LayerBitmap[ALayerIndex];
+    if not source.Empty then
+    begin
+      shape := TRectShape.Create(orig);
+      shape.QuickDefine(PointF(-0.5,-0.5),PointF(FSourceBounds.Width-0.5,FSourceBounds.Height-0.5));
+      shape.PenStyle := ClearPenStyle;
+      temp := source.GetPart(FSourceBounds) as TBGRABitmap;
+      shape.BackFill.SetTexture(temp,AffineMatrixIdentity,255,trNone);
+      temp.FreeReference;
+      orig.AddShape(shape);
+    end;
   end;
   result := orig;
 end;
 
+constructor TReplaceLayerByVectorOriginalDifference.Create(AFromState: TState;
+  AIndex: integer; AAlwaysStoreBitmap: boolean);
+var
+  imgState: TImageState;
+begin
+  imgState := AFromState as TImageState;
+  FShouldRenderOriginal:= imgState.LayeredBitmap.LayerOriginalClass[AIndex]=TBGRALayerGradientOriginal;
+  inherited Create(AFromState, AIndex, AAlwaysStoreBitmap);
+end;
+
 { TReplaceLayerByImageOriginalDifference }
 
 function TReplaceLayerByImageOriginalDifference.CreateOriginal(AState: TState; ALayerIndex: integer): TBGRALayerCustomOriginal;
@@ -1016,6 +1080,11 @@ begin
   Result:= idkChangeImage;
 end;
 
+function TReplaceLayerByOriginalDifference.ShouldRenderOriginal: boolean;
+begin
+  result := false;
+end;
+
 constructor TReplaceLayerByOriginalDifference.Create(
   AFromState: TState; AIndex: integer; AAlwaysStoreBitmap: boolean);
 var
@@ -1055,7 +1124,7 @@ begin
   if FOriginalGuid = GUID_NULL then FOriginalGuid := orig.Guid;
   imgState.LayeredBitmap.LayerOriginalGuid[layerIdx] := imgState.LayeredBitmap.OriginalGuid[origIndex];
   imgState.LayeredBitmap.LayerOriginalMatrix[layerIdx] := FNextMatrix;
-  if FNextMatrix = FPrevMatrix then
+  if (FNextMatrix = FPrevMatrix) and not ShouldRenderOriginal then
     imgState.LayeredBitmap.LayerOriginalRenderStatus[layerIdx] := orsProof
   else
   begin

+ 17 - 2
lazpaint/tools/utoolfloodfill.pas

@@ -6,7 +6,7 @@ interface
 
 uses
   Classes, SysUtils, UTool, UToolVectorial, BGRABitmap, BGRABitmapTypes,
-  BGRAGradientOriginal, LCVectorOriginal;
+  BGRAGradientOriginal, BGRALayerOriginal, LCVectorOriginal, UStateType;
 
 type
 
@@ -32,6 +32,7 @@ type
     procedure QuickDefineShape(AStart,AEnd: TPointF); override;
     function SlowShape: boolean; override;
     function GetStatusText: string; override;
+    function ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference; override;
   public
     function GetContextualToolbars: TContextualToolbars; override;
   end;
@@ -39,7 +40,7 @@ type
 implementation
 
 uses ugraph, LazPaintType, BGRAGradientScanner, LCVectorRectShapes,
-  math, BGRATransform;
+  math, BGRATransform, UImageDiff;
 
 { TToolGradient }
 
@@ -104,6 +105,20 @@ begin
     Result:=inherited GetStatusText;
 end;
 
+function TToolGradient.ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference;
+var
+  gradientOrig: TBGRALayerCustomOriginal;
+begin
+  if Manager.Image.CurrentLayerEmpty then
+  begin
+    gradientOrig := FShape.BackFill.Gradient.Duplicate;
+    result := TReplaceLayerByCustomOriginalDifference.Create(Manager.Image.CurrentState,
+      Manager.Image.CurrentLayerIndex, false, gradientOrig);
+    ARect := rect(0,0,Manager.Image.Width,Manager.Image.Height);
+  end else
+    Result:= inherited ReplaceLayerAndAddShape(ARect);
+end;
+
 function TToolGradient.GetContextualToolbars: TContextualToolbars;
 begin
   Result:= [ctColor, ctGradient];

+ 35 - 23
lazpaint/tools/utoolvectorial.pas

@@ -8,7 +8,7 @@ uses
   Classes, SysUtils, LCLType, BGRABitmap, BGRABitmapTypes,
   BGRALayerOriginal, BGRAGraphics, LCVectorOriginal,
   UTool, UImageType, ULayerAction, LCVectorRectShapes,
-  BGRAGradientOriginal;
+  BGRAGradientOriginal, UStateType;
 
 type
   TToolSplineMode = (tsmMovePoint, tsmCurveModeAuto, tsmCurveModeAngle, tsmCurveModeSpline);
@@ -60,6 +60,7 @@ type
     procedure QuickDefineEnd; virtual;
     procedure OnTryStop({%H-}sender: TCustomLayerAction); override;
     procedure UpdateUseOriginal;
+    function ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference; virtual;
   public
     function ValidateShape: TRect;
     function CancelShape: TRect;
@@ -134,7 +135,7 @@ type
 implementation
 
 uses LazPaintType, LCVectorPolyShapes, LCVectorTextShapes, LCVectorialFill, BGRASVGOriginal,
-  ULoading, BGRATransform, math, UStateType, UImageDiff, Controls, BGRAPen, UResourceStrings, ugraph,
+  ULoading, BGRATransform, math, UImageDiff, Controls, BGRAPen, UResourceStrings, ugraph,
   LCScaleDPI, LCVectorClipboard, BGRAGradientScanner;
 
 const PointSize = 6;
@@ -1150,14 +1151,35 @@ begin
     FUseOriginal:= false;
 end;
 
-function TVectorialTool.ValidateShape: TRect;
+function TVectorialTool.ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference;
 var
+  transf: TAffineMatrix;
   diff: TComposedImageDifference;
-  layerId: LongInt;
   replaceDiff: TReplaceLayerByVectorOriginalDifference;
-  transf: TAffineMatrix;
+  layerId: integer;
   addDiff: TAddShapeToVectorOriginalDifference;
+begin
+  layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
+  transf := VectorTransform;
+  diff := TComposedImageDifference.Create;
+  replaceDiff := TReplaceLayerByVectorOriginalDifference.Create(Manager.Image.CurrentState,Manager.Image.CurrentLayerIndex,
+                   Manager.Image.LayerOriginalClass[Manager.Image.CurrentLayerIndex]=TVectorOriginal);
+  diff.Add(replaceDiff);
+  transf := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex])*transf;
+  FShape.Transform(transf);
+  addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
+  diff.Add(addDiff);
+  result := diff;
+  ARect := addDiff.ChangingBounds;
+  FShape := nil;
+end;
+
+function TVectorialTool.ValidateShape: TRect;
+var
+  layerId: LongInt;
   rF: TRectF;
+  changeBounds: TRect;
+  addDiff: TAddShapeToVectorOriginalDifference;
 begin
   if Assigned(FShape) then
   begin
@@ -1171,29 +1193,19 @@ begin
       rF := FShape.GetRenderBounds(rect(0,0,Manager.Image.Width,Manager.Image.Height), VectorTransform);
       if rF.IntersectsWith(rectF(0,0,Manager.Image.Width,Manager.Image.Height)) then
       begin
-        layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
         if UseOriginal then
         begin
+          layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
           addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
+          changeBounds := addDiff.ChangingBounds;
           Manager.Image.AddUndo(addDiff);
+          FShape := nil;
         end
         else
-        begin
-          transf := VectorTransform;
-          diff := TComposedImageDifference.Create;
-          replaceDiff := TReplaceLayerByVectorOriginalDifference.Create(Manager.Image.CurrentState,Manager.Image.CurrentLayerIndex,
-                           Manager.Image.LayerOriginalClass[Manager.Image.CurrentLayerIndex]=TVectorOriginal);
-          diff.Add(replaceDiff);
-          transf := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex])*transf;
-          FShape.Transform(transf);
-          addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
-          diff.Add(addDiff);
-          Manager.Image.AddUndo(diff);
-        end;
-        Manager.Image.ImageMayChange(addDiff.ChangingBounds);
-      end else
-        FShape.Free;
-      FShape := nil;
+          Manager.Image.AddUndo(ReplaceLayerAndAddShape(changeBounds));
+        Manager.Image.ImageMayChange(changeBounds);
+      end;
+      FreeAndNil(FShape);
       FEditor.Clear;
     end else
     begin
@@ -1238,7 +1250,7 @@ begin
        inc(result, 5)
     else if ((vsfBackFill in AOriginal.Shape[i].Fields) and
        (AOriginal.Shape[i].BackFill.FillType = vftGradient)) then
-       inc(result,20)
+       inc(result,15)
     else
       inc(result,2);
 end;

+ 2 - 1
lazpaintcontrols/lcvectorrectshapes.pas

@@ -843,6 +843,7 @@ end;
 
 procedure TRectShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
   ADraft: boolean);
+const GradientDithering = false;
 var
   pts: Array of TPointF;
   orthoRect: TRectF;
@@ -870,7 +871,7 @@ begin
       begin
         if Assigned(backScan) then
         begin
-          if BackFill.FillType = vftGradient then
+          if (BackFill.FillType = vftGradient) and GradientDithering then
           begin
             with orthoRect do
               r := rect(floor(Left),floor(Top),ceil(Right),ceil(Bottom));