| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- // SPDX-License-Identifier: LGPL-3.0-linking-exception
- { This component partialy solve problem with no alpha in lazarus GTK.
- It is using BGRABitmap library for drawing icons.
- originally written in 2011 by Krzysztof Dibowski dibowski at interia.pl
- }
- (******************************** CONTRIBUTOR(S) ******************************
- - Edivando S. Santos Brasil | [email protected]
- (Compatibility with delphi VCL 11/2018) { #note -oMaxM : VCL Compatibility? }
- - Massimo Magnano
- 2024/12
- Added Before/AfterDraw events (don't works with Widgetsets)
- Added UseBGRADraw ( " )
- Added Proportionally add methods
- 2025/01
- Added Indexed image reading/writing and Load/SaveFile
- ***************************** END CONTRIBUTOR(S) *****************************)
- unit BGRAImageList;
- {$I bgracontrols.inc}
- interface
- uses
- Classes, SysUtils,
- {$ifdef FPC}
- LResources, LCLVersion,
- {$endif}
- Controls, Graphics,
- GraphType, BGRABitmap, BGRABitmapTypes, {%H-}ImgList;
- {$ifdef LCLgtk or LCLgtk2}
- { $DEFINE BGRA_DRAW}
- {$endif}
- const
- { #note -oMaxM : redeclared because are not public consts }
- SIG_LAZ1 = #1#0;
- SIG_LAZ2 = 'li';
- SIG_LAZ3 = 'Li';
- SIG_LAZ4 = 'Lz';
- SIG_D3 = 'IL';
- sInvalidIndex = 'Invalid ImageList Index';
- sInvalidFormat ='Invalid Stream Format Signature';
- type
- TImageListSignature = array[0..1] of char; { #note -oMaxM : redeclared because is not a public type }
- { TBGRAImageListResolution }
- TBGRAImageListResolution = class(TDragImageListResolution)
- protected
- {$if lcl_fullversion >= 4990000}
- procedure ReadData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); virtual; overload;
- procedure WriteData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); virtual; overload;
- {$endif}
- public
- procedure BGRADraw(ACanvas: TCanvas; ARect: TRect; AIndex: Integer; AOverlay: TOverlay;
- ADrawingStyle: TDrawingStyle; AImageType: TImageType;
- ADrawEffect: TGraphicsDrawEffect; ABkColor, ABlendColor: TColor; AStretch: Boolean=False); virtual;
- procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: integer; ADrawingStyle: TDrawingStyle; AImageType: TImageType;
- ADrawEffect: TGraphicsDrawEffect); override;
- procedure DrawOverlay(ACanvas: TCanvas; AX, AY, AIndex: Integer; AOverlay: TOverlay; ADrawingStyle:
- TDrawingStyle; AImageType: TImageType; ADrawEffect: TGraphicsDrawEffect); overload;
- procedure StretchDrawOverlay(ACanvas: TCanvas; AIndex: Integer; ARect: TRect; AOverlay: TOverlay;
- AEnabled: Boolean = True); virtual;
- end;
- { TBGRAImageList }
- TBGRAImageList = class;
- //Return True whether the default draw should be called
- TCustomImageListBeforeDraw= function (Sender: TBGRAImageList;
- ACanvas: TCanvas; var ARect: TRect; var AIndex: Integer;
- var ADrawingStyle: TDrawingStyle; var AImageType: TImageType;
- var ADrawOverlay: Boolean; var AOverlay: TOverlay;
- var ADrawEffect: TGraphicsDrawEffect): Boolean of object;
- TCustomImageListAfterDraw= procedure (Sender: TBGRAImageList;
- ACanvas: TCanvas; ARect: TRect; AIndex: Integer;
- ADrawingStyle: TDrawingStyle; AImageType: TImageType;
- ADrawOverlay: Boolean; AOverlay: TOverlay;
- ADrawEffect: TGraphicsDrawEffect) of object;
- {$if lcl_fullversion < 4990000}
- TOverlaysArray = array[TOverlay] of Integer;
- {$endif}
- TBGRAImageList = class(TImageList)
- private
- rUseBGRADraw: Boolean;
- FBGRA: TBGRABitmap;
- FBmp: TBitmap;
- procedure SetUseBGRADraw(AValue: Boolean);
- protected
- FOnBeforeDraw: TCustomImageListBeforeDraw;
- FOnAfterDraw: TCustomImageListAfterDraw;
- {$if lcl_fullversion < 4990000}
- { #note -oMaxM : we keep our copy of the FOverlays array since it is declared private without any logic,
- so derived classes cannot use it in any way also because there is no property to read them
- see merged code freepascal.org/lazarus/lazarus!429
- }
- rOverlays: TOverlaysArray;
- {$endif}
- function GetResolution(AImageWidth: Integer): TBGRAImageListResolution;
- function CreateEmptyBitmap(AImageWidth, AImageHeight: Integer;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout;
- var imgRect: TRect): TBitmap;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function GetResolutionClass: TCustomImageListResolutionClass; override;
- procedure ReadData(AStream: TStream); override; overload;
- {$if lcl_fullversion >= 4990000}
- //Read/Write AIndex image from Stream without read/write all the images
- procedure ReadData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); virtual; overload;
- procedure WriteData(AStream: TStream); override; overload;
- procedure WriteData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); virtual; overload;
- //Read/Write from File
- procedure LoadFromFile(const AFilename: string; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); overload;
- procedure LoadFromFileUTF8(const AFilenameUTF8: string; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); overload;
- procedure SaveToFile(const AFilename: string; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); overload;
- procedure SaveToFileUTF8(const AFilenameUTF8: string; AIndex: Integer;
- StartStreamPos: Int64=0; CalcPos: Boolean=True); overload;
- {$else}
- procedure Overlay(AIndex: Integer; AOverlay: TOverlay);
- property Overlays: TOverlaysArray read rOverlays;
- {$endif}
- procedure LoadFromFile(const AFilename: string); overload;
- procedure LoadFromFileUTF8(const AFilenameUTF8: string); overload;
- procedure SaveToFile(const AFilename: string); overload;
- procedure SaveToFileUTF8(const AFilenameUTF8: string); overload;
- function CreateProportionalImage(AImage: TCustomBitmap;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap; overload;
- function CreateProportionalImage(AImageFileName: String;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap; overload;
- function CreateMaskImage(AImage: TCustomBitmap; MaskColor: TColor): TBitmap; overload;
- function CreateMaskImage(AImageFileName: String; MaskColor: TColor): TBitmap; overload;
- function CreateProportionalMaskImage(AImage: TCustomBitmap; MaskColor: TColor;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap; overload;
- function CreateProportionalMaskImage(AImageFileName: String; MaskColor: TColor;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap; overload;
- procedure StretchDrawOverlay(ACanvas: TCanvas; AIndex: Integer; ARect: TRect; AOverlay: TOverlay; AEnabled: Boolean = True);
- function AddProportionally(Image: TCustomBitmap; Mask: TCustomBitmap=nil;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter): Integer; overload;
- function AddProportionally(AImageFileName: String; AMaskFileName: String='';
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter): Integer; overload;
- function AddMaskedProportionally(Image: TCustomBitmap; MaskColor: TColor;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter): Integer; overload;
- function AddMaskedProportionally(AImageFileName: String; MaskColor: TColor;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter): Integer; overload;
- procedure InsertProportionally(AIndex: Integer; AImage: TCustomBitmap; AMask: TCustomBitmap=nil;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure InsertProportionally(AIndex: Integer; AImageFileName: String; AMaskFileName: String='';
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure InsertMaskedProportionally(AIndex: Integer; AImage: TCustomBitmap; MaskColor: TColor;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure InsertMaskedProportionally(AIndex: Integer; AImageFileName: String; MaskColor: TColor;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure ReplaceProportionally(AIndex: Integer; AImage: TCustomBitmap; AMask: TCustomBitmap=nil;
- const AllResolutions: Boolean = True;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure ReplaceProportionally(AIndex: Integer; AImageFileName: String; AMaskFileName: String='';
- const AllResolutions: Boolean = True;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure ReplaceMaskedProportionally(AIndex: Integer; AImage: TCustomBitmap; MaskColor: TColor;
- const AllResolutions: Boolean = True;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- procedure ReplaceMaskedProportionally(AIndex: Integer; AImageFileName: String; MaskColor: TColor;
- const AllResolutions: Boolean = True;
- AHorizAlign: TAlignment=taCenter; AVertAlign: TTextLayout=tlCenter); overload;
- published
- property UseBGRADraw: Boolean read rUseBGRADraw write SetUseBGRADraw;
- { #note -oMaxM : This Events don't works inside Widgetsets that use the imagelist handle
- but only if you draw directly on the Canvas using ImageList Draw methods }
- property OnBeforeDraw: TCustomImageListBeforeDraw read FOnBeforeDraw write FOnBeforeDraw;
- property OnAfterDraw: TCustomImageListAfterDraw read FOnAfterDraw write FOnAfterDraw;
- end;
- {$ifdef FPC}procedure Register;{$endif}
- implementation
- uses BGRAUTF8 {$ifdef FPC}, WSImgList{$endif};
- const
- EffectMap: array[Boolean] of TGraphicsDrawEffect = (
- gdeDisabled,
- gdeNormal
- );
- {$ifdef FPC}
- procedure Register;
- begin
- RegisterComponents('BGRA Controls', [TBGRAImageList]);
- end;
- {$endif}
- { TBGRAImageListResolution }
- {$if lcl_fullversion >= 4990000}
- procedure TBGRAImageListResolution.ReadData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- var
- oStreamPos: Int64;
- Signature: TImageListSignature;
- datPos, sCount: Integer;
- begin
- if (AIndex<0) or (AIndex>=Count) then raise EInvalidOperation.Create(SInvalidIndex);
- oStreamPos:= AStream.Position;
- try
- AStream.Position:= StartStreamPos;
- datPos:= AIndex * Width * Height;
- if CalcPos
- then begin
- AStream.Read(Signature, SizeOf(Signature));
- if Signature = SIG_LAZ3
- then begin
- sCount:=ReadLRSInteger(AStream);
- if (AIndex>=sCount) then raise EInvalidOperation.Create(SInvalidIndex);
- AStream.Position:= oStreamPos+SizeOf(Signature)+(3*4)+(datPos*SizeOf(FData[0]));
- AStream.Read(FData[datPos], Width * Height * SizeOf(FData[0]));
- end
- else raise Exception.Create(sInvalidFormat+' '+Signature);
- end
- else AStream.Read(FData[datPos], Width * Height * SizeOf(FData[0]));
- if HandleAllocated
- then TWSCustomImageListResolutionClass(WidgetSetClass).Replace(Self, AIndex, @FData[datPos]);
- finally
- AStream.Position:= oStreamPos;
- end;
- end;
- procedure TBGRAImageListResolution.WriteData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- var
- oStreamPos: Int64;
- Signature: TImageListSignature;
- datPos: Integer;
- begin
- if (AIndex<0) or (AIndex>=Count) then raise EInvalidOperation.Create(SInvalidIndex);
- oStreamPos:= AStream.Position;
- try
- AStream.Position:= StartStreamPos;
- datPos:= AIndex * Width * Height;
- if CalcPos
- then begin
- AStream.Read(Signature, SizeOf(Signature));
- if Signature = SIG_LAZ3
- then begin
- WriteLRSInteger(AStream, Count);
- AStream.Position:= oStreamPos+SizeOf(Signature)+(3*4)+(datPos*SizeOf(FData[0]));
- AStream.Write(FData[datPos], Width * Height * SizeOf(FData[0]));
- end
- else raise Exception.Create(sInvalidFormat+' '+Signature);
- end
- else AStream.Write(FData[datPos], Width * Height * SizeOf(FData[0]));
- finally
- AStream.Position:= oStreamPos;
- end;
- end;
- {$endif}
- procedure TBGRAImageListResolution.BGRADraw(ACanvas: TCanvas; ARect: TRect; AIndex: Integer; AOverlay: TOverlay;
- ADrawingStyle: TDrawingStyle; AImageType: TImageType;
- ADrawEffect: TGraphicsDrawEffect; ABkColor, ABlendColor: TColor; AStretch: Boolean);
- var
- bmpDrawEffect: TGraphicsDrawEffect;
- OverlayI: Integer;
- begin
- if (AIndex < 0) or (AIndex >= Count) then Exit;
- ReferenceNeeded;
- with TBGRAImageList(ImageList) do
- begin
- if (FBGRA = nil) then FBGRA:= TBGRABitmap.Create;
- if (FBmp = nil) then FBmp:= TBitmap.Create;
- {*** BGRA Drawing *** }
- if (ADrawEffect = gdeDisabled)
- then bmpDrawEffect:= gdeNormal
- else bmpDrawEffect:= ADrawEffect;
- {$ifdef FPC}
- GetBitmap(AIndex, FBmp, bmpDrawEffect);
- {$else}
- GetBitmapRaw(AIndex, FBmp, bmpDrawEffect);
- {$endif}
- FBGRA.Assign(FBmp);
- if (AOverlay > 0) then
- begin
- OverlayI := Overlays[AOverlay];
- if (OverlayI in [0..Count-1]) then
- begin
- {$ifdef FPC}
- GetBitmap(OverlayI, FBmp, bmpDrawEffect);
- {$else}
- GetBitmapRaw(OverlayI, FBmp, bmpDrawEffect);
- {$endif}
- FBmp.Mask(ImageList.BkColor);
- FBGRA.PutImage(0, 0, FBmp, dmLinearBlend);
- end;
- end;
- if (ADrawEffect = gdeDisabled) then BGRAReplace(FBGRA, FBGRA.FilterGrayscale);
- if (ADrawingStyle in [dsFocus, dsSelected]) then FBGRA.ApplyGlobalOpacity(128);
- if AStretch
- then FBGRA.Draw(ACanvas, ARect, (ABkColor <> clNone))
- else FBGRA.Draw(ACanvas, ARect.Left, ARect.Top, (ABkColor <> clNone));
- end;
- end;
- procedure TBGRAImageListResolution.Draw(ACanvas: TCanvas; AX, AY, AIndex: integer; ADrawingStyle: TDrawingStyle;
- AImageType: TImageType; ADrawEffect: TGraphicsDrawEffect);
- var
- vRect: TRect;
- vIndex: Integer;
- vDrawingStyle: TDrawingStyle;
- vImageType: TImageType;
- vDrawOverlay,
- stdDraw: Boolean;
- vOverlay: TOverlay;
- vDrawEffect: TGraphicsDrawEffect;
- rImageList: TBGRAImageList;
- begin
- if (AIndex < 0) or (AIndex >= Count) then Exit;
- ReferenceNeeded;
- rImageList:= TBGRAImageList(ImageList);
- //Copy Parameters to vars
- vRect:= Rect(AX, AY, Width, Height);
- vIndex:= AIndex;
- vDrawingStyle:= ADrawingStyle;
- vImageType:= AImageType;
- vDrawOverlay:= False;
- vOverlay:= 0;
- vDrawEffect:= ADrawEffect;
- stdDraw:= True;
- if Assigned(rImageList.FOnBeforeDraw)
- then stdDraw:= rImageList.FOnBeforeDraw(rImageList, ACanvas, vRect, vIndex, vDrawingStyle, vImageType,
- vDrawOverlay, vOverlay, vDrawEffect);
- if stdDraw then
- begin
- if not(vDrawOverlay) then vOverlay:= 0;
- if rImageList.rUseBGRADraw
- then BGRADraw(ACanvas, vRect, vIndex, vOverlay, vDrawingStyle, vImageType, vDrawEffect,
- rImageList.BkColor, rImageList.BlendColor)
- else begin
- if vDrawOverlay
- then inherited DrawOverlay(ACanvas, vRect.Left, vRect.Top, vIndex, vOverlay, vDrawingStyle, vImageType, vDrawEffect)
- else inherited Draw(ACanvas, vRect.Left, vRect.Top, vIndex, vDrawingStyle, vImageType, vDrawEffect);
- end;
- end;
- if Assigned(rImageList.FOnAfterDraw)
- then rImageList.FOnAfterDraw(rImageList, ACanvas, vRect, vIndex, vDrawingStyle, vImageType,
- vDrawOverlay, vOverlay, vDrawEffect);
- end;
- procedure TBGRAImageListResolution.DrawOverlay(ACanvas: TCanvas; AX, AY, AIndex: Integer; AOverlay: TOverlay;
- ADrawingStyle: TDrawingStyle; AImageType: TImageType; ADrawEffect: TGraphicsDrawEffect);
- var
- vRect: TRect;
- vIndex: Integer;
- vDrawingStyle: TDrawingStyle;
- vImageType: TImageType;
- vDrawOverlay,
- stdDraw: Boolean;
- vOverlay: TOverlay;
- vDrawEffect: TGraphicsDrawEffect;
- rImageList: TBGRAImageList;
- begin
- if (AIndex < 0) or (AIndex >= Count) then Exit;
- ReferenceNeeded;
- rImageList:= TBGRAImageList(ImageList);
- //Copy Parameters to vars
- vRect:= Rect(AX, AY, Width, Height);
- vIndex:= AIndex;
- vDrawingStyle:= ADrawingStyle;
- vImageType:= AImageType;
- vDrawOverlay:= True;
- vOverlay:= AOverlay;
- vDrawEffect:= ADrawEffect;
- stdDraw:= True;
- if Assigned(rImageList.FOnBeforeDraw)
- then stdDraw:= rImageList.FOnBeforeDraw(rImageList, ACanvas, vRect, vIndex, vDrawingStyle, vImageType,
- vDrawOverlay, vOverlay, vDrawEffect);
- if stdDraw then
- begin
- if not(vDrawOverlay) then vOverlay:= 0;
- if rImageList.rUseBGRADraw
- then BGRADraw(ACanvas, vRect, vIndex, vOverlay, vDrawingStyle, vImageType, vDrawEffect,
- rImageList.BkColor, rImageList.BlendColor)
- else begin
- if vDrawOverlay
- then inherited DrawOverlay(ACanvas, vRect.Left, vRect.Top, vIndex, vOverlay, vDrawingStyle, vImageType, vDrawEffect)
- else inherited Draw(ACanvas, vRect.Left, vRect.Top, vIndex, vDrawingStyle, vImageType, vDrawEffect);
- end;
- end;
- if Assigned(TBGRAImageList(ImageList).FOnAfterDraw)
- then TBGRAImageList(ImageList).FOnAfterDraw(TBGRAImageList(ImageList), ACanvas, vRect, vIndex, vDrawingStyle, vImageType,
- vDrawOverlay, vOverlay, vDrawEffect);
- end;
- procedure TBGRAImageListResolution.StretchDrawOverlay(ACanvas: TCanvas; AIndex: Integer; ARect: TRect;
- AOverlay: TOverlay; AEnabled: Boolean);
- var
- Bmp: TBitmap;
- vRect: TRect;
- OverlayI,
- vIndex: Integer;
- vDrawingStyle: TDrawingStyle;
- vImageType: TImageType;
- vDrawOverlay,
- stdDraw: Boolean;
- vOverlay: TOverlay;
- vDrawEffect: TGraphicsDrawEffect;
- rImageList: TBGRAImageList;
- begin
- if ((ARect.Right-ARect.Left)=Width) and ((ARect.Bottom-ARect.Top)=Height) then
- DrawOverlay(ACanvas, ARect.Left, ARect.Top, AIndex, AOverlay, AEnabled)
- else
- begin
- rImageList:= TBGRAImageList(ImageList);
- //Copy Parameters to vars
- vRect:= ARect;
- vIndex:= AIndex;
- vDrawingStyle:= rImageList.DrawingStyle;
- vImageType:= rImageList.ImageType;
- vDrawOverlay:= True;
- vOverlay:= AOverlay;
- vDrawEffect:= EffectMap[AEnabled];
- stdDraw:= True;
- if Assigned(rImageList.FOnBeforeDraw)
- then stdDraw:= rImageList.FOnBeforeDraw(rImageList, ACanvas, vRect, vIndex, vDrawingStyle, vImageType,
- vDrawOverlay, vOverlay, vDrawEffect);
- if stdDraw then
- begin
- if not(vDrawOverlay) then vOverlay:= 0;
- if rImageList.rUseBGRADraw
- then BGRADraw(ACanvas, vRect, vIndex, vOverlay, vDrawingStyle, vImageType, vDrawEffect,
- rImageList.BkColor, rImageList.BlendColor, True)
- else begin
- try
- Bmp := TBitmap.Create;
- {$ifdef FPC}
- GetBitmap(vIndex, Bmp, vDrawEffect);
- {$else}
- GetBitmapRaw(vIndex, Bmp, vDrawEffect);
- {$endif}
- ACanvas.StretchDraw(vRect, Bmp);
- if vDrawOverlay and (vOverlay > 0) then
- begin
- OverlayI := rImageList.Overlays[vOverlay];
- {$ifdef FPC}
- GetBitmap(OverlayI, Bmp, vDrawEffect);
- {$else}
- GetBitmapRaw(OverlayI, Bmp, vDrawEffect);
- {$endif}
- Bmp.Mask(rImageList.BkColor);
- ACanvas.StretchDraw(vRect, Bmp);
- end;
- finally
- Bmp.Free;
- end;
- end;
- end;
- if Assigned(rImageList.FOnAfterDraw)
- then rImageList.FOnAfterDraw(rImageList, ACanvas, vRect, vIndex, vDrawingStyle, vImageType,
- vDrawOverlay, vOverlay, vDrawEffect);
- end;
- end;
- procedure TBGRAImageList.SetUseBGRADraw(AValue: Boolean);
- begin
- if (rUseBGRADraw<>AValue) then
- begin
- rUseBGRADraw:=AValue;
- if Assigned(OnChange) then OnChange(Self);
- end;
- end;
- function TBGRAImageList.GetResolution(AImageWidth: Integer): TBGRAImageListResolution;
- begin
- Result := TBGRAImageListResolution(inherited GetResolution(AImageWidth));
- end;
- function TBGRAImageList.CreateEmptyBitmap(AImageWidth, AImageHeight: Integer; AHorizAlign: TAlignment;
- AVertAlign: TTextLayout; var imgRect: TRect): TBitmap;
- var
- rW, rH:Single;
- newWidth,
- newHeight:Integer;
- begin
- if (AImageWidth > 0) and (AImageHeight > 0) then
- begin
- imgRect.Left:= 0;
- imgRect.Top:= 0;
- rW := AImageWidth / Width;
- rH := AImageHeight / Height;
- if (rW > rH)
- then begin
- newHeight:= round(AImageHeight / rW);
- newWidth := Width;
- end
- else begin
- newWidth := round(AImageWidth / rH);
- newHeight := Height;
- end;
- case AHorizAlign of
- taCenter: imgRect.Left:= (Width-newWidth) div 2;
- taRightJustify: imgRect.Left:= Width-newWidth;
- end;
- case AVertAlign of
- tlCenter: imgRect.Top:= (Height-newHeight) div 2;
- tlBottom: imgRect.Top:= Height-newHeight;
- end;
- imgRect.Right:= imgRect.Left+newWidth;
- imgRect.Bottom:= imgRect.Top+newHeight;
- Result := TBitmap.Create;
- if (BkColor = clNone) then
- begin
- Result.Transparent:= True;
- Result.TransparentColor:= clNone;
- end;
- Result.SetSize(Width, Height);
- Result.Canvas.Brush.Color := BkColor;
- Result.Canvas.FillRect(0, 0, Width, Height);
- end;
- end;
- function TBGRAImageList.CreateProportionalImage(AImage: TCustomBitmap;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap;
- var
- imgRect: TRect;
- Bitmap, BitmapR :TBGRABitmap;
- begin
- Result:= nil;
- if (AImage <> nil) and (AImage.Width > 0) and (AImage.Height > 0) then
- try
- Result:= CreateEmptyBitmap(AImage.Width, AImage.Height, AHorizAlign, AVertAlign, imgRect);
- //Use our Stretch since TBitmap's one sucks
- Bitmap := TBGRABitmap.Create;
- Bitmap.Assign(AImage);
- BitmapR :=Bitmap.Resample(imgRect.Width, imgRect.Height);
- BitmapR.Draw(Result.Canvas, imgRect, False);
- finally
- Bitmap.Free;
- BitmapR.Free;
- end;
- end;
- function TBGRAImageList.CreateProportionalImage(AImageFileName: String;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap;
- var
- pict: TPicture;
- begin
- Result:= nil;
- if FileExists(AImageFileName) then
- try
- pict:= TPicture.Create;
- pict.LoadFromFile(AImageFileName);
- Result:= CreateProportionalImage(pict.Bitmap, AHorizAlign, AVertAlign);
- finally
- pict.Free;
- end;
- end;
- function TBGRAImageList.CreateMaskImage(AImage: TCustomBitmap; MaskColor: TColor): TBitmap;
- begin
- Result:= nil;
- if (AImage <> nil) and (AImage.Width > 0) and (AImage.Height > 0) then
- begin
- Result := TBitmap.Create;
- Result.Assign(AImage);
- Result.TransparentColor := MaskColor;
- Result.TransparentMode := tmFixed;
- Result.Transparent := True;
- Result.Masked:= True;
- end;
- end;
- function TBGRAImageList.CreateMaskImage(AImageFileName: String; MaskColor: TColor): TBitmap;
- var
- //bmpBGRA: TBGRABitmap;
- pict: TPicture;
- begin
- Result:= nil;
- if FileExists(AImageFileName) then
- try
- (*bmpBGRA:= TBGRABitmap.Create;
- bmpBGRA.LoadFromFile(AImageFileName);
- Result := bmpBGRA.MakeBitmapCopy(MaskColor, False);
- *)
- pict:= TPicture.Create;
- pict.LoadFromFile(AImageFileName);
- Result:=TBitmap.Create;
- Result.Assign(pict.Bitmap);
- Result.TransparentColor := MaskColor;
- Result.TransparentMode := tmFixed;
- Result.Transparent := True;
- Result.Masked:= True;
- finally
- pict.Free;
- //bmpBGRA.Free;
- end;
- end;
- function TBGRAImageList.CreateProportionalMaskImage(AImage: TCustomBitmap; MaskColor: TColor;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap;
- var
- MaskBmp: TBitmap;
- begin
- try
- MaskBmp:= CreateMaskImage(AImage, MaskColor);
- Result:= CreateProportionalImage(MaskBmp, AHorizAlign, AVertAlign);
- Result.TransparentColor:= MaskBmp.TransparentColor;
- finally
- MaskBmp.Free;
- end;
- end;
- function TBGRAImageList.CreateProportionalMaskImage(AImageFileName: String; MaskColor: TColor;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout): TBitmap;
- var
- MaskBmp: TBitmap;
- begin
- try
- MaskBmp:= CreateMaskImage(AImageFileName, MaskColor);
- Result:= CreateProportionalImage(MaskBmp, AHorizAlign, AVertAlign);
- Result.TransparentColor:= MaskBmp.TransparentColor;
- finally
- MaskBmp.Free;
- end;
- end;
- function TBGRAImageList.GetResolutionClass: TCustomImageListResolutionClass;
- begin
- Result := TBGRAImageListResolution;
- end;
- procedure TBGRAImageList.ReadData(AStream: TStream);
- begin
- inherited ReadData(AStream);
- end;
- procedure TBGRAImageList.LoadFromFile(const AFilename: string);
- begin
- LoadFromFileUTF8(SysToUtf8(AFilename));
- end;
- procedure TBGRAImageList.LoadFromFileUTF8(const AFilenameUTF8: string);
- var
- stream: TFileStreamUTF8;
- begin
- stream := TFileStreamUTF8.Create(AFilenameUTF8, fmOpenRead or fmShareDenyWrite);
- try
- ReadData(stream);
- finally
- stream.Free;
- end;
- end;
- procedure TBGRAImageList.SaveToFile(const AFilename: string);
- begin
- SaveToFileUTF8(SysToUtf8(AFilename));
- end;
- procedure TBGRAImageList.SaveToFileUTF8(const AFilenameUTF8: string);
- var
- stream: TFileStreamUTF8;
- begin
- stream := TFileStreamUTF8.Create(AFilenameUTF8, fmCreate);
- try
- WriteData(stream);
- finally
- stream.Free;
- end;
- end;
- {$if lcl_fullversion>=4990000}
- procedure TBGRAImageList.ReadData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- begin
- GetResolution(Width).ReadData(AStream, AIndex, StartStreamPos, CalcPos);
- end;
- procedure TBGRAImageList.WriteData(AStream: TStream);
- begin
- if (csDesigning in ComponentState)
- then inherited WriteData(AStream)
- else GetResolution(Width).WriteData(AStream, False); // don't compress data so we can write the image n without rewriting everything.
- end;
- procedure TBGRAImageList.WriteData(AStream: TStream; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- begin
- GetResolution(Width).WriteData(AStream, AIndex, StartStreamPos, CalcPos);
- end;
- procedure TBGRAImageList.LoadFromFile(const AFilename: string; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- begin
- LoadFromFileUTF8(SysToUtf8(AFilename), AIndex, StartStreamPos, CalcPos);
- end;
- procedure TBGRAImageList.LoadFromFileUTF8(const AFilenameUTF8: string; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- var
- stream: TFileStreamUTF8;
- begin
- stream := TFileStreamUTF8.Create(AFilenameUTF8, fmOpenRead or fmShareDenyWrite);
- try
- ReadData(stream, AIndex, StartStreamPos, CalcPos);
- finally
- stream.Free;
- end;
- end;
- procedure TBGRAImageList.SaveToFile(const AFilename: string; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- begin
- SaveToFileUTF8(SysToUtf8(AFilename), AIndex, StartStreamPos, CalcPos);
- end;
- procedure TBGRAImageList.SaveToFileUTF8(const AFilenameUTF8: string; AIndex: Integer;
- StartStreamPos: Int64; CalcPos: Boolean);
- var
- stream: TFileStreamUTF8;
- begin
- stream := TFileStreamUTF8.Create(AFilenameUTF8, fmOpenReadWrite);
- try
- WriteData(stream, AIndex, StartStreamPos, CalcPos);
- finally
- stream.Free;
- end;
- end;
- {$else}
- procedure TBGRAImageList.Overlay(AIndex: Integer; AOverlay: TOverlay);
- begin
- TImageList(Self).Overlay(AIndex, AOverlay);
- rOverlays[AOverlay] := AIndex;
- end;
- {$endif}
- procedure TBGRAImageList.StretchDrawOverlay(ACanvas: TCanvas; AIndex: Integer; ARect: TRect; AOverlay: TOverlay;
- AEnabled: Boolean);
- begin
- GetResolution(Width).StretchDrawOverlay(ACanvas, AIndex, ARect, AOverlay, AEnabled);
- end;
- function TBGRAImageList.AddProportionally(Image: TCustomBitmap; Mask: TCustomBitmap; AHorizAlign: TAlignment;
- AVertAlign: TTextLayout): Integer;
- begin
- try
- Result:= Count;
- InsertProportionally(Result, Image, Mask, AHorizAlign, AVertAlign);
- except
- Result:= -1;
- end;
- end;
- function TBGRAImageList.AddProportionally(AImageFileName: String; AMaskFileName: String; AHorizAlign: TAlignment;
- AVertAlign: TTextLayout): Integer;
- begin
- try
- Result := Count;
- InsertProportionally(Result, AImageFileName, AMaskFileName, AHorizAlign, AVertAlign);
- except
- Result:= -1;
- end;
- end;
- function TBGRAImageList.AddMaskedProportionally(Image: TCustomBitmap; MaskColor: TColor; AHorizAlign: TAlignment;
- AVertAlign: TTextLayout): Integer;
- begin
- try
- Result := Count;
- InsertMaskedProportionally(Result, Image, MaskColor, AHorizAlign, AVertAlign);
- except
- Result:= -1;
- end;
- end;
- function TBGRAImageList.AddMaskedProportionally(AImageFileName: String; MaskColor: TColor; AHorizAlign: TAlignment;
- AVertAlign: TTextLayout): Integer;
- begin
- try
- Result := Count;
- InsertMaskedProportionally(Result, AImageFileName, MaskColor, AHorizAlign, AVertAlign);
- except
- Result:= -1;
- end;
- end;
- procedure TBGRAImageList.InsertProportionally(AIndex: Integer; AImage: TCustomBitmap; AMask: TCustomBitmap;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- Bmp,
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalImage(AMask, AHorizAlign, AVertAlign);
- Bmp := CreateProportionalImage(AImage, AHorizAlign, AVertAlign);
- Insert(AIndex, Bmp, BmpMask);
- finally
- BmpMask.Free;
- Bmp.Free;
- end;
- end;
- procedure TBGRAImageList.InsertProportionally(AIndex: Integer; AImageFileName: String; AMaskFileName: String;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- Bmp,
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalImage(AMaskFileName, AHorizAlign, AVertAlign);
- Bmp := CreateProportionalImage(AImageFileName, AHorizAlign, AVertAlign);
- Insert(AIndex, Bmp, BmpMask);
- finally
- BmpMask.Free;
- Bmp.Free;
- end;
- end;
- procedure TBGRAImageList.InsertMaskedProportionally(AIndex: Integer; AImage: TCustomBitmap; MaskColor: TColor;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalMaskImage(AImage, MaskColor, AHorizAlign, AVertAlign);
- InsertMasked(AIndex, BmpMask, MaskColor);
- finally
- BmpMask.Free;
- end;
- end;
- procedure TBGRAImageList.InsertMaskedProportionally(AIndex: Integer; AImageFileName: String; MaskColor: TColor;
- AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- BmpMask: TBitmap;
- begin
- try
- BmpMask:= CreateProportionalMaskImage(AImageFileName, MaskColor, AHorizAlign, AVertAlign);
- InsertMasked(AIndex, BmpMask, MaskColor);
- finally
- BmpMask.Free;
- end;
- end;
- procedure TBGRAImageList.ReplaceProportionally(AIndex: Integer; AImage: TCustomBitmap; AMask: TCustomBitmap;
- const AllResolutions: Boolean; AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- Bmp,
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalImage(AMask, AHorizAlign, AVertAlign);
- Bmp := CreateProportionalImage(AImage, AHorizAlign, AVertAlign);
- Replace(AIndex, Bmp, BmpMask, AllResolutions);
- finally
- BmpMask.Free;
- Bmp.Free;
- end;
- end;
- procedure TBGRAImageList.ReplaceProportionally(AIndex: Integer; AImageFileName: String; AMaskFileName: String;
- const AllResolutions: Boolean; AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- Bmp,
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalImage(AMaskFileName, AHorizAlign, AVertAlign);
- Bmp := CreateProportionalImage(AImageFileName, AHorizAlign, AVertAlign);
- Replace(AIndex, Bmp, BmpMask, AllResolutions);
- finally
- BmpMask.Free;
- Bmp.Free;
- end;
- end;
- procedure TBGRAImageList.ReplaceMaskedProportionally(AIndex: Integer; AImage: TCustomBitmap; MaskColor: TColor;
- const AllResolutions: Boolean; AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalMaskImage(AImage, MaskColor, AHorizAlign, AVertAlign);
- ReplaceMasked(AIndex, BmpMask, MaskColor, AllResolutions);
- finally
- BmpMask.Free;
- end;
- end;
- procedure TBGRAImageList.ReplaceMaskedProportionally(AIndex: Integer; AImageFileName: String; MaskColor: TColor;
- const AllResolutions: Boolean; AHorizAlign: TAlignment; AVertAlign: TTextLayout);
- var
- BmpMask: TBitmap;
- begin
- try
- BmpMask := CreateProportionalMaskImage(AImageFileName, MaskColor, AHorizAlign, AVertAlign);
- ReplaceMasked(AIndex, BmpMask, MaskColor, AllResolutions);
- finally
- BmpMask.Free;
- end;
- end;
- constructor TBGRAImageList.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- {$ifdef BGRA_DRAW}
- rUseBGRADraw:= True;
- {$endif}
- end;
- destructor TBGRAImageList.Destroy;
- begin
- if (FBGRA <> nil) then FBGRA.Free;
- if (FBmp <> nil) then FBmp.Free;
- inherited Destroy;
- end;
- end.
|