You've already forked lazarus-ccr
* Add urotatebitmap to the package file so the ide can track changes in it (Changes acknowledged by eugen) git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1173 8e941d3f-bd1b-0410-a28a-d453659cc2b4
297 lines
7.1 KiB
ObjectPascal
297 lines
7.1 KiB
ObjectPascal
unit uRotateBitmap;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, Buttons, LCLType, IntfGraphics, Types;
|
|
|
|
type
|
|
|
|
TRotateDirection = (rdNormal, rdRight, rdLeft);
|
|
|
|
{ TCustomRotatedBitmap }
|
|
|
|
TCustomRotatedBitmap = class
|
|
private
|
|
FActiveBitmap: TBitmap;
|
|
FDirection: TRotateDirection;
|
|
FNormalBitmap: TBitmap;
|
|
FRotatedBitmap: TBitmap;
|
|
FTransparent: Boolean;
|
|
FActiveBitmapNeedsUpdate: Boolean;
|
|
function GetBitmap : TBitmap;
|
|
function GetEmpty: Boolean;
|
|
procedure NormalBitmapChanged(Sender: TObject);
|
|
procedure SetBitmap(const AValue: TBitmap);
|
|
procedure SetDirection(const AValue: TRotateDirection);
|
|
procedure SetTransparent(const AValue: Boolean);
|
|
procedure UpdateActiveBitmap; virtual;
|
|
protected
|
|
procedure NotifyBitmapChange; virtual;
|
|
function GetWidth: Integer; virtual;
|
|
function GetHeight: Integer; virtual;
|
|
property Bitmap: TBitmap read GetBitmap write SetBitmap;
|
|
property Transparent: Boolean read FTransparent write SetTransparent;
|
|
public
|
|
constructor Create; virtual;
|
|
destructor Destroy; override;
|
|
procedure Draw(Canvas: TCanvas; X, Y: Integer); virtual;
|
|
function IsBitmapStored : Boolean;
|
|
property Direction: TRotateDirection read FDirection write SetDirection;
|
|
property Empty: Boolean read GetEmpty;
|
|
property Width: Integer read GetWidth;
|
|
property Height: Integer read GetHeight;
|
|
end;
|
|
|
|
{ TRotatedBitmap }
|
|
|
|
TRotatedBitmap = class (TCustomRotatedBitmap)
|
|
public
|
|
property Bitmap;
|
|
property Transparent;
|
|
end;
|
|
|
|
{ TRotatedGlyph }
|
|
|
|
TRotatedGlyph = class (TCustomRotatedBitmap)
|
|
private
|
|
FGlyph : TButtonGlyph;
|
|
FButtonState : TButtonState;
|
|
FOnChange: TNotifyEvent;
|
|
procedure SetButtonState(Value: TButtonState);
|
|
procedure UpdateActiveBitmap; override;
|
|
protected
|
|
procedure NotifyBitmapChange; override;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
procedure Draw(Canvas: TCanvas; X, Y: Integer); override;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
property State: TButtonState read FButtonState write SetButtonState;
|
|
property Bitmap;
|
|
property Transparent;
|
|
end;
|
|
|
|
function CreateRotatedBitmap(SrcImage: TRasterImage; Direction: TRotateDirection): TBitmap;
|
|
|
|
procedure DrawRotatedText(Canvas: TCanvas; X, Y, TextWidth, TextHeight: Integer;
|
|
const Text: String; Direction: TRotateDirection);
|
|
|
|
implementation
|
|
|
|
uses
|
|
LCLProc;
|
|
|
|
function CreateRotatedBitmap(SrcImage: TRasterImage; Direction: TRotateDirection): TBitmap;
|
|
var
|
|
px, py, nx, ny : Integer;
|
|
RotateImg, NormalImg: TLazIntfImage;
|
|
begin
|
|
Result := TBitmap.Create;
|
|
if (SrcImage.Width = 0) or (SrcImage.Height = 0) then
|
|
begin
|
|
Exit;
|
|
end;
|
|
|
|
NormalImg := SrcImage.CreateIntfImage;
|
|
RotateImg := TLazIntfImage.Create(NormalImg.Height, NormalImg.Width);
|
|
RotateImg.DataDescription := NormalImg.DataDescription;
|
|
RotateImg.SetSize(NormalImg.Height, NormalImg.Width);
|
|
RotateImg.FillPixels(TColorToFPColor(clBlack));
|
|
|
|
for px := 0 to NormalImg.Width - 1 do
|
|
for py := 0 to NormalImg.Height - 1 do
|
|
begin
|
|
if Direction = rdRight then
|
|
begin
|
|
nx := RotateImg.Width - 1 - py;
|
|
ny := px;
|
|
end else begin
|
|
nx := py;
|
|
ny := RotateImg.Height - 1 - px;
|
|
end;
|
|
|
|
RotateImg.Colors[nx,ny] := NormalImg.Colors[px,py];
|
|
end;
|
|
|
|
Result.LoadFromIntfImage(RotateImg);
|
|
|
|
if SrcImage.Masked then
|
|
Result.TransparentColor := SrcImage.TransparentColor;
|
|
Result.Transparent := SrcImage.Transparent;
|
|
|
|
RotateImg.Free;
|
|
NormalImg.Free;
|
|
end;
|
|
|
|
procedure DrawRotatedText(Canvas: TCanvas; X, Y, TextWidth, TextHeight: Integer;
|
|
const Text: String; Direction: TRotateDirection);
|
|
begin
|
|
case Direction of
|
|
rdNormal:
|
|
begin
|
|
Canvas.Font.Orientation := 0;
|
|
Canvas.TextOut(X, Y, Text);
|
|
end;
|
|
rdLeft:
|
|
begin
|
|
Canvas.Font.Orientation := 900;
|
|
Canvas.TextOut(X, Y + TextHeight, Text);
|
|
end;
|
|
rdRight:
|
|
begin
|
|
Canvas.Font.Orientation := -900;
|
|
Canvas.TextOut(X + TextWidth, Y, Text);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TCustomRotatedBitmap }
|
|
|
|
function TCustomRotatedBitmap.GetBitmap: TBitmap;
|
|
begin
|
|
Result := FNormalBitmap;
|
|
end;
|
|
|
|
function TCustomRotatedBitmap.GetEmpty: Boolean;
|
|
begin
|
|
Result := (FNormalBitmap.Width = 0) or (FNormalBitmap.Height = 0);
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.NormalBitmapChanged(Sender: TObject);
|
|
begin
|
|
FActiveBitmapNeedsUpdate := True;
|
|
NotifyBitmapChange;
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.SetBitmap(const AValue: TBitmap);
|
|
begin
|
|
FNormalBitmap.Assign(AValue);
|
|
FActiveBitmapNeedsUpdate := True;
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.SetDirection(const AValue: TRotateDirection);
|
|
begin
|
|
if FDirection = AValue then
|
|
Exit;
|
|
FDirection := AValue;
|
|
FActiveBitmapNeedsUpdate := True;
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.SetTransparent(const AValue: Boolean);
|
|
begin
|
|
if FTransparent = AValue then exit;
|
|
FTransparent := AValue;
|
|
FActiveBitmap.Transparent := FTransparent;
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.UpdateActiveBitmap;
|
|
begin
|
|
FreeAndNil(FRotatedBitmap);
|
|
if FDirection = rdNormal then
|
|
FActiveBitmap := FNormalBitmap
|
|
else
|
|
begin
|
|
FRotatedBitmap := CreateRotatedBitmap(FNormalBitmap, FDirection);
|
|
FActiveBitmap := FRotatedBitmap;
|
|
end;
|
|
FActiveBitmapNeedsUpdate := False;
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.NotifyBitmapChange;
|
|
begin
|
|
|
|
end;
|
|
|
|
function TCustomRotatedBitmap.GetWidth: Integer;
|
|
begin
|
|
if FActiveBitmapNeedsUpdate then
|
|
UpdateActiveBitmap;
|
|
Result := FActiveBitmap.Width;
|
|
end;
|
|
|
|
function TCustomRotatedBitmap.GetHeight: Integer;
|
|
begin
|
|
if FActiveBitmapNeedsUpdate then
|
|
UpdateActiveBitmap;
|
|
Result := FActiveBitmap.Height;
|
|
end;
|
|
|
|
constructor TCustomRotatedBitmap.Create;
|
|
begin
|
|
FDirection := rdNormal;
|
|
FNormalBitmap := TBitmap.Create;
|
|
FNormalBitmap.OnChange := @NormalBitmapChanged;
|
|
FActiveBitmap := FNormalBitmap;
|
|
end;
|
|
|
|
destructor TCustomRotatedBitmap.Destroy;
|
|
begin
|
|
FNormalBitmap.Destroy;
|
|
FRotatedBitmap.Free;
|
|
end;
|
|
|
|
procedure TCustomRotatedBitmap.Draw(Canvas: TCanvas; X, Y: Integer);
|
|
begin
|
|
if FActiveBitmapNeedsUpdate then
|
|
UpdateActiveBitmap;
|
|
Canvas.Draw(X, Y, FActiveBitmap);
|
|
end;
|
|
|
|
function TCustomRotatedBitmap.IsBitmapStored : Boolean;
|
|
begin
|
|
Result := (not FActiveBitmap.Empty)
|
|
and (FActiveBitmap.Width>0) and (FActiveBitmap.Height>0);
|
|
end;
|
|
|
|
{ TRotatedGlyph }
|
|
|
|
procedure TRotatedGlyph.SetButtonState(Value: TButtonState);
|
|
begin
|
|
FButtonState := Value;
|
|
end;
|
|
|
|
procedure TRotatedGlyph.UpdateActiveBitmap;
|
|
begin
|
|
inherited UpdateActiveBitmap;
|
|
FGlyph.Glyph := FActiveBitmap;
|
|
end;
|
|
|
|
procedure TRotatedGlyph.NotifyBitmapChange;
|
|
begin
|
|
if Assigned(FOnChange) then
|
|
FOnChange(Self);
|
|
end;
|
|
|
|
constructor TRotatedGlyph.Create;
|
|
begin
|
|
inherited Create;
|
|
FGlyph := TButtonGlyph.Create;
|
|
end;
|
|
|
|
destructor TRotatedGlyph.Destroy;
|
|
begin
|
|
FGlyph.Destroy;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TRotatedGlyph.Draw(Canvas: TCanvas; X, Y: Integer);
|
|
var
|
|
R: TRect;
|
|
P: TPoint;
|
|
begin
|
|
if FActiveBitmapNeedsUpdate then
|
|
UpdateActiveBitmap;
|
|
R := Rect(0, 0, FActiveBitmap.Width, FActiveBitmap.Height);
|
|
P := Point(X, Y);
|
|
//DebugLn(DbgS(R));
|
|
//DebugLn(DbgS(P));
|
|
//DebugLn('Transparent: '+BoolToStr(Transparent, true));
|
|
FGlyph.Draw(Canvas, R, P, FButtonState, Transparent, 0);
|
|
end;
|
|
|
|
end.
|
|
|