CEF4Delphi/source/uCEFBrowserBitmap.pas
salvadordf ca8bc9dff4 Added cef4delphi.chm help file
Added the PDS file to extract the HTML Help files using PasDoc
Added more XML documentation
Fixed some XML errors.
Removed the license copy from the pas units.
Updated the LICENSE.md file
2023-08-09 19:38:57 +02:00

187 lines
4.7 KiB
ObjectPascal

unit uCEFBrowserBitmap;
{$IFDEF FPC}
{$MODE OBJFPC}{$H+}
{$ENDIF}
{$I cef.inc}
interface
uses
{$IFDEF DELPHI16_UP}
{$IFDEF MSWINDOWS}Winapi.Windows,{$ELSE}System.SyncObjs,{$ENDIF} System.Classes, System.SysUtils, Vcl.Graphics;
{$ELSE}
{$IFDEF MSWINDOWS}Windows,{$ENDIF} Classes, SysUtils, Graphics
{$IFDEF FPC}, LCLProc, LCLType, LCLIntf, LResources, InterfaceBase{$ENDIF}
{$IFNDEF MSWINDOWS}, SyncObjs{$ENDIF};
{$ENDIF}
type
TCEFBrowserBitmap = class(TBitmap)
protected
FScanlineSize : integer;
FDeviceScaleFactor : single;
{$IFDEF MSWINDOWS}
FSyncObj : THandle;
{$ELSE}
FSyncObj : TCriticalSection;
{$ENDIF}
function GetBufferBits : pointer;
procedure CreateSyncObj;
procedure DestroySyncObj;
public
constructor Create; override;
destructor Destroy; override;
function BeginBufferDraw : boolean;
procedure EndBufferDraw;
function UpdateBufferDimensions(aWidth, aHeight : integer) : boolean;
function BufferIsResized(aUseMutex : boolean = True) : boolean;
procedure BufferDraw(const aBitmap : TBitmap; const aSrcRect, aDstRect : TRect);
property ScanlineSize : integer read FScanlineSize;
property BufferBits : pointer read GetBufferBits;
property DeviceScaleFactor : single read FDeviceScaleFactor write FDeviceScaleFactor;
end;
implementation
uses
uCEFMiscFunctions;
constructor TCEFBrowserBitmap.Create;
begin
inherited Create;
FScanlineSize := 0;
FDeviceScaleFactor := 1;
CreateSyncObj;
end;
destructor TCEFBrowserBitmap.Destroy;
begin
DestroySyncObj;
inherited Destroy;
end;
procedure TCEFBrowserBitmap.CreateSyncObj;
begin
{$IFDEF MSWINDOWS}
FSyncObj := CreateMutex(nil, False, nil);
{$ELSE}
FSyncObj := TCriticalSection.Create;
{$ENDIF}
end;
procedure TCEFBrowserBitmap.DestroySyncObj;
begin
{$IFDEF MSWINDOWS}
if (FSyncObj <> 0) then
begin
CloseHandle(FSyncObj);
FSyncObj := 0;
end;
{$ELSE}
if (FSyncObj <> nil) then FreeAndNil(FSyncObj);
{$ENDIF}
end;
function TCEFBrowserBitmap.GetBufferBits : pointer;
begin
if (Height <> 0) then
Result := Scanline[pred(Height)]
else
Result := nil;
end;
function TCEFBrowserBitmap.BeginBufferDraw : boolean;
begin
{$IFDEF MSWINDOWS}
Result := (FSyncObj <> 0) and (WaitForSingleObject(FSyncObj, 5000) = WAIT_OBJECT_0);
{$ELSE}
if (FSyncObj <> nil) then
begin
FSyncObj.Acquire;
Result := True;
end
else
Result := False;
{$ENDIF}
end;
procedure TCEFBrowserBitmap.EndBufferDraw;
begin
{$IFDEF MSWINDOWS}
if (FSyncObj <> 0) then ReleaseMutex(FSyncObj);
{$ELSE}
if (FSyncObj <> nil) then FSyncObj.Release;
{$ENDIF}
end;
function TCEFBrowserBitmap.UpdateBufferDimensions(aWidth, aHeight : integer) : boolean;
begin
Result := False;
FScanlineSize := aWidth * SizeOf(TRGBQuad);
if (Width <> aWidth) or
(Height <> aHeight) then
begin
{$IFDEF DELPHI16_UP}
SetSize(aWidth, aHeight);
{$ELSE}
Width := aWidth;
Height := aHeight;
{$ENDIF}
Result := True;
end;
end;
function TCEFBrowserBitmap.BufferIsResized(aUseMutex : boolean) : boolean;
var
TempDevWidth, TempLogWidth, TempDevHeight, TempLogHeight : integer;
begin
Result := False;
if not(aUseMutex) or BeginBufferDraw then
begin
if (FDeviceScaleFactor = 1) then
Result := (Width = Width) and
(Height = Height)
else
begin
// CEF and Chromium use 'floor' to round the float values in Device <-> Logical unit conversions
// and Delphi uses MulDiv, which uses the bankers rounding, to resize the components in high DPI mode.
// This is the cause of slight differences in size between the buffer and the panel in some occasions.
TempLogWidth := DeviceToLogical(Width, FDeviceScaleFactor);
TempLogHeight := DeviceToLogical(Height, FDeviceScaleFactor);
TempDevWidth := LogicalToDevice(TempLogWidth, FDeviceScaleFactor);
TempDevHeight := LogicalToDevice(TempLogHeight, FDeviceScaleFactor);
Result := (Width = TempDevWidth) and
(Height = TempDevHeight);
end;
if aUseMutex then EndBufferDraw;
end;
end;
procedure TCEFBrowserBitmap.BufferDraw(const aBitmap : TBitmap; const aSrcRect, aDstRect : TRect);
begin
if (aBitmap <> nil) then
begin
Canvas.Lock;
aBitmap.Canvas.Lock;
Canvas.CopyRect(aDstRect, aBitmap.Canvas, aSrcRect);
aBitmap.Canvas.UnLock;
Canvas.UnLock;
end;
end;
end.