228 lines
5.6 KiB
ObjectPascal

// SPDX-License-Identifier: LGPL-3.0-linking-exception
{
Created by BGRA Controls Team
Dibo, Circular, lainz (007) and contributors.
For detailed information see readme.txt
Site: https://sourceforge.net/p/bgra-controls/
Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
Forum: http://forum.lazarus.freepascal.org/index.php/board,46.0.html
}
{******************************* CONTRIBUTOR(S) ******************************
- Edivando S. Santos Brasil | mailedivando@gmail.com
(Compatibility with delphi VCL 11/2018)
***************************** END CONTRIBUTOR(S) *****************************}
unit BCEffect;
{$I bgracontrols.inc}
{$IFDEF FPC}
{$modeswitch advancedrecords}
{$ENDIF}
interface
uses
Classes, SysUtils, {$IFDEF FPC}LCLProc, LazUTF8, {$ELSE}Types, BGRAGraphics, GraphType, FPImage, {$ENDIF} BGRABitmapTypes;
{-- Fading --}
type
TFadingMode = (fmSuspended, fmFadeIn, fmFadeOut, fmFadeInCycle, fmFadeOutCycle, fmFadeInOut, fmFadeOutIn);
const
FadingModeStr: array[TFadingMode] of string = ('Suspended', 'Fade In', 'Fade Out', 'Fade In Cycle','Fade Out Cycle', 'Fade In Out', 'Fade Out In');
function StrToTFadingMode(const s: ansistring): TFadingMode;
procedure FadingModeStrList(s: TStrings);
type
{ TFading }
TFading = record
private
FAlpha: byte;
FMode: TFadingMode;
FAlphaStep: byte;
FDuration: integer;
FPrevDate: TDateTime;
FElapsedMsAccumulator: integer;
public
procedure SetFAlpha(AValue: byte);
procedure SetFMode(AValue: TFadingMode);
procedure SetFAlphaStep(AValue: byte);
procedure SetFDuration(AValue: integer);
public
function Execute(AStepCount: integer= 1): byte; // execute and return new alpha
function Reset: byte; // reset and return new alpha
procedure PutImage(ADestination: TBGRACustomBitmap; AX,AY: integer; ASource: TBGRACustomBitmap);
procedure FillRect(ADestination: TBGRACustomBitmap; ARect: TRect; AColor: TBGRAPixel);
public
property Alpha: byte read FAlpha write SetFAlpha;
property Mode: TFadingMode read FMode write SetFMode;
property Step: byte read FAlphaStep write SetFAlphaStep;
property Duration: integer read FDuration write SetFDuration;
end;
{-- Fading --}
implementation
{-- Fading --}
function StrToTFadingMode(const s: ansistring): TFadingMode;
var
fm: TFadingMode;
ls: ansistring;
begin
ls := {$IFDEF FPC}UTF8LowerCase{$ELSE}LowerCase{$ENDIF}(s);
for fm := low(TFadingMode) to high(TFadingMode) do
if ls = {$IFDEF FPC}UTF8LowerCase{$ELSE}LowerCase{$ENDIF}(FadingModeStr[fm]) then
begin
Result := fm;
break;
end;
Result := fm;
end;
procedure FadingModeStrList(s: TStrings);
var
fm: TFadingMode;
begin
for fm := low(TFadingMode) to high(TFadingMode) do
s.Add(FadingModeStr[fm]);
end;
{ TFading }
procedure TFading.SetFAlpha(AValue: byte);
begin
if FAlpha = AValue then
Exit;
FAlpha := AValue;
end;
procedure TFading.SetFMode(AValue: TFadingMode);
begin
if FMode = AValue then
Exit;
FMode := AValue;
FPrevDate:= 0;
end;
procedure TFading.SetFAlphaStep(AValue: byte);
begin
if FAlphaStep = AValue then
Exit
else
FAlphaStep := AValue;
end;
procedure TFading.SetFDuration(AValue: integer);
begin
FDuration:= AValue;
end;
function TFading.Execute(AStepCount: integer= 1): byte;
var curDate: TDateTime;
alphaStep: byte;
timeGrain: integer;
begin
if FAlphaStep <= 0 then
alphaStep := 1
else
alphaStep := FAlphaStep;
if FDuration > 0 then
begin
curDate := Now;
if FPrevDate = 0 then
begin
FPrevDate := curDate;
FElapsedMsAccumulator := 0;
result := FAlpha;
exit;
end;
inc(FElapsedMsAccumulator, round((curDate-FPrevDate)*(24*60*60*1000)) );
timeGrain := round(FDuration*alphaStep/255);
if timeGrain <= 0 then timeGrain := 1;
AStepCount := FElapsedMsAccumulator div timeGrain;
FElapsedMsAccumulator:= FElapsedMsAccumulator mod timeGrain;
FPrevDate := curDate;
end;
if AStepCount < 0 then AStepCount := 0
else if AStepCount > 255 then AStepCount := 255;
case FMode of
fmFadeIn, fmFadeInOut, fmFadeInCycle:
begin
if (FAlpha = 255) and (FMode = fmFadeInCycle) then
FAlpha := 0
else
if FAlpha + alphaStep*AStepCount >= 255 then
begin
FAlpha := 255;
if FMode = fmFadeInOut then
FMode := fmFadeOutIn
else if FMode <> fmFadeInCycle then
FMode := fmSuspended;
end
else
FAlpha := FAlpha + (alphaStep*AStepCount);
end;
fmFadeOut,fmFadeOutIn, fmFadeOutCycle:
begin
if (FAlpha = 0) and (FMode = fmFadeOutCycle) then
FAlpha := 255
else
if FAlpha - alphaStep*AStepCount <= 0 then
begin
FAlpha := 0;
if FMode = fmFadeOutIn then
FMode := fmFadeInOut
else if FMode <> fmFadeOutCycle then
FMode := fmSuspended;
end
else
FAlpha := FAlpha - (alphaStep*AStepCount);
end;
end;
Result := FAlpha;
end;
function TFading.Reset: byte;
begin
case FMode of
fmFadeIn, fmFadeInOut:
begin
FAlpha := 0;
end;
fmFadeOut,fmFadeOutIn:
begin
FAlpha := 255;
end;
end;
Result := FAlpha;
FPrevDate := 0;
end;
procedure TFading.PutImage(ADestination: TBGRACustomBitmap; AX, AY: integer;
ASource: TBGRACustomBitmap);
begin
ADestination.PutImage(AX,AY,ASource,dmDrawWithTransparency,Alpha);
end;
procedure TFading.FillRect(ADestination: TBGRACustomBitmap; ARect: TRect;
AColor: TBGRAPixel);
begin
ADestination.FillRect(ARect, BGRA(AColor.red,AColor.green,AColor.blue,AColor.alpha*Alpha div 255),dmDrawWithTransparency);
end;
{-- Fading --}
end.