sxskinbitmapmanager.pas

来自「skin components for design of your appli」· PAS 代码 · 共 412 行

PAS
412
字号
unit SXSkinBitmapManager;

////////////////////////////////////////////////////////////////////////////////
// SXSkinComponents: Skinnable Visual Controls for Delphi and C++Builder      //
//----------------------------------------------------------------------------//
// Version: 1.2.1                                                             //
// Author: Alexey Sadovnikov                                                  //
// Web Site: http://www.saarixx.info/sxskincomponents/                        //
// E-Mail: sxskincomponents@saarixx.info                                      //
//----------------------------------------------------------------------------//
// LICENSE:                                                                   //
// 1. You may freely distribute this file.                                    //
// 2. You may not make any changes to this file.                              //
// 3. The only person who may change this file is Alexey Sadovnikov.          //
// 4. You may use this file in your freeware projects.                        //
// 5. If you want to use this file in your shareware or commercial project,   //
//    you should purchase a project license or a personal license of          //
//    SXSkinComponents: http://saarixx.info/sxskincomponents/en/purchase.htm  //
// 6. You may freely use, distribute and modify skins for SXSkinComponents.   //
// 7. You may create skins for SXSkinComponents.                              //
//----------------------------------------------------------------------------//
// Copyright (C) 2006-2007, Alexey Sadovnikov. All Rights Reserved.           //
////////////////////////////////////////////////////////////////////////////////

interface

{$I Compilers.inc}

uses Windows, Classes, SXSkinLibrary, GR32, SysUtils, GR32_Resamplers,
     SXZipUtils;

type

 TSXSkinPreloadedBitmap=class
  public
   Filter:TSXFilterData;
   Resized:Boolean;
   StretchFilter:TSXImageStretchFilter;
   Width:Integer;
   Height:Integer;
   FilePath:String;
   Bitmap:TBitmap32;
   SkinLibrary:TSXSkinLibrary;
   constructor Create;
   destructor Destroy; override;
 end;

 TSXSkinPreloadedBitmapList=class
  protected
   FItem:TList;
   function Get(const Index:Integer):TSXSkinPreloadedBitmap;
   procedure Put(const Index:Integer;const Item:TSXSkinPreloadedBitmap);
   function GetCount:Integer;
  public
   procedure Add(Bitmap:TSXSkinPreloadedBitmap);
   function GetBitmapIndex(Bitmap:TSXSkinPreloadedBitmap):Integer;
   procedure Delete(const Index:Integer);
   procedure Clear;
   constructor Create;
   destructor Destroy; override;
   property Item[const Index:Integer]:TSXSkinPreloadedBitmap read Get write Put; default;
   property Count:Integer read GetCount;
 end;

function GetPreloadedBitmap(SkinLibrary:TSXSkinLibrary;
           const FilePath,ZipFilePath:String;Resized:Boolean;Width:Integer;
           Height:Integer;StretchFilter:TSXImageStretchFilter;
           Filter:TSXFilterData):TBitmap32;
procedure DeletePreloadedBitmaps(SkinLibrary:TSXSkinCustomLibrary);

var PreloadedBitmaps:TSXSkinPreloadedBitmapList;

implementation

uses Math, jpeg, SXPNGUtils;

function CompareBitmaps(Bitmap1,Bitmap2:TSXSkinPreloadedBitmap):Integer;
begin
 Result:=CompareValue(Integer(Bitmap1.SkinLibrary),Integer(Bitmap2.SkinLibrary));
 if Result=0 then
  Result:=CompareStr(Bitmap1.FilePath,Bitmap2.FilePath) else exit;
 if Result=0 then
  Result:=CompareValue(Ord(Bitmap1.Resized),Ord(Bitmap2.Resized)) else exit;
 if Result<>0 then exit;
 if Bitmap1.Resized then
  begin
   Result:=CompareValue(Ord(Bitmap1.Width),Ord(Bitmap2.Width));
   if Result=0 then
    Result:=CompareValue(Ord(Bitmap1.Height),Ord(Bitmap2.Height)) else exit;
   if Result=0 then
    Result:=CompareValue(Ord(Bitmap1.StretchFilter),Ord(Bitmap2.StretchFilter)) else exit;
   if Result<>0 then exit;
  end;
 if Result=0 then
  Result:=CompareValue(Ord(Bitmap1.Filter.AType),Ord(Bitmap2.Filter.AType)) else exit;
 if Result=0 then
  Result:=CompareValue(Ord(Bitmap1.Filter.Value),Ord(Bitmap2.Filter.Value)) else exit;
 if Result=0 then
  Result:=CompareValue(Ord(Bitmap1.Filter.Color),Ord(Bitmap2.Filter.Color)) else exit;
 if Result=0 then
  Result:=CompareValue(Ord(Bitmap1.Filter.Color2),Ord(Bitmap2.Filter.Color2)) else exit;
end;

{ TSXSkinPreloadedBitmap }

constructor TSXSkinPreloadedBitmap.Create;
begin
 inherited;
end;

destructor TSXSkinPreloadedBitmap.Destroy;
begin
 Bitmap.Free;
 inherited;
