262 lines
6.9 KiB
ObjectPascal

// SPDX-License-Identifier: LGPL-3.0-linking-exception
{ Implementation of BGRABitmap for MSEgui }
unit BGRAMSEguiBitmap;
{ It should NOT be added to the **uses** clause. }
{$mode objfpc}{$H+}
interface
uses
SysUtils, BGRAClasses, BGRAGraphics, BGRABitmapTypes, BGRADefaultBitmap,
BGRAText, msebitmap;
type
{ Implementation of TBGRABitmap for MSEgui }
TBGRAMSEguiBitmap = class(TBGRADefaultBitmap)
protected
procedure CopyDataToBitmap(AData: Pointer; AWidth,AHeight: integer; ALineOrder: TRawImageLineOrder; ABitmap: TBitmap);
procedure RebuildBitmap; override;
procedure DoLoadFromBitmap; override;
function CreateDefaultFontRenderer: TBGRACustomFontRenderer; override;
function LoadFromRawImage({%H-}ARawImage: TRawImage; {%H-}DefaultOpacity: byte;
{%H-}AlwaysReplaceAlpha: boolean=False; {%H-}RaiseErrorOnInvalidPixelFormat: boolean
=True): boolean; override;
procedure FreeBitmap; override;
procedure NotAvailable;
procedure InternalAssignBitmapPixels(ASource: TBitmap);
function GetCanvas: TCanvas; override;
public
procedure Assign(ASource: TPersistent); override;
procedure AssignToBitmap(ADestination: TBitmap);
destructor Destroy; override;
procedure GetImageFromCanvas({%H-}CanvasSource: TCanvas; {%H-}x, {%H-}y: integer); override; //not available
procedure DataDrawTransparent({%H-}ACanvas: TCanvas; {%H-}Rect: TRect; {%H-}AData: Pointer;
{%H-}ALineOrder: TRawImageLineOrder; {%H-}AWidth, {%H-}AHeight: integer); override;
procedure DataDrawOpaque({%H-}ACanvas: TCanvas; {%H-}Rect: TRect; {%H-}AData: Pointer;
{%H-}ALineOrder: TRawImageLineOrder; {%H-}AWidth, {%H-}AHeight: integer); override;
procedure TakeScreenshot({%H-}ARect: TRect); override; //not available
procedure TakeScreenshotOfPrimaryMonitor; override; //not available
procedure LoadFromDevice({%H-}DC: HDC); override; //not available
procedure LoadFromDevice({%H-}DC: HDC; {%H-}ARect: TRect); override; //not available
end;
type
{ Tracker of bitmap changes }
TBitmapTracker = class(TMaskedBitmap)
protected
FUser: TBGRADefaultBitmap;
procedure DoChange; override;
public
constructor Create(AUser: TBGRADefaultBitmap); overload;
end;
implementation
uses msegraphics, msegraphutils, math;
{ TBitmapTracker }
constructor TBitmapTracker.Create(AUser: TBGRADefaultBitmap);
begin
FUser := AUser;
inherited Create(bmk_rgb);
end;
procedure TBitmapTracker.DoChange;
begin
if FUser <> nil then
FUser.NotifyBitmapChange;
inherited DoChange;
end;
{ TBGRAMSEguiBitmap }
procedure TBGRAMSEguiBitmap.CopyDataToBitmap(AData: Pointer; AWidth,AHeight: integer; ALineOrder: TRawImageLineOrder; ABitmap: TBitmap);
var
ppix: PLongword;
pbmp: PLongword;
pmask: PByte;
x,y,yBmp : integer;
setMask: boolean;
begin
ABitmap.Size := Size(AWidth, AHeight);
ppix := AData;
pmask := nil;
if ABitmap is TMaskedBitmap then
begin
setMask := true;
TMaskedBitmap(ABitmap).Masked := true;
TMaskedBitmap(ABitmap).MaskKind := bmk_gray;
end else
setMask := false;
for y := 0 to Height-1 do
begin
if ALineOrder = riloTopToBottom then
yBmp := y else yBmp := Height-1-y;
pbmp := ABitmap.Scanline[yBmp];
if setMask then pmask := TMaskedBitmap(ABitmap).Mask.Scanline[yBmp];
for x := 0 to Width-1 do
begin
pbmp^ := ppix^ and $ffffff;
if setMask then
begin
pmask^ := ppix^ shr 24;
inc(pmask);
end;
inc(ppix);
inc(pbmp);
end;
end;
end;
procedure TBGRAMSEguiBitmap.RebuildBitmap;
begin
if FBitmap = nil then
FBitmap := TBitmapTracker.Create(self);
CopyDataToBitmap(Data, Width, Height, LineOrder, FBitmap);
end;
procedure TBGRAMSEguiBitmap.InternalAssignBitmapPixels(ASource: TBitmap);
var
ppix,pbmp: PLongword;
pmask: PByte;
getMask: boolean;
x,y,wm1: integer;
begin
if ASource is TMaskedBitmap then
getMask := TMaskedBitmap(ASource).Masked
else getMask := false;
wm1 := min(Width-1, ASource.Width-1);
for y := 0 to min(Height-1, ASource.Height-1) do
begin
ppix := plongword(GetScanlineFast(y));
pbmp := ASource.Scanline[y];
if getMask then pmask := TMaskedBitmap(ASource).Mask.Scanline[y];
for x := 0 to wm1 do
begin
if getMask then
begin
ppix^ := (pbmp^ and $ffffff) or (pmask^ shl 24);
inc(pmask);
end else
ppix^ := (pbmp^ and $ffffff) or $ff000000;
inc(ppix);
inc(pbmp);
end;
end;
end;
function TBGRAMSEguiBitmap.GetCanvas: TCanvas;
begin
result := inherited GetCanvas;
NotifyBitmapChange;
end;
procedure TBGRAMSEguiBitmap.Assign(ASource: TPersistent);
var bmp: TBitmap;
begin
if ASource is TBitmap then
begin
bmp := TBitmap(ASource);
SetSize(bmp.Width, bmp.Height);
InternalAssignBitmapPixels(bmp);
InvalidateBitmap;
end else
inherited Assign(ASource);
end;
procedure TBGRAMSEguiBitmap.AssignToBitmap(ADestination: TBitmap);
begin
ADestination.Assign(Bitmap);
end;
procedure TBGRAMSEguiBitmap.DoLoadFromBitmap;
begin
if Assigned(FBitmap) then
InternalAssignBitmapPixels(FBitmap);
end;
function TBGRAMSEguiBitmap.CreateDefaultFontRenderer: TBGRACustomFontRenderer;
begin
result := TMSEFontRenderer.Create;
end;
function TBGRAMSEguiBitmap.LoadFromRawImage(ARawImage: TRawImage;
DefaultOpacity: byte; AlwaysReplaceAlpha: boolean;
RaiseErrorOnInvalidPixelFormat: boolean): boolean;
begin
self.Assign(ARawImage);
result := true;
end;
procedure TBGRAMSEguiBitmap.FreeBitmap;
begin
FreeAndNil(FBitmap);
end;
procedure TBGRAMSEguiBitmap.NotAvailable;
begin
raise exception.Create('Function not available with MSEgui');
end;
destructor TBGRAMSEguiBitmap.Destroy;
begin
inherited Destroy;
end;
procedure TBGRAMSEguiBitmap.GetImageFromCanvas(CanvasSource: TCanvas; x,
y: integer);
begin
(Bitmap as TMaskedBitmap).Masked := false;
Bitmap.Canvas.CopyArea(CanvasSource, MakeRect(x,y,Bitmap.Width,Bitmap.Height),
Point(0,0));
end;
procedure TBGRAMSEguiBitmap.DataDrawTransparent(ACanvas: TCanvas; Rect: TRect;
AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer);
var
bmp: TMaskedBitmap;
begin
bmp := TMaskedBitmap.Create(bmk_rgb);
CopyDataToBitmap(Data, Width, Height, ALineOrder, bmp);
bmp.Paint(ACanvas, Rect);
bmp.Free;
end;
procedure TBGRAMSEguiBitmap.DataDrawOpaque(ACanvas: TCanvas; Rect: TRect;
AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer);
var
bmp: TBitmap;
begin
bmp := TBitmap.Create(bmk_rgb);
CopyDataToBitmap(AData, AWidth, AHeight, ALineOrder, bmp);
bmp.Paint(ACanvas, Rect);
bmp.Free;
end;
procedure TBGRAMSEguiBitmap.TakeScreenshot(ARect: TRect);
begin
NotAvailable;
end;
procedure TBGRAMSEguiBitmap.TakeScreenshotOfPrimaryMonitor;
begin
NotAvailable;
end;
procedure TBGRAMSEguiBitmap.LoadFromDevice(DC: HDC);
begin
NotAvailable;
end;
procedure TBGRAMSEguiBitmap.LoadFromDevice(DC: HDC; ARect: TRect);
begin
NotAvailable;
end;
end.