Double Gradient
│
Deutsch (de) │
English (en) │
Unit
With this unit 'ngradient' you can easily make gradients for toolbars, buttons, etc. Save the below code in a text file 'ngradient.pas' and add 'ngradient' in the 'uses' section of your project.
<delphi>unit ngradient;
{$mode objfpc}{$H+}
interface
uses
Classes, Graphics;
type
TnGradientInfo = record StartColor,StopColor:TColor; Direction: TGradientDirection; endPercent:single; // This is not the percent of the width, this is the percent of the end of the rect- which means, if this value is 1 - the rect could be from 0.99 to 1 and needs not be from 0 to 1 end;
function nGradientFill(ARect: TRect;APos: TGradientDirection; AGradient: array of TnGradientInfo): TBitmap;
implementation
function nGradientFill(ARect: TRect;APos: TGradientDirection; AGradient: array of TnGradientInfo): TBitmap; var
i:integer; AnRect,OldRect: TRect;
begin
Result := TBitmap.Create; Result.Width:=ARect.Right-ARect.Left; Result.Height:=ARect.Bottom-ARect.Top; OldRect := ARect; if APos = gdVertical then OldRect.Bottom := ARect.Top else OldRect.Right := ARect.Left ; // upside down... in case of i = 0...
for i := 0 to high(AGradient) do begin AnRect:=OldRect; if APos = gdVertical then begin AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGradient[i].endPercent + ARect.Top); AnRect.Top:=OldRect.Bottom; end else begin AnRect.Right:=Round((ARect.Right-ARect.Left) * AGradient[i].endPercent + ARect.Left); AnRect.Left:=OldRect.Right; end;
Result.Canvas.GradientFill(AnRect,AGradient[i].StartColor,AGradient[i].StopColor,AGradient[i].Direction); OldRect := AnRect; end;
end;<delphi>
DoubleGradientFill & DoubleGradientAlphaFill:
<delphi>unit doublegradient;
{$mode objfpc}{$H+}
interface
uses
Classes, Graphics, BGRABitmap, BGRABitmapTypes;
function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBitmap;
implementation
function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
var
ABitmap: TBGRABitmap; ARect1,ARect2: TRect; APoint1,APoint2,APoint3,APoint4: TPointF;
begin
ABitmap := TBGRABitmap.Create(ARect.Right,ARect.Bottom); if AValue <> 0 then ARect1:=ARect; if AValue <> 1 then ARect2:=ARect; if APos = gdVertical then begin ARect1.Bottom:=Round(ARect1.Bottom * AValue); ARect2.Top:=ARect1.Bottom; end else if APos = gdHorizontal then begin ARect1.Right:=Round(ARect1.Right * AValue); ARect2.Left:=ARect1.Right; end; if ADirection1 = gdVertical then begin APoint1:=PointF(ARect1.Left,ARect1.Top); APoint2:=PointF(ARect1.Left,ARect1.Bottom); end else if ADirection1 = gdHorizontal then begin APoint1:=PointF(ARect1.Left,ARect1.Top); APoint2:=PointF(ARect1.Right,ARect1.Top); end; if ADirection2 = gdVertical then begin APoint3:=PointF(ARect2.Left,ARect2.Top); APoint4:=PointF(ARect2.Left,ARect2.Bottom); end else if ADirection2 = gdHorizontal then begin APoint3:=PointF(ARect2.Left,ARect2.Top); APoint4:=PointF(ARect2.Right,ARect2.Top); end; if AValue <> 0 then ABitmap.GradientFill(ARect1.Left,ARect1.Top,ARect1.Right,ARect1.Bottom, AStart1,AStop1,gtLinear,APoint1,APoint2,dmDrawWithTransparency,True,False); if AValue <> 1 then ABitmap.GradientFill( ARect2.Left,ARect2.Top,ARect2.Right,ARect2.Bottom, AStart2,AStop2,gtLinear,APoint3,APoint4,dmDrawWithTransparency,True,False); Result:=ABitmap;
end;
function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBitmap;
var
ABitmap: TBitmap; ARect1,ARect2: TRect;
begin
ABitmap := TBitmap.Create; ABitmap.Width:=ARect.Right; ABitmap.Height:=ARect.Bottom; if AValue <> 0 then ARect1:=ARect; if AValue <> 1 then ARect2:=ARect; if APos = gdVertical then begin ARect1.Bottom:=Round(ARect1.Bottom * AValue); ARect2.Top:=ARect1.Bottom; end else if APos = gdHorizontal then begin ARect1.Right:=Round(ARect1.Right * AValue); ARect2.Left:=ARect1.Right; end; if AValue <> 0 then ABitmap.Canvas.GradientFill(ARect1,AStart1,AStop1,ADirection1); if AValue <> 1 then ABitmap.Canvas.GradientFill(ARect2,AStart2,AStop2,ADirection2); Result:=ABitmap;
end;
end.</delphi>
And now you can use alpha color with BGRABitmap, use DoubleGradientAlphaFill:
<delphi> unit doublegradientalpha;
{$mode objfpc}{$H+}
interface
uses
Classes, Graphics, BGRABitmap, BGRABitmapTypes;
function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
implementation
function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
var
ABitmap: TBGRABitmap; ARect1,ARect2: TRect; APoint1,APoint2,APoint3,APoint4: TPointF;
begin
ABitmap := TBGRABitmap.Create(ARect.Right,ARect.Bottom); if AValue <> 0 then ARect1:=ARect; if AValue <> 1 then ARect2:=ARect; if APos = gdVertical then begin ARect1.Bottom:=Round(ARect1.Bottom * AValue); ARect2.Top:=ARect1.Bottom; end else if APos = gdHorizontal then begin ARect1.Right:=Round(ARect1.Right * AValue); ARect2.Left:=ARect1.Right; end; if ADirection1 = gdVertical then begin APoint1:=PointF(ARect1.Left,ARect1.Top); APoint2:=PointF(ARect1.Left,ARect1.Bottom); end else if ADirection1 = gdHorizontal then begin APoint1:=PointF(ARect1.Left,ARect1.Top); APoint2:=PointF(ARect1.Right,ARect1.Top); end; if ADirection2 = gdVertical then begin APoint3:=PointF(ARect2.Left,ARect2.Top); APoint4:=PointF(ARect2.Left,ARect2.Bottom); end else if ADirection2 = gdHorizontal then begin APoint3:=PointF(ARect2.Left,ARect2.Top); APoint4:=PointF(ARect2.Right,ARect2.Top); end; if AValue <> 0 then ABitmap.GradientFill(ARect1.Left,ARect1.Top,ARect1.Right,ARect1.Bottom, AStart1,AStop1,gtLinear,APoint1,APoint2,dmDrawWithTransparency,True,False); if AValue <> 1 then ABitmap.GradientFill( ARect2.Left,ARect2.Top,ARect2.Right,ARect2.Bottom, AStart2,AStop2,gtLinear,APoint3,APoint4,dmDrawWithTransparency,True,False); Result:=ABitmap;
end; </delphi>
Usage
First you must have a 'TBitmap' to store the gradient, then you can draw the image, for example, in all the 'Form1' visible area:
This is the result (using DoubleGradientFill).
<delphi>procedure TForm1.FormPaint(Sender: TObject); var
ABitmap: TBitmap;
begin
ABitmap:=DoubleGradientFill(Self.ClientRect,clMedGray,clWhite,clSilver,clGray,gdVertical,gdVertical,gdVertical,0.50); Self.Canvas.Draw(0,0,ABitmap); ABitmap.Free
end;</delphi>
Editor
nGradient Editor is an updated version of Double Gradient Editor with a lot of changes and improvements, like the ability to create gradients with 'n' number of gradients.
nGradient Editor
With nGradient Editor you can use 'n' (number) of gradients.
Version 1.1
- Renamed to 'n Gradient Edit', just because it is not any more double...
- I don't really understand how to save configs - please correct it. Thanks
- I commented the Copy-to-clipboard thing - to lazy to correct it...
- I stopped the dpi thing because the editor doesn't look ok on my pc, remove "//" in Form.Create if you want to use it.
- I changed the editor for arrays, I use a stringlist. Double Click on StartColor /StopColor or Gradient for an Combobox / ColorDialog.
- I paint on an Image.
- The image is not longer in the middle - I had some problems, if you could fix it : great.
- You can scale the form.
- I tried to separate render and the rest...
Bugfixes: <delphi>(Rect.Bottom) *37 //and I corrected them to (Rect.Bottom - Rect.Top) * 37 + Rect.Top. //If Top and Left was 0 there was no problem ...</delphi>
<delphi>//Also I just changed the line GradientPB.Canvas.Draw(0,0,ABitmap); //to Panel1.Canvas.Draw(0,0,ABitmap);</delphi>
Double Gradient Editor
Also you can use the 'Double Gradient Editor' that is a GUI to instantly see the result (only for double gradients), save to a bitmap file, save to '*.doublegradient' session file or just copy code to clipboard to use in lazarus.
- To access the menu right click the ScrollBox (gradient area):
- Save bitmap.. Show a dialog to save as a *.bmp file.
- Load gradient.. Show a dialog to load a *.doublegradient session file.
- Save gradient.. Show a dialog to save the current session settings to a file.
- Copy code to clipboard.. Just copy the settings as text in the clipboard, then you can use it to paste in lazarus source editor to call the doublegradientfill procedure.
- default.doublegradient: this file has the last settings in the editor, is loaded at startup, saved when you close the application.
Downloads
nGradient Editor 1.1 (With alpha support) Source Code ngdedit1.1alpha.zip (22.58 KB) / forum attach
nGradient Editor 1.1 Source Code ngdedit1.1.zip (26.14 KB) / forum attach
Double Gradient Editor 1.0 Source Code dbgdedit1.0.zip (5.64 KB)
You are free to edit and improve this editor, this is free of charge.