瀏覽代碼

tool universal brush

johann 5 年之前
父節點
當前提交
194de7aa3f
共有 2 個文件被更改,包括 79 次插入35 次删除
  1. 50 0
      lazpaint/tools/utool.pas
  2. 29 35
      lazpaint/tools/utoolbasic.pas

+ 50 - 0
lazpaint/tools/utool.pas

@@ -74,6 +74,9 @@ type
   TGenericTool = class
   private
     FAction: TLayerAction;
+    FForeFill, FBackFill: TVectorialFill;
+    FBackFillScan, FForeFillScan: TBGRACustomScanner;
+    function GetUniversalBrush(ASource: TVectorialFill; var ADest: TVectorialFill; var AScan: TBGRACustomScanner): TUniversalBrush;
     function GetLayerOffset: TPoint;
   protected
     FManager: TToolManager;
@@ -97,6 +100,9 @@ type
     Cursor: TCursor;
     constructor Create(AManager: TToolManager); virtual;
     destructor Destroy; override;
+    function GetForeUniversalBrush: TUniversalBrush;
+    function GetBackUniversalBrush: TUniversalBrush;
+    procedure ReleaseUniversalBrushes;
     procedure ValidateAction;
     procedure ValidateActionPartially;
     procedure CancelAction;
@@ -124,6 +130,7 @@ type
     property StatusText: string read GetStatusText;
     property Validating: boolean read FValidating;
     property Canceling: boolean read FCanceling;
+    property ForeUniversalBrush: TUniversalBrush read GetForeUniversalBrush;
   end;
 
   { TReadonlyTool }
@@ -395,6 +402,7 @@ type
     function ApplyPressure(AColor: TBGRAPixel): TBGRAPixel;
     function ApplyPressure(AOpacity: byte): byte;
     procedure SetPressure(APressure: single);
+    function GetPressureB: Byte;
 
     function GetCurrentToolType: TPaintToolType;
     function SetCurrentToolType(tool: TPaintToolType): boolean;
@@ -644,6 +652,35 @@ begin
       result := Point(0,0);
 end;
 
+function TGenericTool.GetUniversalBrush(ASource: TVectorialFill;
+  var ADest: TVectorialFill; var AScan: TBGRACustomScanner): TUniversalBrush;
+begin
+  FreeAndNil(AScan);
+  FreeAndNil(ADest);
+  case ASource.FillType of
+  vftNone: TBGRABitmap.IdleBrush(result);
+  vftSolid: TBGRABitmap.SolidBrush(result, Manager.ApplyPressure(ASource.SolidColor));
+  else
+    begin
+      ADest := ASource.Duplicate;
+      ADest.FitGeometry(TAffineBox.AffineBox(RectF(0,0,Manager.Image.Width,Manager.Image.Height)));
+      ADest.ApplyOpacity(Manager.GetPressureB);
+      AScan := ADest.CreateScanner(AffineMatrixIdentity, false);
+      TBGRABitmap.ScannerBrush(result, AScan);
+    end;
+  end;
+end;
+
+function TGenericTool.GetForeUniversalBrush: TUniversalBrush;
+begin
+  result := GetUniversalBrush(Manager.ForeFill, FForeFill, FForeFillScan);
+end;
+
+function TGenericTool.GetBackUniversalBrush: TUniversalBrush;
+begin
+  result := GetUniversalBrush(Manager.BackFill, FBackFill, FBackFillScan);
+end;
+
 function TGenericTool.GetStatusText: string;
 begin
   result := '';
@@ -747,6 +784,14 @@ begin
   inherited Destroy;
 end;
 
+procedure TGenericTool.ReleaseUniversalBrushes;
+begin
+  FreeAndNil(FForeFillScan);
+  FreeAndNil(FForeFill);
+  FreeAndNil(FBackFillScan);
+  FreeAndNil(FBackFill);
+end;
+
 procedure TGenericTool.ValidateAction;
 begin
   if Assigned(FAction) then
@@ -2540,6 +2585,11 @@ begin
     FToolPressure:= APressure;
 end;
 
+function TToolManager.GetPressureB: Byte;
+begin
+  result := round(FToolPressure*255);
+end;
+
 procedure TToolManager.InternalSetCurrentToolType(tool: TPaintToolType);
 begin
   if (tool <> FCurrentToolType) or (FCurrentTool=nil) then

+ 29 - 35
lazpaint/tools/utoolbasic.pas

