lazarus/lcl/widgetset/wsimglist.pp
ondrej 90f22ba7fd LCL: High-DPI ImageList: LCL runtime and win32
git-svn-id: branches/HiDPIImageList@57039 -
2018-01-10 12:46:42 +00:00

271 lines
8.8 KiB
ObjectPascal

{ $Id$}
{
*****************************************************************************
* WSImgList.pp *
* ------------ *
* *
* *
*****************************************************************************
*****************************************************************************
This file is part of the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
}
unit WSImgList;
{$mode objfpc}{$H+}
{$I lcl_defines.inc}
interface
////////////////////////////////////////////////////
// I M P O R T A N T
////////////////////////////////////////////////////
// 1) Only class methods allowed
// 2) Class methods have to be published and virtual
// 3) To get as little as posible circles, the uses
// clause should contain only those LCL units
// needed for registration. WSxxx units are OK
// 4) To improve speed, register only classes in the
// initialization section which actually
// implement something
// 5) To enable your XXX widgetset units, look at
// the uses clause of the XXXintf.pp
////////////////////////////////////////////////////
uses
Classes, GraphType, Graphics, IntfGraphics, ImgList, LCLType, LCLIntf,
WSLCLClasses, WSProc, WSReferences, WSFactory;
type
{ TWSCustomImageListResolution }
TWSCustomImageListResolution = class(TWSLCLReferenceComponent)
published
class procedure Clear(AList: TCustomImageListResolution); virtual;
class function CreateReference(AList: TCustomImageListResolution; ACount, AGrow, AWidth,
AHeight: Integer; AData: PRGBAQuad): TWSCustomImageListReference; virtual;
class procedure Delete(AList: TCustomImageListResolution; AIndex: Integer); virtual;
class procedure DestroyReference(AComponent: TComponent); override;
class procedure Draw(AList: TCustomImageListResolution; AIndex: Integer; ACanvas: TCanvas;
ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); virtual;
class procedure Insert(AList: TCustomImageListResolution; AIndex: Integer; AData: PRGBAQuad); virtual;
class procedure Move(AList: TCustomImageListResolution; ACurIndex, ANewIndex: Integer); virtual;
class procedure Replace(AList: TCustomImageListResolution; AIndex: Integer; AData: PRGBAQuad); virtual;
end;
TWSCustomImageListResolutionClass = class of TWSCustomImageListResolution;
procedure RegisterCustomImageListResolution;
implementation
type
{ TDefaultImageListImplementor }
// Dont use TObjectList due to a bug in it (fixed in fpc > 2.2.2)
TDefaultImageListImplementor = class(TList)
private
FList: TCustomImageListResolution;
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
public
constructor Create(AList: TCustomImageListResolution); reintroduce;
procedure Draw(AIndex: Integer; ACanvas: TCanvas; ABounds: TRect; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle);
end;
{ TDefaultImageListImplementor }
procedure TDefaultImageListImplementor.Notify(Ptr: Pointer;
Action: TListNotification);
begin
if Action = lnDeleted then
TBitmap(Ptr).Free;
inherited Notify(Ptr, Action);
end;
constructor TDefaultImageListImplementor.Create(AList: TCustomImageListResolution);
begin
inherited Create;
FList := AList;
end;
procedure TDefaultImageListImplementor.Draw(AIndex: Integer; ACanvas: TCanvas;
ABounds: TRect; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle);
var
ABitmap: TBitmap;
RawImg: TRawImage;
ListImg, DeviceImg: TLazIntfImage;
ImgHandle, MskHandle: HBitmap;
begin
if (AIndex < 0) or (AIndex >= Count) then Exit;
if ADrawEffect = gdeNormal then
begin
ABitmap := TBitmap(Items[AIndex]);
ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap);
end
else
begin
FList.GetRawImage(AIndex, RawImg);
RawImg.PerformEffect(ADrawEffect, True);
ABitmap := TBitmap.Create;
if not CreateCompatibleBitmaps(RawImg, ImgHandle, MskHandle, True)
then begin
// bummer, the widgetset doesn't support our 32bit format, try device
ListImg := TLazIntfImage.Create(RawImg, False);
DeviceImg := TLazIntfImage.Create(0, 0, []);
DeviceImg.DataDescription := GetDescriptionFromDevice(0, FList.Width, FList.Height);
DeviceImg.CopyPixels(ListImg);
DeviceImg.GetRawImage(RawImg);
RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle);
DeviceImg.Free;
ListImg.Free;
end;
ABitmap.SetHandles(ImgHandle, MskHandle);
ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap);
ABitmap.Free;
RawImg.FreeData;
end;
end;
function InternalCreateBitmap(AList: TCustomImageListResolution; AWidth, AHeight: Integer; AData: PRGBAQuad): TBitmap;
var
hbmImage, hbmMask: HBitmap;
RawImg: TRawImage;
begin
FillChar(RawImg, SizeOf(RawImg), 0);
AList.FillDescription(RawImg.Description);
RawImg.DataSize := AWidth * AHeight * SizeOF(AData[0]);
RawImg.Data := PByte(AData);
CreateCompatibleBitmaps(RawImg, hbmImage, hbmMask);
//RawImage_CreateBitmaps(RawImg, hbmImage, hbmMask);
Result := TBitmap.Create;
Result.SetHandles(hbmImage, hbmMask);
end;
{ TWSCustomImageListResolution }
class procedure TWSCustomImageListResolution.Clear(AList: TCustomImageListResolution);
begin
if not WSCheckReferenceAllocated(AList, 'Clear')
then Exit;
TDefaultImageListImplementor(AList.Reference.Ptr).Clear;
end;
class function TWSCustomImageListResolution.CreateReference(
AList: TCustomImageListResolution; ACount, AGrow, AWidth, AHeight: Integer;
AData: PRGBAQuad): TWSCustomImageListReference;
var
impl: TDefaultImageListImplementor;
ABitmap: TBitmap;
i: integer;
begin
impl := TDefaultImageListImplementor.Create(AList);
Result{%H-}._Init(impl);
if AData <> nil then
begin
// this is very slow method :(
for i := 0 to ACount - 1 do
begin
ABitmap := InternalCreateBitmap(AList, AWidth, AHeight, @AData[AWidth * AHeight * i]);
impl.Add(ABitmap);
end;
end;
end;
class procedure TWSCustomImageListResolution.Delete(AList: TCustomImageListResolution;
AIndex: Integer);
begin
if not WSCheckReferenceAllocated(AList, 'Delete')
then Exit;
TDefaultImageListImplementor(AList.Reference.Ptr).Delete(AIndex);
end;
class procedure TWSCustomImageListResolution.DestroyReference(AComponent: TComponent);
begin
if not WSCheckReferenceAllocated(TCustomImageListResolution(AComponent), 'DestroyReference')
then Exit;
TObject(TCustomImageListResolution(AComponent).Reference.Ptr).Free;
end;
class procedure TWSCustomImageListResolution.Draw(AList: TCustomImageListResolution;
AIndex: Integer; ACanvas: TCanvas; ABounds: TRect; ABkColor,
ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle;
AImageType: TImageType);
begin
if not WSCheckReferenceAllocated(AList, 'Draw')
then Exit;
TDefaultImageListImplementor(AList.Reference.Ptr).Draw(AIndex, ACanvas, ABounds, ADrawEffect, AStyle);
end;
class procedure TWSCustomImageListResolution.Insert(AList: TCustomImageListResolution;
AIndex: Integer; AData: PRGBAQuad);
var
AImageList: TDefaultImageListImplementor;
ACount: Integer;
ABitmap: TBitmap;
begin
if not WSCheckReferenceAllocated(AList, 'Insert')
then Exit;
AImageList := TDefaultImageListImplementor(AList.Reference.Ptr);
ACount := AImageList.Count;
if (AIndex <= ACount) and (AIndex >= 0) then
begin
ABitmap := InternalCreateBitmap(AList, AList.Width, AList.Height, AData);
AImageList.Add(ABitmap);
if AIndex <> ACount then
Move(AList, ACount, AIndex);
end;
end;
class procedure TWSCustomImageListResolution.Move(AList: TCustomImageListResolution;
ACurIndex, ANewIndex: Integer);
begin
if not WSCheckReferenceAllocated(AList, 'Move')
then Exit;
if ACurIndex = ANewIndex
then Exit;
TDefaultImageListImplementor(AList.Reference.Ptr).Move(ACurIndex, ANewIndex);
end;
class procedure TWSCustomImageListResolution.Replace(AList: TCustomImageListResolution;
AIndex: Integer; AData: PRGBAQuad);
var
ABitmap: TBitmap;
begin
if not WSCheckReferenceAllocated(AList, 'Replace')
then Exit;
ABitmap := InternalCreateBitmap(AList, AList.Width, AList.Height, AData);
TDefaultImageListImplementor(AList.Reference.Ptr)[AIndex] := ABitmap;
end;
{ WidgetSetRegistration }
procedure RegisterCustomImageListResolution;
const
Done: Boolean = False;
begin
if Done then exit;
if not WSRegisterCustomImageListResolution then
RegisterWSComponent(TCustomImageListResolution, TWSCustomImageListResolution);
Done := True;
end;
end.