end;

{ TSXSkinPreloadedBitmapList }

function TSXSkinPreloadedBitmapList.Get(const Index:Integer):TSXSkinPreloadedBitmap;
begin
 Result:=TSXSkinPreloadedBitmap(FItem[Index]);
end;

procedure TSXSkinPreloadedBitmapList.Put(const Index:Integer;const Item:TSXSkinPreloadedBitmap);
begin
 FItem[Index]:=Item;
end;

function TSXSkinPreloadedBitmapList.GetCount:Integer;
begin
 Result:=FItem.Count;
end;

procedure TSXSkinPreloadedBitmapList.Add(Bitmap:TSXSkinPreloadedBitmap);
var L,H,A,C:Integer;
begin
 L:=0;
 H:=Count-1;
 while L<=H do
  begin
   A:=(L+H) shr 1;
   C:=CompareBitmaps(Bitmap,Item[A]);
   if C<0 then L:=A+1 else
    begin
     H:=A-1;
     if C=0 then L:=A;
    end;
  end;
 FItem.Insert(L,Bitmap);
end;

function TSXSkinPreloadedBitmapList.GetBitmapIndex(Bitmap:TSXSkinPreloadedBitmap):Integer;
var  A,C:Integer;
     L,H:Integer;
begin
 L:=0;
 H:=Count-1;
 while L<=H do
  begin
   A:=(L+H) shr 1;
   C:=CompareBitmaps(Bitmap,Item[A]);
   if C<0 then L:=A+1 else
    begin
     H:=A-1;
     if C=0 then L:=A;
    end;
  end;
 if (L>=0) and (L<Count) and (CompareBitmaps(Bitmap,Item[L])=0) then
  Result:=L else Result:=-1;
end;

procedure TSXSkinPreloadedBitmapList.Delete(const Index:Integer);
begin
 Item[Index].Free;
 FItem.Delete(Index);
end;

procedure TSXSkinPreloadedBitmapList.Clear;
var A:Integer;
begin
 for A:=0 to Count-1 do
  Item[A].Free;
 FItem.Clear;
end;

constructor TSXSkinPreloadedBitmapList.Create;
begin
 inherited Create;
 FItem:=TList.Create;
end;

destructor TSXSkinPreloadedBitmapList.Destroy;
begin
 Clear;
 FItem.Free;
 inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////

function GetPreloadedBitmap(SkinLibrary:TSXSkinLibrary;
           const FilePath,ZipFilePath:String;Resized:Boolean;Width:Integer;
           Height:Integer;StretchFilter:TSXImageStretchFilter;
           Filter:TSXFilterData):TBitmap32;
var  A,W,H:Integer;
         B:TSXSkinPreloadedBitmap;
        B2:TBitmap32; 
       JPG:TJpegImage;
       PNG:TPNGObject;
        MS:TMemoryStream;
 ImageType:TSXSkinStyleImageType;
   ZipFile:TZipFile;