@@ -45,13 +45,12 @@ type
   TToolPen = class(TGenericTool)
   protected
     class var HintShowed: boolean;
-    penDrawing: boolean;
+    penDrawing, penDrawingRight: boolean;
     penOrigin: TPointF;
-    penColor: TBGRAPixel;
     snapToPixel: boolean;
     function GetIsSelectingTool: boolean; override;
     function StartDrawing(toolDest: TBGRABitmap; ptF: TPointF; rightBtn: boolean): TRect; virtual;
-    function ContinueDrawing(toolDest: TBGRABitmap; originF, destF: TPointF): TRect; virtual;
+    function ContinueDrawing(toolDest: TBGRABitmap; originF, destF: TPointF; rightBtn: boolean): TRect; virtual;
     function DoToolDown(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF; rightBtn: boolean): TRect; override;
     function DoToolMove(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF): TRect; override;
   public
@@ -70,7 +69,7 @@ type
     procedure ApplySoften(var image: TBGRABitmap);
     function BlurRadius: single;
     function StartDrawing(toolDest: TBGRABitmap; ptF: TPointF; {%H-}rightBtn: boolean): TRect; override;
-    function ContinueDrawing(toolDest: TBGRABitmap; originF, destF: TPointF): TRect; override;
+    function ContinueDrawing(toolDest: TBGRABitmap; originF, destF: TPointF; {%H-}rightBtn: boolean): TRect; override;
   public
     function GetContextualToolbars: TContextualToolbars; override;
   end;
@@ -154,7 +153,7 @@ begin
 end;
 
 function TToolErase.ContinueDrawing(toolDest: TBGRABitmap; originF,
-  destF: TPointF): TRect;
+  destF: TPointF; rightBtn: boolean): TRect;
 var areaCopy, mask: TBGRABitmap;
   pts: ArrayOfTPointF;
 begin
@@ -227,13 +226,15 @@ function TToolPen.StartDrawing(toolDest: TBGRABitmap; ptF: TPointF;
   rightBtn: boolean): TRect;
 var ix,iy: integer;
   r: TRect;
+  b: TUniversalBrush;
 begin
-  if rightBtn then penColor := Manager.BackColor else penColor := Manager.ForeColor;
-  if (snapToPixel or Manager.ShapeOptionAliasing) and (Manager.PenWidth = 1) and (Manager.GetTexture = nil) then
+  if rightBtn then b := GetBackUniversalBrush
+  else b := GetForeUniversalBrush;
+  if (snapToPixel or Manager.ShapeOptionAliasing) and (Manager.PenWidth = 1) then
   begin
     ix := round(ptF.X);
     iy := round(ptF.Y);
-    toolDest.DrawPixel(ix,iy,Manager.ApplyPressure(penColor));
+    toolDest.DrawPixel(ix, iy, b);
     result := rect(ix,iy,ix+1,iy+1);
   end else
   begin
@@ -243,32 +244,29 @@ begin
     begin
       r := rect(round(ptF.X-Manager.PenWidth/2+0.5),round(ptF.Y-Manager.PenWidth/2+0.5),
                 round(ptF.X+Manager.PenWidth/2+0.5),round(ptF.Y+Manager.PenWidth/2+0.5));
-      if Manager.GetTextureAfterAlpha <> nil then
-        toolDest.FillEllipseInRect(r,Manager.GetTextureAfterAlpha,dmDrawWithTransparency)
-      else
-        toolDest.FillEllipseInRect(r,Manager.ApplyPressure(penColor),dmDrawWithTransparency);
+      toolDest.FillEllipseInRect(r, b);
     end
     else
-    begin
-      if Manager.GetTextureAfterAlpha <> nil then
-        toolDest.FillEllipseAntialias(ptF.X,ptF.Y,Manager.PenWidth/2,Manager.PenWidth/2,Manager.GetTextureAfterAlpha)
-      else
-        toolDest.FillEllipseAntialias(ptF.X,ptF.Y,Manager.PenWidth/2,Manager.PenWidth/2,Manager.ApplyPressure(penColor));
-    end;
+      toolDest.FillEllipseAntialias(ptF.X, ptF.Y, Manager.PenWidth/2, Manager.PenWidth/2, b);
     toolDest.NoClip;
   end;
+  ReleaseUniversalBrushes;
 end;
 
-function TToolPen.ContinueDrawing(toolDest: TBGRABitmap; originF, destF: TPointF): TRect;
+function TToolPen.ContinueDrawing(toolDest: TBGRABitmap; originF, destF: TPointF; rightBtn: boolean): TRect;
 var
   pts: ArrayOfTPointF;
+  b: TUniversalBrush;
 begin
-  if (snapToPixel or Manager.ShapeOptionAliasing) and (Manager.PenWidth = 1) and (Manager.GetTexture = nil) then
+  if rightBtn then b := GetBackUniversalBrush
+  else b := GetForeUniversalBrush;
+  if (snapToPixel or Manager.ShapeOptionAliasing) and (Manager.PenWidth = 1) then
   begin
     if Manager.ShapeOptionAliasing then
-      toolDest.DrawLine(round(destF.X),round(destF.Y),round(originF.X),round(originF.Y),Manager.ApplyPressure(penColor),false)
+      toolDest.DrawLine(round(destF.X), round(destF.Y), round(originF.X), round(originF.Y), b, false)
     else
-      toolDest.DrawLineAntialias(round(destF.X),round(destF.Y),round(originF.X),round(originF.Y),Manager.ApplyPressure(penColor),false);
+      toolDest.DrawLineAntialias(round(destF.X), round(destF.Y),
+        round(originF.X), round(originF.Y), b, false);
     result := GetShapeBounds([destF,originF],1);
   end else
   begin
@@ -276,20 +274,14 @@ begin
     toolDest.ClipRect := result;
     if Manager.ShapeOptionAliasing then
     begin
-      pts := toolDest.Pen.ComputePolyline([PointF(destF.X,destF.Y),PointF(originF.X,originF.Y)],Manager.PenWidth,BGRAPixelTransparent,False);
-      if Manager.GetTextureAfterAlpha <> nil then
-        toolDest.FillPoly(pts,Manager.GetTextureAfterAlpha,dmDrawWithTransparency)
-      else
-        toolDest.FillPoly(pts,Manager.ApplyPressure(penColor),dmDrawWithTransparency);
+      pts := toolDest.Pen.ComputePolyline([PointF(destF.X,destF.Y),PointF(originF.X,originF.Y)],
+       Manager.PenWidth, BGRAPixelTransparent, False);
+      toolDest.FillPoly(pts, b);
     end else
-    begin
-      if Manager.GetTextureAfterAlpha <> nil then
-        toolDest.DrawLineAntialias(destF.X,destF.Y,originF.X,originF.Y,Manager.GetTextureAfterAlpha,Manager.PenWidth,False)
-      else
-        toolDest.DrawLineAntialias(destF.X,destF.Y,originF.X,originF.Y,Manager.ApplyPressure(penColor),Manager.PenWidth,False);
-    end;
+      toolDest.DrawLineAntialias(destF.X, destF.Y, originF.X, originF.Y, b, Manager.PenWidth, False);
     toolDest.NoClip;
   end;
+  ReleaseUniversalBrushes;
 end;
 
 function TToolPen.DoToolDown(toolDest: TBGRABitmap; pt: TPoint; ptF: TPointF;
@@ -300,6 +292,7 @@ begin
   begin
     toolDest.PenStyle := psSolid;
     penDrawing := true;
+    penDrawingRight := rightBtn;
     result := StartDrawing(toolDest,ptF,rightBtn);
     penOrigin := ptF;
   end else
@@ -318,7 +311,7 @@ begin
   if penDrawing and (sqr(penOrigin.X-ptF.X)+sqr(penOrigin.Y-ptF.Y) >= 0.999) then
   begin
     toolDest.PenStyle := psSolid;
-    result := ContinueDrawing(toolDest,penOrigin,ptF);
+    result := ContinueDrawing(toolDest,penOrigin,ptF,penDrawingRight);
     penOrigin := ptF;
   end;
 end;
@@ -354,6 +347,7 @@ begin
   if penDrawing then
   begin
     penDrawing:= false;
+    penDrawingRight := false;
     ValidateActionPartially;
   end;
   result := EmptyRect;
@@ -361,7 +355,7 @@ end;
 
 function TToolPen.GetContextualToolbars: TContextualToolbars;
 begin
-  Result:= [ctFill,ctTexture,ctPenWidth,ctAliasing];
+  Result:= [ctFill,ctPenWidth,ctAliasing];
 end;
 
 destructor TToolPen.Destroy;