begin
 B:=TSXSkinPreloadedBitmap.Create;
 B.SkinLibrary:=SkinLibrary;
 B.FilePath:=FilePath;
 B.Resized:=Resized;
 B.Width:=Width;
 B.Height:=Height;
 B.StretchFilter:=StretchFilter;
 B.Filter:=Filter;
 A:=PreloadedBitmaps.GetBitmapIndex(B);
 if A>=0 then
  begin
   Result:=PreloadedBitmaps[A].Bitmap;
   B.Free;
   exit;
  end;
 if Filter.AType<>iftNone then
  begin
   B.Filter.AType:=iftNone;
   B.Filter.Value:=0;
   B.Filter.Color:=0;
   B.Filter.Color2:=0;
   A:=PreloadedBitmaps.GetBitmapIndex(B);
   if A>=0 then
    begin
     B.Filter:=Filter;
     B.Bitmap:=TBitmap32.Create;
     B.Bitmap.Assign(PreloadedBitmaps[A].Bitmap);
     ApplyFilterToBitmap(B.Bitmap,Filter);
     Result:=B.Bitmap;
     PreloadedBitmaps.Add(B);
     exit;
    end;
  end;
 if Resized then
  begin
   B.Resized:=False;
   B.Width:=0; B.Height:=0;
   A:=PreloadedBitmaps.GetBitmapIndex(B);
   if A>=0 then
    begin
     B.Filter:=Filter;
     B.Resized:=True;
     B.Width:=Width; B.Height:=Height;
     W:=Width; H:=Height;
     if W=0 then W:=PreloadedBitmaps[A].Bitmap.Width;
     if H=0 then H:=PreloadedBitmaps[A].Bitmap.Height;
     B.Bitmap:=TBitmap32.Create;
     B.Bitmap.SetSize(W,H);
     B.Bitmap.Clear(0);
     B.Bitmap.DrawMode:=dmBlend;
     B.Bitmap.CombineMode:=cmMerge;
     case StretchFilter of
      isfLinear:   TLinearResampler.Create(PreloadedBitmaps[A].Bitmap);
      else         begin
                    TKernelResampler.Create(PreloadedBitmaps[A].Bitmap);
                    case StretchFilter of
                     isfSpline:   TKernelResampler(PreloadedBitmaps[A].Bitmap.Resampler).
                                   Kernel:=TSplineKernel.Create;
                     isfLanczos:  TKernelResampler(PreloadedBitmaps[A].Bitmap.Resampler).
                                   Kernel:=TLanczosKernel.Create;
                     isfMitchell: TKernelResampler(PreloadedBitmaps[A].Bitmap.Resampler).
                                   Kernel:=TMitchellKernel.Create;
                    end;
                   end;
     end;
     PreloadedBitmaps[A].Bitmap.DrawTo(B.Bitmap,Rect(0,0,W,H));
     TNearestResampler.Create(PreloadedBitmaps[A].Bitmap);
     ApplyFilterToBitmap(B.Bitmap,Filter);
     Result:=B.Bitmap;
     PreloadedBitmaps.Add(B);
     exit;
    end;
  end;
 B.Filter:=Filter;
 B.Resized:=Resized;
 B.Width:=Width;
 B.Height:=Height;
 //
 if SameText(ExtractFileExt(FilePath),'.png') then
  ImageType:=ssitPNG else ImageType:=ssitJPEG;
 case ImageType of
  ssitJPEG: begin
             JPG:=TJpegImage.Create;
             try
              try
               if ZipFilePath<>'' then
                begin
                 MS:=TMemoryStream.Create;
                 try
                  ZipFile:=GetPreloadedZipFile(SkinLibrary,ZipFilePath);
                  if ZipFile<>nil then
                   begin
                    ZipFile.WriteFileToStream(MS,FilePath);
                    MS.Seek(0,soFromBeginning);
                    if MS.Size>0 then
                     JPG.LoadFromStream(MS);
                   end;
                 finally
                  MS.Free;
                 end;
                end else
               if FileExists(FilePath) then
                JPG.LoadFromFile(FilePath);
              except
              end;
              B.Bitmap:=TBitmap32.Create;
              B.Bitmap.Assign(JPG);
             finally
              JPG.Free;
             end;
            end;
  ssitPNG:  begin
             PNG:=TPNGObject.Create;
             try
              try
               if ZipFilePath<>'' then
                begin
                 MS:=TMemoryStream.Create;
                 try
                  ZipFile:=GetPreloadedZipFile(SkinLibrary,ZipFilePath);
                  if ZipFile<>nil then
                   begin
                    ZipFile.WriteFileToStream(MS,FilePath);
                    MS.Seek(0,soFromBeginning);
                    if MS.Size>0 then
                     PNG.LoadFromStream(MS);
                   end;
                 finally
                  MS.Free;
                 end;
                end else
               if FileExists(FilePath) then
                PNG.LoadFromFile(FilePath);
              except
              end;
              B.Bitmap:=TBitmap32.Create;
              PNGObjectToBitmap32(PNG,B.Bitmap);
              if (PNG.Width>0) and (PNG.Header.ColorType in [COLOR_GRAYSCALEALPHA,COLOR_RGBALPHA]) then
               begin
                B.Bitmap.DrawMode:=dmBlend;
                B.Bitmap.CombineMode:=cmMerge;
               end;
             finally
              PNG.Free;
             end;
            end;
 end;
 //
 if Resized then
  begin
   W:=Width; H:=Height;
   if W=0 then W:=B.Bitmap.Width;
   if H=0 then H:=B.Bitmap.Height;
   B2:=TBitmap32.Create;
   B2.SetSize(W,H);
   B2.Clear(0);
   B2.DrawMode:=dmBlend;
   B2.CombineMode:=cmMerge;
   case StretchFilter of
    isfLinear:   TLinearResampler.Create(B.Bitmap);
    else         begin
                  TKernelResampler.Create(B.Bitmap);
                  case StretchFilter of
                   isfSpline:   TKernelResampler(B.Bitmap.Resampler).
                                 Kernel:=TSplineKernel.Create;
                   isfLanczos:  TKernelResampler(B.Bitmap.Resampler).
                                 Kernel:=TLanczosKernel.Create;
                   isfMitchell: TKernelResampler(B.Bitmap.Resampler).
                                 Kernel:=TMitchellKernel.Create;
                  end;
                 end;
   end;
   B.Bitmap.DrawTo(B2,Rect(0,0,W,H));
   B.Bitmap.Free;
   B.Bitmap:=B2;
  end;
 ApplyFilterToBitmap(B.Bitmap,Filter);
 Result:=B.Bitmap;
 PreloadedBitmaps.Add(B);
end;

procedure DeletePreloadedBitmaps(SkinLibrary:TSXSkinCustomLibrary);
var A:Integer;
begin
 for A:=PreloadedBitmaps.Count-1 downto 0 do
  if PreloadedBitmaps[A].SkinLibrary=SkinLibrary then
   PreloadedBitmaps.Delete(A);
end;

initialization

 PreloadedBitmaps:=TSXSkinPreloadedBitmapList.Create;

finalization

 PreloadedBitmaps.Free;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?