16275 lines
441 KiB
Plaintext
16275 lines
441 KiB
Plaintext
(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *)
|
||
(*
|
||
Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved.
|
||
Copyright (c) 2011-2017 by Xequte Software.
|
||
|
||
This software comes without express or implied warranty.
|
||
In no case shall the author be liable for any damage or unwanted behavior of any
|
||
computer hardware and/or software.
|
||
|
||
Author grants you the right to include the component
|
||
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE.
|
||
|
||
ImageEn, IEvolution and ImageEn ActiveX may not be included in any
|
||
commercial, shareware or freeware libraries or components.
|
||
|
||
www.ImageEn.com
|
||
*)
|
||
|
||
(*
|
||
File version 1200
|
||
*)
|
||
|
||
|
||
unit hyieutils;
|
||
|
||
{$IFDEF FPC}
|
||
{$MODE DELPHI}
|
||
{$ENDIF}
|
||
|
||
|
||
{$R-}
|
||
{$Q-}
|
||
|
||
{$I ie.inc}
|
||
|
||
interface
|
||
|
||
uses
|
||
Windows, Messages, Forms, Classes, StdCtrls, Graphics, hyiedefs, SysUtils, Controls, ievision,
|
||
Contnrs;
|
||
|
||
|
||
type
|
||
|
||
{!!
|
||
<FS>TIOFileType
|
||
|
||
<FM>Declaration<FC>
|
||
TIOFileType = integer;
|
||
|
||
<FM>Description<FN>
|
||
Specifies a file format supported by ImageEn (may be read-write, read-only or write-only).
|
||
|
||
<TABLE>
|
||
<R> <H>Constant</H> <H>Description</H> </R>
|
||
<R> <C>ioUnknown</C> <C>Unknown file format</C> </R>
|
||
<R> <C>ioTIFF</C> <C>TIFF Bitmap</C> </R>
|
||
<R> <C>ioGIF</C> <C>GIF</C> </R>
|
||
<R> <C>ioJPEG</C> <C>Jpeg bitmap</C> </R>
|
||
<R> <C>ioPCX</C> <C>PaintBrush PCX</C> </R>
|
||
<R> <C>ioBMP</C> <C>Windows Bitmap</C> </R>
|
||
<R> <C>ioICO</C> <C>Windows Icon</C> </R>
|
||
<R> <C>ioCUR</C> <C>Windows Cursor</C> </R>
|
||
<R> <C>ioPNG</C> <C>Portable Network Graphics</C> </R>
|
||
<R> <C>ioWMF</C> <C>Windows Metafile</C> </R>
|
||
<R> <C>ioEMF</C> <C>Enhanced Windows Metafile</C> </R>
|
||
<R> <C>ioTGA</C> <C>Targa Bitmap</C> </R>
|
||
<R> <C>ioPXM</C> <C>Portable Pixmap, GreyMap, BitMap</C> </R>
|
||
<R> <C>ioJP2</C> <C>Jpeg2000</C> </R>
|
||
<R> <C>ioJ2K</C> <C>Jpeg2000</C> </R>
|
||
<R> <C>ioAVI</C> <C>AVI video</C> </R>
|
||
<R> <C>ioWBMP</C> <C>Wireless bitmap</C> </R>
|
||
<R> <C>ioPS</C> <C>Postscript</C> </R>
|
||
<R> <C>ioPDF</C> <C>Adobe PDF</C> </R>
|
||
<R> <C>ioSVG</C> <C>Scalable Vector Graphics</C> </R>
|
||
<R> <C>ioDCX</C> <C>Multipage PCX</C> </R>
|
||
<R> <C>ioRAW</C> <C>Digital Camera RAW (requires <L ImageEn DLLs and 64bit Support>ielib or ievision</L>)</C> </R>
|
||
<R> <C>ioBMPRAW</C> <C>Bitmap RAW</C> </R>
|
||
<R> <C>ioWMV</C> <C>Windows Media</C> </R>
|
||
<R> <C>ioMPEG</C> <C>Video MPEG</C> </R>
|
||
<R> <C>ioPSD</C> <C>Adobe Photoshop PSD</C> </R>
|
||
<R> <C>ioIEV</C> <C>Vectorial objects (<A TImageEnVect.SaveToFileIEV>)</C> </R>
|
||
<R> <C>ioIEN</C> <C>ImageEn native image format with layers (formerly ioLYR)</C> </R>
|
||
<R> <C>ioALL</C> <C>Combined layers and vectorial objects (<A TImageEnVect.SaveToFileAll>)</C> </R>
|
||
<R> <C>ioDICOM</C> <C>DICOM medical imaging</C> </R>
|
||
<R> <C>ioHDP</C> <C>Microsoft HD Photo. Requires Windows XP (SP2) with .Net 3.0, Windows Vista or newer</C> </R>
|
||
<R> <C>ioOtherDLLPlugIns + offset</C> <C>External plugins (e.g. JBIG)</C> </R>
|
||
<R> <C>ioMiscDLLPlugIns + offset</C> <C>Misc External plugins (e.g. PCL)</C> </R>
|
||
<R> <C>ioUSER + offset</C> <C>User registered file formats</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIOFileType = integer;
|
||
|
||
const
|
||
// types for TIOFileType
|
||
ioUnknown = 0;
|
||
ioTIFF = 1;
|
||
ioGIF = 2;
|
||
ioJPEG = 3;
|
||
ioPCX = 4;
|
||
ioBMP = 5;
|
||
ioICO = 6;
|
||
ioCUR = 7;
|
||
ioPNG = 8;
|
||
ioWMF = 9;
|
||
ioEMF = 10;
|
||
ioTGA = 11;
|
||
ioPXM = 12;
|
||
ioJP2 = 13;
|
||
ioJ2K = 14;
|
||
ioAVI = 15;
|
||
ioWBMP = 16;
|
||
ioPS = 17;
|
||
ioPDF = 18;
|
||
ioDCX = 19;
|
||
ioRAW = 20;
|
||
ioBMPRAW = 21;
|
||
ioWMV = 22;
|
||
ioMPEG = 23;
|
||
ioPSD = 24;
|
||
ioIEV = 25;
|
||
ioIEN = 26; {$ifdef IEIncludeDeprecatedInV6} ioLYR = ioIEN; {$endif}
|
||
ioALL = 27;
|
||
ioDICOM = 28;
|
||
ioHDP = 29;
|
||
ioRAS = 30; // sun RAS (supported by ievision)
|
||
ioSVG = 31;
|
||
ioOtherDLLPlugIns = 4097;
|
||
ioMiscDLLPlugIns = 8192;
|
||
ioUSER = 10000;
|
||
|
||
|
||
// Support PDF loading by WP PDF Plug-In
|
||
const iomscWPPDF = ioMiscDLLPlugIns + 30;
|
||
|
||
// Used only by TImageEnView.LayersImport
|
||
const ioDXF = 9001;
|
||
|
||
type
|
||
{!!
|
||
<FS>TIEMTruncSide
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEMTruncSide = (iemtsLeft, iemtsRight);
|
||
{!!}
|
||
|
||
|
||
{!!
|
||
<FS>TIEDataAccess
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEDataAccess = set of (iedRead, iedWrite);
|
||
{!!}
|
||
|
||
|
||
{!!
|
||
<FS>TIEDitherMethod
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEDitherMethod = (ieOrdered, ieThreshold, ieDithering);
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIEHAlign
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEHAlign = (iehLeft, iehCenter, iehRight);
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIEVAlign
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEVAlign = (ievTop, ievCenter, ievBottom);
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIEPixelFormat
|
||
|
||
<FM>Declaration<FC>
|
||
TIEPixelFormat = (ienull,
|
||
ie1g,
|
||
ie8p,
|
||
ie8g,
|
||
ie16g,
|
||
ie24RGB,
|
||
ie32f,
|
||
ieCMYK,
|
||
ie48RGB,
|
||
ieCIELab,
|
||
ie32RGB);
|
||
|
||
|
||
<FM>Description<FN>
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C><FC>ienull<FN></C> <C>Invalid pixel format.</C> </R>
|
||
<R> <C><FC>ie1g<FN></C> <C>Black/White (1 bit per pixel).</C> </R>
|
||
<R> <C><FC>ie8p<FN></C> <C>RGB color with colormap (256 colors, 8 bit per pixel).</C> </R>
|
||
<R> <C><FC>ie8g<FN></C> <C>Gray scale (256 shades of gray, 8 bit per pixel).</C> </R>
|
||
<R> <C><FC>ie16g<FN></C> <C>Gray scale (65536 shades of gray, 16 bit per pixel).</C> </R>
|
||
<R> <C><FC>ie24RGB<FN></C> <C>RGB true color (16M colors, 24 bit per pixel, 8 bit per channel).</C> </R>
|
||
<R> <C><FC>ie32f<FN></C> <C>Gray scale (0..1 floating point shades of gray, 32 bit per pixel).</C> </R>
|
||
<R> <C><FC>ieCMYK<FN></C> <C>CMYK color (32 bit per pixel, reversed 8 bit per channel).</C> </R>
|
||
<R> <C><FC>ie48RGB<FN></C> <C>RGB color (48 bit per pixel, 16 bit per channel).</C> </R>
|
||
<R> <C><FC>ieCIELab<FN></C> <C>CIELab color (24 bit per pixel, 8 bit per channel).</C> </R>
|
||
<R> <C><FC>ie32RGB<FN></C> <C>RGBA color (32 bit per pixel, 8 bit per channel, for compatibility with Windows DIB pixel format, last 8 bit unused with some exceptions).</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIEPixelFormat = (ienull,
|
||
ie1g, // gray scale (black/white)
|
||
ie8p, // color (palette)
|
||
ie8g, // gray scale (256 levels)
|
||
ie16g, // gray scale (65536 levels)
|
||
ie24RGB, // RGB 24 bit (8 bit per channel)
|
||
ie32f, // floating point values, 32 bit - Single in Pascal - gray scale
|
||
ieCMYK, // CMYK (reversed 8 bit values)
|
||
ie48RGB, // RGB 48 bit (16 bit per channel)
|
||
ieCIELab, // CIELab (8 bit per channel)
|
||
ie32RGB // RGB 32 bit (8 bit per channel), last 8 bit are unused with some exceptions
|
||
);
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIEPixelFormatSet
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEPixelFormatSet = set of TIEPixelFormat;
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIECompareFunction
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIECompareFunction = function(Index1, Index2: integer): integer of object;
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIESwapFunction
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIESwapFunction = procedure(Index1, Index2: integer) of object;
|
||
{!!}
|
||
|
||
|
||
{!!
|
||
<FS>TIEDialogCenter
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEDialogCenter = procedure(Wnd: HWnd);
|
||
{!!}
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TFitMethod
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TFitMethod = (_fmFitWithinRect, // Normal Usage: All the image is made to fit within the available area (with border area)
|
||
_fmFillRect_WithOverlap); // Return an image that may be bigger than the available area but that does not have any border area showing
|
||
{!!}
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIERenderOperation
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIERenderOperation = (
|
||
ielNormal,
|
||
ielAdd, // Additive
|
||
ielSub, // Difference
|
||
ielDiv,
|
||
ielMul,
|
||
ielOR,
|
||
ielAND,
|
||
ielXOR,
|
||
ielMAX, // Lighten
|
||
ielMIN, // Darken
|
||
ielAverage,
|
||
ielScreen,
|
||
ielNegation,
|
||
ielExclusion,
|
||
ielOverlay,
|
||
ielHardLight,
|
||
ielSoftLight,
|
||
ielXFader,
|
||
ielColorEdge,
|
||
ielColorBurn,
|
||
ielInverseColorDodge,
|
||
ielInverseColorBurn,
|
||
ielSoftDodge,
|
||
ielSoftBurn,
|
||
ielReflect,
|
||
ielGlow,
|
||
ielFreeze,
|
||
ielEat,
|
||
ielSubtractive,
|
||
ielInterpolation,
|
||
ielStamp,
|
||
ielRed,
|
||
ielGreen,
|
||
ielBlue,
|
||
ielHue,
|
||
ielSaturation,
|
||
ielColor,
|
||
ielLuminosity,
|
||
ielStereoBW,
|
||
ielStereoColor,
|
||
ielStereoColorDubois,
|
||
ielStereoEven,
|
||
ielStereoOdd,
|
||
ielLuminosity2
|
||
);
|
||
{!!}
|
||
|
||
|
||
{!!
|
||
<FS>TIEOpSys
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEOpSys = (ieosWin95, ieosWin98, ieosWinME, ieosWinNT4, ieosWin2000, ieosWinXP, ieosWin2003, ieosWinVista, ieosWin7, ieosWin8, ieosWin10, ieosUnknown);
|
||
{!!}
|
||
|
||
|
||
TIEShadowType = (iestNone, iestSolid, iestSmooth1, iestSmooth2);
|
||
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TPreviewParams
|
||
|
||
<FM>Declaration<FC>
|
||
type TPreviewParams = set of (ppALL, ppAUTO, ppJPEG, ppTIFF, ppGIF, ppBMP, ppPCX, ppPNG, ppTGA, ppJ2000);
|
||
|
||
<FM>Description<FN>
|
||
Specify which pages are included in the IO Parameters dialog:
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C>ppALL</C> <C>Show all pages</C> </R>
|
||
<R> <C>ppAUTO</C> <C>Show the relevant page for the current file type (i.e. as specified in <L TIOParams.FileType>Params.FileType</L>)</C> </R>
|
||
<R> <C>ppJPEG</C> <C>Show JPEG parameters</C> </R>
|
||
<R> <C>ppTIFF</C> <C>Show TIFF paramaters</C> </R>
|
||
<R> <C>ppGIF</C> <C>Show GIF (non-animated) parameters</C> </R>
|
||
<R> <C>ppBMP</C> <C>Show BMP parameters</C> </R>
|
||
<R> <C>ppPCX</C> <C>Show PCX parameters</C> </R>
|
||
<R> <C>ppPNG</C> <C>Show PNG parameters</C> </R>
|
||
<R> <C>ppTGA</C> <C>Show TGA parameters</C> </R>
|
||
<R> <C>ppJ2000</C> <C>Show JPEG2000 parameters</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TPreviewParams = set of (
|
||
ppALL,
|
||
ppAUTO,
|
||
ppJPEG,
|
||
ppTIFF,
|
||
ppGIF,
|
||
ppBMP,
|
||
ppPCX,
|
||
ppPNG,
|
||
ppTGA
|
||
{$IFDEF IEINCLUDEJPEG2000}
|
||
, ppJ2000
|
||
{$ENDIF}
|
||
);
|
||
|
||
// previews properties
|
||
|
||
{!!
|
||
<FS>TIOPreviewsParamsItems
|
||
|
||
<FM>Declaration<FC>
|
||
TIOPreviewsParamsItems = (ioppDefaultLockPreview, ioppApplyButton);
|
||
|
||
<FM>Description<FN>
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C>ioppDefaultLockPreview</C> <C>Enable "Lock preview" by default</C> </R>
|
||
<R> <C>ioppApplyButton</C> <C>Display an "Apply" button</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Example<FC>
|
||
// Show preview by default
|
||
ImageEnView1.IO.PreviewsParams := ImageEnView1.IO.PreviewsParams + [ ioppDefaultLockPreview ];
|
||
!!}
|
||
TIOPreviewsParamsItems = (ioppDefaultLockPreview, ioppApplyButton);
|
||
|
||
{!!
|
||
<FS>TIOPreviewsParams
|
||
|
||
<FM>Declaration<FC>
|
||
TIOPreviewsParams = set of <A TIOPreviewsParamsItems>;
|
||
|
||
<FM>Description<FN>
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C>ioppDefaultLockPreview</C> <C>Enable "Lock preview" by default</C> </R>
|
||
<R> <C>ioppApplyButton</C> <C>Display an "Apply" button</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Example<FC>
|
||
// Show preview by default
|
||
ImageEnView1.IO.PreviewsParams := ImageEnView1.IO.PreviewsParams + [ ioppDefaultLockPreview ];
|
||
|
||
!!}
|
||
TIOPreviewsParams = set of TIOPreviewsParamsItems;
|
||
|
||
|
||
{!!
|
||
<FS>TImageEnPaletteDialog
|
||
|
||
<FM>Description<FN>
|
||
TImageEnPaletteDialog is a dialog that shows a color palette and allows a color to be selected from it.
|
||
|
||
See also: <A TImageEnProc.CalcImagePalette>
|
||
|
||
<FM>Methods<FN>
|
||
<A TImageEnPaletteDialog.Execute>
|
||
<A TImageEnPaletteDialog.SetPalette>
|
||
!!}
|
||
TImageEnPaletteDialog = class(TForm)
|
||
private
|
||
MouseCol: integer;
|
||
fPalette: PRGBROW;
|
||
fNumCol: integer;
|
||
procedure FormPaint(Sender: TObject);
|
||
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; x, y: integer);
|
||
procedure FormClick(Sender: TObject);
|
||
public
|
||
ButtonCancel: TButton;
|
||
SelCol: TColor;
|
||
property NumCol: integer read MouseCol;
|
||
constructor Create(AOwner: TComponent); override;
|
||
procedure SetPalette(var Palette: array of TRGB; NumCol: integer);
|
||
function Execute: boolean;
|
||
end;
|
||
|
||
|
||
|
||
|
||
TIEWideStrings = class
|
||
private
|
||
fStrings: TList;
|
||
function CreateCopyBuffer(const S: WideString): PWideChar;
|
||
function GetCount: integer;
|
||
function GetString(idx: integer): WideString;
|
||
procedure SetString(idx: integer; const S: WideString);
|
||
public
|
||
constructor Create;
|
||
destructor Destroy; override;
|
||
procedure Clear;
|
||
property Count: integer read GetCount;
|
||
function Add(const S: WideString): integer;
|
||
property Strings[idx: integer]: WideString read GetString write SetString; default;
|
||
end;
|
||
|
||
|
||
|
||
{
|
||
Example:
|
||
var
|
||
dir: TIEDirContent;
|
||
sFilename : WideString;
|
||
begin
|
||
dir := TIEDirContent.Create('C:\images\*.jpg');
|
||
while dir.GetItem(sFilename) do
|
||
begin
|
||
Memo.Lines.Add(sFileName);
|
||
end;
|
||
dir.free;
|
||
end;
|
||
}
|
||
TIEDirContent = class
|
||
private
|
||
fFirstGot : boolean;
|
||
fHandle : THandle;
|
||
fFindData : WIN32_FIND_DATAW;
|
||
fIsDir : boolean;
|
||
fIsHidden : boolean;
|
||
fFileSizeBytes : Int64;
|
||
fCreateDate : TDateTime;
|
||
fEditDate : TDateTime;
|
||
public
|
||
constructor Create(const dir: WideString);
|
||
destructor Destroy; override;
|
||
function GetItem(out sFilename : WideString; bGetFiles: boolean = True; bGetDirs: boolean = False; bGetHidden : Boolean = True): boolean;
|
||
property IsFolder : boolean read fIsDir;
|
||
property IsHiddenFile : boolean read fIsHidden;
|
||
property FileSizeBytes : Int64 read fFileSizeBytes;
|
||
property CreateDate : TDateTime read fCreateDate;
|
||
property EditDate : TDateTime read fEditDate;
|
||
class procedure PopulateStrings(const path: WideString; strings: TStrings; bGetFiles: boolean = True; bGetDirs: boolean = False; bGetHidden : Boolean = True);
|
||
end;
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEExecutor
|
||
//
|
||
// A thread that can be or not be a thread!
|
||
|
||
TIEExecutorFunc = procedure() of object;
|
||
|
||
|
||
|
||
{$HINTS OFF}
|
||
TIEExecutorThread = class(TThread)
|
||
private
|
||
fExecFunc: TIEExecutorFunc;
|
||
constructor Create(execFunc: TIEExecutorFunc);
|
||
procedure Execute(); override;
|
||
end;
|
||
{$HINTS ON}
|
||
|
||
|
||
TIEExecutor = class
|
||
private
|
||
fThread: TIEExecutorThread;
|
||
public
|
||
constructor Create(execInThread: Boolean);
|
||
destructor Destroy(); override;
|
||
procedure Execute(); virtual; abstract;
|
||
function GetThread(): TThread;
|
||
end;
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEThreadPool
|
||
|
||
TIEThreadPool = class
|
||
private
|
||
fThreads: TList;
|
||
function GetThreads(idx: integer): TIEExecutor;
|
||
public
|
||
constructor Create();
|
||
destructor Destroy; override;
|
||
procedure Add(Thread: TIEExecutor);
|
||
procedure Join();
|
||
procedure WaitFor();
|
||
property Threads[idx: integer]: TIEExecutor read GetThreads; default;
|
||
end;
|
||
|
||
// TIEThreadPool
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEDictionary
|
||
|
||
|
||
TIEStrHashFunction = function (const str: WideString; bucketCount: cardinal): cardinal;
|
||
|
||
|
||
TIEDictionaryValueWideString = class
|
||
value: WideString;
|
||
constructor Create(value: WideString);
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
TIEDictionaryValueInteger = class
|
||
value: integer;
|
||
constructor Create(value: integer);
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
TIEDictionaryValueDouble = class
|
||
value: double;
|
||
constructor Create(value: double);
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
TIEDictionaryValueBoolean = class
|
||
value: boolean;
|
||
constructor Create(value: boolean);
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
TIEDictionaryBucket = class
|
||
key: WideString;
|
||
value: TObject;
|
||
next: TIEDictionaryBucket;
|
||
|
||
constructor Create(const key_: WideString; const value_: TObject; next_: TIEDictionaryBucket = nil); overload;
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
TIEStrStrEnumerator = class
|
||
bucket: cardinal;
|
||
item: TIEDictionaryBucket;
|
||
|
||
constructor Create();
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionaryParserLang
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEDictionaryParserLang = (ieplJSON, ieplXML);
|
||
{!!}
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary
|
||
|
||
<FM>Declaration<FC>
|
||
TIEDictionary = class;
|
||
|
||
|
||
<FM>Description<FN>
|
||
TIEDictionary is a String->Object dictionary (hashmap).
|
||
It can import/export key-values in a JSON-like (not fully compatible yet) style.
|
||
|
||
<FM>Methods and Properties<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Create></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Clear></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEDictionary.Count></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Dump></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Erase></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.HasKey></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Get></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetBoolean></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetDictionary></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetDouble></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetInteger></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetList></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetNext></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.GetString></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Insert></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.IsEmpty></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDictionary.Parse></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Example<FC>
|
||
var
|
||
dict: TIEDictionary;
|
||
begin
|
||
dict := TIEDictionary.Create();
|
||
dict.Insert('doublekey', 10.1);
|
||
dict.Insert('integerkey', 100);
|
||
dict.Insert('stringkey', 'hello');
|
||
dict.Insert('bool_true', true);
|
||
dict.Insert('bool_false', false);
|
||
dict.Insert('dict', TIEDictionary.Create());
|
||
dict.GetDictionary('dict').Insert('one', 1);
|
||
dict.GetDictionary('dict').Insert('two', 'two');
|
||
dict.Insert('list', TObjectList.Create());
|
||
dict.GetList('list').Add( TIEDictionaryValueWideString.Create('mike') );
|
||
dict.GetList('list').Add( TIEDictionaryValueWideString.Create('robert') );
|
||
dict.GetList('list').Add( TIEDictionaryValueWideString.Create('john') );
|
||
dict.GetList('list').Add( TIEDictionaryValueInteger.Create(2013) );
|
||
|
||
memo1.lines.add(dict.dump());
|
||
|
||
dict.free;
|
||
end;
|
||
!!}
|
||
TIEDictionary = class
|
||
private
|
||
m_initDone: boolean;
|
||
m_bucketCount: cardinal;
|
||
m_buckets: array of TIEDictionaryBucket;
|
||
m_hashFunction: TIEStrHashFunction;
|
||
m_caseSensitive: boolean;
|
||
m_count: integer;
|
||
|
||
procedure CheckInit();
|
||
function GetInBucket(bucket: cardinal; key: WideString; out lastItem: TIEDictionaryBucket): TIEDictionaryBucket;
|
||
|
||
function DumpJSON(obj: TObject): WideString; overload;
|
||
function DumpJSON(obj: TObjectList): WideString; overload;
|
||
function DumpJSON(): WideString; overload;
|
||
|
||
function DumpXML(obj: TObject): WideString; overload;
|
||
function DumpXML(obj: TObjectList): WideString; overload;
|
||
function DumpXML(): WideString; overload;
|
||
|
||
function EncodeString(Text: WideString): WideString;
|
||
function FindInDictionaries(key: WideString): TObject;
|
||
|
||
function execHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
function keysMatch(const key1: WideString; const key2: WideString): boolean;
|
||
|
||
public
|
||
constructor Create(buckets: cardinal; hashFunction: TIEStrHashFunction; caseSensitive: boolean = false); overload;
|
||
constructor Create(buckets: cardinal = 103; caseSensitive: boolean = false); overload;
|
||
destructor Destroy(); override;
|
||
|
||
procedure Clear();
|
||
function IsEmpty(): boolean;
|
||
function HasKey(key: WideString; recursive: boolean = true): boolean;
|
||
function Get(key: WideString; silent: boolean = false; recursive: boolean = true): TObject;
|
||
function GetString(key: WideString; recursive: boolean = true): WideString;
|
||
function GetInteger(key: WideString; recursive: boolean = true): integer;
|
||
function GetDouble(key: WideString; recursive: boolean = true): double;
|
||
function GetBoolean(key: WideString; recursive: boolean = true): boolean;
|
||
function GetDictionary(key: WideString; recursive: boolean = true): TIEDictionary;
|
||
function GetList(key: WideString; recursive: boolean = true): TObjectList;
|
||
procedure Insert(key: WideString; value: TObject); overload;
|
||
procedure Insert(key: WideString; value: WideString); overload;
|
||
procedure Insert(key: WideString; value: integer); overload;
|
||
procedure Insert(key: WideString; value: double); overload;
|
||
procedure Insert(key: WideString; value: boolean); overload;
|
||
procedure Insert(key: WideString; value: TIEDictionary); overload;
|
||
procedure Insert(key: WideString; value: TObjectList); overload;
|
||
function Erase(key: WideString; freeValue: boolean = true): boolean;
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Count
|
||
|
||
<FM>Declaration<FC>
|
||
property Count: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the number of entries in the dictionary.
|
||
!!}
|
||
property Count: integer read m_Count;
|
||
|
||
function GetNext(current: TIEStrStrEnumerator): boolean;
|
||
|
||
function Dump(dumpType: TIEDictionaryParserLang): WideString;
|
||
function Parse(text: WideString): boolean;
|
||
|
||
procedure Assign(Source: TIEDictionary);
|
||
end;
|
||
|
||
|
||
|
||
TIEDictionaryParser = class
|
||
private
|
||
m_text: WideString;
|
||
m_textLen: integer;
|
||
m_textPos: integer;
|
||
m_abort: boolean;
|
||
m_lang: TIEDictionaryParserLang;
|
||
|
||
procedure AbortParse();
|
||
function IsToken(c: WideChar): boolean;
|
||
function IsSpace(c: WideChar): boolean;
|
||
procedure ByPassSpaces();
|
||
function HasChar(): boolean;
|
||
function GetChar(): WideChar;
|
||
function PeekChar(): WideChar;
|
||
function GetToken(): WideChar;
|
||
function PeekToken(): WideChar;
|
||
function GetString(): WideString;
|
||
function ParseString(): TIEDictionaryValueWideString;
|
||
function ParseIdentifier(): TObject;
|
||
function SavePos(): integer;
|
||
procedure RestorePos(pos: integer);
|
||
function DecodeString(Text: WideString): WideString;
|
||
|
||
function JSON_ParseDictionary(mergeWith: TIEDictionary = nil): TIEDictionary;
|
||
function JSON_ParseValue(): TObject;
|
||
function JSON_ParseArray(): TObjectList;
|
||
|
||
function XML_ParseContent(mergeWith: TIEDictionary = nil): TIEDictionary;
|
||
function XML_GetName(): WideString;
|
||
function XML_ParseAttributes(): TIEDictionary;
|
||
|
||
public
|
||
constructor Create(Text: WideString);
|
||
function Parse(mergeWith: TIEDictionary = nil): TIEDictionary;
|
||
|
||
property Aborted: boolean read m_abort;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEHashStream
|
||
|
||
{!!
|
||
<FS>TIEHashAlgorithm
|
||
|
||
<FM>Declaration<FC>
|
||
TIEHashAlgorithm = (
|
||
iehaMD2, // MD2 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
iehaMD4, // MD4 hashing algorithm.
|
||
iehaMD5, // MD5 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
iehaSHA // SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
);
|
||
!!}
|
||
{$ifdef IEHASCONSTENUM}
|
||
TIEHashAlgorithm = (
|
||
iehaMD2 = $00008001, // MD2 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
iehaMD4 = $00008002, // MD4 hashing algorithm.
|
||
iehaMD5 = $00008003, // MD5 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
iehaSHA = $00008004 // SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
);
|
||
{$else}
|
||
type TIEHashAlgorithm = integer;
|
||
const iehaMD2 = $00008001; // MD2 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
const iehaMD4 = $00008002; // MD4 hashing algorithm.
|
||
const iehaMD5 = $00008003; // MD5 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
const iehaSHA = $00008004; // SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
{$endif}
|
||
|
||
type
|
||
|
||
{!!
|
||
<FS>TIEHashStream
|
||
|
||
<FM>Description<FN>
|
||
Builds a hash string from a stream.
|
||
Hash algorithm can be MD2, MD4, MD5 and SHA.
|
||
|
||
<FM>Examples<FC>
|
||
// saves the file with an unique name (create hash from the jpeg content and use it as file name)
|
||
var
|
||
hashStream: TIEHashStream;
|
||
begin
|
||
hashStream := TIEHashStream.Create(iehaMD5);
|
||
try
|
||
ImageEnView1.IO.SaveToStreamJpeg(hashStream);
|
||
hashStream.SaveToFile(hashStream.GetHash()+'.jpg');
|
||
finally
|
||
hashStream.Free;
|
||
end;
|
||
end;
|
||
|
||
<FM>Methods and Properties<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.Create></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.GetHash></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.LoadFromFile></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.LoadFromStream></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.Write></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.Read></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.Seek></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.SaveToFile></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEHashStream.SaveToStream></C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIEHashStream = class(TStream)
|
||
private
|
||
m_MemStream: TMemoryStream;
|
||
m_CryptProvider: pointer;
|
||
m_CryptHash: pointer;
|
||
public
|
||
constructor Create(Algorithm: TIEHashAlgorithm=iehaMD5; Buffered: boolean=true);
|
||
destructor Destroy; override;
|
||
function GetHash: AnsiString;
|
||
function Write(const Buffer; Count: longint): longint; override;
|
||
function Read(var Buffer; Count: longint): longint; override;
|
||
{$ifdef IEOLDSEEKDEF}
|
||
function Seek(Offset: longint; Origin: word): longint; override;
|
||
{$else}
|
||
function Seek(const Offset: int64; Origin: TSeekOrigin): int64; override;
|
||
{$endif}
|
||
procedure SaveToFile(const filename: WideString);
|
||
procedure SaveToStream(Stream: TStream);
|
||
procedure LoadFromFile(const filename: WideString);
|
||
procedure LoadFromStream(Stream: TStream);
|
||
end;
|
||
|
||
|
||
// TIEHashStream
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
// a memorystream that doesn't create the memory space (and doesn't free it)
|
||
TIEMemStream = class(TCustomMemoryStream)
|
||
public
|
||
constructor Create(Ptr: pointer; Size: integer);
|
||
procedure SetSize(NewSize: Longint); override;
|
||
function Write(const Buffer; Count: Longint): Longint; override;
|
||
end;
|
||
|
||
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEScrollBarParams
|
||
|
||
{!!
|
||
<FS>TIEScrollBarParams
|
||
|
||
<FM>Description<FN>
|
||
Allows an application to customize the scrollbar behavior, including tracking (display refresh on mouse dragging), up/down buttons pixel scroll, pagedown/up pixel scroll.
|
||
|
||
<FM>Properties<FN>
|
||
- <A TIEScrollBarParams.LineStep>
|
||
- <A TIEScrollBarParams.PageStep>
|
||
- <A TIEScrollBarParams.Tracking>
|
||
!!}
|
||
TIEScrollBarParams = class
|
||
private
|
||
fLineStep: integer; // click on up/down/left/right (-1=default size)
|
||
fPageStep: integer; // page step (-1=default size)
|
||
fTracking: boolean; // scroll-bar updates display in real-time (true=default)
|
||
public
|
||
constructor Create;
|
||
destructor Destroy; override;
|
||
|
||
{!!
|
||
<FS>TIEScrollBarParams.LineStep
|
||
|
||
<FM>Declaration<FC>
|
||
property LineStep: integer;
|
||
|
||
<FM>Description<FN>
|
||
Specifies the number of pixels to scroll when the user clicks the Up or Down button on the scroll bar.
|
||
Setting the property to -1 will make the control scroll one thumbnail per click.
|
||
|
||
Default: -1
|
||
!!}
|
||
property LineStep: integer read fLineStep write fLineStep;
|
||
|
||
{!!
|
||
<FS>TIEScrollBarParams.PageStep
|
||
|
||
<FM>Declaration<FC>
|
||
property PageStep: integer;
|
||
|
||
<FM>Description<FN>
|
||
Specifies is the number of pixels to scroll when the user clicks near the cursor (PAGEUP or PAGEDOWN).
|
||
Setting the property to -1 will make the control scroll by one page (i.e. client height) per click.
|
||
|
||
Default: -1
|
||
!!}
|
||
property PageStep: integer read fPageStep write fPageStep;
|
||
|
||
{!!
|
||
<FS>TIEScrollBarParams.Tracking
|
||
|
||
<FM>Declaration<FC>
|
||
property Tracking: boolean
|
||
|
||
<FM>Description<FN>
|
||
Set False to disable display refreshing during mouse dragging.
|
||
|
||
Default: True
|
||
!!}
|
||
property Tracking: boolean read fTracking write fTracking;
|
||
|
||
end;
|
||
|
||
// TIEScrollBarParams
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEMouseWheelParams
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParamsAction
|
||
|
||
<FM>Declaration<FC>
|
||
TIEMouseWheelParamsAction = (iemwNone, iemwVScroll, iemwZoom, iemwNavigate, iemwZoomView);
|
||
|
||
<FM>Description<FN>
|
||
The effect that rolling the mouse wheel has upon a control.
|
||
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C><FC>iemwNone<FN></C> <C>Mouse wheel has no effect</C> </R>
|
||
<R> <C><FC>iemwVScroll<FN></C> <C>Scroll the control up/down</C> </R>
|
||
<R> <C><FC>iemwZoom<FN></C> <C>Enlarge/Reduce the image (TImageEnView) or thumbnails (TImageEnMView)</C> </R>
|
||
<R> <C><FC>iemwZoomView<FN></C> <C>In TImageEnMView this cycles through the <L TImageEnMView.SetStyleEx>common display styles and sizes</L>. With TImageEnView it works the same way as <FC>iemwZoom<FN></C> </R>
|
||
<R> <C><FC>iemwNavigate<FN></C> <C>Navigate to the next/previous image. Note: In <A TImageEnView> this is only relevant for images with multiple frames such as TIFFs and GIFs</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIEMouseWheelParamsAction = (iemwNone, iemwVScroll, iemwZoom, iemwNavigate, iemwZoomView);
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParamsVariation
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEMouseWheelParamsVariation = (iemwAbsolute, iemwPercentage);
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParamsZoomPosition
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEMouseWheelParamsZoomPosition = (iemwCenter, iemwMouse);
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParams
|
||
|
||
<FM>Description<FN>
|
||
Properties to customize the mouse wheel behavior.
|
||
|
||
<FM>Properties<FN>
|
||
- <A TIEMouseWheelParams.InvertDirection>
|
||
- <A TIEMouseWheelParams.Action>
|
||
- <A TIEMouseWheelParams.Variation>
|
||
- <A TIEMouseWheelParams.Value>
|
||
- <A TIEMouseWheelParams.ZoomPosition>
|
||
!!}
|
||
TIEMouseWheelParams = class( TPersistent )
|
||
private
|
||
fInvertDirection: boolean;
|
||
fAction: TIEMouseWheelParamsAction;
|
||
fVariation: TIEMouseWheelParamsVariation;
|
||
fValue: integer;
|
||
fZoomPosition: TIEMouseWheelParamsZoomPosition;
|
||
public
|
||
|
||
procedure Assign(Source: TPersistent); override;
|
||
constructor Create(DefaultAction : TIEMouseWheelParamsAction);
|
||
destructor Destroy; override;
|
||
|
||
published
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParams.InvertDirection
|
||
|
||
<FM>Declaration<FC>
|
||
property InvertDirection: boolean;
|
||
|
||
<FM>Description<FN>
|
||
Set to True to invert the wheel direction.
|
||
|
||
Default: False
|
||
!!}
|
||
property InvertDirection: boolean read fInvertDirection write fInvertDirection default False;
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParams.Action
|
||
|
||
<FM>Declaration<FC>
|
||
property Action: <A TIEMouseWheelParamsAction>;
|
||
|
||
<FM>Description<FN>
|
||
Action specifies the task to perform on mouse wheel events.
|
||
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C><FC>iemwNone<FN></C> <C>Mouse wheel has no effect</C> </R>
|
||
<R> <C><FC>iemwVScroll<FN></C> <C>Scroll the control up/down</C> </R>
|
||
<R> <C><FC>iemwZoom<FN></C> <C>Enlarge/Reduce the image (TImageEnView) or thumbnails (TImageEnMView)</C> </R>
|
||
<R> <C><FC>iemwZoomView<FN></C> <C>In TImageEnMView this cycles through the <L TImageEnMView.SetStyleEx>common display styles and sizes</L>. With TImageEnView it works the same way as <FC>iemwZoom<FN></C> </R>
|
||
<R> <C><FC>iemwNavigate<FN></C> <C>Navigate to the next/previous image. Note: In <A TImageEnView> this is only relevant for images with multiple frames such as TIFFs and GIFs</C> </R>
|
||
</TABLE>
|
||
|
||
TImageEnView default: iemwZoom
|
||
TImageEnMView default: iemwVScroll
|
||
TImageEnMView default (Alt): iemwZoom
|
||
|
||
!!}
|
||
property Action: TIEMouseWheelParamsAction read fAction write fAction; // No default
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParams.Variation
|
||
|
||
<FM>Declaration<FC>
|
||
property Variation: <A TIEMouseWheelParamsVariation>;
|
||
|
||
<FM>Description<FN>
|
||
Specifies how much scrolling or zooming occurs in response to mouse wheel rotation
|
||
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C><FC>iemwAbsolute<FN></C> <C><A TIEMouseWheelParams.Value> contains the absolute value to add or subtract from the current value</C> </R>
|
||
<R> <C><FC>iemwPercentage<FN></C> <C><A TIEMouseWheelParams.Value> contains the percentage of variation from the current value</C> </R>
|
||
</TABLE>
|
||
|
||
Default: iemwPercentage
|
||
|
||
Notes:
|
||
- In the case of <A TImageEnMView>, the height is actually based on a theoretical grid of 12.5 thumbnails high. So if <FC>iemwPercentage<FN> is used 8% equates to scrolling one thumbnail per wheel click, whereas 4% would scroll 1/2 a thumbnail
|
||
- Has no effect if <A TIEMouseWheelParams.Action> is <FC>iemwNavigate<FN>
|
||
!!}
|
||
property Variation: TIEMouseWheelParamsVariation read fVariation write fVariation default iemwPercentage;
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParams.Value
|
||
|
||
<FM>Declaration<FC>
|
||
property Value: integer;
|
||
|
||
<FM>Description<FN>
|
||
Specifies the Value or percentage of variation.
|
||
|
||
<TABLE>
|
||
<R> <H>Setting for <A TIEMouseWheelParams.Variation></H> <H>Description</H> </R>
|
||
<R> <C><FC>iemwAbsolute<FN></C> <C><FC>value<FN> is a specific value to zoom (percentage points) or scroll (pixels) the image</C> </R>
|
||
<R> <C><FC>iemwPercentage<FN></C> <C><FC>value<FN> refers to the percentage to increase or decrease the zoom, or the percentage of the window to scroll (e.g. the default of 8 will scroll the window 8% with each mouse wheel click)</C> </R>
|
||
</TABLE>
|
||
|
||
Default: 8
|
||
|
||
Notes:
|
||
- In the case of <A TImageEnMView>, the height is actually based on a theoretical grid of 12.5 thumbnails high. So if <FC>iemwPercentage<FN> is used 8% equates to scrolling one thumbnail per wheel click, whereas 4% would scroll 1/2 a thumbnail
|
||
- Has no effect if <A TIEMouseWheelParams.Action> is <FC>iemwNavigate<FN>
|
||
|
||
!!}
|
||
property Value: integer read fValue write fValue default 8; // value or percentage of variation
|
||
|
||
{!!
|
||
<FS>TIEMouseWheelParams.ZoomPosition
|
||
|
||
<FM>Declaration<FC>
|
||
property ZoomPosition: <A TIEMouseWheelParamsZoomPosition>;
|
||
|
||
<FM>Description<FN>
|
||
If Action is iemwZoom, ZoomPosition specifies where the zoom acts. The default is the center of the control, otherwise (iemwMouse) zooms from the mouse<73>s position.
|
||
|
||
Default: iemwCenter
|
||
|
||
Note: Has no effect with <A TImageEnMView>
|
||
!!}
|
||
property ZoomPosition: TIEMouseWheelParamsZoomPosition read fZoomPosition write fZoomPosition default iemwCenter;
|
||
end;
|
||
|
||
// TIEMouseWheelParams
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
TIEClientSocket = class
|
||
private
|
||
m_socket: pointer;
|
||
m_littleEndian: boolean;
|
||
function GetConnected: boolean;
|
||
public
|
||
constructor Create;
|
||
destructor Destroy; override;
|
||
// options
|
||
property LittleEndian: boolean read m_littleEndian write m_littleEndian;
|
||
// receive
|
||
procedure ReceiveBuffer(buf: pointer; len: integer);
|
||
function ReceiveBufferSilent(buf: pointer; len: integer): Boolean;
|
||
procedure ReceivePad(len: integer);
|
||
function ReceiveByte(): byte;
|
||
function ReceiveByteSilent(var b: Byte): Boolean;
|
||
function ReceiveWord(): word;
|
||
function ReceiveDWord(): dword;
|
||
// send
|
||
procedure SendBuffer(buf: pointer; len: integer);
|
||
procedure SendPad(len: integer);
|
||
procedure SendByte(value: byte);
|
||
procedure SendWord(value: word);
|
||
procedure SendDWord(value: dword);
|
||
// connect/disconnect
|
||
procedure Connect(const Address: string; Port: word);
|
||
procedure Disconnect();
|
||
property Connected: boolean read GetConnected;
|
||
end;
|
||
|
||
|
||
|
||
TIEByteArray = class
|
||
private
|
||
fSize: integer; // size of datas
|
||
fRSize: integer; // size of allocated buffer
|
||
fBlockSize: integer; // allocation block size
|
||
procedure SetSize(v: integer);
|
||
public
|
||
Data: pbytearray;
|
||
constructor Create(InitBlockSize: integer=8192);
|
||
destructor Destroy; override;
|
||
procedure AddByte(v: byte);
|
||
property Size: integer read fSize write SetSize;
|
||
property BlockSize: integer read fBlockSize write fBlockSize;
|
||
procedure Clear;
|
||
function AppendFromStream(Stream: TStream; Count: integer): integer;
|
||
end;
|
||
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/// TIEIntegerMap (uses integer as keys, integer as values)
|
||
|
||
// handles hash code for numeric values
|
||
TIEIntegerMapItem = class
|
||
key: integer;
|
||
value: integer;
|
||
nextitem: TIEIntegerMapItem; // nil=end of list
|
||
end;
|
||
|
||
TIEIntegerMap = class
|
||
private
|
||
fItems: array of TIEIntegerMapItem;
|
||
fIterateIndex: integer;
|
||
fIterateItem: TIEIntegerMapItem;
|
||
fKeysCount: integer;
|
||
function HashFunc(key: integer): integer;
|
||
public
|
||
constructor Create(bucketsCount: integer = 262144);
|
||
destructor Destroy(); override;
|
||
function Insert(key: integer): boolean; overload;
|
||
function Insert(key: integer; var item: TIEIntegerMapItem): boolean; overload;
|
||
function KeyExists(key: integer): boolean; overload;
|
||
property KeysCount: integer read fKeysCount;
|
||
procedure Clear();
|
||
|
||
function IterateBegin(): boolean;
|
||
function IterateNext(): boolean;
|
||
function IterateGetKey(): integer; overload;
|
||
function IterateGetValue(): integer; overload;
|
||
|
||
function DumpStats(): string;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
// TIERGBMap (uses TRGB as keys, integer as values)
|
||
|
||
TIERGBMap = class(TIEIntegerMap)
|
||
public
|
||
function Insert(const key: TRGB): boolean; overload;
|
||
function Insert(const key: TRGB; value: integer): boolean; overload;
|
||
function KeyExists(const key: TRGB): boolean; overload;
|
||
function IterateGetKey(): TRGB; overload;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
|
||
TNulStream = class(TStream)
|
||
private
|
||
fposition: integer;
|
||
fsize: integer;
|
||
public
|
||
constructor Create;
|
||
destructor Destroy; override;
|
||
function Read(var Buffer; Count: Longint): Longint; override;
|
||
function Write(const Buffer; Count: Longint): Longint; override;
|
||
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/// TIELIST and associated classes
|
||
|
||
TIEListChanges = set of (ielItems, ielRange, ielCurrentValue);
|
||
|
||
TIEListCurrentValueEvent = procedure(Sender: TObject; Value: pointer) of object;
|
||
|
||
{!!
|
||
<FS>TIEListSortCompareFunc
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
TIEListSortCompareFunc = function(Item1, Item2: Pointer): Integer of object;
|
||
{!!}
|
||
|
||
{!!
|
||
<FS>TIEList
|
||
|
||
<FM>Description<FN>
|
||
This is the abstract class for <A TIEDoubleList> and <A TIEIntegerList>.
|
||
|
||
<FM>Implemented Methods<FN>
|
||
<A TIEList.Clear>
|
||
<A TIEList.Delete>
|
||
<A TIEList.Sort>
|
||
<A TIEList.ExchangeItems>
|
||
|
||
<FM>Implemented Properties<FN>
|
||
<A TIEList.Changed>
|
||
<A TIEList.Count>
|
||
!!}
|
||
// abstract class for IE lists
|
||
TIEList = class
|
||
private
|
||
fCapacity: integer;
|
||
fCount: integer;
|
||
fOnGetCurrentValue: TIEListCurrentValueEvent;
|
||
fOnSetCurrentValue: TIEListCurrentValueEvent;
|
||
|
||
procedure ListQuickSort(L, R: Integer; SCompare: TIEListSortCompareFunc);
|
||
protected
|
||
fItemSize: integer; // sizeof(...)
|
||
fData: pointer;
|
||
fChanged: TIEListChanges;
|
||
procedure SetCount(v: integer); virtual;
|
||
function AddItem(v: pointer): integer;
|
||
procedure InsertItem(idx: integer; v: pointer);
|
||
function IndexOfItem(v: pointer): integer;
|
||
function BaseGetItem(idx: integer): pointer;
|
||
procedure BaseSetItem(idx: integer; v: pointer);
|
||
procedure DoGetCurrentValue(value: pointer);
|
||
procedure DoSetCurrentValue(value: pointer);
|
||
constructor Create(OnGetCurrentValue: TIEListCurrentValueEvent = nil; OnSetCurrentValue: TIEListCurrentValueEvent = nil);
|
||
public
|
||
destructor Destroy; override;
|
||
procedure Delete(idx: integer); virtual;
|
||
procedure ExchangeItems(idx1, idx2: integer);
|
||
property Count: integer read fCount write SetCount;
|
||
procedure Clear; virtual;
|
||
procedure Assign(Source: TIEList); virtual;
|
||
procedure Sort(Compare: TIEListSortCompareFunc);
|
||
|
||
{!!
|
||
<FS>TIEList.Changed
|
||
|
||
<FM>Declaration<FC>
|
||
property Changed: TIEListChanges;
|
||
|
||
<FM>Description<FN>
|
||
Changed is True whenever the items array, Range or CurrentValue changes.
|
||
!!}
|
||
property Changed: TIEListChanges read fChanged write fChanged;
|
||
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList
|
||
|
||
<FM>Declaration<FC>
|
||
TIEDoubleList = class(<A TIEList>);
|
||
|
||
<FM>Description<FN>
|
||
TIEDoubleList is a list of double values. You can handle this object as a standard TList object.
|
||
An ImageEn list contains an array of values, a current value (not an index of the array), and an allowed range of values.
|
||
|
||
<FM>Methods and Properties<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIEDoubleList.Add></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDoubleList.Clear></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEDoubleList.CurrentValue></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDoubleList.IndexOf></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEDoubleList.Insert></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEDoubleList.Items></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEDoubleList.RangeMax></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEDoubleList.RangeMin></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEDoubleList.RangeStep></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEList.Changed> (inherited from TIEList)</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIEDoubleList = class(TIEList)
|
||
private
|
||
fRangeMin: double;
|
||
fRangeMax: double;
|
||
fRangeStep: double;
|
||
fCurrentValue: double;
|
||
function GetItem(idx: integer): double;
|
||
procedure SetItem(idx: integer; v: double);
|
||
procedure SetRangeMax(v: double);
|
||
procedure SetRangeMin(v: double);
|
||
procedure SetRangeStep(v: double);
|
||
procedure SetCurrentValue(v: double);
|
||
function GetCurrentValue(): double;
|
||
public
|
||
constructor Create(OnGetCurrentValue: TIEListCurrentValueEvent = nil; OnSetCurrentValue: TIEListCurrentValueEvent = nil); overload;
|
||
function Add(v: double): integer;
|
||
procedure Insert(idx: integer; v: double);
|
||
procedure Clear; override;
|
||
function IndexOf(v: double): integer;
|
||
property RangeMin: double read fRangeMin write SetRangeMin;
|
||
property RangeMax: double read fRangeMax write SetRangeMax;
|
||
property RangeStep: double read fRangeStep write SetRangeStep;
|
||
property Items[idx: integer]: double read GetItem write SetItem; default;
|
||
procedure Assign(Source: TIEList); override;
|
||
property CurrentValue: double read GetCurrentValue write SetCurrentValue;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList
|
||
|
||
<FM>Declaration<FC>
|
||
TIEIntegerList = class(<A TIEList>);
|
||
|
||
<FM>Description<FN>
|
||
TIEIntegerList is a list of integer values. You can handle this object as a standard TList object.
|
||
An ImageEn list contains an array of values, a current value (not an index of the array), and an allowed range of values.
|
||
|
||
<FM>Methods and Properties<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIEIntegerList.Add></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEIntegerList.Clear></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEIntegerList.CurrentValue></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEIntegerList.IndexOf></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEIntegerList.Insert></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEIntegerList.Items></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEIntegerList.RangeMax></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEIntegerList.RangeMin></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEIntegerList.RangeStep></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEList.Changed> (inherited from TIEList)</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIEIntegerList = class(TIEList)
|
||
private
|
||
fRangeMin: integer;
|
||
fRangeMax: integer;
|
||
fRangeStep: integer;
|
||
fCurrentValue: integer;
|
||
function GetItem(idx: integer): integer;
|
||
procedure SetItem(idx: integer; v: integer);
|
||
procedure SetRangeMax(v: integer);
|
||
procedure SetRangeMin(v: integer);
|
||
procedure SetRangeStep(v: integer);
|
||
procedure SetCurrentValue(v: integer);
|
||
function GetCurrentValue(): integer;
|
||
public
|
||
constructor Create(OnGetCurrentValue: TIEListCurrentValueEvent = nil; OnSetCurrentValue: TIEListCurrentValueEvent = nil); overload;
|
||
function Add(v: integer): integer;
|
||
procedure Insert(idx: integer; v: integer);
|
||
procedure Clear; override;
|
||
function IndexOf(v: integer): integer;
|
||
property RangeMin: integer read fRangeMin write SetRangeMin;
|
||
property RangeMax: integer read fRangeMax write SetRangeMax;
|
||
property RangeStep: integer read fRangeStep write SetRangeStep;
|
||
property Items[idx: integer]: integer read GetItem write SetItem; default;
|
||
procedure Assign(Source: TIEList); override;
|
||
property CurrentValue: integer read GetCurrentValue write SetCurrentValue;
|
||
end;
|
||
|
||
TIERecordList = class(TIEList)
|
||
private
|
||
function GetItem(idx: integer): pointer;
|
||
procedure SetItem(idx: integer; v: pointer);
|
||
public
|
||
constructor Create(RecordSize: integer; OnGetCurrentValue: TIEListCurrentValueEvent = nil; OnSetCurrentValue: TIEListCurrentValueEvent = nil); overload;
|
||
function Add(v: pointer): integer;
|
||
procedure Insert(idx: integer; v: pointer);
|
||
function IndexOf(v: pointer): integer;
|
||
property Items[idx: integer]: pointer read GetItem write SetItem; default;
|
||
end;
|
||
|
||
|
||
/// TIELIST and associated classes
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
TIETemporaryFileStream = class(THandleStream)
|
||
private
|
||
FHandle: THandle;
|
||
public
|
||
constructor Create(const FileName: string);
|
||
destructor Destroy; override;
|
||
end;
|
||
|
||
TIEWideFileStream = class(THandleStream)
|
||
private
|
||
FFileName: WideString;
|
||
public
|
||
constructor Create(const FileName: WideString; Mode: Word);
|
||
destructor Destroy; override;
|
||
property FileName: WideString read FFileName;
|
||
end;
|
||
|
||
TIEFileBufferItem = record
|
||
Pos: int64; // buffer position inside the file
|
||
Size: int64; // buffer size
|
||
ptr: pointer; // allocated buffer
|
||
access: TIEDataAccess;
|
||
end;
|
||
PIEFileBufferItem = ^TIEFileBufferItem;
|
||
|
||
// emulates a memory mapped file
|
||
TIEFileBuffer = class
|
||
private
|
||
function IndexOf(ptr: pointer): integer;
|
||
public
|
||
fSimFile: TStream; // 3.0.3, can be TIETemporaryFileStream or TMemoryStream
|
||
fFileName: string;
|
||
fMapped: TList; // list of TIEFileBufferItem structures
|
||
|
||
constructor Create;
|
||
destructor Destroy; override;
|
||
function AllocateFile(InSize: int64; const Descriptor: string; UseDisk: boolean): boolean;
|
||
procedure ReAllocateFile(NewSize: int64);
|
||
function Map(InPos, InSize: int64; DataAccess: TIEDataAccess): pointer;
|
||
procedure UnMap(ptr: pointer);
|
||
procedure UnMapAll;
|
||
function IsAllocated: boolean;
|
||
procedure DeAllocate;
|
||
procedure CopyTo(Dest: TIEFileBuffer; InPos, InSize: int64); overload;
|
||
procedure CopyTo(Dest: TStream; InPos, InSize: int64); overload;
|
||
procedure CopyFrom(DestPos: int64; Source: pointer; Size: int64);
|
||
end;
|
||
|
||
|
||
{$ifdef IEINCLUDERESOURCEEXTRACTOR}
|
||
|
||
{!!
|
||
<FS>TIEResourceBookmark
|
||
|
||
<FM>Demo<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_DEMO> <C>Demos\InputOutput\ResourceLoader\ResourceLoader.dpr </C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Methods and properties<FN>
|
||
- <A TIEResourceBookmark.TypeIndex>
|
||
- <A TIEResourceBookmark.NameIndex>
|
||
- <A TIEResourceBookmark.FrameIndex>
|
||
!!}
|
||
TIEResourceBookmark = class
|
||
private
|
||
m_TypeIndex: integer;
|
||
m_NameIndex: integer;
|
||
m_FrameIndex: integer;
|
||
|
||
public
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceBookmark.TypeIndex
|
||
|
||
<FM>Declaration<FC>
|
||
property TypeIndex: integer;
|
||
|
||
<FM>Description<FN>
|
||
Resource type index of this bookmark.
|
||
!!}
|
||
property TypeIndex: integer read m_TypeIndex;
|
||
|
||
{!!
|
||
<FS>TIEResourceBookmark.NameIndex
|
||
|
||
<FM>Declaration<FC>
|
||
property NameIndex: integer;
|
||
|
||
<FM>Description<FN>
|
||
Resource name index of this bookmark.
|
||
!!}
|
||
property NameIndex: integer read m_NameIndex;
|
||
|
||
{!!
|
||
<FS>TIEResourceBookmark.FrameIndex
|
||
|
||
<FM>Declaration<FC>
|
||
property FrameIndex: integer;
|
||
|
||
<FM>Description<FN>
|
||
Frame index of a grouped resource of this bookmark.
|
||
!!}
|
||
property FrameIndex: integer read m_FrameIndex;
|
||
|
||
constructor Create(TypeIndex_, NameIndex_, FrameIndex_: integer);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor
|
||
|
||
<FM>Description<FN>
|
||
TIEResourceExtractor class helps to extract resources from a PE files like EXE, DLL, OCX, ICL, BPL, etc..
|
||
In details, it is intended to extract Icons, Bitmaps, Cursors and other image resources.
|
||
|
||
<FM>Demo<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_DEMO> <C>Demos\InputOutput\ResourceLoader\ResourceLoader.dpr </C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Example<FC>
|
||
// loads resource 143, in "Bitmap"s, from "explorer.exe" (should be a little Windows logo)
|
||
var
|
||
re: TIEResourceExtractor;
|
||
buffer: pointer;
|
||
bufferLen: integer;
|
||
begin
|
||
re := TIEResourceExtractor.Create('explorer.exe');
|
||
try
|
||
buffer := re.GetBuffer('Bitmap', 'INTRESOURCE:143', bufferLen);
|
||
ImageEnView1.IO.Params.IsResource := true;
|
||
ImageEnView1.IO.LoadFromBuffer(buffer, bufferLen, ioBMP);
|
||
finally
|
||
re.Free;
|
||
end;
|
||
end;
|
||
|
||
<FM>Methods and Properties<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIEResourceExtractor.Create></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.FriendlyTypes></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEResourceExtractor.GetBuffer></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEResourceExtractor.GetFrameBuffer></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEResourceExtractor.GetGroupAndFrame></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEResourceExtractor.GetResourceBookmark></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.GroupCountFrames></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.GroupFrameDepth></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.GroupFrameHeight></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.GroupFrameName></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.GroupFrameWidth></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIEResourceExtractor.IndexOfType></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.IsGroup></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.IsGrouped></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.IsValid></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.Names></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.NamesCount></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.TypesCount></C> </R>
|
||
<R> <C_IMG_PROPERTY> <C><A TIEResourceExtractor.Types></C> </R>
|
||
</TABLE>
|
||
|
||
!!}
|
||
TIEResourceExtractor = class
|
||
private
|
||
m_hlib: THandle;
|
||
m_typesList: TStringList;
|
||
m_resourceBookmarks: TList;
|
||
function GetTypesCount: integer;
|
||
function GetNamesCount(TypeIndex: integer): integer;
|
||
function GetTypes(TypeIndex: integer): AnsiString;
|
||
function GetNames(TypeIndex: integer; NameIndex: integer): AnsiString;
|
||
function GetFriendlyTypes(TypeIndex: integer): AnsiString;
|
||
function GetIsValid: boolean;
|
||
function GetGroupCountFrames(TypeIndex: integer; NameIndex: integer): integer;
|
||
function GetGroupFrameWidth(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): integer;
|
||
function GetGroupFrameHeight(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): integer;
|
||
function GetGroupFrameDepth(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): integer;
|
||
function GetGroupFrameName(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): AnsiString;
|
||
function GetIsGroup(TypeIndex: integer): boolean;
|
||
function GetIsGrouped(TypeIndex: integer): boolean;
|
||
public
|
||
constructor Create(const Filename: WideString);
|
||
destructor Destroy; override;
|
||
property TypesCount: integer read GetTypesCount;
|
||
property Types[TypeIndex: integer]: AnsiString read GetTypes;
|
||
property FriendlyTypes[TypeIndex: integer]: AnsiString read GetFriendlyTypes;
|
||
property NamesCount[TypeIndex: integer]: integer read GetNamesCount;
|
||
property Names[TypeIndex: integer; NameIndex: integer]: AnsiString read GetNames;
|
||
function GetBuffer(TypeIndex: integer; NameIndex: integer; var BufferLength: integer): pointer; overload;
|
||
function GetBuffer(const TypeStr: AnsiString; const NameStr: AnsiString; var BufferLength: integer): pointer; overload;
|
||
function GetBuffer(ResourceBookmark: TIEResourceBookmark; var BufferLength: integer): pointer; overload;
|
||
property IsValid: boolean read GetIsValid;
|
||
property IsGroup[TypeIndex: integer]: boolean read GetIsGroup;
|
||
property IsGrouped[TypeIndex: integer]: boolean read GetIsGrouped;
|
||
property GroupCountFrames[TypeIndex: integer; NameIndex: integer]: integer read GetGroupCountFrames; // number of frames for specified icon/cursor
|
||
property GroupFrameWidth[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: integer read GetGroupFrameWidth;
|
||
property GroupFrameHeight[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: integer read GetGroupFrameHeight;
|
||
property GroupFrameDepth[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: integer read GetGroupFrameDepth;
|
||
property GroupFrameName[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: AnsiString read GetGroupFrameName;
|
||
procedure GetGroupAndFrame(TypeIndex: integer; NameIndex: integer; var GroupTypeIndex: integer; var GroupIndex: integer; var GroupFrameIndex: integer);
|
||
function IndexOfType(TypeName: AnsiString): integer;
|
||
function GetFrameBuffer(TypeIndex: integer; NameIndex: integer; FrameIndex: integer; var BufferLength: integer): pointer;
|
||
function GetResourceBookmark(TypeIndex: integer; NameIndex: integer; FrameIndex: integer = -1): TIEResourceBookmark;
|
||
end;
|
||
|
||
{$endif} // IEINCLUDERESOURCEEXTRACTOR
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// Xorshift pseudo number generator by George Marsaglia
|
||
//type
|
||
TIERandomGenerator = class
|
||
private
|
||
x, y, z, w: dword;
|
||
public
|
||
constructor Create(Seed: dword); overload;
|
||
constructor Create(Seed: AnsiString); overload;
|
||
constructor Create(Seed1, Seed2, Seed3, Seed4: dword); overload;
|
||
function NextDWORD(): dword;
|
||
function NextINT64(): int64;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
TIE8087ExceptionsDisabler = class
|
||
private
|
||
FPUControlWord: Word;
|
||
public
|
||
constructor Create();
|
||
destructor Destroy(); override;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEStringSplitter
|
||
// Another way to split a string using delimiters
|
||
// Use inplace of TStringList.DelimitedText, when possible
|
||
|
||
TIEStringSplitter = class
|
||
private
|
||
procedure SetText(const Text: string);
|
||
function GetText(): string;
|
||
function GetString(Index: integer): string;
|
||
function GetCount(): integer;
|
||
function GetDelimiters(): string;
|
||
procedure SetDelimiters(const Value: string);
|
||
function GetBypassSpaces(): boolean;
|
||
procedure SetBypassSpaces(Value: boolean);
|
||
function IsSpace(c: char): boolean;
|
||
|
||
protected
|
||
procedure Update();
|
||
|
||
public
|
||
constructor Create(const Text: string = ''; const Delimiters: string = ' ');
|
||
destructor Destroy(); override;
|
||
|
||
property Text: string read GetText write SetText;
|
||
property Strings[Index: integer]: string read GetString; default;
|
||
property Count: integer read GetCount;
|
||
property Delimiters: string read GetDelimiters write SetDelimiters;
|
||
property BypassSpaces: boolean read GetBypassSpaces write SetBypassSpaces;
|
||
|
||
private
|
||
m_text: string;
|
||
m_strings: TStringList;
|
||
m_delimiters: string;
|
||
m_bypassSpaces: boolean;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
// Functions
|
||
|
||
function _GetBitCount(b: Integer): Integer;
|
||
function IEGetFirstSetBit(b: Integer): Integer;
|
||
function _NColToBitsPixel(NCol: integer): integer;
|
||
function IEBitmapRowLen(Width: integer; BitCount: integer; align: integer): int64;
|
||
function IEVCLPixelFormat2RowLen(Width: integer; PixelFormat: TPixelFormat): integer;
|
||
function IEVCLPixelFormat2BitCount(PixelFormat: TPixelFormat): integer;
|
||
function IEBitCount2VCLPixelformat(Bitcount: integer): TPixelFormat;
|
||
function IEVCLPixelFormat2ImageEnPixelFormat(PixelFormat: TPixelFormat): TIEPixelFormat;
|
||
function IEPixelFormat2BitCount(PixelFormat: TIEPixelFormat): integer;
|
||
function IEPixelFormat2ChannelCount(PixelFormat: TIEPixelFormat): integer;
|
||
|
||
{$ifdef IEUSEASM}
|
||
procedure ReverseBits(var inp: dword); assembler;
|
||
{$else}
|
||
procedure ReverseBits(var inp: dword);
|
||
{$endif}
|
||
|
||
procedure ReverseBitsB(var inp: byte);
|
||
procedure _CastPolySelCC(const x1, y1: integer; var x2, y2: integer);
|
||
function _RectXRect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2: integer): boolean;
|
||
function _RectPRect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2: integer): integer;
|
||
function IEPointInRect(xx, yy, x1, y1, x2, y2: integer): boolean; overload;
|
||
function IEPointInRect(xx, yy : integer; ARect: TRect): boolean; overload;
|
||
function _InRectO(xx, yy, x1, y1, x2, y2: integer): boolean;
|
||
function IEGetFileSize(const FileName: string): int64;
|
||
function PromptForColor(var AColor : TColor): Boolean;
|
||
procedure IESaveStringToStream(Stream: TStream; const ss: AnsiString); overload;
|
||
procedure IELoadStringFromStream(Stream: TStream; var ss: AnsiString); overload;
|
||
{$IfDef UNICODE}
|
||
procedure IESaveStringToStream(Stream: TStream; const ss: UnicodeString); overload;
|
||
procedure IELoadStringFromStream(Stream: TStream; var ss: UnicodeString); overload;
|
||
{$EndIf}
|
||
procedure IESaveStringToStreamW(Stream: TStream; const ss: widestring);
|
||
procedure IELoadStringFromStreamW(Stream: TStream; var ss: widestring); overload;
|
||
procedure IELoadStringFromStreamW(Stream: TStream; var ss: String); overload;
|
||
procedure IESaveStringListToStream(Stream: TStream; sl: TStringList);
|
||
procedure IELoadStringListFromStream(Stream: TStream; sl: TStringList);
|
||
|
||
procedure IELoadFontFromStream(Stream: TStream; var Font: TFont);
|
||
procedure IESaveFontToStream(Stream: TStream; const Font: TFont);
|
||
|
||
function _GetNumCol(BitsPerSample: integer; SamplesPerPixel: integer): integer;
|
||
function iemsg(const msg: TMsgLanguageWords): WideString;
|
||
|
||
procedure IESetTranslationWord(const lang: TMsgLanguage; const msg: TMsgLanguageWords; const trans: AnsiString);
|
||
procedure IESetTranslationWordU(const lang: TMsgLanguage; const msg: TMsgLanguageWords; const trans: string);
|
||
|
||
function _DistPoint2Line(xp, yp, x1, y1, x2, y2: integer): double;
|
||
function _DistPoint2Seg(xp, yp, x1, y1, x2, y2: integer): double;
|
||
function _DistPoint2Point(x1, y1, x2, y2: integer): double;
|
||
function IEDDistPoint2Point(x1, y1, x2, y2: double): double;
|
||
function _DistPoint2Polyline(x, y: integer; PolyPoints: PPointArray; PolyPointsCount: integer; ToSubX, ToSubY, ToAddX, ToAddY: integer; ToMulX, ToMulY: double; penWidth: integer; closed: boolean): double;
|
||
function IEDistPoint2Ellipse(x, y, x1, y1, x2, y2: integer; filled: boolean; penWidth: integer): double;
|
||
function IEDist2Box(x, y, x1, y1, x2, y2: integer; filled: boolean; penWidth: integer): double;
|
||
function IEDistParallelLines(FirstLinePointA: TIE2DPoint; FirstLinePointB: TIE2DPoint; SecondLinePoint: TIE2DPoint): double;
|
||
function IESignedTriangleArea(Point1: TIE2DPoint; Point2: TIE2DPoint; Point3: TIE2DPoint): double;
|
||
procedure IEOrthogonalTranslate(OrigSegmentA, OrigSegmentB: TIE2DPoint; Point: TIE2DPoint; out OffsetX: double; out OffsetY: double);
|
||
|
||
function IEMMXSupported: bytebool;
|
||
//procedure IEMul64(op1, op2: dword; resultlo: pdword; resulthi: pdword);
|
||
//function IEAdd64(op1_lo, op1_hi, op2_lo, op2_hi: dword; result_lo, result_hi: pdword): integer;
|
||
//function IEGreater64(op1_lo, op1_hi, op2_lo, op2_hi: dword): boolean;
|
||
procedure SafeStreamWrite(Stream: TStream; var Aborting: boolean; const Buffer; Count: Longint);
|
||
// procedure IEBitmapMapXCopy(map: pbyte; maprowlen: dword; mapbitcount: dword; bitmap: TBitmap; mapx, mapy, bitmapx, bitmapy, dx, dy: dword; dir: integer);
|
||
function IEPower2(const Base, Exponent: Double): Double;
|
||
function IESwapWord(i: word): word;
|
||
function IESwapDWord(i: integer): integer;
|
||
function IESwapInt64(i: int64): int64;
|
||
|
||
procedure IESwap(var a: integer; var b: integer); overload;
|
||
procedure IESwap(var a: double; var b: double); overload;
|
||
procedure IESwap(var a: boolean; var b: boolean); overload;
|
||
procedure IESwap(var a: TIELayerMagnification; var b: TIELayerMagnification); overload;
|
||
procedure IESwap(var a: TIERenderOperation; var b: TIERenderOperation); overload;
|
||
procedure IESwap(var a: pointer; var b: pointer); overload;
|
||
procedure IESwap(var a: TResampleFilter; var b: TResampleFilter); overload;
|
||
procedure IESwap(var a: AnsiString; var b: AnsiString); overload;
|
||
{$IfDef UNICODE}
|
||
procedure IESwap(var a: UnicodeString; var b: UnicodeString); overload;
|
||
{$EndIf}
|
||
procedure IESwap(var a: TGuid; var b: TGuid); overload;
|
||
procedure IESwap(var a: TRGB; var b: TRGB); overload;
|
||
procedure IESwap(var a: TIEArrayOfTRGB; var b: TIEArrayOfTRGB); overload;
|
||
procedure IESwap(var a: TRect; var b: TRect); overload;
|
||
procedure IESwap(var a: TIEShape; var b: TIEShape); overload;
|
||
procedure IESwap(var a: TColor; var b: TColor); overload;
|
||
procedure IESwap(var a: TFont; var b: TFont); overload;
|
||
procedure IESwap(var a: TPoint; var b: TPoint); overload;
|
||
|
||
procedure IEChangeEndiannessWordArray(buffer: pword; items: integer);
|
||
procedure IEChangeEndiannessDWordArray(buffer: pdword; items: integer);
|
||
|
||
procedure IERightShadow(Canvas: TCanvas; DestBitmap: TBitmap; x1, y1, x2, y2: integer; st: TIEShadowType; dstColor: TColor);
|
||
procedure IEBottomShadow(Canvas: TCanvas; DestBitmap: TBitmap; x1, y1, x2, y2: integer; st: TIEShadowType; dstColor: TColor);
|
||
procedure IERectShadow(Bitmap: TBitmap; x1, y1, x2, y2: integer; dstColor: TColor);
|
||
function IEFloatToStrA(Value: Extended): AnsiString;
|
||
function IEFloatToStrW(Value: Extended): WideString;
|
||
function IEFloatToStrS(Value: Extended): string;
|
||
function IEFindHandle(cmp: TComponent): HWND;
|
||
procedure DrawDibDrawEmu(hdd: THandle; hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer; wFlags: UInt);
|
||
procedure DrawDib(hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer);
|
||
function IEDrawDibClose(hdd: hDrawDib): Boolean;
|
||
function IEDrawDibDraw(hdd: hDrawDib; hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer; wFlags: UInt): Boolean;
|
||
function IEDrawDibOpen: hDrawDib;
|
||
function IEDrawDibRealize(hdd: hDrawDib; hDC: THandle; fBackground: Bool): UInt;
|
||
procedure IECenterWindow(Wnd: HWnd);
|
||
procedure IEResetPrinter;
|
||
function IEStrToFloatDefA(s: AnsiString; Def: extended): extended;
|
||
function IEStrToFloatDefW(s: WideString; Def: extended): extended;
|
||
function IEStrToFloatDefS(s: String; Def: extended): extended;
|
||
function IEStrToFloatDef(s: String; Def: extended): extended;
|
||
function IERGB2CIELAB(rgb: TRGB): TCIELAB;
|
||
function IECIELAB2RGB(const lab: TCIELAB): TRGB;
|
||
procedure IEDraw3DRect(Canvas: TCanvas; x1, y1, x2, y2: integer; cl1, cl2: TColor);
|
||
procedure IEDraw3DRect2(Canvas: TObject; x1, y1, x2, y2: integer; cl1, cl2: TColor);
|
||
procedure IEDrawHint(Canvas: TCanvas; var x, y: integer; const ss: string; Font: TFont; Brush: TBrush; var SaveBitmap: TBitmap; MaxWidth, MaxHeight: integer; Border1, Border2: TColor);
|
||
procedure IEDrawHint2(Canvas: TCanvas; var x, y: integer; const ss: string; const minText: string);
|
||
function IEDirectoryExists(const Name: string): Boolean;
|
||
procedure IEForceDirectories(Dir: string);
|
||
function IEGetMemory(freememory: boolean): int64;
|
||
procedure IECalcUnitsPerPixel(DpiX, DpiY: Integer; mu: TIEUnits; out cx, cy: double);
|
||
procedure IESetPlim(var plim: trect; x, y: integer);
|
||
function IEAngle(x1, y1, x2, y2, x3, y3: double): double;
|
||
function IEAngle2(x1, y1, x2, y2: integer): double;
|
||
function IEAngle3(x1, y1, xc, yc, x2, y2: integer): double;
|
||
function IEGetReferenceAngle(Angle: double): double;
|
||
function IEArcCos(X: Extended): Extended;
|
||
function IEDegreesToRadians(Angle: Double): Double;
|
||
function IERadiansToDegrees(Rad: Double): Double;
|
||
function IEExtractStylesFromLogFont(logfont: PLogFontA): TFontStyles;
|
||
function IEExtractStylesFromLogFontW(logfont: PLogFontW): TFontStyles;
|
||
procedure IECopyLogFont(src: PLogFontA; dst: PLogFontW);
|
||
function IEConvertGUIDToString(g: PGUID): AnsiString;
|
||
function CompareGUID(const g1, g2: TGuid): boolean;
|
||
procedure IEConvertAStringToGUID(invar: AnsiString; gg: PGUID);
|
||
procedure IEConvertWStringToGUID(invar: WideString; gg: PGUID);
|
||
procedure IEGetFitResampleSize(owidth, oheight, fwidth, fheight: integer; out rwidth, rheight: integer);
|
||
procedure IEGetFitResampleSizeWithAutoCrop(iImageWidth, iImageHeight, iAvailableWidth, iAvailableHeight: integer; out RWidth, RHeight: integer;
|
||
iAutoCropPercent : Integer; out RAutoWidth, RAutoHeight: integer);
|
||
function IEIsRemoteSession(): boolean;
|
||
|
||
|
||
// timeout support
|
||
function IESetupTimeout(): dword;
|
||
function IEIsTimeoutExpired(startTime: dword; timeout: dword): boolean;
|
||
|
||
procedure IERotatePoints(var rpt: array of TPoint; PointCount: Integer; angle: double; CenterX, CenterY: integer);
|
||
procedure IEDRotatePoints(var rpt: array of TIE2DPoint; angle: double);
|
||
procedure IEDRotatePointsWithCenter(var rpt: array of TIE2DPoint; angle: double; CenterX, CenterY: double);
|
||
procedure IEDRotateTwoPoints(Angle: double; const P1: TIE2DPoint; const P2: TIE2DPoint; out OutP1: TIE2DPoint; out OutP2: TIE2DPoint);
|
||
procedure IERotatePoint(var px, py: integer; angle: double; CenterX, CenterY: integer);
|
||
procedure IEDRotatePoint(var px, py: double; angle: double; CenterX, CenterY: double);
|
||
function IECalcRotatedRectBoundingBox(Rectangle: TIEDRectangle; RotationCenter: TIE2DPoint; RotationAngle: double): TIEDRectangle;
|
||
procedure IECalcRotatedBitmapSizes(Width, Height: integer; RotationCenter: TIE2DPoint; RotationAngle: double; out NewWidth: integer; out NewHeight: integer);
|
||
procedure IERotateBits(Bits: TIEArrayOfByte; Width, Height: integer; RowAlignment: integer; RotationCenter: TIE2DPoint; RotationAngle: double; Background: integer; MaintainOriginalSize: boolean; out outBits: TIEArrayOfByte; out outWidth: integer; out outHeight: integer);
|
||
|
||
procedure IEGetPointsRange(rpt: array of TPoint; PointCount: Integer; out MinX: Integer; out MinY: Integer; out MaxX: Integer; out MaxY: Integer);
|
||
procedure IEScalePoints(var rpt: array of TPoint; PointCount: Integer; MinX, MinY, MaxX, MaxY: Integer; MaintainAR: Boolean = False);
|
||
|
||
function IECalcOrthogonalLinesIntersectingPoint(FirstLinePoint: TIE2DPoint; FirstLineSlope: double; SecondLinePoint: TIE2DPoint): TIE2DPoint;
|
||
|
||
function IECalcPolygonCentroid(polygon: array of TIE2DPoint): TIE2DPoint;
|
||
|
||
function IECreateRotatedCursor(CursorIntResource: integer; RotationAngle: double): HCURSOR;
|
||
|
||
procedure IECenterRectInRect(OuterRectX1, OuterRectY1, OuterRectX2, OuterRectY2: integer; var InnerRectX1: integer; var InnerRectY1: integer; var InnerRectX2: integer; var InnerRectY2: integer);
|
||
procedure CalcLineWithinRect(R: TRect; Angle: Integer; out Pt1, Pt2: TPoint);
|
||
function OffsetPoint(Pt: TPoint; Dist: Double; Angle: Double) : TPoint;
|
||
|
||
function IEISPointInPoly(x, y: integer; poly: array of TPoint): boolean;
|
||
function IEDISPointInPoly(x, y: double; poly: array of TIE2DPoint): boolean;
|
||
function IEISPointInPoly2(x, y: integer; PolyPoints: PPointArray; PolyPointsCount: integer; ToSubX, ToSubY, ToAddX, ToAddY: integer; ToMulX, ToMulY: double): boolean;
|
||
|
||
function IEASCII85EncodeBlock(var inbytes: pbyte; buflen: integer; var outstr: PAnsiChar; var asciilen: integer): integer;
|
||
function IEASCII85DecodeBlock(var instr: PAnsiChar; buflen: integer; var outbytes: pbyte): integer;
|
||
function IEPSRunLengthEncode(inbytes: pbytearray; inlen: integer; outbytes: pbytearray): integer;
|
||
procedure IEWriteStrLn(s: TStream; ss: AnsiString);
|
||
function IECopyFrom(Dest: TStream; Source: TStream; Count: int64): int64;
|
||
|
||
function IEStrLen(const Str: PAnsiChar): Cardinal;
|
||
function IEStrLenW(Str: PWideChar): Cardinal;
|
||
function IEStrCopy(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar;
|
||
function IEStrCopyW(Dest: PWideChar; Source: PWideChar): PWideChar;
|
||
function IEStrPCopy(Dest: PAnsiChar; const Source: AnsiString): PAnsiChar;
|
||
function IEStrPCopyW(Dest: PWideChar; const Source: WideString): PWideChar;
|
||
function IEStrPCopyWA(Dest: PWideChar; Source: TIEArrayOfAnsiChar): PWideChar;
|
||
function IEStrMove(Dest: PAnsiChar; const Source: PAnsiChar; Count: Cardinal): PAnsiChar;
|
||
function IEAnsiStrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
|
||
function IEStrScan(const Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
|
||
function IEStrRScan(const Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
|
||
function IETextToFloat(Buffer: PAnsiChar; var Value; ValueType: TFloatValue): Boolean; overload;
|
||
|
||
function IEGetDecimalSeparator: Char;
|
||
procedure IESetDecimalSeparator(c: Char);
|
||
|
||
|
||
function IEOpenClipboard: boolean;
|
||
|
||
procedure IEDrawGrayedOut(Canvas: TCanvas; XDst, YDst, WidthDst, HeightDst: integer; SX1, SY1, SX2, SY2: integer);
|
||
|
||
{!!
|
||
<FS>IEGetCoresCount
|
||
|
||
<FM>Declaration<FC>
|
||
function IEGetCoresCount(): integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the total amount of processor's cores present on the system.
|
||
|
||
Some Windows operating system versions cannot communicate this information, so it defaults to <A TIEImageEnGlobalSettings.DefaultCoresCount>.
|
||
!!}
|
||
function IEGetCoresCount(): integer;
|
||
|
||
|
||
function IEGetRequiredThreads(ImageWidth, ImageHeight: integer): integer;
|
||
|
||
|
||
procedure IEEncode64(SrcStream: TStream; DstStream: TStream; linesize: integer); overload;
|
||
function IEEncode64(SrcBuffer: pbyte; SrcBufferLength: integer; linesize: integer): AnsiString; overload;
|
||
procedure IEDecode64(SrcStream: TStream; DstStream: TStream); overload;
|
||
function IEDecode64(SrcString: AnsiString): TIEArrayOfByte; overload;
|
||
|
||
function IEStreamFindString(Stream: TStream; Text: AnsiString; StopAtPos: int64): int64;
|
||
|
||
function IEGetDosOutput(CommandLine: AnsiString; Work: AnsiString = 'C:\'): AnsiString;
|
||
|
||
|
||
{$ifndef IEHASUINT64}
|
||
function UInt64(v : Pointer) : int64; overload;
|
||
function UInt64(v : Integer) : int64; overload;
|
||
{$endif}
|
||
|
||
{$ifndef IEHASNATIVEINT}
|
||
function Nativeint(v: Pointer): DWORD; overload;
|
||
function Nativeint(v: Char): DWORD; overload;
|
||
{$endif}
|
||
|
||
|
||
|
||
{$IfNDef Delphi6orNewer}
|
||
function Get8087CW: Word; // for D5
|
||
{$ENDIF}
|
||
|
||
function IESetScrollRange(hWnd: HWND; nBar, nMinPos, nMaxPos: Integer; bRedraw: BOOL; flat: boolean): BOOL;
|
||
procedure IESetSBPageSize(HScrollBar: THandle; fnBar: integer; PageSize: Integer; Redraw: boolean; flat: boolean);
|
||
function IESetScrollPos(hWnd: HWND; nBar, nPos: Integer; bRedraw: BOOL; flat: boolean): Integer;
|
||
function IEEnableScrollBar(hWnd: HWND; wSBflags, wArrows: UINT; flat: boolean = False): BOOL;
|
||
function IEShowScrollBar(hWnd: HWND; wBar: Integer; bShow: BOOL; flat: boolean = False): BOOL;
|
||
function IESetScrollInfo(hWnd: HWND; BarFlag: Integer; const ScrollInfo: TScrollInfo; Redraw: BOOL; flat: boolean): Integer;
|
||
procedure IESetScrollBar(hWnd: HWND; nBar: integer; nMinPos: integer; nMaxPos: integer; PageSize: integer; nPos: integer; bRedraw: boolean; flat: boolean = False);
|
||
|
||
function IEIsSpace(c: AnsiChar): boolean;
|
||
|
||
function IERemoveCtrlCharsA(const text: AnsiString): AnsiString;
|
||
function IERemoveCtrlCharsW(const text: WideString): WideString;
|
||
function IERemoveCtrlCharsS(const text: String): String;
|
||
|
||
function IERGBColorsMatch(rgb1, rgb2 : TRGB; Tolerance : Integer = 0): Boolean;
|
||
function IERGB2StrS(c: TRGB): string;
|
||
function IERGB2StrW(c: TRGB): WideString;
|
||
function IEBool2StrS(v: boolean): string;
|
||
function IEBool2StrW(v: boolean): WideString;
|
||
function IEStr2RGBS(const rgbstr: string): TRGB;
|
||
function IEStr2RGBW(const rgbstr: WideString): TRGB;
|
||
function IEStr2BoolS(const v: string): boolean;
|
||
function IEStr2BoolW(const v: WideString): boolean;
|
||
function IEStr2BoolA(const v: AnsiString): boolean;
|
||
function IEStr2ColorDefS(const v : string; ADefault : TColor) : TColor;
|
||
|
||
function IECopyArrayOfByte(const Input: TIEArrayOfByte): TIEArrayOfByte;
|
||
function IECopyArrayOfInteger(const Input: TIEArrayOfInteger): TIEArrayOfInteger;
|
||
|
||
procedure IEQuickSort(ItemsCount: integer; CompareFunction: TIECompareFunction; SwapFunction: TIESwapFunction);
|
||
|
||
function IEGetTempFileName(const Descriptor: string; const Directory: string): string;
|
||
function IEGetTempFileName2: string;
|
||
function IEGetNewFilename(const sBaseFilename: string; const sSepChar: Char = ' '): string;
|
||
|
||
procedure IERGB2YCbCr(rgb: TRGB; var Y, Cb, Cr: integer);
|
||
procedure IEYCbCr2RGB(var rgb: TRGB; Y, Cb, Cr: integer);
|
||
|
||
function IESystemAlloc(ASize: int64): pointer;
|
||
procedure IESystemFree(var P);
|
||
function IEAutoAlloc(ASize: int64): pointer;
|
||
procedure IEAutoFree(var P);
|
||
|
||
procedure IESilentGetMem(var P; Size: Integer);
|
||
|
||
procedure IECreateOSXBackgroundPaper(bmp: TBitmap; width, height: integer);
|
||
procedure IECreateOSXBackgroundMetal(bmp: TBitmap; width, height: integer);
|
||
|
||
// clipboard helpers
|
||
function IEEnumClipboardNames: TStringList;
|
||
function IEGetClipboardDataByName(const name: string): THandle;
|
||
|
||
// alpha/opacity
|
||
function IEAlphaToOpacity(Alpha: integer ): integer;
|
||
function IEOpacityToAlpha(Opacity: integer): integer;
|
||
|
||
function IEIsLeftMouseButtonPressed: boolean;
|
||
|
||
function IERGBToStr(rgb: TRGB): AnsiString;
|
||
|
||
function IEExtractFileExtS(const FileName: string; includeDot: boolean=true): string;
|
||
function IEExtractFileExtW(const FileName: WideString; includeDot: boolean=true): WideString;
|
||
function IEExtractFileExtA(const FileName: AnsiString; includeDot: boolean=true): AnsiString;
|
||
function IEAddBackSlash(const Path: String): String;
|
||
function IETrim(const v: AnsiString): AnsiString;
|
||
function IEUpperCase(const v: AnsiString): AnsiString;
|
||
function IELowerCase(const v: AnsiString): AnsiString;
|
||
function IEIntToStr(v: integer): AnsiString;
|
||
function IEStrToIntDef(const s: AnsiString; def: integer): integer;
|
||
function IEBytesToStr(v: integer; iThreshold: Integer = 100 * 1024): AnsiString;
|
||
function IEBytesToStr2(iBytes: Int64) : AnsiString;
|
||
function IEIntToFormattedStr(v: integer; iMaxDigitsOfPrecision: Integer = 0): AnsiString;
|
||
function IECopy(S: AnsiString; Index, Count: Integer): AnsiString;
|
||
function IEFloatToStrFA(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): AnsiString;
|
||
function IEFloatToStrFS(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): string;
|
||
function IEIntToHex(Value: Integer; Digits: Integer): AnsiString;
|
||
function IEPos(Substr: AnsiString; S: AnsiString): Integer;
|
||
function IEStrDup(s: PAnsiChar): PAnsiChar;
|
||
function IEStrDupW(s: PWideChar): PWideChar;
|
||
function IEExtractFilePathA(const FileName: AnsiString): AnsiString;
|
||
function IEExtractFilePathW(const FileName: WideString): WideString;
|
||
function IEExtractFileNameW(const FileName: WideString): WideString;
|
||
function IEExtractFileNameWithoutExt(const FileName: String): String;
|
||
function IE2DPoint(X, Y: double): TIE2DPoint;
|
||
function IEFindNearestColor(color: TRGB; palette: TIEArrayOfTRGB; colorCount: integer): integer;
|
||
|
||
function IEGetOpSys(): TIEOpSys;
|
||
function IEGetDisplayOrientation(): integer;
|
||
|
||
function IEFilenameInExtensions(const sFileName, sExtensions : String) : Boolean;
|
||
function IEFileExtInExtensions(sFileExt : String; const sExtensions : String) : Boolean;
|
||
|
||
function GetImageRectWithinArea(iImageWidth, iImageHeight : Integer;
|
||
iAvailableWidth, iAvailableHeight : Integer;
|
||
iHorzOffset : Integer = 0;
|
||
iVertOffset : integer = 0;
|
||
bAllowStretching : boolean = true;
|
||
bAllowShrinking : boolean = true;
|
||
bCenterHorz : boolean = true;
|
||
bCenterVert : boolean = true;
|
||
iAutoCropPercent : Integer = 0;
|
||
FitMethod: TFitMethod = _fmFitWithinRect) : TRect; overload;
|
||
|
||
function GetImageRectWithinArea(iImageWidth, iImageHeight: Integer;
|
||
ADestRect : TRect;
|
||
bAllowStretching : boolean = true;
|
||
bAllowShrinking : boolean = true;
|
||
bCenterHorz : boolean = true;
|
||
bCenterVert : boolean = true;
|
||
iAutoCropPercent : Integer = 0;
|
||
FitMethod: TFitMethod = _fmFitWithinRect) : TRect; overload;
|
||
|
||
function GetImageSizeWithinArea(iImageWidth, iImageHeight : integer;
|
||
iAvailableWidth, iAvailableHeight : integer;
|
||
bAllowStretching : boolean = TRUE;
|
||
FitMethod: TFitMethod = _fmFitWithinRect
|
||
) : TPoint;
|
||
|
||
function IEAdjustRectToAspectRatio(InRect : TRect;
|
||
iImageWidth, iImageHeight: Integer;
|
||
iDisplayWidth, iDisplayHeight : Integer;
|
||
FitMethod: TFitMethod = _fmFitWithinRect ) : TRect;
|
||
|
||
function IERectifiedRectangleAspectRatio(x0, y0, x1, y1, x2, y2, x3, y3, cx, cy: double): double;
|
||
|
||
function IEBilinear(needX, needY: Double; centerValue, rightValue, bottomValue, BottomRightValue: integer): integer;
|
||
|
||
|
||
function AngleToImageEnRotateAngle(Angle: Double): Double;
|
||
function ImageEnRotateAngleToAngle(Angle: Double): Double;
|
||
|
||
procedure IEInitializeComboBox(AComboBox : TComboBox);
|
||
procedure IEDrawComboListBoxItem(ControlCanvas : TCanvas;
|
||
CanvasRect : trect;
|
||
ControlEnabled: Boolean;
|
||
const Text : string;
|
||
AnImageList : TImageList = nil;
|
||
iGlyph : Short = -1);
|
||
|
||
function GetNextZoomValue(iCurrentZoom: double;
|
||
bZoomIn: boolean;
|
||
iIdealZoom: double = 0) : double;
|
||
|
||
function IEIsWindowsVistaOrNewer : Boolean;
|
||
|
||
function IEIsKeyPressed(aKey: Word): Boolean;
|
||
|
||
function IEFileExists(const FileName: string): Boolean;
|
||
function IEFileExistsW(const FileName: WideString): Boolean;
|
||
procedure IEDecimalToFraction(value: double; var numerator: integer; var denominator: integer; accuracy: double = 0.000000005);
|
||
|
||
procedure IECopyTList(source: TList; dest: TList);
|
||
|
||
function IERectangle(x, y, width, height: integer): TIERectangle; overload;
|
||
function IERectangle(Rect: TRect): TIERectangle; overload;
|
||
|
||
function IETextWidthW(Canvas: TCanvas; const Text: WideString): integer;
|
||
function IETextHeightW(Canvas: TCanvas; const Text: WideString): integer;
|
||
|
||
function IETruncateStr(sCaption : WideString; TruncSide: TIEMTruncSide; ACanvas : TCanvas; iMaxWidth : Integer) : Widestring;
|
||
|
||
function IEFileTimeToDateTime(ft: TFileTime): TDateTime;
|
||
function IELargeFileSize(nFileSizeHigh, nFileSizeLow: DWORD) : Int64;
|
||
function IEGetFileDetails(const sFilename: string;
|
||
out iFileSizeBytes: Int64;
|
||
out dtCreateDate: TDateTime;
|
||
out dtEditDate: TDateTime
|
||
): boolean;
|
||
function IEFileSetDate(const sFilename: string; DateTime: TDateTime): boolean;
|
||
|
||
// convert a real value into a string with decimal places
|
||
function IEFloatToFormatString(Value: Extended;
|
||
iDecimalCount: Integer;
|
||
bStripZeros: boolean): string;
|
||
|
||
// Returns a suitable font to use for Preview dialogs. Segoe UI 9 on Vista, 7. Tahoma 8 on XP, etc
|
||
function IEGetDefaultDialogFont() : TFont;
|
||
|
||
{$IfNdef Delphi6orNewer}
|
||
function RoundTo(const AValue: Double; ADigit: Integer): Double;
|
||
{$endif}
|
||
|
||
|
||
type
|
||
TIEURLType = (ieurlUNKNOWN, ieurlHTTP, ieurlHTTPS, ieurlFTP);
|
||
|
||
function IEGetURLTypeA(const URL: AnsiString): TIEURLType;
|
||
function IEGetURLTypeW(const URL: WideString): TIEURLType;
|
||
|
||
|
||
function IESendMessageTimeout(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM; fuFlags, uTimeout: UINT; lpdwResult: pointer): LRESULT;
|
||
|
||
|
||
function IEIsPrime(x: integer): boolean;
|
||
function IENextPrime(x: integer): integer;
|
||
|
||
// GPS
|
||
function IEGPSConvertDMSToDegDec(degrees: Double; minutes: Double; seconds: Double; ref: AnsiString): Double;
|
||
procedure IEGPSConvertDegDecToDMS(dir: AnsiString; value: Double; var degrees: Double; var minutes: Double; var seconds: Double; var ref: AnsiString);
|
||
|
||
|
||
{$ifdef IEVISION}
|
||
function IEVisionBGR8ToTRGB(visionBGR8: TIEVisionBGR8): TRGB;
|
||
function IETRGBToVisionBGR8(rgb: TRGB): TIEVisionBGR8;
|
||
procedure IEVisionConvPixelFormat(PixelFormat: TIEPixelFormat; out channelFormat: TIEVisionChannelFormat; out channelCount: integer); overload;
|
||
function IEVisionConvPixelFormat(channelFormat: TIEVisionChannelFormat; channelCount: integer): TIEPixelFormat; overload;
|
||
//function IEVision
|
||
{$endif}
|
||
|
||
|
||
procedure IEBlend(var src: TRGB; var dst: TRGB; RenderOperation: TIERenderOperation; row: integer);
|
||
procedure IEBlendRGBA(var src: TRGBA; var dst: TRGBA; RenderOperation: TIERenderOperation; row: integer);
|
||
procedure IEBezier2D4Controls(p0: TPoint; c0: TPoint; c1: TPoint; p1: TPoint; pResultArray: PPointArray; nSteps: integer);
|
||
|
||
function IEWStrCopy(Dest: PWideChar; const Source: PWideChar): PWideChar;
|
||
|
||
{$IfNdef Delphi6orNewer}
|
||
function Sign(const AValue: Double): Integer;
|
||
{$ENDIF}
|
||
|
||
// Hash Functions
|
||
function IE_ELFHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
function IE_RSHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
function IE_JSHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
function IE_MMHash(const str: WideString; const Seed: Cardinal = $9747b28c): Cardinal;
|
||
|
||
function IEDrawGradient(R: TRect; DC: HDC; ColorStart, ColorStop: TColor; bVertical: boolean): Boolean;
|
||
procedure IEPixelFormatToBPSAndSPP(PixelFormat: TIEPixelFormat; out iBitsPerSample: Integer; out iSamplesPerPixel: Integer);
|
||
procedure BitCountToBPSAndSPP(BitCount: Integer; bAllow32bit: Boolean; out iBitsPerSample: Integer; out iSamplesPerPixel: Integer);
|
||
|
||
procedure IEPrintLogWrite(const ss: String);
|
||
|
||
procedure IESetStringA(var S: AnsiString; Buffer: PAnsiChar; Length: Integer);
|
||
|
||
{$IfNdef Delphi7orNewer}
|
||
function BoolToStr(B: Boolean): string;
|
||
{$endif}
|
||
|
||
function IECreateRect(Left, Top, Right, Bottom: Integer): TRect;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>dmin
|
||
|
||
<FM>Declaration<FC>
|
||
function dmin(v1, v2: Double): Double;
|
||
|
||
<FM>Description<FN>
|
||
Returns the minimum of v1 and v2.
|
||
!!}
|
||
function dmin(v1, v2: Double): Double;
|
||
|
||
{!!
|
||
<FS>dmax
|
||
|
||
<FM>Declaration<FC>
|
||
function dmax(v1, v2: Double): Double;
|
||
|
||
<FM>Description<FN>
|
||
Returns the maximum of v1 and v2.
|
||
!!}
|
||
function dmax(v1, v2: Double): Double;
|
||
|
||
function dwmax(v1, v2: DWord): DWord;
|
||
|
||
{!!
|
||
<FS>imin
|
||
|
||
<FM>Declaration<FC>
|
||
function imin(v1, v2: Integer): Integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the minimum of v1 and v2.
|
||
!!}
|
||
function imin(v1, v2: Integer): Integer;
|
||
|
||
|
||
{$IFDEF IEHASUINT64}
|
||
function u64min(v1, v2: uint64): uint64;
|
||
{$ENDIF}
|
||
function i64min(v1, v2: int64): int64;
|
||
function i64max(v1, v2: int64): int64;
|
||
|
||
{!!
|
||
<FS>imax
|
||
|
||
<FM>Declaration<FC>
|
||
function imax(v1, v2: Integer): Integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the maximum of v1 and v2.
|
||
!!}
|
||
function imax(v1, v2: Integer): Integer;
|
||
|
||
{!!
|
||
<FS>ilimit
|
||
|
||
<FM>Declaration<FC>
|
||
function ilimit(vv, min, max: Integer): Integer;
|
||
|
||
<FM>Description<FN>
|
||
Ensures vv is in the range of min and max.
|
||
!!}
|
||
function ilimit(vv, min, max: Integer): Integer;
|
||
|
||
{!!
|
||
<FS>blimit
|
||
|
||
<FM>Declaration<FC>
|
||
function blimit(vv: Integer): Integer;
|
||
|
||
<FM>Description<FN>
|
||
Ensures vv is in the range of 0 to 255.
|
||
!!}
|
||
function blimit(vv: Integer): Integer;
|
||
|
||
{!!
|
||
<FS>wlimit
|
||
|
||
<FM>Declaration<FC>
|
||
function wlimit(vv: Integer): word;
|
||
|
||
<FM>Description<FN>
|
||
Ensures vv is in the range of 0 to 65535.
|
||
!!}
|
||
function wlimit(vv: Integer): word;
|
||
|
||
{!!
|
||
<FS>iswap
|
||
|
||
<FM>Declaration<FC>
|
||
procedure iswap(var B1, B2: LongInt);
|
||
|
||
<FM>Description<FN>
|
||
Swap B1 with B2.
|
||
!!}
|
||
procedure iswap(var B1, B2: LongInt); assembler;
|
||
|
||
procedure dwswap(var B1, B2: dword); assembler;
|
||
|
||
procedure dswap(var v1, v2: Double);
|
||
|
||
{!!
|
||
<FS>bswap
|
||
|
||
<FM>Declaration<FC>
|
||
procedure bswap(var B1, B2: Byte);
|
||
|
||
<FM>Description<FN>
|
||
Swap B1 with B2.
|
||
!!}
|
||
procedure bswap(var B1, B2: Byte); assembler;
|
||
|
||
procedure iedswap(var d1, d2: Double);
|
||
|
||
procedure i64swap(var v1, v2: int64);
|
||
|
||
{!!
|
||
<FS>OrdCor
|
||
|
||
<FM>Declaration<FC>
|
||
procedure OrdCor(var x1, y1, x2, y2: Integer);
|
||
|
||
<FM>Description<FN>
|
||
Sorts x1, y1, x2, y2 so that x1, y1 is at the top-left and x2, y2 is at the bottom-right vertex of the rectangle.
|
||
!!}
|
||
procedure OrdCor(var x1, y1, x2, y2: Integer);
|
||
|
||
{!!
|
||
<FS>TRGB2TColor
|
||
|
||
<FM>Declaration<FC>
|
||
function TRGB2TColor(rgb: <A TRGB>): TColor;
|
||
|
||
<FM>Description<FN>
|
||
Converts a TRGB color to TColor.
|
||
|
||
<FM>Example<FC>
|
||
Panel1.Color := TRGB2TColor(CreateRGB(255, 0, 0)); // Panel1.Color will be clRed
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
function TRGB2TColor(rgb: TRGB): TColor;
|
||
|
||
|
||
{!!
|
||
<FS>RGB2TColor
|
||
|
||
<FM>Declaration<FC>
|
||
function RGB2TColor(r, g, b: Integer): TColor;
|
||
|
||
<FM>Description<FN>
|
||
Converts R, G, B values to TColor.
|
||
|
||
<FM>Example<FC>
|
||
Panel1.Color := RGB2TColor(255, 0, 0); // Panel1.Color will be clRed
|
||
|
||
<FM>See Also<FN>
|
||
- <A TRGB2TColor>
|
||
- <A RGB2TColor>
|
||
!!}
|
||
function RGB2TColor(r, g, b: Integer): TColor;
|
||
|
||
{!!
|
||
<FS>TColor2TRGB
|
||
|
||
<FM>Declaration<FC>
|
||
function TColor2TRGB(cl: TColor): <A TRGB>;
|
||
|
||
<FM>Description<FN>
|
||
Converts a TColor to TRGB.
|
||
|
||
<FM>Example<FC>
|
||
var
|
||
rgb: TRGB;
|
||
Begin
|
||
rgb := TColor2TRGB( clRed );
|
||
// Which is the same as rgb := CreateRGB( 255, 0, 0 );
|
||
...
|
||
End;
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
!!}
|
||
function TColor2TRGB(cl: TColor): TRGB;
|
||
|
||
|
||
{!!
|
||
<FS>TColor2TRGBA
|
||
|
||
<FM>Declaration<FC>
|
||
function TColor2TRGBA(cl: TColor): <A TRGBA>; overload;
|
||
function TColor2TRGBA(cl: TColor; transparency: Integer): <A TRGBA>;
|
||
|
||
<FM>Description<FN>
|
||
Converts TColor and transparency to TRGBA.
|
||
|
||
<FM>Example<FC>
|
||
var
|
||
rgb: TRGBA;
|
||
Begin
|
||
rgb := TColor2TRGBA( clRed, 255 );
|
||
...
|
||
End;
|
||
!!}
|
||
function TColor2TRGBA(cl: TColor; transparency: Integer): TRGBA; overload;
|
||
function TColor2TRGBA(cl: TColor): TRGBA; overload;
|
||
|
||
|
||
{!!
|
||
<FS>IEApplyAlphaToColor
|
||
|
||
<FM>Declaration<FC>
|
||
function IEApplyAlphaToColor(Color: TColor; Alpha: Integer): TColor; overload;
|
||
function IEApplyAlphaToColor(rgb: <A TRGB>; Alpha: Integer): <A TRGB>; overload;
|
||
|
||
<FM>Description<FN>
|
||
Applies Alpha (0=fully transparent, 255=fully visible) to the specified color.
|
||
|
||
<FM>Examples<FC>
|
||
Color := IEApplyAlphaToColor( clRed, 255 ); // Returns Pure Red
|
||
Color := IEApplyAlphaToColor( clRed, 175 ); // Returns Dark Pink
|
||
Color := IEApplyAlphaToColor( clRed, 50 ); // Returns Pale Pink
|
||
Color := IEApplyAlphaToColor( clRed, 0 ); // Returns White
|
||
!!}
|
||
function IEApplyAlphaToColor(Color: TColor; Alpha: Integer): TColor; overload;
|
||
function IEApplyAlphaToColor(rgb: TRGB; Alpha: Integer): TRGB; overload;
|
||
|
||
{!!
|
||
<FS>RGB2HSL
|
||
|
||
<FM>Declaration<FC>
|
||
procedure RGB2HSL(px: <A TRGB>; var Hue, Sat, Lum: Double);
|
||
|
||
<FM>Description<FN>
|
||
Converts a TRGB color to HSL values.
|
||
|
||
Note: Hue, Sat and Lum will be in range 0 to 1.
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
procedure RGB2HSL(px: TRGB; var Hue, Sat, Lum: Double);
|
||
|
||
{!!
|
||
<FS>ColorToHSL
|
||
|
||
<FM>Declaration<FC>
|
||
procedure ColorToHSL(cl: TColor; var Hue, Sat, Lum: Double);
|
||
|
||
<FM>Description<FN>
|
||
Converts a TColor to HSL values.
|
||
|
||
Note: Hue, Sat and Lum will be in range 0 to 1.
|
||
!!}
|
||
procedure ColorToHSL(cl: TColor; var Hue, Sat, Lum: Double);
|
||
|
||
{!!
|
||
<FS>HSL2RGB
|
||
|
||
<FM>Declaration<FC>
|
||
procedure HSL2RGB(var px: <A TRGB>; Hue, Sat, Lum: Double);
|
||
|
||
<FM>Description<FN>
|
||
Converts an HSL value (Hue, Sat, Lum) with a TRGB (px).
|
||
|
||
Hue, Sat and Lum are in range 0 to 1.
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
procedure HSL2RGB(var px: TRGB; Hue, Sat, Lum: Double);
|
||
|
||
{!!
|
||
<FS>HSLToColor
|
||
|
||
<FM>Declaration<FC>
|
||
function HSLToColor(Hue, Sat, Lum: Double) : TColor;
|
||
|
||
<FM>Description<FN>
|
||
Converts HSL values (Hue, Sat, Lum) to a TColor.
|
||
|
||
Hue, Sat and Lum are in range 0 to 1.
|
||
!!}
|
||
function HSLToColor(Hue, Sat, Lum: Double) : TColor;
|
||
|
||
{!!
|
||
<FS>HSV2RGB
|
||
|
||
<FM>Declaration<FC>
|
||
procedure HSV2RGB(var px: <A TRGB>; H, S, V: Integer);
|
||
|
||
<FM>Description<FN>
|
||
Converts a HSV values to TRGB.
|
||
|
||
H (Hue) is from 0 to 359 (corresponding to 0..359 degrees around a hexcone).
|
||
S (Saturation) is from 0 (shade of gray) to 99 (pure color).
|
||
V (Value) is from 0 (black) to 99 (white).
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
procedure HSV2RGB(var px: TRGB; H, S, V: Integer);
|
||
|
||
|
||
{!!
|
||
<FS>HSVToColor
|
||
|
||
<FM>Declaration<FC>
|
||
function HSVToColor(h, s, v: Integer): TColor;
|
||
|
||
<FM>Description<FN>
|
||
Converts HSV values to a TColor.
|
||
|
||
H (Hue) is from 0 to 359 (corresponding to 0..359 degrees around a hexcone).
|
||
S (Saturation) is from 0 (shade of gray) to 99 (pure color).
|
||
V (Value) is from 0 (black) to 99 (white).
|
||
!!}
|
||
function HSVToColor(h, s, v: Integer): TColor;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>RGB2HSV
|
||
|
||
<FM>Declaration<FC>
|
||
procedure RGB2HSV(RGB: <A TRGB>; var h, s, v: Integer);
|
||
|
||
<FM>Description<FN>
|
||
Converts a TRGB color to HSV values.
|
||
|
||
H (Hue) is from 0 to 359 (corresponding to 0..359 degrees around a hexcone).
|
||
S (Saturation) is from 0 (shade of gray) to 99 (pure color).
|
||
V (Value) is from 0 (black) to 99 (white).
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
procedure RGB2HSV(RGB: TRGB; var h, s, v: Integer);
|
||
|
||
|
||
{!!
|
||
<FS>ColorToHSV
|
||
|
||
<FM>Declaration<FC>
|
||
procedure ColorToHSV(cl: TColor; var h, s, v: Integer);
|
||
|
||
<FM>Description<FN>
|
||
Converts a TColor to HSV values.
|
||
|
||
H (Hue) is from 0 to 359 (corresponding to 0..359 degrees around a hexcone).
|
||
S (Saturation) is from 0 (shade of gray) to 99 (pure color).
|
||
V (Value) is from 0 (black) to 99 (white).
|
||
!!}
|
||
procedure ColorToHSV(cl: TColor; var h, s, v: Integer);
|
||
|
||
|
||
{!!
|
||
<FS>ColorToHex
|
||
|
||
<FM>Declaration<FC>
|
||
function ColorToHex(Color : TColor): string;
|
||
|
||
<FM>Description<FN>
|
||
Returns a hex representation of a TColor (e.g. for use in HTML)
|
||
|
||
<FM>Example<FC>
|
||
sHex := ColorToHex(clWhite); // Would return "#FFFFFF'
|
||
!!}
|
||
function ColorToHex(Color : TColor): string;
|
||
|
||
{!!
|
||
<FS>CreateRGB
|
||
|
||
<FM>Declaration<FC>
|
||
function CreateRGB(r, g, b: byte): <A TRGB>;
|
||
|
||
<FM>Description<FN>
|
||
Returns a TRGB record.
|
||
|
||
<FM>Example<FC>
|
||
rgb := CreateRGB( 255, 0, 0 );
|
||
// Which is the same as rgb := TColor2TRGB( clRed );
|
||
|
||
<FM>See Also<FN>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
function CreateRGB(r, g, b: byte): TRGB;
|
||
|
||
{!!
|
||
<FS>CreateRGB48
|
||
|
||
<FM>Declaration<FC>
|
||
function CreateRGB48(r, g, b: word): <A TRGB48>;
|
||
|
||
<FM>Description<FN>
|
||
Returns a TRGB48 record.
|
||
!!}
|
||
function CreateRGB48(r, g, b: word): TRGB48;
|
||
|
||
|
||
{!!
|
||
<FS>CreateCMYK
|
||
|
||
<FM>Declaration<FC>
|
||
function CreateCMYK(c, m, y, k: byte): <A TCMYK>;
|
||
|
||
<FM>Description<FN>
|
||
Returns a TCMYK record.
|
||
!!}
|
||
function CreateCMYK(c, m, y, k: byte): TCMYK;
|
||
|
||
|
||
{!!
|
||
<FS>CreateRGBA
|
||
|
||
<FM>Declaration<FC>
|
||
function CreateRGBA(r, g, b, a: byte): <A TRGBA>;
|
||
|
||
<FM>Description<FN>
|
||
Returns a TRGBA record.
|
||
!!}
|
||
function CreateRGBA(r, g, b, a: byte): TRGBA;
|
||
|
||
|
||
function CreateRGBFromInt(r, g, b: Integer): TRGB;
|
||
|
||
{!!
|
||
<FS>EqualRGB
|
||
|
||
<FM>Declaration<FC>
|
||
function EqualRGB(rgb1, rgb2: <A TRGB>): Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns True if rgb1 and rgb2 are equal.
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
function EqualRGB(rgb1, rgb2: TRGB): Boolean;
|
||
|
||
{!!
|
||
<FS>IEAverageColor
|
||
|
||
<FM>Declaration<FC>
|
||
function IEAverageColor(c1, c2 : TColor): TColor; overload;
|
||
function IEAverageColor(c1, c2 : TRGB): TRGB; overload;
|
||
|
||
<FM>Description<FN>
|
||
Returns the average of two colors.
|
||
!!}
|
||
function IEAverageColor(c1, c2 : TColor): TColor; overload;
|
||
function IEAverageColor(rgb1, rgb2 : TRGB): TRGB; overload;
|
||
|
||
|
||
|
||
procedure YUV2RGB(y, u, v: Integer; var RGB: TRGB);
|
||
procedure IERGBtoHSB(const cRed, cGreen, cBlue: byte; var H, S, B: word);
|
||
procedure IEHSBtoRGB(const H, S, B: word; var cRed, cGreen, cBlue: byte);
|
||
|
||
|
||
|
||
|
||
procedure IEInitializeImageEn;
|
||
procedure IEFinalizeImageEn;
|
||
procedure IEInitialize_hyieutils;
|
||
procedure IEFinalize_hyieutils;
|
||
|
||
|
||
// Gestures
|
||
procedure IEInitialize_gestures();
|
||
procedure IEFinalize_gestures();
|
||
function IEHasGestures(): boolean;
|
||
|
||
|
||
function ProgressRec(Sender: TObject; OnProgress: TIEProgressEvent; var bAborting: Boolean) : TProgressRec; overload;
|
||
function ProgressRec(Sender: TObject; OnProgress: TIEProgressEvent; pAborting: PBoolean) : TProgressRec; overload;
|
||
function NullProgressRec(var bAborting: Boolean; bResetAborting : Boolean = true) : TProgressRec; overload;
|
||
function NullProgressRec(pAborting: PBoolean; bResetAborting : Boolean = true) : TProgressRec; overload;
|
||
|
||
var
|
||
IEGetGestureInfo: function(hGestureInfo: HGESTUREINFO; pGestureInfo: PIEGESTUREINFO): longbool; stdcall = nil;
|
||
IECloseGestureInfoHandle: function(hGestureInfo: HGESTUREINFO): longbool; stdcall = nil;
|
||
IESetGestureConfig: function(hwnd: THandle; dwReserved: DWORD; cIDS: DWORD; pGestureConfig: PIEGESTURECONFIG; cbSize: DWORD): longbool; stdcall = nil;
|
||
IEUnregisterTouchWindow: function(hwnd: THandle): longbool; stdcall = nil;
|
||
|
||
var
|
||
// Windows CMS
|
||
mscms: THandle;
|
||
|
||
implementation
|
||
|
||
uses
|
||
math,
|
||
SyncObjs,
|
||
{$ifdef Delphi7orNewer}
|
||
Types,
|
||
{$endif}
|
||
{$ifdef DelphiXE4orNewer}
|
||
AnsiStrings,
|
||
{$endif}
|
||
{$ifdef IEHASUITYPES}System.UITypes,{$endif}
|
||
imageenview, imageenproc, imageenio, ieview, neurquant, tiffilt, ievect, printers, ielcms,
|
||
iej2000, tifccitt, ietextc, iewia, iewic, iepresetim, iesettings, iedicom, iemiscplugins, iemview
|
||
{$ifdef IEUSEVCLZLIB}, zlib{$else}, iezlib{$endif}
|
||
{$ifdef IEINCLUDEFLATSB}, flatsb{$endif}
|
||
, iegdiplus, iewords, Dialogs, iexBitmaps;
|
||
|
||
{$R-}
|
||
|
||
var
|
||
IECosineTab: array[0..255] of integer;
|
||
|
||
|
||
|
||
// DRAWDIB LIBRARY
|
||
const
|
||
DLL = 'MsVfW32.dll';
|
||
|
||
function DrawDibClose(hdd: hDrawDib): Boolean; stdcall; external DLL name 'DrawDibClose';
|
||
function DrawDibDraw(hdd: hDrawDib; hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer; wFlags: UInt): Boolean; stdcall; external DLL name 'DrawDibDraw';
|
||
function DrawDibOpen: hDrawDib; stdcall; external DLL name 'DrawDibOpen';
|
||
function DrawDibRealize(hdd: hDrawDib; hDC: THandle; fBackground: Bool): UInt; stdcall; external DLL name 'DrawDibRealize';
|
||
|
||
// not available on old Delphi versions
|
||
function IE_EnumDisplaySettingsExW(lpszDeviceName: PWideChar; iModeNum: DWORD; var lpDevMode: TIEDeviceModeW; dwFlags: DWORD): BOOL; stdcall; external user32 name 'EnumDisplaySettingsExW';
|
||
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEResourceExtractor
|
||
|
||
{$ifdef IEINCLUDERESOURCEEXTRACTOR}
|
||
|
||
function IEIS_INTRESOURCE(const ResID: PAnsiChar): boolean;
|
||
begin
|
||
Result := (Windows.HiWord(Windows.DWORD(ResID)) = 0);
|
||
end;
|
||
|
||
function EnumTypesProc(hModule: THandle; lpszType: PAnsiChar; lParam: pointer): longbool; stdcall;
|
||
var
|
||
typesList: TStringList;
|
||
begin
|
||
typesList := TStringList(lParam);
|
||
if IEIS_INTRESOURCE(lpszType) then
|
||
typesList.Add('INTRESOURCE:'+IntToStr(NativeInt(lpszType)))
|
||
else
|
||
typesList.Add(string(AnsiString(lpszType)));
|
||
result := true;
|
||
end;
|
||
|
||
function EnumNamesProc(hModule: THandle; lpszType: PAnsiChar; lpszName: PAnsiChar; lParam: pointer): longbool; stdcall;
|
||
var
|
||
namesList: TStringList;
|
||
begin
|
||
namesList := TStringList(lParam);
|
||
if IEIS_INTRESOURCE(lpszName) then
|
||
namesList.Add('INTRESOURCE:'+IntToStr(NativeInt(lpszName)))
|
||
else
|
||
namesList.Add(string(AnsiString(lpszName)));
|
||
result := true;
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.Create
|
||
|
||
<FM>Declaration<FC>
|
||
constructor Create(const Filename: WideString);
|
||
|
||
<FM>Description<FN>
|
||
Creates a new instance of TIEResourceExtractor loading the specified PE file (EXE, DLL, OCX, ICL, BPL, etc..).
|
||
It is possible to check the success of loading reading <A TIEResourceExtractor.IsValid> property.
|
||
<FC>FileName<FN> specifies the path and filename of PE module.
|
||
|
||
<FM>Example<FC>
|
||
re := TIEResourceExtractor.Create('explorer.exe');
|
||
try
|
||
...
|
||
finally
|
||
re.Free;
|
||
end;
|
||
|
||
!!}
|
||
constructor TIEResourceExtractor.Create(const Filename: WideString);
|
||
const
|
||
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = $00000040;
|
||
LOAD_LIBRARY_AS_IMAGE_RESOURCE = $00000020;
|
||
var
|
||
resType: PAnsiChar;
|
||
resTypeStr: AnsiString;
|
||
i: integer;
|
||
begin
|
||
inherited Create;
|
||
|
||
m_hlib := 0;
|
||
m_typesList := nil;
|
||
m_resourceBookmarks := nil;
|
||
|
||
if IEGlobalSettings().OpSys < ieosWinVista then
|
||
m_hlib := LoadLibraryExW(PWideChar(Filename), 0, LOAD_LIBRARY_AS_DATAFILE or DONT_RESOLVE_DLL_REFERENCES)
|
||
else
|
||
m_hlib := LoadLibraryExW(PWideChar(Filename), 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE or LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||
if m_hlib=0 then
|
||
exit;
|
||
|
||
// enum types
|
||
m_typesList := TStringList.Create;
|
||
EnumResourceTypesA(m_hlib, @EnumTypesProc, NativeInt(m_typesList));
|
||
|
||
// enum names
|
||
for i := 0 to m_typesList.Count-1 do
|
||
begin
|
||
m_typesList.Objects[i] := TStringList.Create; // associates a list of names to this resource type
|
||
resTypeStr := AnsiString(m_typesList[i]);
|
||
if copy(resTypeStr, 1, 12) = 'INTRESOURCE:' then
|
||
resType := MakeIntResourceA(IEStrToIntDef(IECopy(resTypeStr, 13, length(resTypeStr)-12), 0))
|
||
else
|
||
resType := PAnsiChar(resTypeStr);
|
||
EnumResourceNamesA(m_hlib, resType, @EnumNamesProc, NativeInt(m_typesList.Objects[i]));
|
||
end;
|
||
|
||
m_resourceBookmarks := TList.Create;
|
||
end;
|
||
|
||
|
||
destructor TIEResourceExtractor.Destroy;
|
||
var
|
||
i: integer;
|
||
begin
|
||
|
||
if assigned(m_resourceBookmarks) then
|
||
begin
|
||
for i := 0 to m_resourceBookmarks.Count-1 do
|
||
TIEResourceBookmark(m_resourceBookmarks[i]).Free;
|
||
m_resourceBookmarks.Free;
|
||
end;
|
||
|
||
if assigned(m_typesList) then
|
||
begin
|
||
for i := 0 to m_typesList.Count-1 do
|
||
if assigned(TStringList(m_typesList.Objects[i])) then
|
||
TStringList(m_typesList.Objects[i]).Free;
|
||
m_typesList.Free;
|
||
end;
|
||
|
||
if m_hlib<>0 then
|
||
FreeLibrary(m_hlib);
|
||
|
||
inherited;
|
||
end;
|
||
|
||
|
||
|
||
type
|
||
TRES_ICOHEADER = packed record
|
||
wReserved: word;
|
||
wResID: word;
|
||
wNumImages: word;
|
||
end;
|
||
PRES_ICOHEADER = ^TRES_ICOHEADER;
|
||
|
||
TRES_ICODIRENTRY = packed record
|
||
bWidth: byte;
|
||
bHeight: byte;
|
||
bColors: byte;
|
||
bReserved: byte;
|
||
wPlanes: word;
|
||
wBitCount: word;
|
||
dwBytesInImage: dword;
|
||
wID: word;
|
||
end;
|
||
PRES_ICODIRENTRY = ^TRES_ICODIRENTRY;
|
||
|
||
TRES_CURHEADER = packed record
|
||
wReserved: word;
|
||
wResID: word;
|
||
wNumImages: word;
|
||
end;
|
||
PRES_CURHEADER = ^TRES_CURHEADER;
|
||
|
||
TRES_CURDIRENTRY = packed record
|
||
wWidth: word;
|
||
wHeight: word;
|
||
wPlanes: word;
|
||
wBitCount: word;
|
||
dwBytesInImage: dword;
|
||
wID: word;
|
||
end;
|
||
PRES_CURDIRENTRY = ^TRES_CURDIRENTRY;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.IsGroup
|
||
|
||
<FM>Declaration<FC>
|
||
property IsGroup[TypeIndex: integer]: boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns <FC>true<FN> if the resource type is "GroupIcon" (RT_GROUP_ICON) or "GroupCursor" (RT_GROUP_CURSOR).
|
||
This means that resources inside this type must be handled as groups.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
</TABLE>
|
||
|
||
!!}
|
||
function TIEResourceExtractor.GetIsGroup(TypeIndex: integer): boolean;
|
||
begin
|
||
result := (FriendlyTypes[TypeIndex] = 'GroupIcon') or (FriendlyTypes[TypeIndex] = 'GroupCursor');
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.IsGrouped
|
||
|
||
<FM>Declaration<FC>
|
||
property IsGrouped[TypeIndex: integer]: boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns <FC>true<FN> if the resource type is "Icon" (RT_ICON) or "Cursor" (RT_CURSOR).
|
||
This means that resources inside this type must be grouped in "GroupIcon" or "GroupCursor" resources.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEResourceExtractor.GetIsGrouped(TypeIndex: integer): boolean;
|
||
begin
|
||
result := (FriendlyTypes[TypeIndex] = 'Icon') or (FriendlyTypes[TypeIndex] = 'Cursor');
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GroupCountFrames
|
||
|
||
<FM>Declaration<FC>
|
||
property GroupCountFrames[TypeIndex: integer; NameIndex: integer]: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the number of frames of specified resource (can be Icon or Cursor resource).
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEResourceExtractor.GetGroupCountFrames(TypeIndex: integer; NameIndex: integer): integer;
|
||
var
|
||
iconGroupIndex: integer;
|
||
iconHeader: PRES_ICOHEADER;
|
||
curGroupIndex: integer;
|
||
curHeader: PRES_CURHEADER;
|
||
buffer: pointer;
|
||
bufferLen: integer;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'GroupIcon' then
|
||
begin
|
||
iconGroupIndex := IndexOfType('GroupIcon');
|
||
buffer := GetBuffer(iconGroupIndex, NameIndex, bufferLen);
|
||
iconHeader := PRES_ICOHEADER(buffer);
|
||
result := iconHeader^.wNumImages;
|
||
end
|
||
else
|
||
if FriendlyTypes[TypeIndex] = 'GroupCursor' then
|
||
begin
|
||
curGroupIndex := IndexOfType('GroupCursor');
|
||
buffer := GetBuffer(curGroupIndex, NameIndex, bufferLen);
|
||
curHeader := PRES_CURHEADER(buffer);
|
||
result := curHeader^.wNumImages;
|
||
end
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
function GetIconFrameInfo(ResourceExtractor: TIEResourceExtractor; TypeIndex: integer; IconIndex: integer; FrameIndex: integer): PRES_ICODIRENTRY;
|
||
var
|
||
buffer: pointer;
|
||
bufferLen: integer;
|
||
begin
|
||
result := nil;
|
||
|
||
buffer := ResourceExtractor.GetBuffer(TypeIndex, IconIndex, bufferLen);
|
||
|
||
// check for buffer overrun
|
||
if sizeof(TRES_ICOHEADER) + sizeof(TRES_ICODIRENTRY)*(FrameIndex+1) > bufferLen then
|
||
exit;
|
||
|
||
inc(PRES_ICOHEADER(buffer)); // bypass TRES_ICOHEADER
|
||
inc(PRES_ICODIRENTRY(buffer), FrameIndex); // bypass unwanted frames (TRES_ICODIRENTRY)
|
||
result := PRES_ICODIRENTRY(buffer);
|
||
end;
|
||
|
||
function GetCurFrameInfo(ResourceExtractor: TIEResourceExtractor; TypeIndex: integer; CurIndex: integer; FrameIndex: integer): PRES_CURDIRENTRY;
|
||
var
|
||
buffer: pointer;
|
||
bufferLen: integer;
|
||
begin
|
||
buffer := ResourceExtractor.GetBuffer(TypeIndex, CurIndex, bufferLen);
|
||
inc(pbyte(buffer), sizeof(TRES_CURHEADER)); // bypass TRES_CURHEADER
|
||
inc(pbyte(buffer), sizeof(TRES_CURDIRENTRY)*FrameIndex); // bypass unwanted frames (TRES_CURDIRENTRY)
|
||
result := PRES_CURDIRENTRY(buffer);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GroupFrameWidth
|
||
|
||
<FM>Declaration<FC>
|
||
property GroupFrameWidth[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the icon or cursor width. <FC>TypeIndex<FN> must refer to a "GroupIcon" or "GroupCursor" resource type.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEResourceExtractor.GetGroupFrameWidth(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): integer;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'GroupIcon' then
|
||
begin
|
||
result := GetIconFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.bWidth;
|
||
if result = 0 then
|
||
result := 256;
|
||
end
|
||
else
|
||
if FriendlyTypes[TypeIndex] = 'GroupCursor' then
|
||
result := GetCurFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.wWidth
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GroupFrameHeight
|
||
|
||
<FM>Declaration<FC>
|
||
property GroupFrameHeight[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the icon or cursor height. <FC>TypeIndex<FN> must refer to a "GroupIcon" or "GroupCursor" resource type.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEResourceExtractor.GetGroupFrameHeight(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): integer;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'GroupIcon' then
|
||
begin
|
||
result := GetIconFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.bHeight;
|
||
if result = 0 then
|
||
result := 256;
|
||
end
|
||
else
|
||
if FriendlyTypes[TypeIndex] = 'GroupCursor' then
|
||
result := GetCurFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.wHeight div 2
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GroupFrameDepth
|
||
|
||
<FM>Declaration<FC>
|
||
property GroupFrameDepth[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the icon or cursor bit depth. <FC>TypeIndex<FN> must refer to a "GroupIcon" or "GroupCursor" resource type.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEResourceExtractor.GetGroupFrameDepth(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): integer;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'GroupIcon' then
|
||
result := GetIconFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.wBitCount
|
||
else
|
||
if FriendlyTypes[TypeIndex] = 'GroupCursor' then
|
||
result := GetCurFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.wBitCount
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GroupFrameName
|
||
|
||
<FM>Declaration<FC>
|
||
property GroupFrameName[TypeIndex: integer; NameIndex: integer; FrameIndex: integer]: AnsiString;
|
||
|
||
<FM>Description<FN>
|
||
Returns the icon or cursor resource name. <FC>TypeIndex<FN> must refer to a "GroupIcon" or "GroupCursor" resource type.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEResourceExtractor.GetGroupFrameName(TypeIndex: integer; NameIndex: integer; FrameIndex: integer): AnsiString;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'GroupIcon' then
|
||
result := 'INTRESOURCE:'+IEIntToStr(GetIconFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.wID)
|
||
else
|
||
if FriendlyTypes[TypeIndex] = 'GroupCursor' then
|
||
result := 'INTRESOURCE:'+IEIntToStr(GetCurFrameInfo(self, TypeIndex, NameIndex, FrameIndex)^.wID)
|
||
else
|
||
result := '';
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GetGroupAndFrame
|
||
|
||
<FM>Declaration<FC>
|
||
procedure GetGroupAndFrame(TypeIndex: integer; NameIndex: integer; var GroupTypeIndex: integer; var GroupIndex: integer; var GroupFrameIndex: integer);
|
||
|
||
<FM>Description<FN>
|
||
This method finds the associated grouping resource for the specified resource.
|
||
Grouping resources types are "GroupIcon" or "GroupCursor".
|
||
<FC>TypeIndex<FN> must be "Icon" or "Cursor", otherwise returns values are undefined.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
<R> <C><FC>GroupTypeIndex<FN></C> <C><Return value: associated group resource type./C> </R>
|
||
<R> <C><FC>GroupIndex<FN></C> <C><Return value: associated group resource name./C> </R>
|
||
<R> <C><FC>GroupFrameIndex<FN></C> <C><Return value: associated group resource frame./C> </R>
|
||
</TABLE>
|
||
!!}
|
||
procedure TIEResourceExtractor.GetGroupAndFrame(TypeIndex: integer; NameIndex: integer; var GroupTypeIndex: integer; var GroupIndex: integer; var GroupFrameIndex: integer);
|
||
var
|
||
a_GroupCount: integer;
|
||
a_GroupCountFrames: integer;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'Icon' then
|
||
GroupTypeIndex := IndexOfType('GroupIcon')
|
||
else
|
||
if FriendlyTypes[TypeIndex] = 'Cursor' then
|
||
GroupTypeIndex := IndexOfType('GroupCursor')
|
||
else
|
||
exit;
|
||
|
||
a_GroupCount := NamesCount[GroupTypeIndex];
|
||
GroupIndex := 0;
|
||
while GroupIndex < a_GroupCount do
|
||
begin
|
||
a_GroupCountFrames := GroupCountFrames[GroupTypeIndex, GroupIndex];
|
||
GroupFrameIndex := 0;
|
||
while GroupFrameIndex < a_GroupCountFrames do
|
||
begin
|
||
if GroupFrameName[GroupTypeIndex, GroupIndex, GroupFrameIndex] = Names[TypeIndex, NameIndex] then
|
||
exit;
|
||
inc(GroupFrameIndex);
|
||
end;
|
||
inc(GroupIndex);
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GetFrameBuffer
|
||
|
||
<FM>Declaration<FC>
|
||
function GetFrameBuffer(TypeIndex: integer; NameIndex: integer; FrameIndex: integer; var BufferLength: integer): pointer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the buffer of specified frame, for multi-frame resources.
|
||
TypeIndex must be 'GroupIcon' or 'GroupCursor'.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
<R> <C><FC>FrameIndex<FN></C> <C>The frame index. 0 is first resource name, <A TIEResourceExtractor.GroupCountFrames>-1 is last frame.</C> </R>
|
||
<R> <C><FC>BufferLength<FN></C> <C></C> </R>
|
||
</TABLE>
|
||
|
||
!!}
|
||
function TIEResourceExtractor.GetFrameBuffer(TypeIndex: integer; NameIndex: integer; FrameIndex: integer; var BufferLength: integer): pointer;
|
||
begin
|
||
if FriendlyTypes[TypeIndex] = 'GroupIcon' then
|
||
result := GetBuffer('Icon', GroupFrameName[TypeIndex, NameIndex, FrameIndex], BufferLength)
|
||
else
|
||
result := GetBuffer('Cursor', GroupFrameName[TypeIndex, NameIndex, FrameIndex], BufferLength);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.IndexOfType
|
||
|
||
<FM>Declaration<FC>
|
||
function IndexOfType(TypeName: AnsiString): integer;
|
||
|
||
<FM>Description<FN>
|
||
Finds the index of specified type name (ex. 'Icon', 'Cursor', 'GroupIcon'...).
|
||
!!}
|
||
function TIEResourceExtractor.IndexOfType(TypeName: AnsiString): integer;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := m_typesList.IndexOf(string(TypeName));
|
||
if result=-1 then
|
||
// search as friendly type
|
||
for i := 0 to m_typesList.Count-1 do
|
||
if FriendlyTypes[i] = TypeName then
|
||
begin
|
||
result := i;
|
||
break;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.IsValid
|
||
|
||
<FM>Declaration<FC>
|
||
property IsValid: boolean;
|
||
|
||
<FM>Description<FN>
|
||
Checks if TIEResourceExtractor contains valid data.
|
||
|
||
<FM>Example<FC>
|
||
re := TIEResourceExtractor.Create('explorer.exe');
|
||
if re.IsValid then
|
||
begin
|
||
...
|
||
end;
|
||
re.Free;
|
||
!!}
|
||
function TIEResourceExtractor.GetIsValid: boolean;
|
||
begin
|
||
result := (m_hlib<>0);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.TypesCount
|
||
|
||
<FM>Declaration<FC>
|
||
property TypesCount: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns number of resource types found in the PE module.
|
||
!!}
|
||
function TIEResourceExtractor.GetTypesCount: integer;
|
||
begin
|
||
result := m_typesList.Count;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.NamesCount
|
||
|
||
<FM>Declaration<FC>
|
||
property NamesCount[TypeIndex: integer]: integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns number of resource names found in the PE module, for the specified resource type.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
</TABLE>
|
||
|
||
!!}
|
||
function TIEResourceExtractor.GetNamesCount(TypeIndex: integer): integer;
|
||
begin
|
||
if TypeIndex < 0 then
|
||
result := 0
|
||
else
|
||
result := TStringList(m_typesList.Objects[TypeIndex]).Count;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.Types
|
||
|
||
<FM>Declaration<FC>
|
||
property Types[TypeIndex: integer]: AnsiString;
|
||
|
||
<FM>Description<FN>
|
||
Returns the specified resource type name.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
</TABLE>
|
||
|
||
See also: <A TIEResourceExtractor.FriendlyTypes> for more friendly type strings.
|
||
!!}
|
||
function TIEResourceExtractor.GetTypes(TypeIndex: integer): AnsiString;
|
||
begin
|
||
result := AnsiString(m_typesList[TypeIndex]);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.Names
|
||
|
||
<FM>Declaration<FC>
|
||
property Names[TypeIndex: integer; NameIndex: integer]: AnsiString;
|
||
|
||
<FM>Description<FN>
|
||
Returns the resource name for specified type and name index.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
</TABLE>
|
||
|
||
!!}
|
||
function TIEResourceExtractor.GetNames(TypeIndex: integer; NameIndex: integer): AnsiString;
|
||
begin
|
||
result := AnsiString(TStringList(m_typesList.Objects[TypeIndex])[NameIndex]);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.FriendlyTypes
|
||
|
||
<FM>Declaration<FC>
|
||
property FriendlyTypes[TypeIndex: integer]: AnsiString;
|
||
|
||
<FM>Description<FN>
|
||
Returns the specified resource type friendly name (for know types like RT_CURSOR, RT_BITMAP, etc...).
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
</TABLE>
|
||
|
||
Here is the list of Windows resource types and related friendly string.
|
||
|
||
<TABLE>
|
||
<R> <H>Windows resource</H> <H>Friendly type name</H> </R>
|
||
<R> <C><FC>RT_ACCELERATOR<FN></C> <C>'Accelerator'</C> </R>
|
||
<R> <C><FC>RT_ANICURSOR<FN></C> <C>'AniCursor'</C> </R>
|
||
<R> <C><FC>RT_ANIICON<FN></C> <C>'AniIcon'</C> </R>
|
||
<R> <C><FC>RT_BITMAP<FN></C> <C>'Bitmap'</C> </R>
|
||
<R> <C><FC>RT_CURSOR<FN></C> <C>'Cursor'</C> </R>
|
||
<R> <C><FC>RT_DIALOG<FN></C> <C>'Dialog'</C> </R>
|
||
<R> <C><FC>RT_DLGINCLUDE<FN></C> <C>'DlgInclude'</C> </R>
|
||
<R> <C><FC>RT_FONT<FN></C> <C>'Font'</C> </R>
|
||
<R> <C><FC>RT_FONTDIR<FN></C> <C>'FontDir'</C> </R>
|
||
<R> <C><FC>RT_GROUP_CURSOR<FN></C> <C>'GroupCursor'</C> </R>
|
||
<R> <C><FC>RT_GROUP_ICON<FN></C> <C>'GroupIcon'</C> </R>
|
||
<R> <C><FC>RT_HTML<FN></C> <C>'HTML'</C> </R>
|
||
<R> <C><FC>RT_ICON<FN></C> <C>'Icon'</C> </R>
|
||
<R> <C><FC>RT_MANIFEST<FN></C> <C>'Manifest'</C> </R>
|
||
<R> <C><FC>RT_MENU<FN></C> <C>'Menu'</C> </R>
|
||
<R> <C><FC>RT_MESSAGETABLE<FN></C> <C>'MessageTable'</C> </R>
|
||
<R> <C><FC>RT_PLUGPLAY<FN></C> <C>'PlugPlay'</C> </R>
|
||
<R> <C><FC>RT_RCDATA<FN></C> <C>'RCData'</C> </R>
|
||
<R> <C><FC>RT_STRING<FN></C> <C>'String'</C> </R>
|
||
<R> <C><FC>RT_VERSION<FN></C> <C>'Version'</C> </R>
|
||
<R> <C><FC>RT_VXD<FN></C> <C>'VXD'</C> </R>
|
||
</TABLE>
|
||
|
||
See also: <A TIEResourceExtractor.Types> for less friendly type strings.
|
||
!!}
|
||
function TIEResourceExtractor.GetFriendlyTypes(TypeIndex: integer): AnsiString;
|
||
const
|
||
RT_ACCELERATOR = $00000009;
|
||
RT_ANICURSOR = $00000015;
|
||
RT_ANIICON = $00000016;
|
||
RT_BITMAP = $00000002;
|
||
RT_CURSOR = $00000001;
|
||
RT_DIALOG = $00000005;
|
||
RT_DLGINCLUDE = $00000011;
|
||
RT_FONT = $00000008;
|
||
RT_FONTDIR = $00000007;
|
||
RT_GROUP_CURSOR = $0000000C;
|
||
RT_GROUP_ICON = $0000000E;
|
||
RT_HTML = $00000017;
|
||
RT_ICON = $00000003;
|
||
RT_MANIFEST = $00000018;
|
||
RT_MENU = $00000004;
|
||
RT_MESSAGETABLE = $0000000B;
|
||
RT_PLUGPLAY = $00000013;
|
||
RT_RCDATA = $0000000A;
|
||
RT_STRING = $00000006;
|
||
RT_VERSION = $00000010;
|
||
RT_VXD = $00000014;
|
||
var
|
||
resInt: integer;
|
||
begin
|
||
result := Types[TypeIndex];
|
||
if copy(result, 1, 12) = 'INTRESOURCE:' then
|
||
begin
|
||
resInt := IEStrToIntDef(copy(result, 13, length(result)-12), 0);
|
||
case resInt of
|
||
integer(RT_ACCELERATOR): result := 'Accelerator';
|
||
integer(RT_ANICURSOR): result := 'AniCursor';
|
||
integer(RT_ANIICON): result := 'AniIcon';
|
||
integer(RT_BITMAP): result := 'Bitmap';
|
||
integer(RT_CURSOR): result := 'Cursor';
|
||
integer(RT_DIALOG): result := 'Dialog';
|
||
integer(RT_DLGINCLUDE): result := 'DlgInclude';
|
||
integer(RT_FONT): result := 'Font';
|
||
integer(RT_FONTDIR): result := 'FontDir';
|
||
integer(RT_GROUP_CURSOR): result := 'GroupCursor';
|
||
integer(RT_GROUP_ICON): result := 'GroupIcon';
|
||
integer(RT_HTML): result := 'HTML';
|
||
integer(RT_ICON): result := 'Icon';
|
||
integer(RT_MANIFEST): result := 'Manifest';
|
||
integer(RT_MENU): result := 'Menu';
|
||
integer(RT_MESSAGETABLE): result := 'MessageTable';
|
||
integer(RT_PLUGPLAY): result := 'PlugPlay';
|
||
integer(RT_RCDATA): result := 'RCData';
|
||
integer(RT_STRING): result := 'String';
|
||
integer(RT_VERSION): result := 'Version';
|
||
integer(RT_VXD): result := 'VXD';
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GetBuffer
|
||
|
||
<FM>Declaration<FC>
|
||
function GetBuffer(TypeIndex: integer; NameIndex: integer; var BufferLength: integer): pointer;
|
||
function GetBuffer(const TypeStr: AnsiString; const NameStr: AnsiString; var BufferLength: integer): pointer;
|
||
function GetBuffer(ResourceBookmark: <A TIEResourceBookmark>; var BufferLength: integer): pointer;
|
||
|
||
<FM>Description<FN>
|
||
Returns memory buffer for the specified resource.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
<R> <C><FC>BufferLength<FN></C> <C>Field filled with the resulting buffer length (in bytes).</C> </R>
|
||
<R> <C><FC>TypeStr<FN></C> <C>Type as string (ie 'Bitmap', 'Cursor').</C> </R>
|
||
<R> <C><FC>NameStr<FN></C> <C>Resource name as string (ie 'INTRESOURCE:100', 'Hand').</C> </R>
|
||
<R> <C><FC>ResourceBookmark<FN></C> <C>A resource bookmark returned by <A TIEResourceExtractor.GetResourceBookmark>.</C> </R>
|
||
</TABLE>
|
||
|
||
The buffer must not be freed.
|
||
|
||
<FM>Example<FC>
|
||
// loads resource 143, in "Bitmap"s, from "explorer.exe" (should be a little Windows logo)
|
||
var
|
||
re: TIEResourceExtractor;
|
||
buffer: pointer;
|
||
bufferLen: integer;
|
||
begin
|
||
re := TIEResourceExtractor.Create('explorer.exe');
|
||
try
|
||
buffer := re.GetBuffer('Bitmap', 'INTRESOURCE:143', bufferLen);
|
||
ImageEnView1.IO.Params.IsResource := true;
|
||
ImageEnView1.IO.LoadFromBuffer(buffer, bufferLen, ioBMP);
|
||
finally
|
||
re.Free;
|
||
end;
|
||
end;
|
||
|
||
|
||
// loads the resource specified by parameters "resTypeIndex" and "resNameIndex"
|
||
var
|
||
buffer: pointer;
|
||
bufferLen: integer;
|
||
begin
|
||
buffer := m_ResourceExtractor.GetBuffer(resTypeIndex, resNameIndex, bufferLen);
|
||
|
||
ImageEnView1.IO.Params.IsResource := true;
|
||
|
||
if m_ResourceExtractor.FriendlyTypes[resTypeIndex] = 'Bitmap' then
|
||
ImageEnView1.IO.LoadFromBuffer(buffer, bufferLen, ioBMP)
|
||
else
|
||
if m_ResourceExtractor.FriendlyTypes[resTypeIndex] = 'Cursor' then
|
||
ImageEnView1.IO.LoadFromBuffer(buffer, bufferLen, ioCUR)
|
||
else
|
||
if m_ResourceExtractor.FriendlyTypes[resTypeIndex] = 'Icon' then
|
||
ImageEnView1.IO.LoadFromBuffer(buffer, bufferLen, ioICO)
|
||
else
|
||
// We cannot use ioUnknown (autodect) for BMP, CUR and ICO because it is not possible to autodetect BMP, CUR and ICO when they are resources.
|
||
ImageEnView1.IO.LoadFromBuffer(buffer, bufferLen, ioUnknown) // for jpegs, GIF, etc...
|
||
|
||
end;
|
||
!!}
|
||
function TIEResourceExtractor.GetBuffer(TypeIndex: integer; NameIndex: integer; var BufferLength: integer): pointer;
|
||
var
|
||
resName: PAnsiChar;
|
||
resType: PAnsiChar;
|
||
resNameStr: AnsiString;
|
||
resTypeStr: AnsiString;
|
||
resInfo: THandle;
|
||
resData: THandle;
|
||
begin
|
||
result := nil;
|
||
BufferLength := 0;
|
||
|
||
resTypeStr := Types[TypeIndex];
|
||
if copy(resTypeStr, 1, 12) = 'INTRESOURCE:' then
|
||
resType := MakeIntResourceA(IEStrToIntDef(copy(resTypeStr, 13, length(resTypeStr)-12), 0))
|
||
else
|
||
resType := PAnsiChar(resTypeStr);
|
||
|
||
resNameStr := Names[TypeIndex, NameIndex];
|
||
if copy(resNameStr, 1, 12) = 'INTRESOURCE:' then
|
||
resName := MakeIntResourceA(IEStrToIntDef(IECopy(resNameStr, 13, length(resNameStr)-12), 0))
|
||
else
|
||
resName := PAnsiChar(resNameStr);
|
||
|
||
resInfo := FindResourceA(m_hlib, resName, resType);
|
||
if resInfo = 0 then
|
||
exit;
|
||
|
||
resData := LoadResource(m_hlib, resInfo);
|
||
if resData = 0 then
|
||
exit;
|
||
|
||
BufferLength := SizeOfResource(m_hlib, resInfo);
|
||
result := LockResource(resData);
|
||
end;
|
||
|
||
function TIEResourceExtractor.GetBuffer(const TypeStr: AnsiString; const NameStr: AnsiString; var BufferLength: integer): pointer;
|
||
var
|
||
TypeIndex: integer;
|
||
NameIndex: integer;
|
||
i: integer;
|
||
begin
|
||
result := nil;
|
||
|
||
TypeIndex := m_typesList.IndexOf(string(TypeStr));
|
||
if TypeIndex=-1 then
|
||
for i := 0 to m_typesList.Count-1 do
|
||
if FriendlyTypes[i] = TypeStr then
|
||
begin
|
||
TypeIndex := i;
|
||
break;
|
||
end;
|
||
|
||
if TypeIndex>-1 then
|
||
begin
|
||
NameIndex := TStringList(m_typesList.Objects[TypeIndex]).IndexOf(string(NameStr));
|
||
if NameIndex>-1 then
|
||
result := GetBuffer(TypeIndex, NameIndex, BufferLength);
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEResourceExtractor.GetResourceBookmark
|
||
|
||
<FM>Declaration<FC>
|
||
function GetResourceBookmark(TypeIndex: integer; NameIndex: integer; FrameIndex: integer = -1): <A TIEResourceBookmark>;
|
||
|
||
<FM>Description<FN>
|
||
Creates a bookmark for the specified resource (or resource frame).
|
||
Bookmarks are automatically freed.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>TypeIndex<FN></C> <C>Index of resource type. 0 is first resource type, <A TIEResourceExtractor.TypesCount>-1 is last resource type.</C> </R>
|
||
<R> <C><FC>NameIndex<FN></C> <C>Index of actual resource. 0 is first resource name, <A TIEResourceExtractor.NamesCount>-1 is last resource name.</C> </R>
|
||
<R> <C><FC>FrameIndex<FN></C> <C>The frame index. 0 is first resource name, <A TIEResourceExtractor.GroupCountFrames>-1 is last frame.</C> </R>
|
||
</TABLE>
|
||
|
||
!!}
|
||
function TIEResourceExtractor.GetResourceBookmark(TypeIndex: integer; NameIndex: integer; FrameIndex: integer = -1): TIEResourceBookmark;
|
||
begin
|
||
result := TIEResourceBookmark.Create(TypeIndex, NameIndex, FrameIndex);
|
||
m_resourceBookmarks.Add(result);
|
||
end;
|
||
|
||
function TIEResourceExtractor.GetBuffer(ResourceBookmark: TIEResourceBookmark; var BufferLength: integer): pointer;
|
||
begin
|
||
if ResourceBookmark.m_FrameIndex < 0 then
|
||
result := GetBuffer(ResourceBookmark.m_TypeIndex, ResourceBookmark.m_NameIndex, BufferLength)
|
||
else
|
||
result := GetFrameBuffer(ResourceBookmark.m_TypeIndex, ResourceBookmark.m_NameIndex, ResourceBookmark.m_FrameIndex, BufferLength);
|
||
end;
|
||
|
||
constructor TIEResourceBookmark.Create(TypeIndex_, NameIndex_, FrameIndex_: integer);
|
||
begin
|
||
inherited Create;
|
||
m_TypeIndex := TypeIndex_;
|
||
m_NameIndex := NameIndex_;
|
||
m_FrameIndex := FrameIndex_;
|
||
end;
|
||
|
||
{$endif} // IEINCLUDERESOURCEEXTRACTOR
|
||
|
||
// TIEResourceExtractor
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
constructor TIERandomGenerator.Create(Seed: dword);
|
||
begin
|
||
x := 123456789 xor (Seed);
|
||
y := 362436069 xor (Seed shl 8);
|
||
z := 521288629 xor (Seed shl 16);
|
||
w := 88675123 xor (Seed shl 24);
|
||
end;
|
||
|
||
constructor TIERandomGenerator.Create(Seed: AnsiString);
|
||
var
|
||
i: integer;
|
||
begin
|
||
x := 123456789;
|
||
y := 362436069;
|
||
z := 521288629;
|
||
w := 88675123;
|
||
for i := 1 to length(Seed) do
|
||
begin
|
||
x := x xor (ord(Seed[i]));
|
||
y := y xor (ord(Seed[i]) shl 8);
|
||
z := z xor (ord(Seed[i]) shl 16);
|
||
w := w xor (ord(Seed[i]) shl 24);
|
||
end;
|
||
end;
|
||
|
||
constructor TIERandomGenerator.Create(Seed1, Seed2, Seed3, Seed4: dword);
|
||
begin
|
||
x := Seed1;
|
||
y := Seed2;
|
||
z := Seed3;
|
||
w := Seed4;
|
||
end;
|
||
|
||
function TIERandomGenerator.NextDWORD(): dword;
|
||
var
|
||
t: dword;
|
||
begin
|
||
t := x xor (x shl 11);
|
||
x := y; y := z; z := w;
|
||
w := w xor (w shr 19) xor (t xor (t shr 8));
|
||
result := w;
|
||
end;
|
||
|
||
function TIERandomGenerator.NextINT64(): int64;
|
||
begin
|
||
result := NextDWORD() or (NextDWORD() shl 32);
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
constructor TIE8087ExceptionsDisabler.Create();
|
||
begin
|
||
inherited;
|
||
FPUControlWord := Get8087CW();
|
||
Set8087CW($133F);
|
||
end;
|
||
|
||
destructor TIE8087ExceptionsDisabler.Destroy();
|
||
begin
|
||
Set8087CW(FPUControlWord);
|
||
inherited;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
constructor TIEStringSplitter.Create(const Text: string; const Delimiters: string);
|
||
begin
|
||
inherited Create();
|
||
|
||
m_text := Text;
|
||
m_strings := TStringList.Create();
|
||
m_delimiters := Delimiters;
|
||
m_bypassSpaces := true;
|
||
|
||
try
|
||
Update();
|
||
except
|
||
m_strings.Free();
|
||
raise;
|
||
end;
|
||
end;
|
||
|
||
destructor TIEStringSplitter.Destroy();
|
||
begin
|
||
m_strings.Free();
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEStringSplitter.SetText(const Text: string);
|
||
begin
|
||
m_text := Text;
|
||
Update();
|
||
end;
|
||
|
||
function TIEStringSplitter.GetText(): string;
|
||
begin
|
||
result := m_text;
|
||
end;
|
||
|
||
function TIEStringSplitter.GetString(Index: integer): string;
|
||
begin
|
||
result := m_strings[Index];
|
||
end;
|
||
|
||
function TIEStringSplitter.GetCount(): integer;
|
||
begin
|
||
result := m_strings.Count;
|
||
end;
|
||
|
||
function TIEStringSplitter.GetDelimiters(): string;
|
||
begin
|
||
result := m_delimiters;
|
||
end;
|
||
|
||
procedure TIEStringSplitter.SetDelimiters(const Value: string);
|
||
begin
|
||
if Value <> m_delimiters then
|
||
begin
|
||
m_delimiters := Value;
|
||
Update();
|
||
end;
|
||
end;
|
||
|
||
function TIEStringSplitter.GetByPassSpaces(): boolean;
|
||
begin
|
||
result := m_bypassSpaces;
|
||
end;
|
||
|
||
procedure TIEStringSplitter.SetByPassSpaces(Value: boolean);
|
||
begin
|
||
if Value <> m_bypassSpaces then
|
||
begin
|
||
m_bypassSpaces := Value;
|
||
Update();
|
||
end;
|
||
end;
|
||
|
||
function TIEStringSplitter.IsSpace(c: char): boolean;
|
||
begin
|
||
result := (c = #$20) or (c = #$09) or (c = #$0a) or (c = #$0b) or (c = #$0c) or (c = #$0d);
|
||
end;
|
||
|
||
procedure TIEStringSplitter.Update();
|
||
var
|
||
p, i, l, len: integer;
|
||
|
||
procedure bypassSpaces();
|
||
begin
|
||
if m_bypassSpaces then
|
||
while (i <= len) and IsSpace(m_text[i]) do
|
||
inc(i);
|
||
end;
|
||
|
||
function isDelimiter(c: char): boolean;
|
||
begin
|
||
result := Pos(c, m_delimiters) > 0;
|
||
end;
|
||
|
||
procedure add(start: integer; length: integer);
|
||
begin
|
||
if m_bypassSpaces then
|
||
m_strings.Add(trim(Copy(m_text, start, length)))
|
||
else
|
||
m_strings.Add(Copy(m_text, start, length));
|
||
end;
|
||
|
||
begin
|
||
m_strings.Clear();
|
||
|
||
len := length(m_text);
|
||
if m_bypassSpaces then
|
||
while (len > 0) and (IsSpace(m_text[len])) do
|
||
dec(len);
|
||
|
||
i := 1;
|
||
bypassSpaces();
|
||
p := i;
|
||
while i <= len do
|
||
begin
|
||
if isDelimiter(m_text[i]) then
|
||
begin
|
||
add(p, i - p);
|
||
inc(i);
|
||
bypassSpaces();
|
||
p := i;
|
||
end
|
||
else
|
||
inc(i);
|
||
end;
|
||
|
||
l := len - p + 1;
|
||
if (l > 0) or ((length(m_text) > 0) and isDelimiter(m_text[i - 1])) then
|
||
add(p, l);
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEFileBuffer
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
constructor TIEFileBuffer.Create;
|
||
begin
|
||
inherited;
|
||
fFileName := '';
|
||
fMapped := TList.Create;
|
||
fSimFile := nil;
|
||
end;
|
||
|
||
destructor TIEFileBuffer.Destroy;
|
||
begin
|
||
DeAllocate;
|
||
FreeAndNil(fMapped);
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEFileBuffer.DeAllocate;
|
||
begin
|
||
if IsAllocated then
|
||
begin
|
||
UnMapAll;
|
||
FreeAndNil(fSimFile);
|
||
DeleteFile(fFileName);
|
||
end;
|
||
end;
|
||
|
||
function TIEFileBuffer.IsAllocated: boolean;
|
||
begin
|
||
result := fSimFile <> nil
|
||
end;
|
||
|
||
// if FileName is '', creates a temp file name in DefTEMPPATH
|
||
function TIEFileBuffer.AllocateFile(InSize: int64; const Descriptor: string; UseDisk: boolean): boolean;
|
||
var
|
||
temppath: array[0..MAX_PATH] of Char;
|
||
tp: string;
|
||
begin
|
||
if IsAllocated then
|
||
DeAllocate;
|
||
result := false;
|
||
if IEGlobalSettings().DefTEMPPATH = '' then
|
||
begin
|
||
GetTempPath(250, temppath);
|
||
tp := string(temppath);
|
||
end
|
||
else
|
||
tp := IEGlobalSettings().DefTEMPPATH;
|
||
fFileName := IEGetTempFileName(Descriptor, tp);
|
||
try
|
||
if UseDisk then
|
||
begin
|
||
(*
|
||
problems of DiskFree: cannot detect disk>2GB, (0)=current directory (imagine changing directory to USB disk or CDROM)
|
||
if InSize>(DiskFree(0)-128000000) then
|
||
exit;
|
||
*)
|
||
fSimFile := TIETemporaryFileStream.Create(fFileName);
|
||
end
|
||
else
|
||
fSimFile := TMemoryStream.Create;
|
||
fSimFile.Size := InSize;
|
||
result := true;
|
||
except
|
||
end;
|
||
end;
|
||
|
||
procedure TIEFileBuffer.ReAllocateFile(NewSize: int64);
|
||
begin
|
||
fSimFile.Size := NewSize;
|
||
end;
|
||
|
||
// can copy maximum 2^31 bytes
|
||
|
||
procedure TIEFileBuffer.CopyTo(Dest: TIEFileBuffer; InPos, InSize: int64);
|
||
const
|
||
BUFSIZE = 1024 * 1024;
|
||
var
|
||
i: integer;
|
||
buf: pbyte;
|
||
begin
|
||
if (not IsAllocated) or (not Dest.IsAllocated) then
|
||
exit;
|
||
UnMapAll;
|
||
Dest.UnMapAll;
|
||
(*
|
||
// disabled because since 2.2.7 we use TIETemporaryFileStream instead of TFileStream
|
||
if (InPos = 0) and (InSize = fSimFile.Size) then
|
||
begin
|
||
// copy the full file using operating system functions
|
||
FreeAndNil(fSimFile);
|
||
FreeAndNil(Dest.fSimFile);
|
||
deletefile(Dest.fFileName);
|
||
copyfile(PAnsiChar(fFileName), PAnsiChar(Dest.fFileName), false);
|
||
Dest.fSimFile := TFileStream.Create(Dest.fFileName, fmOpenReadWrite);
|
||
fSimFile := TFileStream.Create(fFileName, fmOpenReadWrite);
|
||
end
|
||
else
|
||
*)
|
||
begin
|
||
fSimFile.Position := InPos;
|
||
Dest.fSimFile.Position := InPos;
|
||
getmem(buf, BUFSIZE);
|
||
repeat
|
||
if InSize < BUFSIZE then
|
||
i := InSize
|
||
else
|
||
i := BUFSIZE;
|
||
fSimFile.Read(buf^, i);
|
||
Dest.fSimFile.Write(buf^, i);
|
||
dec(InSize, i);
|
||
until InSize <= 0;
|
||
freemem(buf);
|
||
end;
|
||
end;
|
||
|
||
procedure TIEFileBuffer.CopyTo(Dest: TStream; InPos, InSize: int64);
|
||
begin
|
||
if (not IsAllocated) then
|
||
exit;
|
||
UnMapAll;
|
||
fSimFile.Position := InPos;
|
||
IECopyFrom(Dest, fSimFile, InSize);
|
||
end;
|
||
|
||
function TIEFileBuffer.IndexOf(ptr: pointer): integer;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := -1;
|
||
for i := 0 to fMapped.Count - 1 do
|
||
if PIEFileBufferItem(fMapped[i])^.ptr = ptr then
|
||
begin
|
||
result := i;
|
||
break;
|
||
end;
|
||
end;
|
||
|
||
function TIEFileBuffer.Map(InPos, InSize: int64; DataAccess: TIEDataAccess): pointer;
|
||
var
|
||
item: PIEFileBufferItem;
|
||
begin
|
||
result := IEAutoAlloc(InSize);
|
||
if result <> nil then
|
||
begin
|
||
if (fSimFile <> nil) and (iedRead in DataAccess) then
|
||
begin
|
||
fSimFile.Position := InPos;
|
||
fSimFile.Read(pbyte(result)^, InSize);
|
||
end;
|
||
new(item);
|
||
item^.Pos := InPos;
|
||
item^.Size := InSize;
|
||
item^.ptr := result;
|
||
item^.access := DataAccess;
|
||
fMapped.Add(item);
|
||
end;
|
||
end;
|
||
|
||
procedure TIEFileBuffer.UnMap(ptr: pointer);
|
||
var
|
||
i: integer;
|
||
item: PIEFileBufferItem;
|
||
begin
|
||
if ptr <> nil then
|
||
begin
|
||
i := IndexOf(ptr);
|
||
item := fMapped[i];
|
||
if (fSimFile<>nil) and (iedWrite in item^.access) then
|
||
begin
|
||
fSimFile.Position := item^.Pos;
|
||
fSimFile.Write(pbyte(ptr)^, item^.Size);
|
||
end;
|
||
dispose(item);
|
||
fMapped.Delete(i);
|
||
IEAutoFree(ptr);
|
||
end;
|
||
end;
|
||
|
||
procedure TIEFileBuffer.UnMapAll;
|
||
begin
|
||
if IsAllocated then
|
||
while fMapped.Count > 0 do
|
||
UnMap(PIEFileBufferItem(fMapped[fMapped.Count - 1]).ptr);
|
||
end;
|
||
|
||
procedure TIEFileBuffer.CopyFrom(DestPos: int64; Source: pointer; Size: int64);
|
||
begin
|
||
if fSimFile <> nil then
|
||
begin
|
||
fSimFile.Position := DestPos;
|
||
fSimFile.Write(pbyte(Source)^, Size);
|
||
end;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIETemporaryFileStream
|
||
|
||
constructor TIETemporaryFileStream.Create(const FileName: string);
|
||
begin
|
||
FHandle := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE or FILE_ATTRIBUTE_TEMPORARY, 0);
|
||
if FHandle = INVALID_HANDLE_VALUE then
|
||
raise EInOutError.Create('Unable to create '+FileName);
|
||
inherited Create(FHandle);
|
||
end;
|
||
|
||
destructor TIETemporaryFileStream.Destroy;
|
||
begin
|
||
if FHandle <> INVALID_HANDLE_VALUE then
|
||
FileClose(FHandle);
|
||
inherited Destroy;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Hash functions
|
||
|
||
function IE_ELFHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
var
|
||
i: cardinal;
|
||
x: cardinal;
|
||
begin
|
||
result := 0;
|
||
for i := 1 to length(str) do
|
||
begin
|
||
result := (result shl 4) + ord(str[i]);
|
||
x := result and $F0000000;
|
||
if (x <> 0) then
|
||
result := (result xor (x shr 24)) and (not x);
|
||
end;
|
||
result := result mod bucketCount;
|
||
end;
|
||
|
||
|
||
function IE_RSHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
const
|
||
b = 378551;
|
||
var
|
||
a : cardinal;
|
||
i : integer;
|
||
begin
|
||
a := 63689;
|
||
result := 0;
|
||
for i := 1 to length(str) do
|
||
begin
|
||
result := result * a + ord(str[i]);
|
||
a := a * b;
|
||
end;
|
||
result := result mod bucketCount;
|
||
end;
|
||
|
||
|
||
function IE_JSHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := 1315423911;
|
||
for i := 1 to length(str) do
|
||
result := result xor ((result shl 5) + ord(str[i]) + (result shr 2));
|
||
result := result mod bucketCount;
|
||
end;
|
||
|
||
// MurmurHash
|
||
function IE_MMHash(const str: WideString; const Seed: Cardinal = $9747b28c): Cardinal;
|
||
var
|
||
h: Cardinal;
|
||
len: Cardinal;
|
||
k: Cardinal;
|
||
data: Integer;
|
||
const
|
||
// 'm' and 'r' are mixing constants that work well.
|
||
m = $5bd1e995;
|
||
r = 24;
|
||
begin
|
||
len := Length( str );
|
||
h := seed xor len;
|
||
|
||
// Mix 4 bytes at a time into the hash
|
||
data := 1;
|
||
while len >= 4 do
|
||
begin
|
||
k := pCardinal( @str[ data ] )^;
|
||
|
||
k := k * m;
|
||
k := k xor (k shr r);
|
||
k := k * m;
|
||
|
||
h := h * m;
|
||
h := h xor k;
|
||
|
||
data := data + 4;
|
||
len := len - 4;
|
||
end;
|
||
|
||
// Handle last few bytes of the input array
|
||
if len = 3 then
|
||
h := h xor ( Cardinal( str[ data + 2 ]) shl 16 );
|
||
if len >= 2 then
|
||
h := h xor ( Cardinal( str[ data + 1 ]) shl 8 );
|
||
if len >= 1 then
|
||
begin
|
||
h := h xor ( Cardinal( str[ data ]));
|
||
h := h * m;
|
||
end;
|
||
|
||
// Do a few final mixes of the hash to ensure the last few
|
||
// bytes are well-incorporated.
|
||
h := h xor ( h shr 13 );
|
||
h := h * m;
|
||
h := h xor ( h shr 15 );
|
||
|
||
Result := h;
|
||
end;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEDictionary
|
||
|
||
|
||
constructor TIEDictionaryValueWideString.Create(value: WideString);
|
||
begin
|
||
self.value := value;
|
||
end;
|
||
|
||
destructor TIEDictionaryValueWideString.Destroy();
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
|
||
constructor TIEDictionaryValueInteger.Create(value: integer);
|
||
begin
|
||
self.value := value;
|
||
end;
|
||
|
||
destructor TIEDictionaryValueInteger.Destroy();
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
|
||
constructor TIEDictionaryValueDouble.Create(value: double);
|
||
begin
|
||
self.value := value;
|
||
end;
|
||
|
||
destructor TIEDictionaryValueDouble.Destroy();
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
|
||
constructor TIEDictionaryValueBoolean.Create(value: boolean);
|
||
begin
|
||
self.value := value;
|
||
end;
|
||
|
||
destructor TIEDictionaryValueBoolean.Destroy();
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
|
||
constructor TIEDictionaryBucket.Create(const key_: WideString; const value_: TObject; next_: TIEDictionaryBucket);
|
||
begin
|
||
inherited Create;
|
||
key := key_;
|
||
value := value_;
|
||
next := next_;
|
||
end;
|
||
|
||
|
||
destructor TIEDictionaryBucket.Destroy();
|
||
begin
|
||
value.Free();
|
||
end;
|
||
|
||
|
||
constructor TIEStrStrEnumerator.Create();
|
||
begin
|
||
inherited Create;
|
||
bucket := 0;
|
||
item := nil;
|
||
end;
|
||
|
||
destructor TIEStrStrEnumerator.Destroy();
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
|
||
|
||
procedure TIEDictionary.CheckInit();
|
||
var
|
||
i: cardinal;
|
||
begin
|
||
if not m_initDone then
|
||
begin
|
||
if not IEIsPrime(m_bucketCount) then
|
||
m_bucketCount := IENextPrime(m_bucketCount);
|
||
|
||
SetLength(m_buckets, m_bucketCount);
|
||
for i := 0 to m_bucketCount - 1 do
|
||
m_buckets[i] := nil;
|
||
|
||
m_initDone := true;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Create
|
||
|
||
<FM>Declaration<FC>
|
||
constructor Create(buckets: cardinal; hashFunction: TIEStrHashFunction; caseSensitive: boolean = false); overload;
|
||
constructor Create(buckets: cardinal = 103; caseSensitive: boolean = false); overload;
|
||
|
||
<FM>Description<FN>
|
||
Creates a new instance of TIEDictionary.
|
||
!!}
|
||
constructor TIEDictionary.Create(buckets: cardinal; hashFunction: TIEStrHashFunction; caseSensitive: boolean);
|
||
begin
|
||
inherited Create;
|
||
m_initDone := false;
|
||
m_bucketCount := buckets;
|
||
m_hashFunction := hashFunction;
|
||
m_caseSensitive := caseSensitive;
|
||
m_count := 0;
|
||
end;
|
||
|
||
|
||
constructor TIEDictionary.Create(buckets: cardinal; caseSensitive: boolean);
|
||
begin
|
||
inherited Create;
|
||
m_initDone := false;
|
||
m_bucketCount := buckets;
|
||
m_hashFunction := @IE_ELFHash;
|
||
m_caseSensitive := caseSensitive;
|
||
m_count := 0;
|
||
end;
|
||
|
||
|
||
destructor TIEDictionary.Destroy();
|
||
begin
|
||
Clear();
|
||
inherited;
|
||
end;
|
||
|
||
|
||
function TIEDictionary.execHash(const str: WideString; bucketCount: cardinal): cardinal;
|
||
begin
|
||
if m_caseSensitive then
|
||
result := m_hashFunction(str, bucketCount)
|
||
else
|
||
result := m_hashFunction(UpperCase(str), bucketCount);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Clear
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Clear();
|
||
|
||
<FM>Description<FN>
|
||
Empties the dictionary.
|
||
!!}
|
||
procedure TIEDictionary.Clear();
|
||
var
|
||
i: cardinal;
|
||
nxt, ths: TIEDictionaryBucket;
|
||
begin
|
||
if m_initDone then
|
||
begin
|
||
for i := 0 to m_bucketCount - 1 do
|
||
begin
|
||
ths := m_buckets[i];
|
||
while ths <> nil do
|
||
begin
|
||
nxt := ths.next;
|
||
ths.Free();
|
||
ths := nxt;
|
||
end;
|
||
m_buckets[i] := nil;
|
||
end;
|
||
m_count := 0;
|
||
end;
|
||
end;
|
||
|
||
|
||
function TIEDictionary.keysMatch(const key1: WideString; const key2: WideString): boolean;
|
||
begin
|
||
if m_caseSensitive then
|
||
result := key1 = key2
|
||
else
|
||
result := UpperCase(key1) = UpperCase(key2);
|
||
end;
|
||
|
||
|
||
function TIEDictionary.GetInBucket(bucket: cardinal; key: WideString; out lastItem: TIEDictionaryBucket): TIEDictionaryBucket;
|
||
var
|
||
ths: TIEDictionaryBucket;
|
||
begin
|
||
CheckInit();
|
||
result := nil;
|
||
ths := m_buckets[bucket];
|
||
lastItem := ths;
|
||
while (ths <> nil) and (result = nil) do
|
||
begin
|
||
lastItem := ths;
|
||
if keysMatch(ths.key, key) then
|
||
result := ths;
|
||
ths := ths.next;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.HasKey
|
||
|
||
<FM>Declaration<FC>
|
||
function HasKey(key: WideString; recursive: boolean = true): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns the true if the key exists.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.HasKey(key: WideString; recursive: boolean): boolean;
|
||
begin
|
||
result := Get(key, true, recursive) <> nil;
|
||
end;
|
||
|
||
|
||
// recursive key search
|
||
function TIEDictionary.FindInDictionaries(key: WideString): TObject;
|
||
var
|
||
current: TIEStrStrEnumerator;
|
||
olist: TObjectList;
|
||
i: integer;
|
||
begin
|
||
result := nil;
|
||
current := TIEStrStrEnumerator.Create();
|
||
while GetNext(current) do
|
||
begin
|
||
if current.item.value is TIEDictionary then
|
||
begin
|
||
result := (current.item.value as TIEDictionary).Get(key, true, true);
|
||
if result <> nil then
|
||
break;
|
||
end
|
||
else if current.item.value is TObjectList then
|
||
begin
|
||
olist := current.item.value as TObjectList;
|
||
for i := 0 to olist.Count - 1 do
|
||
begin
|
||
if olist[i] is TIEDictionary then
|
||
result := (olist[i] as TIEDictionary).Get(key, true, true);
|
||
if result <> nil then
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
current.Free();
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Get
|
||
|
||
<FM>Declaration<FC>
|
||
function Get(key: WideString; silent: boolean = false; recursive: boolean = true): TObject;
|
||
|
||
<FM>Description<FN>
|
||
Returns the value to which the key is mapped in this dictionary. If the key doesn't exist returns <FC>nil<FN> or raises an exception.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>silent<FN></C> <C>If true no exception is raised if the key doesn't exist</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.Get(key: WideString; silent: boolean; recursive: boolean): TObject;
|
||
var
|
||
bucket: cardinal;
|
||
ths, lst: TIEDictionaryBucket;
|
||
begin
|
||
CheckInit();
|
||
bucket := execHash(key, m_bucketCount);
|
||
ths := GetInBucket(bucket, key, lst);
|
||
if ths <> nil then
|
||
result := ths.value
|
||
else
|
||
begin
|
||
result := nil;
|
||
if recursive then
|
||
result := FindInDictionaries(key);
|
||
if (result = nil) and not silent then
|
||
raise EIEException.Create(Format('Key "%s" not found', [key]));
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetString
|
||
|
||
<FM>Declaration<FC>
|
||
function GetString(key: WideString; recursive: boolean = true): WideString;
|
||
|
||
<FM>Description<FN>
|
||
Returns the string value to which the key is mapped in this dictionary. If the key doesn't exist an exception is raised.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Examples<FC>
|
||
// Return the photo description from the XMP metadata
|
||
sDescription := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'dc:description' );
|
||
|
||
// Return the creation date from the XMP metadata (XMP date strings are formatted the same EXIF date strings)
|
||
dtCreateDate := EXIFDateToDateTime( ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'xmp:CreateDate' ));
|
||
|
||
// Return the creator or author of the asset from the XMP metadata
|
||
sCreator := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'dc:creator' );
|
||
|
||
// Return location information about the content being shown in the image
|
||
sLocation := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'photoshop:City' ) + ', ' +
|
||
ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'photoshop:State' ) + ', ' +
|
||
ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'photoshop:Country' );
|
||
|
||
// Return the document title from the XMP metadata
|
||
sTitle := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'dc:title' );
|
||
|
||
// Return the document keywords from the XMP metadata
|
||
sKeywords := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'dc:subject' );
|
||
|
||
// Return the document copyright information from the XMP metadata
|
||
sCopyright := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'dc:rights' );
|
||
|
||
// Return the Photoshop Headline from the XMP metadata
|
||
sHeadline := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'photoshop:Headline' );
|
||
|
||
// Return the Windows Rating from the XMP metadata (0 to 5)
|
||
sRating := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'xmp:Rating' );
|
||
|
||
!!}
|
||
function TIEDictionary.GetString(key: WideString; recursive: boolean): WideString;
|
||
var
|
||
obj: TObject;
|
||
begin
|
||
obj := Get(key, false, recursive);
|
||
if obj is TIEDictionaryValueInteger then
|
||
result := IntToStr((obj as TIEDictionaryValueInteger).value)
|
||
else
|
||
if obj is TIEDictionaryValueDouble then
|
||
result := IEFloatToStrW((obj as TIEDictionaryValueDouble).value)
|
||
else
|
||
if obj is TIEDictionary then
|
||
result := (obj as TIEDictionary).GetString('#text', true)
|
||
else
|
||
result := (obj as TIEDictionaryValueWideString).value;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetInteger
|
||
|
||
<FM>Declaration<FC>
|
||
function GetInteger(key: WideString; recursive: boolean = true): integer;
|
||
|
||
<FM>Description<FN>
|
||
Returns the integer value to which the key is mapped in this dictionary. If the key doesn't exist an exception is raised.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Examples<FC>
|
||
// Return the Photoshop Color Mode from the XMP metadata
|
||
iColorMode := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetInteger( 'photoshop:ColorMode' );
|
||
|
||
!!}
|
||
function TIEDictionary.GetInteger(key: WideString; recursive: boolean): integer;
|
||
var
|
||
obj: TObject;
|
||
begin
|
||
obj := Get(key, false, recursive);
|
||
if obj is TIEDictionaryValueDouble then
|
||
result := trunc( (obj as TIEDictionaryValueDouble).value )
|
||
else
|
||
if obj is TIEDictionaryValueWideString then
|
||
result := StrToInt((obj as TIEDictionaryValueWideString).value)
|
||
else
|
||
if obj is TIEDictionary then
|
||
result := (obj as TIEDictionary).GetInteger('#text', true)
|
||
else
|
||
result := (obj as TIEDictionaryValueInteger).value;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetDouble
|
||
|
||
<FM>Declaration<FC>
|
||
function GetDouble(key: WideString; recursive: boolean = true): double;
|
||
|
||
<FM>Description<FN>
|
||
Returns the double value to which the key is mapped in this dictionary. If the key doesn't exist an exception is raised.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.GetDouble(key: WideString; recursive: boolean): double;
|
||
var
|
||
obj: TObject;
|
||
begin
|
||
obj := Get(key, false, recursive);
|
||
if obj is TIEDictionaryValueInteger then
|
||
result := (obj as TIEDictionaryValueInteger).value
|
||
else
|
||
if obj is TIEDictionaryValueWideString then
|
||
result := IEStrToFloatDefW((obj as TIEDictionaryValueWideString).value, 0.0)
|
||
else
|
||
if obj is TIEDictionary then
|
||
result := (obj as TIEDictionary).GetDouble('#text', true)
|
||
else
|
||
result := (obj as TIEDictionaryValueDouble).value;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetBoolean
|
||
|
||
<FM>Declaration<FC>
|
||
function GetBoolean(key: WideString; recursive: boolean = true): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns the boolean value to which the key is mapped in this dictionary. If the key doesn't exist an exception is raised.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.GetBoolean(key: WideString; recursive: boolean): boolean;
|
||
var
|
||
obj: TObject;
|
||
begin
|
||
obj := Get(key, false, recursive);
|
||
if obj is TIEDictionaryValueInteger then
|
||
result := (obj as TIEDictionaryValueInteger).value <> 0
|
||
else
|
||
if obj is TIEDictionaryValueDouble then
|
||
result := (obj as TIEDictionaryValueDouble).value <> 0.0
|
||
else
|
||
if obj is TIEDictionaryValueWideString then
|
||
result := (obj as TIEDictionaryValueWideString).value = 'true'
|
||
else
|
||
if obj is TIEDictionary then
|
||
result := (obj as TIEDictionary).GetBoolean('#text', true)
|
||
else
|
||
result := (obj as TIEDictionaryValueBoolean).value;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetDictionary
|
||
|
||
<FM>Declaration<FC>
|
||
function GetDictionary(key: WideString; recursive: boolean = true): <A TIEDictionary>;
|
||
|
||
<FM>Description<FN>
|
||
Returns the <A TIEDictionary> value to which the key is mapped in this dictionary. If the key doesn't exist an exception is raised.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.GetDictionary(key: WideString; recursive: boolean): TIEDictionary;
|
||
begin
|
||
result := Get(key, false, recursive) as TIEDictionary;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetList
|
||
|
||
<FM>Declaration<FC>
|
||
function GetList(key: WideString; recursive: boolean = true): TObjectList;
|
||
|
||
<FM>Description<FN>
|
||
Returns the TObjectList value to which the key is mapped in this dictionary. If the key doesn't exist an exception is raised.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>recursive<FN></C> <C>If true then search this key inside subdictionaries</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.GetList(key: WideString; recursive: boolean): TObjectList;
|
||
begin
|
||
result := Get(key, false, recursive) as TObjectList;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Insert
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Insert(key: WideString; value: TObject); overload;
|
||
procedure Insert(key: WideString; value: WideString); overload;
|
||
procedure Insert(key: WideString; value: integer); overload;
|
||
procedure Insert(key: WideString; value: double); overload;
|
||
procedure Insert(key: WideString; value: boolean); overload;
|
||
procedure Insert(key: WideString; value: <A TIEDictionary>); overload;
|
||
procedure Insert(key: WideString; value: TObjectList); overload;
|
||
|
||
<FM>Description<FN>
|
||
Maps the specified key to the specified object or value in this dictionary.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A string key</C> </R>
|
||
<R> <C><FC>value<FN></C> <C>Object/value to store. The dictionary owns the object: it will be automatically disposed.</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
procedure TIEDictionary.Insert(key: WideString; value: TObject);
|
||
var
|
||
bucket: cardinal;
|
||
ths, lst: TIEDictionaryBucket;
|
||
begin
|
||
CheckInit();
|
||
bucket := execHash(key, m_bucketCount);
|
||
if m_buckets[bucket] = nil then
|
||
begin
|
||
// bucket free, just set this item
|
||
m_buckets[bucket] := TIEDictionaryBucket.Create(key, value);
|
||
inc(m_count);
|
||
end
|
||
else
|
||
begin
|
||
// bucket not free, find for equal item
|
||
ths := GetInBucket(bucket, key, lst);
|
||
if ths = nil then
|
||
begin
|
||
// not equal item, insert this item after the last one
|
||
lst.next := TIEDictionaryBucket.Create(key, value, nil);
|
||
inc(m_count);
|
||
end
|
||
else
|
||
begin
|
||
// equal item found, just replace value
|
||
ths.value.Free();
|
||
ths.value := value;
|
||
// do not inc m_count!
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Insert(key: WideString; value: WideString);
|
||
begin
|
||
Insert(key, TIEDictionaryValueWideString.Create(value));
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Insert(key: WideString; value: integer);
|
||
begin
|
||
Insert(key, TIEDictionaryValueInteger.Create(value));
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Insert(key: WideString; value: double);
|
||
begin
|
||
Insert(key, TIEDictionaryValueDouble.Create(value));
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Insert(key: WideString; value: boolean);
|
||
begin
|
||
Insert(key, TIEDictionaryValueBoolean.Create(value));
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Insert(key: WideString; value: TIEDictionary);
|
||
begin
|
||
Insert(key, TObject(value));
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Insert(key: WideString; value: TObjectList);
|
||
begin
|
||
Insert(key, TObject(value));
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Erase
|
||
|
||
<FM>Declaration<FC>
|
||
function Erase(key: WideString): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Remove the specified key.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>key<FN></C> <C>A key in this dictionary</C> </R>
|
||
<R> <C><FC>freeValue<FN></C> <C>If True the value is deallocated</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
function TIEDictionary.Erase(key: WideString; freeValue: boolean): boolean;
|
||
var
|
||
bucket: cardinal;
|
||
ths, prev: TIEDictionaryBucket;
|
||
begin
|
||
CheckInit();
|
||
result := false;
|
||
bucket := execHash(key, m_bucketCount);
|
||
prev := nil;
|
||
ths := m_buckets[bucket];
|
||
while (ths <> nil) do
|
||
begin
|
||
if keysMatch(ths.key, key) then
|
||
begin
|
||
// found
|
||
if prev = nil then
|
||
// this is the first item in bucket
|
||
m_buckets[bucket] := ths.next
|
||
else
|
||
// has a previous item, change it
|
||
prev.next := ths.next;
|
||
if not freeValue then
|
||
ths.value := nil;
|
||
ths.Free();
|
||
dec(m_count);
|
||
result := true;
|
||
break;
|
||
end;
|
||
prev := ths;
|
||
ths := ths.next;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.GetNext
|
||
|
||
<FM>Declaration<FC>
|
||
function GetNext(current: TIEStrStrEnumerator): boolean;
|
||
|
||
|
||
<FM>Description<FN>
|
||
Allows to iterate among all dictionary elements.
|
||
Returns <FC>true<FN> if an element is available.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>current<FN></C> <C>An object used to store current enumerator state.</C> </R>
|
||
</TABLE>
|
||
|
||
|
||
<FM>Example<FC>
|
||
var current: TIEStrStrEnumerator;
|
||
current := TIEStrStrEnumerator.Create();
|
||
while dict.GetNext(current) do
|
||
begin
|
||
key := current.item.key;
|
||
value := current.item.value;
|
||
...
|
||
end;
|
||
current.Free();
|
||
!!}
|
||
function TIEDictionary.GetNext(current: TIEStrStrEnumerator): boolean;
|
||
var
|
||
next: TIEDictionaryBucket;
|
||
begin
|
||
CheckInit();
|
||
result := false;
|
||
if current.item <> nil then
|
||
begin
|
||
// current doesn't point to "before the first item", so check in current bucket
|
||
next := current.item.next;
|
||
if next <> nil then
|
||
begin
|
||
// return next item of current bucket
|
||
current.item := next;
|
||
result := true;
|
||
exit;
|
||
end;
|
||
inc(current.bucket); // try next bucket
|
||
end;
|
||
while current.bucket < m_bucketCount do
|
||
begin
|
||
current.item := m_buckets[current.bucket];
|
||
if current.item <> nil then
|
||
begin
|
||
result := true;
|
||
break;
|
||
end;
|
||
inc(current.bucket);
|
||
end;
|
||
if result = false then
|
||
begin
|
||
current.bucket := 0;
|
||
current.item := nil;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.IsEmpty
|
||
|
||
<FM>Declaration<FC>
|
||
function IsEmpty(): boolean;
|
||
|
||
|
||
<FM>Description<FN>
|
||
Returns True if the dictionary contains no elements.
|
||
!!}
|
||
function TIEDictionary.IsEmpty(): boolean;
|
||
begin
|
||
result := (m_count = 0);
|
||
end;
|
||
|
||
|
||
function TIEDictionary.EncodeString(Text: WideString): WideString;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := '';
|
||
for i := 1 to length(Text) do
|
||
if Text[i] = '"' then
|
||
result := result + '\"'
|
||
else
|
||
result := result + Text[i];
|
||
end;
|
||
|
||
|
||
function TIEDictionary.DumpJSON(obj: TObject): WideString;
|
||
begin
|
||
if obj is TIEDictionaryValueWideString then
|
||
result := '"' + EncodeString((obj as TIEDictionaryValueWideString).value) + '"'
|
||
else
|
||
if obj is TIEDictionaryValueInteger then
|
||
result := IntToStr((obj as TIEDictionaryValueInteger).value)
|
||
else
|
||
if obj is TIEDictionaryValueDouble then
|
||
result := IEFloatToStrW((obj as TIEDictionaryValueDouble).value)
|
||
else
|
||
if obj is TIEDictionaryValueBoolean then
|
||
case (obj as TIEDictionaryValueBoolean).value of
|
||
false : result := 'false';
|
||
true : result := 'true';
|
||
end
|
||
else
|
||
if obj is TIEDictionary then
|
||
result := (obj as TIEDictionary).DumpJSON()
|
||
else
|
||
if obj is TObjectList then
|
||
result := DumpJSON(TObjectList(obj))
|
||
else
|
||
result := obj.ClassName; // unknown
|
||
end;
|
||
|
||
|
||
function TIEDictionary.DumpJSON(obj: TObjectList): WideString;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := '[';
|
||
for i := 0 to obj.Count - 1 do
|
||
begin
|
||
result := result + DumpJSON(obj[i]);
|
||
if i < obj.Count - 1 then
|
||
result := result + ',';
|
||
end;
|
||
result := result + ']';
|
||
end;
|
||
|
||
|
||
function TIEDictionary.DumpJSON(): WideString;
|
||
var
|
||
current: TIEStrStrEnumerator;
|
||
isfirst: boolean;
|
||
begin
|
||
result := '{';
|
||
current := TIEStrStrEnumerator.Create();
|
||
try
|
||
isfirst := true;
|
||
while GetNext(current) do
|
||
begin
|
||
if not isfirst then
|
||
result := result + ',';
|
||
result := result + '"' + EncodeString(current.item.key) + '"' + ':';
|
||
result := result + DumpJSON(current.item.value);
|
||
isfirst := false;
|
||
end;
|
||
finally
|
||
current.Free();
|
||
end;
|
||
result := result + '}';
|
||
end;
|
||
|
||
|
||
function TIEDictionary.DumpXML(obj: TObject): WideString;
|
||
begin
|
||
if obj is TIEDictionaryValueWideString then
|
||
result := EncodeString((obj as TIEDictionaryValueWideString).value)
|
||
else
|
||
if obj is TIEDictionaryValueInteger then
|
||
result := IntToStr((obj as TIEDictionaryValueInteger).value)
|
||
else
|
||
if obj is TIEDictionaryValueDouble then
|
||
result := IEFloatToStrW((obj as TIEDictionaryValueDouble).value)
|
||
else
|
||
if obj is TIEDictionaryValueBoolean then
|
||
case (obj as TIEDictionaryValueBoolean).value of
|
||
false : result := 'false';
|
||
true : result := 'true';
|
||
end
|
||
else
|
||
if obj is TIEDictionary then
|
||
result := (obj as TIEDictionary).DumpXML()
|
||
else
|
||
if obj is TObjectList then
|
||
result := DumpXML(TObjectList(obj))
|
||
else
|
||
result := obj.ClassName; // unknown
|
||
end;
|
||
|
||
|
||
function TIEDictionary.DumpXML(obj: TObjectList): WideString;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := '';
|
||
for i := 0 to obj.Count - 1 do
|
||
result := result + DumpXML(obj[i]);
|
||
end;
|
||
|
||
|
||
function TIEDictionary.DumpXML(): WideString;
|
||
var
|
||
current: TIEStrStrEnumerator;
|
||
begin
|
||
result := '';
|
||
current := TIEStrStrEnumerator.Create();
|
||
try
|
||
while GetNext(current) do
|
||
begin
|
||
result := result + '<' + EncodeString(current.item.key) + '>';
|
||
result := result + DumpXML(current.item.value);
|
||
result := result + '</' + EncodeString(current.item.key) + '>';
|
||
end;
|
||
finally
|
||
current.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Dump
|
||
|
||
<FM>Declaration<FC>
|
||
function Dump(dumpType: <A TIEDictionaryParserLang>): WideString;
|
||
|
||
|
||
<FM>Description<FN>
|
||
Returns a JSON-like or XML representation of the dictionary.
|
||
Not all dictionary contents can be dumped to XML and correctly parsed back.
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIEDictionary.Parse>
|
||
!!}
|
||
function TIEDictionary.Dump(dumpType: TIEDictionaryParserLang): WideString;
|
||
begin
|
||
case dumpType of
|
||
ieplJSON:
|
||
result := DumpJSON();
|
||
ieplXML:
|
||
result := DumpXML();
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEDictionary.Parse
|
||
|
||
<FM>Declaration<FC>
|
||
function Parse(text: WideString): boolean;
|
||
|
||
|
||
<FM>Description<FN>
|
||
Parses the JSON-like string and populates the dictionary.
|
||
This method doesn't remove existing items.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>text<FN></C> <C>A JSON-like text</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIEDictionary.Dump>
|
||
|
||
<FM>Example<FC>
|
||
}
|
||
// dict.Parse('{"string" : "string content", "myinteger": 1234, "mydouble": 123.456, "a_bool_true" : true, "a_bool_false" : false, "subdict" : {"name": "john", "surname" : "mad"}, "array": [1,2,3,4,"hello", {}, {"alfa":"beta"}, [9,10]] }');
|
||
{!!}
|
||
function TIEDictionary.Parse(text: WideString): boolean;
|
||
var
|
||
parser: TIEDictionaryParser;
|
||
begin
|
||
parser := TIEDictionaryParser.Create(text);
|
||
try
|
||
parser.Parse(self);
|
||
result := not parser.Aborted;
|
||
finally
|
||
parser.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure TIEDictionary.Assign(Source: TIEDictionary);
|
||
begin
|
||
Clear();
|
||
Parse(Source.Dump(ieplJSON));
|
||
end;
|
||
|
||
|
||
constructor TIEDictionaryParser.Create(Text: WideString);
|
||
begin
|
||
m_text := Text;
|
||
m_textLen := length(Text);
|
||
m_textPos := 1;
|
||
m_abort := false;
|
||
|
||
// check language to decode
|
||
m_lang := ieplJSON;
|
||
if PeekToken() <> '{' then
|
||
begin
|
||
m_lang := ieplXML;
|
||
if PeekToken() <> '<' then
|
||
m_abort := true;
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure TIEDictionaryParser.AbortParse();
|
||
begin
|
||
m_abort := true;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.DecodeString(Text: WideString): WideString;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := '';
|
||
i := 1;
|
||
while i <= length(Text) do
|
||
begin
|
||
if (i < length(Text)) and (Text[i] = '\') and (Text[i + 1] = '"') then
|
||
begin
|
||
result := result + '"';
|
||
inc(i);
|
||
end
|
||
else
|
||
result := result + Text[i];
|
||
inc(i);
|
||
end;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.IsToken(c: WideChar): boolean;
|
||
begin
|
||
case m_lang of
|
||
ieplJSON:
|
||
result := (c = '{') or (c = '}') or (c = '[') or (c = ']') or (c = '"') or (c = ':') or (c = ',');
|
||
ieplXML:
|
||
result := (c = '<') or (c = '>') or (c = '/') or (c = '''') or (c = '"') or (c = '=') or (c = '?');
|
||
else
|
||
result := false;
|
||
end;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.IsSpace(c: WideChar): boolean;
|
||
begin
|
||
result := (c = ' ') or (c = #8) or (c = #13) or (c = #10);
|
||
end;
|
||
|
||
|
||
procedure TIEDictionaryParser.ByPassSpaces();
|
||
begin
|
||
while HasChar() and IsSpace(PeekChar()) do
|
||
GetChar();
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.HasChar(): boolean;
|
||
begin
|
||
result := m_textPos <= m_textLen;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.GetChar(): WideChar;
|
||
begin
|
||
result := m_text[m_textPos];
|
||
inc(m_textPos);
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.PeekChar(): WideChar;
|
||
begin
|
||
result := m_text[m_textPos];
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.SavePos(): integer;
|
||
begin
|
||
result := m_textPos;
|
||
end;
|
||
|
||
|
||
procedure TIEDictionaryParser.RestorePos(pos: integer);
|
||
begin
|
||
m_textPos := pos;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.GetToken(): WideChar;
|
||
begin
|
||
while HasChar() do
|
||
begin
|
||
result := GetChar();
|
||
if not IsSpace(result) then
|
||
exit;
|
||
end;
|
||
result := ' '; // end of string?
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.PeekToken(): WideChar;
|
||
var
|
||
lpos: integer;
|
||
begin
|
||
lpos := SavePos();
|
||
result := GetToken();
|
||
RestorePos(lpos);
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.GetString(): WideString;
|
||
var
|
||
c: WideChar;
|
||
prevChar: WideChar;
|
||
marker: WideChar; // character used to open and close string
|
||
begin
|
||
result := '';
|
||
marker := GetToken();
|
||
if (marker <> '"') and (marker <> '''') then // accepts both single quote and double quote
|
||
begin
|
||
AbortParse();
|
||
exit;
|
||
end;
|
||
prevChar := ' ';
|
||
while HasChar() do
|
||
begin
|
||
c := GetChar();
|
||
if (prevChar <> '\') and (c = marker) then
|
||
break;
|
||
result := result + c;
|
||
prevChar := c;
|
||
end;
|
||
// ending marker already passed
|
||
result := DecodeString(result);
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.Parse(mergeWith: TIEDictionary = nil): TIEDictionary;
|
||
begin
|
||
case m_lang of
|
||
ieplJSON:
|
||
result := JSON_ParseDictionary(mergeWith);
|
||
ieplXML:
|
||
result := XML_ParseContent(mergeWith);
|
||
else
|
||
result := nil;
|
||
end;
|
||
end;
|
||
|
||
|
||
// content can be free text or tags
|
||
function TIEDictionaryParser.XML_ParseContent(mergeWith: TIEDictionary): TIEDictionary;
|
||
var
|
||
key: WideString;
|
||
value: TIEDictionary;
|
||
content: TIEDictionary;
|
||
tk: WideChar;
|
||
text: WideString;
|
||
lpos: integer;
|
||
|
||
procedure Ins(key: WideString; value: TObject);
|
||
var
|
||
evalue: TObject;
|
||
arr: TObjectList;
|
||
begin
|
||
if result.HasKey(key, false) then
|
||
begin
|
||
// key already exist, create an array
|
||
evalue := result.Get(key);
|
||
if not (evalue is TObjectList) then
|
||
begin
|
||
result.Erase(key, false); // evalue still exists
|
||
arr := TObjectList.Create();
|
||
result.Insert(key, arr);
|
||
arr.Add(evalue);
|
||
arr.Add(value);
|
||
end
|
||
else
|
||
(evalue as TObjectList).Add(value);
|
||
end
|
||
else
|
||
result.Insert(key, value);
|
||
end;
|
||
|
||
begin
|
||
if mergeWith = nil then
|
||
result := TIEDictionary.Create()
|
||
else
|
||
result := mergeWith;
|
||
text := '';
|
||
while HasChar() and not m_abort do
|
||
begin
|
||
lpos := SavePos();
|
||
if PeekToken() = '<' then
|
||
begin
|
||
GetToken(); // bypass '<'
|
||
if PeekToken() = '/' then
|
||
begin
|
||
// this is an upper enclosing tag, end this procedure
|
||
RestorePos(lpos);
|
||
break;
|
||
end
|
||
else
|
||
if PeekToken() = '?' then
|
||
begin
|
||
// this is an xml declaration (like <?... ?>)
|
||
GetToken(); // bypass '?'
|
||
key := XML_GetName();
|
||
value := XML_ParseAttributes();
|
||
Ins(key, value);
|
||
if (GetToken() = '?') and (GetToken() = '>') then
|
||
continue;
|
||
AbortParse();
|
||
end
|
||
else
|
||
begin
|
||
// this is a tag
|
||
key := XML_GetName();
|
||
value := XML_ParseAttributes();
|
||
Ins(key, value);
|
||
tk := GetToken();
|
||
if (tk = '/') and (PeekToken() = '>') then
|
||
begin
|
||
// empty tag (like <tag .... /> )
|
||
GetToken(); // by pass >
|
||
end
|
||
else
|
||
if (tk = '>') then
|
||
begin
|
||
// tag with content, get content (like <tag ...> content </tag>)
|
||
content := XML_ParseContent();
|
||
value.insert('#content', content);
|
||
if (GetToken() = '<') and (GetToken() = '/') and (XML_GetName() = key) and (GetToken() = '>') then
|
||
continue;
|
||
end;
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
// this is text content
|
||
text := text + GetChar();
|
||
end;
|
||
end;
|
||
text := trim(text);
|
||
if text <> '' then
|
||
result.Insert('#text', text);
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.XML_GetName(): WideString;
|
||
var
|
||
c: WideChar;
|
||
begin
|
||
result := '';
|
||
ByPassSpaces();
|
||
while HasChar() do
|
||
begin
|
||
c := PeekChar();
|
||
if IsSpace(c) or IsToken(c) then
|
||
break;
|
||
result := result + GetChar();
|
||
end;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.XML_ParseAttributes(): TIEDictionary;
|
||
var
|
||
key: WideString;
|
||
value: TIEDictionaryValueWideString;
|
||
tk: WideChar;
|
||
begin
|
||
result := TIEDictionary.Create();
|
||
while HasChar() do
|
||
begin
|
||
tk := PeekToken();
|
||
if (tk = '>') or (tk = '?') or (tk = '/') then
|
||
break;
|
||
key := XML_GetName();
|
||
if GetToken() <> '=' then
|
||
begin
|
||
AbortParse();
|
||
exit;
|
||
end;
|
||
value := ParseString();
|
||
result.Insert(key, value);
|
||
end;
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.JSON_ParseDictionary(mergeWith: TIEDictionary): TIEDictionary;
|
||
var
|
||
key: WideString;
|
||
value: TObject;
|
||
tk: WideChar;
|
||
|
||
procedure Ins(key: WideString; value: TObject);
|
||
var
|
||
evalue: TObject;
|
||
arr: TObjectList;
|
||
begin
|
||
if result.HasKey(key, false) then
|
||
begin
|
||
// key already exist, create an array
|
||
evalue := result.Get(key);
|
||
if not (evalue is TObjectList) then
|
||
begin
|
||
result.Erase(key, false); // evalue still exists
|
||
arr := TObjectList.Create();
|
||
result.Insert(key, arr);
|
||
arr.Add(evalue);
|
||
arr.Add(value);
|
||
end
|
||
else
|
||
(evalue as TObjectList).Add(value);
|
||
end
|
||
else
|
||
result.Insert(key, value);
|
||
end;
|
||
|
||
begin
|
||
if mergeWith = nil then
|
||
result := TIEDictionary.Create()
|
||
else
|
||
result := mergeWith;
|
||
if GetToken() <> '{' then
|
||
begin
|
||
AbortParse();
|
||
exit;
|
||
end;
|
||
while HasChar() and not m_abort do
|
||
begin
|
||
if PeekToken() = '}' then
|
||
break;
|
||
key := GetString();
|
||
if GetToken() <> ':' then
|
||
begin
|
||
AbortParse();
|
||
exit;
|
||
end;
|
||
value := JSON_ParseValue();
|
||
Ins(key, value);
|
||
tk := PeekToken();
|
||
if tk = '}' then
|
||
break
|
||
else
|
||
if tk <> ',' then
|
||
AbortParse()
|
||
else
|
||
GetToken(); // gets ','
|
||
end;
|
||
if GetToken() <> '}' then
|
||
AbortParse();
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.JSON_ParseValue(): TObject;
|
||
var
|
||
token: WideChar;
|
||
begin
|
||
token := PeekToken();
|
||
if token = '{' then
|
||
result := JSON_ParseDictionary()
|
||
else
|
||
if token = '[' then
|
||
result := JSON_ParseArray()
|
||
else
|
||
if token = '"' then
|
||
result := ParseString()
|
||
else
|
||
result := ParseIdentifier();
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.JSON_ParseArray(): TObjectList;
|
||
var
|
||
value: TObject;
|
||
tk: WideChar;
|
||
begin
|
||
result := TObjectList.Create();
|
||
if GetToken() <> '[' then
|
||
begin
|
||
AbortParse();
|
||
exit;
|
||
end;
|
||
while HasChar() and not m_abort do
|
||
begin
|
||
if PeekToken() = ']' then
|
||
break;
|
||
value := JSON_ParseValue();
|
||
if not m_abort then
|
||
result.Add(value);
|
||
tk := PeekToken();
|
||
if tk = ']' then
|
||
break
|
||
else
|
||
if tk <> ',' then
|
||
AbortParse()
|
||
else
|
||
GetToken(); // gets ','
|
||
end;
|
||
if GetToken() <> ']' then
|
||
AbortParse();
|
||
end;
|
||
|
||
|
||
function TIEDictionaryParser.ParseString(): TIEDictionaryValueWideString;
|
||
begin
|
||
result := TIEDictionaryValueWideString.Create( GetString() );
|
||
end;
|
||
|
||
|
||
// true/false/integer/double
|
||
function TIEDictionaryParser.ParseIdentifier(): TObject;
|
||
var
|
||
c: WideChar;
|
||
s: WideString;
|
||
begin
|
||
s := '';
|
||
ByPassSpaces();
|
||
// get identifier up to space
|
||
while HasChar() do
|
||
begin
|
||
c := PeekChar();
|
||
if IsSpace(c) or IsToken(c) then
|
||
break;
|
||
s := s + GetChar();
|
||
end;
|
||
if s = 'false' then
|
||
result := TIEDictionaryValueBoolean.Create(false)
|
||
else
|
||
if s = 'true' then
|
||
result := TIEDictionaryValueBoolean.Create(true)
|
||
else
|
||
begin
|
||
if pos('.', s) > 0 then
|
||
result := TIEDictionaryValueDouble.Create( IEStrToFloatDefW(s, 0.0) )
|
||
else
|
||
result := TIEDictionaryValueInteger.Create( StrToIntDef(s, 0) );
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEHashStream
|
||
|
||
type HCRYPTPROV = pointer;
|
||
type HCRYPTKEY = pointer;
|
||
type HCRYPTHASH = pointer;
|
||
type ALG_ID = DWORD;
|
||
|
||
|
||
function CryptAcquireContext(out phProv: HCRYPTPROV; pszContainer: PAnsiChar; pszProvider: PAnsiChar; dwProvType: DWORD; dwFlags: DWORD): longbool; stdcall; external 'Advapi32.dll' name 'CryptAcquireContextA';
|
||
function CryptCreateHash(hProv: HCRYPTPROV; Algid: ALG_ID; hKey: HCRYPTKEY; dwFlags: DWORD; out phHash: HCRYPTHASH): longbool; stdcall; external 'Advapi32.dll' name 'CryptCreateHash';
|
||
function CryptHashData(hHash: HCRYPTHASH; pbData: pbyte; dwDataLen: DWORD; dwFlags: DWORD): longbool; stdcall; external 'Advapi32.dll' name 'CryptHashData';
|
||
function CryptGetHashParam(hHash: HCRYPTHASH; dwParam: DWORD; pbData: pbyte; pdwDataLen: PDWORD; dwFlags: DWORD): longbool; stdcall; external 'Advapi32.dll' name 'CryptGetHashParam';
|
||
function CryptDestroyHash(hHash: HCRYPTHASH): longbool; stdcall; external 'Advapi32.dll' name 'CryptDestroyHash';
|
||
function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: DWORD): longbool; stdcall; external 'Advapi32.dll' name 'CryptReleaseContext';
|
||
|
||
|
||
|
||
|
||
// ALG_ID values
|
||
const
|
||
CALG_3DES = $00006603; // Triple DES encryption algorithm.
|
||
CALG_3DES_112 = $00006609; // Two-key triple DES encryption with effective key length equal to 112 bits.
|
||
CALG_AES = $00006611; // Advanced Encryption Standard (AES). This algorithm is supported by the Microsoft AES Cryptographic Provider. Windows 2000/NT: This algorithm is not supported.
|
||
CALG_AES_128 = $0000660e; // 128 bit AES. This algorithm is supported by the Microsoft AES Cryptographic Provider. Windows 2000/NT: This algorithm is not supported.
|
||
CALG_AES_192 = $0000660f; // 192 bit AES. This algorithm is supported by the Microsoft AES Cryptographic Provider. Windows 2000/NT: This algorithm is not supported.
|
||
CALG_AES_256 = $00006610; // 256 bit AES. This algorithm is supported by the Microsoft AES Cryptographic Provider. Windows 2000/NT: This algorithm is not supported.
|
||
CALG_AGREEDKEY_ANY = $0000aa03; // Temporary algorithm identifier for handles of Diffie-Hellman<61>agreed keys.
|
||
CALG_CYLINK_MEK = $0000660c; // An algorithm to create a 40-bit DES key that has parity bits and zeroed key bits to make its key length 64 bits. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_DES = $00006601; // DES encryption algorithm.
|
||
CALG_DESX = $00006604; // DESX encryption algorithm.
|
||
CALG_DH_EPHEM = $0000aa02; // Diffie-Hellman ephemeral key exchange algorithm.
|
||
CALG_DH_SF = $0000aa01; // Diffie-Hellman store and forward key exchange algorithm.
|
||
CALG_DSS_SIGN = $00002200; // DSA public key signature algorithm.
|
||
CALG_ECDH = $0000aa05; // Elliptic curve Diffie-Hellman key exchange algorithm. Windows Server 2003, Windows XP, and Windows 2000/NT: This algorithm is not supported.
|
||
CALG_ECDSA = $00002203; // Elliptic curve digital signature algorithm. Windows Server 2003, Windows XP, and Windows 2000/NT: This algorithm is not supported.
|
||
CALG_ECMQV = $0000a001; // Elliptic curve Menezes, Qu, and Vanstone (MQV) key exchange algorithm. Windows Server 2003, Windows XP, and Windows 2000/NT: This algorithm is not supported.
|
||
CALG_HASH_REPLACE_OWF = $0000800b; // One way function hashing algorithm. Windows 2000/NT: This algorithm is not supported.
|
||
CALG_HUGHES_MD5 = $0000a003; // Hughes MD5 hashing algorithm.
|
||
CALG_HMAC = $00008009; // HMAC keyed hash algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_KEA_KEYX = $0000aa04; // KEA key exchange algorithm (FORTEZZA).
|
||
CALG_MAC = $00008005; // MAC keyed hash algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_MD2 = $00008001; // MD2 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_MD4 = $00008002; // MD4 hashing algorithm.
|
||
CALG_MD5 = $00008003; // MD5 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_NO_SIGN = $00002000; // No signature algorithm. Windows 2000/NT: This algorithm is not supported.
|
||
CALG_OID_INFO_CNG_ONLY = $ffffffff; // The algorithm is only implemented in CNG. The macro, IS_SPECIAL_OID_INFO_ALGID, can be used to determine whether a cryptography algorithm is only supported by using the CNG functions.
|
||
CALG_OID_INFO_PARAMETERS = $fffffffe; // The algorithm is defined in the encoded parameters. The algorithm is only supported by using CNG. The macro, IS_SPECIAL_OID_INFO_ALGID, can be used to determine whether a cryptography algorithm is only supported by using the CNG functions.
|
||
CALG_PCT1_MASTER = $00004c04; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_RC2 = $00006602; // RC2 block encryption algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_RC4 = $00006801; // RC4 stream encryption algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_RC5 = $0000660d; // RC5 block encryption algorithm.
|
||
CALG_RSA_KEYX = $0000a400; // RSA public key exchange algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_RSA_SIGN = $00002400; // RSA public key signature algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_SCHANNEL_ENC_KEY = $00004c07; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_SCHANNEL_MAC_KEY = $00004c03; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_SCHANNEL_MASTER_HASH = $00004c02; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_SEAL = $00006802; // SEAL encryption algorithm.
|
||
CALG_SHA = $00008004; // SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_SHA1 = $00008004; // Same as CALG_SHA. This algorithm is supported by the Microsoft Base Cryptographic Provider.
|
||
CALG_SHA_256 = $0000800c; // 256 bit SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. Windows XP and Windows 2000/NT: This algorithm is not supported.
|
||
CALG_SHA_384 = $0000800d; // 384 bit SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. Windows XP and Windows 2000/NT: This algorithm is not supported.
|
||
CALG_SHA_512 = $0000800e; // 512 bit SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. Windows XP and Windows 2000/NT: This algorithm is not supported.
|
||
CALG_SKIPJACK = $0000660a; // Skipjack block encryption algorithm (FORTEZZA).
|
||
CALG_SSL2_MASTER = $00004c05; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_SSL3_MASTER = $00004c01; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_SSL3_SHAMD5 = $00008008; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_TEK = $0000660b; // TEK (FORTEZZA).
|
||
CALG_TLS1_MASTER = $00004c06; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
CALG_TLS1PRF = $0000800a; // Used by the Schannel.dll operations system. This ALG_ID should not be used by applications.
|
||
|
||
// Providers (predefined only)
|
||
const
|
||
PROV_RSA_FULL = 1;
|
||
PROV_RSA_SIG = 2;
|
||
PROV_DSS = 3;
|
||
PROV_FORTEZZA = 4;
|
||
PROV_MS_EXCHANGE = 5;
|
||
PROV_SSL = 6;
|
||
PROV_RSA_SCHANNEL = 12;
|
||
PROV_DSS_DH = 13;
|
||
PROV_DH_SCHANNEL = 18;
|
||
PROV_RSA_AES = 24;
|
||
|
||
// dwFlags definitions for CryptAcquireContext
|
||
const
|
||
CRYPT_VERIFYCONTEXT = $F0000000;
|
||
CRYPT_NEWKEYSET = $00000008;
|
||
CRYPT_DELETEKEYSET = $00000010;
|
||
CRYPT_MACHINE_KEYSET = $00000020;
|
||
CRYPT_SILENT = $00000040;
|
||
CRYPT_DEFAULT_CONTAINER_OPTIONAL = $00000080;
|
||
|
||
const
|
||
HP_ALGID = $0001; // Hash algorithm
|
||
HP_HASHVAL = $0002; // Hash value
|
||
HP_HASHSIZE = $0004; // Hash value size
|
||
HP_HMAC_INFO = $0005; // information for creating an HMAC
|
||
HP_TLS1PRF_LABEL = $0006; // label for TLS1 PRF
|
||
HP_TLS1PRF_SEED = $0007; // seed for TLS1 PRF
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.Create
|
||
|
||
<FM>Declaration<FC>
|
||
constructor Create(Algorithm: <A TIEHashAlgorithm> = iehaMD5; Buffered: boolean = true);
|
||
|
||
<FM>Description<FN>
|
||
Creates a TIEHashStream which will use specified hash algorithm.
|
||
If <FC>Buffered<FN> is true the stream data is written in a temporary memory stream. This is necessary when Seek and Read methods are necessary.
|
||
|
||
<FM>Example<FC>
|
||
// saves the file with an unique name (create hash from the jpeg content and use it as file name)
|
||
var
|
||
hashStream: TIEHashStream;
|
||
begin
|
||
ImageEnView1.IO.LoadFromFile('input.jpg');
|
||
hashStream := TIEHashStream.Create(iehaMD5);
|
||
try
|
||
ImageEnView1.IO.SaveToStreamJpeg(hashStream);
|
||
hashStream.SaveToFile(hashStream.GetHash()+'.jpg');
|
||
finally
|
||
hashStream.Free;
|
||
end;
|
||
end;
|
||
!!}
|
||
constructor TIEHashStream.Create(Algorithm: TIEHashAlgorithm; Buffered: boolean);
|
||
begin
|
||
inherited Create;
|
||
|
||
if Buffered then
|
||
m_MemStream := TMemoryStream.Create
|
||
else
|
||
m_MemStream := nil;
|
||
|
||
if not CryptAcquireContext(m_CryptProvider, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT or CRYPT_MACHINE_KEYSET) then
|
||
raise EIEException.Create('Unable to use CryptoAPI');
|
||
|
||
try
|
||
if not CryptCreateHash(m_CryptProvider, DWORD(Algorithm), nil, 0, m_CryptHash) then
|
||
raise EIEException.Create('Unable to create Crypto Hash');
|
||
except
|
||
CryptReleaseContext(m_CryptProvider, 0);
|
||
raise;
|
||
end;
|
||
end;
|
||
|
||
|
||
destructor TIEHashStream.Destroy;
|
||
begin
|
||
m_MemStream.Free;
|
||
CryptDestroyHash(m_CryptHash);
|
||
CryptReleaseContext(m_CryptProvider, 0);
|
||
inherited Destroy;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.GetHash
|
||
|
||
<FM>Declaration<FC>
|
||
function GetHash: AnsiString;
|
||
|
||
<FM>Description<FN>
|
||
Calculates the hash and returns the string representation of the hash.
|
||
|
||
<FM>Example<FC>
|
||
// saves the file with an unique name (create hash from the jpeg content and use it as file name)
|
||
var
|
||
hashStream: TIEHashStream;
|
||
begin
|
||
ImageEnView1.IO.LoadFromFile('input.jpg');
|
||
hashStream := TIEHashStream.Create(iehaMD5);
|
||
try
|
||
ImageEnView1.IO.SaveToStreamJpeg(hashStream);
|
||
hashStream.SaveToFile(hashStream.GetHash()+'.jpg');
|
||
finally
|
||
hashStream.Free;
|
||
end;
|
||
end;
|
||
!!}
|
||
function TIEHashStream.GetHash: AnsiString;
|
||
var
|
||
hash: pbytearray;
|
||
hashSize: DWORD;
|
||
i: integer;
|
||
dw: DWORD;
|
||
begin
|
||
result := '';
|
||
|
||
if assigned(m_MemStream) then
|
||
if not CryptHashData(m_CryptHash, pbyte(m_MemStream.Memory), m_MemStream.Size, 0) then
|
||
raise EIEException.Create('Unable to add hash data');
|
||
|
||
// get hash size
|
||
dw := 4;
|
||
if not CryptGetHashParam(m_CryptHash, HP_HASHSIZE, @hashSize, @dw, 0) then
|
||
raise EIEException.Create('Unable to create hash');
|
||
|
||
getmem(hash, hashSize);
|
||
|
||
// get hash data
|
||
dw := hashSize;
|
||
if CryptGetHashParam(m_CryptHash, HP_HASHVAL, @hash[0], @dw, 0) then
|
||
for i := 0 to hashSize - 1 do
|
||
result := result + AnsiString(Format('%.2x', [hash[i]]));
|
||
|
||
freemem(hash);
|
||
|
||
result := IELowerCase(result);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.Write
|
||
|
||
<FM>Declaration<FC>
|
||
function Write(const Buffer; Count: longint): longint;
|
||
|
||
<FM>Description<FN>
|
||
Writes data in the hash stream.
|
||
!!}
|
||
function TIEHashStream.Write(const Buffer; Count: longint): longint;
|
||
begin
|
||
if assigned(m_MemStream) then
|
||
result := m_MemStream.Write(Buffer, Count)
|
||
else
|
||
begin
|
||
if not CryptHashData(m_CryptHash, pbyte(@Buffer), Count, 0) then
|
||
raise EIEException.Create('Unable to add hash data');
|
||
result := Count;
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.Read
|
||
|
||
<FM>Declaration<FC>
|
||
function Read(var Buffer; Count: longint): Longint;
|
||
|
||
<FM>Description<FN>
|
||
Reads data in the hash stream. It is necessary to create the stream as "buffered" to use this method.
|
||
!!}
|
||
function TIEHashStream.Read(var Buffer; Count: longint): Longint;
|
||
begin
|
||
if assigned(m_MemStream) then
|
||
result := m_MemStream.Read(Buffer, Count)
|
||
else
|
||
raise EIEException.Create('Read error. Hash stream not Buffered, please create Buffered stream.');
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.Seek
|
||
|
||
<FM>Declaration<FC>
|
||
function Seek(const Offset: int64; Origin: TSeekOrigin): int64;
|
||
|
||
<FM>Description<FN>
|
||
Seeks data in the hash stream. It is necessary to create the stream as "buffered" to use this method.
|
||
!!}
|
||
{$ifdef IEOLDSEEKDEF}
|
||
function TIEHashStream.Seek(Offset: longint; Origin: word): longint;
|
||
{$else}
|
||
function TIEHashStream.Seek(const Offset: int64; Origin: TSeekOrigin): int64;
|
||
{$endif}
|
||
begin
|
||
if assigned(m_MemStream) then
|
||
result := m_MemStream.Seek(Offset, Origin)
|
||
else
|
||
raise EIEException.Create('Seek error. Hash stream not Buffered, please create Buffered stream.');
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.SaveToFile
|
||
|
||
<FM>Declaration<FC>
|
||
procedure TIEHashStream.SaveToFile(const filename: WideString);
|
||
|
||
<FM>Description<FN>
|
||
Saves the stream to file (this is the actual data written, not the hash). This is useful to save the hashed data one time.
|
||
It is necessary to create the stream as "buffered" to use this method.
|
||
|
||
See also: <A TIEHashStream.SaveToStream>
|
||
|
||
<FM>Example<FC>
|
||
// saves the file with an unique name (create hash from the jpeg content and use it as file name)
|
||
var
|
||
hashStream: TIEHashStream;
|
||
begin
|
||
ImageEnView1.IO.LoadFromFile('input.jpg');
|
||
hashStream := TIEHashStream.Create(iehaMD5);
|
||
try
|
||
ImageEnView1.IO.SaveToStreamJpeg(hashStream);
|
||
hashStream.SaveToFile(hashStream.GetHash()+'.jpg');
|
||
finally
|
||
hashStream.Free;
|
||
end;
|
||
end;
|
||
!!}
|
||
procedure TIEHashStream.SaveToFile(const filename: WideString);
|
||
var
|
||
stream: TIEWideFileStream;
|
||
begin
|
||
stream := TIEWideFileStream.Create(filename, fmCreate);
|
||
try
|
||
SaveToStream(stream);
|
||
finally
|
||
stream.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.SaveToStream
|
||
|
||
<FM>Declaration<FC>
|
||
procedure SaveToStream(Stream: TStream);
|
||
|
||
<FM>Description<FN>
|
||
Saves data to stream (this is the actual data written, not the hash). This is useful to save the hashed data one time.
|
||
It is necessary to create the stream as "buffered" to use this method.
|
||
|
||
See also: <A TIEHashStream.SaveToFile>.
|
||
!!}
|
||
procedure TIEHashStream.SaveToStream(Stream: TStream);
|
||
begin
|
||
if assigned(m_MemStream) then
|
||
m_MemStream.SaveToStream(Stream)
|
||
else
|
||
raise EIEException.Create('SaveToStream error. Hash stream not Buffered, please create Buffered stream.');
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.LoadFromFile
|
||
|
||
<FM>Declaration<FC>
|
||
procedure LoadFromFile(const filename: WideString);
|
||
|
||
<FM>Description<FN>
|
||
Loads data to hash from specified file.
|
||
It is necessary to create the stream as "buffered" to use this method.
|
||
!!}
|
||
procedure TIEHashStream.LoadFromFile(const filename: WideString);
|
||
var
|
||
stream: TIEWideFileStream;
|
||
begin
|
||
stream := TIEWideFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
|
||
try
|
||
LoadFromStream(stream);
|
||
finally
|
||
stream.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEHashStream.LoadFromStream
|
||
|
||
<FM>Declaration<FC>
|
||
procedure LoadFromStream(Stream: TStream);
|
||
|
||
<FM>Description<FN>
|
||
Loads data to hash from specified stream.
|
||
It is necessary to create the stream as "buffered" to use this method.
|
||
!!}
|
||
procedure TIEHashStream.LoadFromStream(Stream: TStream);
|
||
begin
|
||
if assigned(m_MemStream) then
|
||
m_MemStream.LoadFromStream(Stream)
|
||
else
|
||
raise EIEException.Create('LoadFromStream error. Hash stream not Buffered, please create Buffered stream.');
|
||
end;
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEExecutorThread
|
||
|
||
constructor TIEExecutorThread.Create(execFunc: TIEExecutorFunc);
|
||
begin
|
||
inherited Create(true); // create suspended
|
||
fExecFunc := execFunc;
|
||
end;
|
||
|
||
procedure TIEExecutorThread.Execute();
|
||
begin
|
||
fExecFunc();
|
||
end;
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEExecutor
|
||
|
||
constructor TIEExecutor.Create(execInThread: Boolean);
|
||
begin
|
||
if execInThread then
|
||
fThread := TIEExecutorThread.Create(execute)
|
||
else
|
||
fThread := nil;
|
||
end;
|
||
|
||
destructor TIEExecutor.Destroy();
|
||
begin
|
||
if assigned(fThread) then
|
||
fThread.Free();
|
||
end;
|
||
|
||
function TIEExecutor.GetThread(): TThread;
|
||
begin
|
||
result := fThread;
|
||
end;
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEThreadPool
|
||
|
||
constructor TIEThreadPool.Create();
|
||
begin
|
||
inherited Create();
|
||
fThreads := TList.Create;
|
||
end;
|
||
|
||
destructor TIEThreadPool.Destroy;
|
||
begin
|
||
Join();
|
||
fThreads.Free;
|
||
inherited;
|
||
end;
|
||
|
||
// like Join() but doesn't destroy threads (you can still access their properties)
|
||
procedure TIEThreadPool.WaitFor();
|
||
var
|
||
i: integer;
|
||
t: TThread;
|
||
begin
|
||
for i := 0 to fThreads.Count - 1 do
|
||
begin
|
||
t := (TObject(fThreads[i]) as TIEExecutor).GetThread();
|
||
if assigned(t) then
|
||
t.WaitFor();
|
||
end;
|
||
end;
|
||
|
||
procedure TIEThreadPool.Join();
|
||
var
|
||
i: integer;
|
||
t: TThread;
|
||
begin
|
||
for i := 0 to fThreads.Count - 1 do
|
||
begin
|
||
t := (TObject(fThreads[i]) as TIEExecutor).GetThread();
|
||
if assigned(t) then
|
||
t.WaitFor();
|
||
(TObject(fThreads[i]) as TIEExecutor).Free();
|
||
end;
|
||
fThreads.Clear;
|
||
end;
|
||
|
||
function TIEThreadPool.GetThreads(idx: integer): TIEExecutor;
|
||
begin
|
||
result := TObject(fThreads[idx]) as TIEExecutor;
|
||
end;
|
||
|
||
procedure TIEThreadPool.Add(Thread: TIEExecutor);
|
||
var
|
||
t: TThread;
|
||
begin
|
||
fThreads.Add(Thread);
|
||
t := Thread.GetThread();
|
||
if assigned(t) then
|
||
begin
|
||
{$ifdef IEHASTTHREADSTART}
|
||
t.Start();
|
||
{$else}
|
||
t.Resume();
|
||
{$endif}
|
||
end
|
||
else
|
||
begin
|
||
// execute inside this thread
|
||
Thread.Execute();
|
||
end;
|
||
end;
|
||
|
||
// TIEThreadPool
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEWideFileStream
|
||
|
||
function IECreateFileW(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
|
||
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
|
||
hTemplateFile: THandle): THandle;
|
||
begin
|
||
if Win32Platform = VER_PLATFORM_WIN32_NT then
|
||
result := CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
|
||
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
|
||
else
|
||
result := CreateFileA(PAnsiChar(AnsiString(lpFileName)), dwDesiredAccess, dwShareMode,
|
||
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
|
||
end;
|
||
|
||
function WideFileCreate(const FileName: WideString): THandle;
|
||
begin
|
||
Result := IECreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||
end;
|
||
|
||
function WideFileOpen(const FileName: WideString; Mode: LongWord): THandle;
|
||
const
|
||
AccessMode: array[0..2] of LongWord = (
|
||
GENERIC_READ,
|
||
GENERIC_WRITE,
|
||
GENERIC_READ or GENERIC_WRITE);
|
||
ShareMode: array[0..4] of LongWord = (
|
||
0,
|
||
0,
|
||
FILE_SHARE_READ,
|
||
FILE_SHARE_WRITE,
|
||
FILE_SHARE_READ or FILE_SHARE_WRITE);
|
||
begin
|
||
Result := INVALID_HANDLE_VALUE;
|
||
if ((Mode and 3) <= fmOpenReadWrite) and ((Mode and $F0) <= fmShareDenyNone) then
|
||
Result := IECreateFileW(PWideChar(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||
end;
|
||
|
||
constructor TIEWideFileStream.Create(const FileName: WideString; Mode: Word);
|
||
const
|
||
SFCreateError = 'Cannot create file %s';
|
||
SFCreateErrorEx = 'Cannot create file "%s". %s';
|
||
SFOpenError = 'Cannot open file %s';
|
||
SFOpenErrorEx = 'Cannot open file "%s". %s';
|
||
var
|
||
CreateHandle: THandle;
|
||
ErrorMessage: WideString;
|
||
begin
|
||
FFileName := FileName;
|
||
if Mode = fmCreate then
|
||
begin
|
||
CreateHandle := WideFileCreate(FileName);
|
||
if CreateHandle = INVALID_HANDLE_VALUE then
|
||
begin
|
||
ErrorMessage := SysErrorMessage(GetLastError);
|
||
raise EFCreateError.CreateFmt(SFCreateErrorEx, [ExpandFileName(FileName), ErrorMessage]);
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
CreateHandle := WideFileOpen(FileName, Mode);
|
||
if CreateHandle = INVALID_HANDLE_VALUE then
|
||
begin
|
||
ErrorMessage := SysErrorMessage(GetLastError);
|
||
raise EFOpenError.CreateFmt(SFOpenErrorEx, [ExpandFileName(FileName), ErrorMessage]);
|
||
end;
|
||
end;
|
||
inherited Create(CreateHandle);
|
||
end;
|
||
|
||
destructor TIEWideFileStream.Destroy;
|
||
begin
|
||
if THandle(Handle) <> INVALID_HANDLE_VALUE then
|
||
FileClose(Handle);
|
||
inherited Destroy;
|
||
end;
|
||
|
||
function IEWStrCopy(Dest: PWideChar; const Source: PWideChar): PWideChar;
|
||
var
|
||
Src : PWideChar;
|
||
begin
|
||
Result := Dest;
|
||
Src := Source;
|
||
while (Src^ <> #$00) do
|
||
begin
|
||
Dest^ := Src^;
|
||
Inc(Src);
|
||
Inc(Dest);
|
||
end;
|
||
Dest^ := #$00;
|
||
end;
|
||
|
||
// TIEWideFileStream
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEWideStrings
|
||
|
||
|
||
constructor TIEWideStrings.Create;
|
||
begin
|
||
inherited;
|
||
fStrings := TList.Create;
|
||
end;
|
||
|
||
destructor TIEWideStrings.Destroy;
|
||
begin
|
||
Clear;
|
||
fStrings.Free;
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEWideStrings.Clear;
|
||
var
|
||
i: integer;
|
||
begin
|
||
for i := 0 to fStrings.Count-1 do
|
||
FreeMem(fStrings[i]);
|
||
fStrings.Clear;
|
||
end;
|
||
|
||
function TIEWideStrings.GetCount: integer;
|
||
begin
|
||
result := fStrings.Count;
|
||
end;
|
||
|
||
function TIEWideStrings.CreateCopyBuffer(const S: WideString): PWideChar;
|
||
var
|
||
lenInBytes: integer;
|
||
begin
|
||
lenInBytes := (length(S)+1)*sizeof(WideChar);
|
||
getmem(result, lenInBytes);
|
||
CopyMemory(result, @S[1], lenInBytes);
|
||
end;
|
||
|
||
function TIEWideStrings.Add(const S: WideString): integer;
|
||
begin
|
||
result := fStrings.Add( CreateCopyBuffer(S) );
|
||
end;
|
||
|
||
procedure TIEWideStrings.SetString(idx: integer; const S: WideString);
|
||
begin
|
||
FreeMem(fStrings[idx]);
|
||
fStrings[idx] := CreateCopyBuffer(S);
|
||
end;
|
||
|
||
function TIEWideStrings.GetString(idx: integer): WideString;
|
||
begin
|
||
result := WideString(PWideChar(fStrings[idx]));
|
||
end;
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEDirContent
|
||
|
||
constructor TIEDirContent.Create(const dir : WideString);
|
||
begin
|
||
inherited Create;
|
||
fHandle := Windows.FindFirstFileW(PWChar(dir), fFindData);
|
||
fFirstGot := false;
|
||
end;
|
||
|
||
destructor TIEDirContent.Destroy;
|
||
begin
|
||
if fHandle <> INVALID_HANDLE_VALUE then
|
||
Windows.FindClose(fHandle);
|
||
inherited;
|
||
end;
|
||
|
||
function TIEDirContent.GetItem(out sFilename : WideString; bGetFiles: boolean = True; bGetDirs: boolean = False; bGetHidden : Boolean = True): boolean;
|
||
|
||
function allowIt: boolean;
|
||
var
|
||
sTempFilename : WideString;
|
||
begin
|
||
sTempFilename := fFindData.cFileName;
|
||
if (sTempFilename = '.') or (sTempFilename = '..') then
|
||
Result := False
|
||
else
|
||
result := (bGetFiles and not boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) or
|
||
(bGetDirs and boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY));
|
||
|
||
if Result and (bGetHidden = False) then
|
||
if boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_HIDDEN) or
|
||
boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_SYSTEM) then
|
||
Result := False;
|
||
end;
|
||
|
||
begin
|
||
result := fHandle <> INVALID_HANDLE_VALUE;
|
||
|
||
sFilename := '';
|
||
fFileSizeBytes := 0;
|
||
fCreateDate := 0;
|
||
fEditDate := 0;
|
||
|
||
// Is this a valid folder?
|
||
if result = False then
|
||
exit;
|
||
|
||
repeat
|
||
if fFirstGot then
|
||
result := Windows.FindNextFileW(fHandle, fFindData); // return false also when fHandle is INVALID_HANDLE_VALUE
|
||
fFirstGot := true;
|
||
until not result or allowIt();
|
||
|
||
fIsDir := boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY);
|
||
fIsHidden := boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_HIDDEN) or
|
||
boolean(fFindData.dwFileAttributes and FILE_ATTRIBUTE_SYSTEM);
|
||
sFilename := fFindData.cFileName;
|
||
|
||
try
|
||
fFileSizeBytes := IELargeFileSize(fFindData.nFileSizeHigh, fFindData.nFileSizeLow);
|
||
fEditDate := IEFileTimeToDateTime(fFindData.ftLastWriteTime);
|
||
fCreateDate := IEFileTimeToDateTime(fFindData.ftCreationTime);
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
|
||
// path must include wildcard, ie: ".\*.jpeg"
|
||
class procedure TIEDirContent.PopulateStrings(const path: WideString; strings: TStrings; bGetFiles: boolean = True; bGetDirs: boolean = False; bGetHidden : Boolean = True);
|
||
var
|
||
dir: TIEDirContent;
|
||
fname: WideString;
|
||
begin
|
||
strings.Clear();
|
||
dir := TIEDirContent.Create(path);
|
||
try
|
||
while dir.getItem(fname, bGetFiles, bGetDirs, bGetHidden) do
|
||
begin
|
||
strings.Add(string(fname));
|
||
end;
|
||
finally
|
||
dir.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEMemStream
|
||
|
||
constructor TIEMemStream.Create(Ptr: pointer; Size: integer);
|
||
begin
|
||
inherited Create;
|
||
SetPointer(Ptr, Size);
|
||
end;
|
||
|
||
procedure TIEMemStream.SetSize(NewSize: Longint);
|
||
begin
|
||
// not implemented
|
||
end;
|
||
|
||
function TIEMemStream.Write(const Buffer; Count: Longint): Longint;
|
||
begin
|
||
// not implemented
|
||
result := 0;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIERecordList
|
||
|
||
constructor TIERecordList.Create(RecordSize: integer; OnGetCurrentValue: TIEListCurrentValueEvent; OnSetCurrentValue: TIEListCurrentValueEvent);
|
||
begin
|
||
inherited Create(OnGetCurrentValue, OnSetCurrentValue);
|
||
fItemSize := RecordSize;
|
||
end;
|
||
|
||
function TIERecordList.GetItem(idx: integer): pointer;
|
||
begin
|
||
result := BaseGetItem(idx);
|
||
end;
|
||
|
||
procedure TIERecordList.SetItem(idx: integer; v: pointer);
|
||
begin
|
||
BaseSetItem(idx, v);
|
||
end;
|
||
|
||
function TIERecordList.Add(v: pointer): integer;
|
||
begin
|
||
result := AddItem(v);
|
||
end;
|
||
|
||
procedure TIERecordList.Insert(idx: integer; v: pointer);
|
||
begin
|
||
InsertItem(idx, v);
|
||
end;
|
||
|
||
function TIERecordList.IndexOf(v: pointer): integer;
|
||
begin
|
||
result := IndexOfItem(v);
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEIntegerMap
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
// sbits: hash table size in bit.
|
||
constructor TIEIntegerMap.Create(bucketsCount: integer);
|
||
begin
|
||
inherited Create;
|
||
SetLength(fItems, bucketsCount);
|
||
fKeysCount := 0;
|
||
end;
|
||
|
||
destructor TIEIntegerMap.Destroy();
|
||
begin
|
||
Clear();
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEIntegerMap.Clear();
|
||
var
|
||
i: integer;
|
||
curItem, nextItem: TIEIntegerMapItem;
|
||
begin
|
||
for i := 0 to length(fItems) - 1 do
|
||
begin
|
||
curItem := fItems[i];
|
||
while curItem <> nil do
|
||
begin
|
||
nextItem := curItem.nextitem;
|
||
curItem.Free();
|
||
curItem := nextItem;
|
||
end;
|
||
fItems[i] := nil;
|
||
end;
|
||
|
||
fKeysCount := 0;
|
||
end;
|
||
|
||
// hash function
|
||
// uses first fHbits-1 as direct index
|
||
function TIEIntegerMap.HashFunc(key: integer): integer;
|
||
begin
|
||
//result := key and (length(fItems) - 1);
|
||
result := key mod (length(fItems) - 1)
|
||
end;
|
||
|
||
// insert a new key (if not already exists)
|
||
// ret TRUE if key didn't exist previously
|
||
function TIEIntegerMap.Insert(key: integer; var item: TIEIntegerMapItem): boolean;
|
||
var
|
||
ix: integer;
|
||
begin
|
||
item := nil;
|
||
ix := HashFunc(key);
|
||
|
||
if fItems[ix] = nil then
|
||
begin
|
||
// bucket empty, add the new key
|
||
item := TIEIntegerMapItem.Create();
|
||
item.key := key;
|
||
item.nextitem := nil;
|
||
fItems[ix] := item;
|
||
result := true;
|
||
end
|
||
else
|
||
begin
|
||
item := fItems[ix];
|
||
while item <> nil do
|
||
begin
|
||
if item.key = key then
|
||
begin
|
||
result := false;
|
||
exit; // key already exists
|
||
end;
|
||
item := item.nextitem;
|
||
end;
|
||
// key not found, add the new key
|
||
item := TIEIntegerMapItem.Create();
|
||
item.key := key;
|
||
item.nextitem := fItems[ix];
|
||
fItems[ix] := item;
|
||
result := true;
|
||
end;
|
||
|
||
inc(fKeysCount);
|
||
end;
|
||
|
||
// insert a new key (if not already exists)
|
||
// ret TRUE if key inserted
|
||
function TIEIntegerMap.Insert(key: integer): boolean;
|
||
var
|
||
item: TIEIntegerMapItem;
|
||
begin
|
||
result := Insert(key, item);
|
||
end;
|
||
|
||
// verify if key key exists
|
||
function TIEIntegerMap.KeyExists(key: integer): boolean;
|
||
var
|
||
curItem: TIEIntegerMapItem;
|
||
begin
|
||
result := false;
|
||
|
||
curItem := fItems[ HashFunc(key) ];
|
||
|
||
while curItem <> nil do
|
||
begin
|
||
if curItem.key = key then
|
||
begin
|
||
result := true;
|
||
break;
|
||
end;
|
||
curItem := curItem.nextitem;
|
||
end;
|
||
end;
|
||
|
||
function TIEIntegerMap.IterateBegin(): boolean;
|
||
begin
|
||
fIterateItem := nil;
|
||
fIterateIndex := -1;
|
||
result := IterateNext();
|
||
end;
|
||
|
||
function TIEIntegerMap.IterateNext(): boolean;
|
||
begin
|
||
if fIterateItem <> nil then
|
||
fIterateItem := fIterateItem.nextitem;
|
||
|
||
while (fIterateItem = nil) do
|
||
begin
|
||
inc(fIterateIndex);
|
||
if fIterateIndex >= length(fItems) then
|
||
break;
|
||
fIterateItem := fItems[fIterateIndex];
|
||
end;
|
||
|
||
result := (fIterateItem <> nil);
|
||
end;
|
||
|
||
function TIEIntegerMap.IterateGetValue: integer;
|
||
begin
|
||
result := fIterateItem.value;
|
||
end;
|
||
|
||
function TIEIntegerMap.IterateGetKey(): integer;
|
||
begin
|
||
result := fIterateItem.key;
|
||
end;
|
||
|
||
function TIEIntegerMap.DumpStats(): string;
|
||
var
|
||
i, c: integer;
|
||
item: TIEIntegerMapItem;
|
||
begin
|
||
result := '';
|
||
for i := 0 to length(fItems) - 1 do
|
||
begin
|
||
c := 0;
|
||
item := fItems[i];
|
||
while item <> nil do
|
||
begin
|
||
inc(c);
|
||
item := item.nextitem;
|
||
end;
|
||
if c > 0 then
|
||
result := result + Format('%d => %d'#13#10, [i, c]);
|
||
end;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIERGBMap
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function TIERGBMap.Insert(const key: TRGB): boolean;
|
||
begin
|
||
result := Insert((key.r shl 16) or (key.g shl 8) or key.b);
|
||
end;
|
||
|
||
function TIERGBMap.Insert(const key: TRGB; value: integer): boolean;
|
||
var
|
||
item: TIEIntegerMapItem;
|
||
begin
|
||
result := Insert((key.r shl 16) or (key.g shl 8) or key.b, item);
|
||
item.value := value;
|
||
end;
|
||
|
||
function TIERGBMap.KeyExists(const key: TRGB): boolean;
|
||
begin
|
||
result := KeyExists((key.r shl 16) or (key.g shl 8) or key.b);
|
||
end;
|
||
|
||
function TIERGBMap.IterateGetKey(): TRGB;
|
||
var
|
||
value: integer;
|
||
begin
|
||
value := inherited IterateGetKey();
|
||
result.r := (value shr 16) and $FF;
|
||
result.g := (value shr 8) and $FF;
|
||
result.b := value and $FF;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
constructor TNulStream.Create;
|
||
begin
|
||
inherited;
|
||
fposition := 0;
|
||
fsize := 0;
|
||
end;
|
||
|
||
destructor TNulStream.Destroy;
|
||
begin
|
||
inherited Destroy;
|
||
end;
|
||
|
||
function TNulStream.Read(var Buffer; Count: Longint): Longint;
|
||
begin
|
||
inc(fposition, Count);
|
||
if fposition >= fsize then
|
||
fsize := fposition;
|
||
result := Count;
|
||
end;
|
||
|
||
function TNulStream.Write(const Buffer; Count: Longint): Longint;
|
||
begin
|
||
inc(fposition, Count);
|
||
if fposition >= fsize then
|
||
fsize := fposition;
|
||
result := Count;
|
||
end;
|
||
|
||
function TNulStream.Seek(Offset: Longint; Origin: Word): Longint;
|
||
begin
|
||
case Origin of
|
||
soFromBeginning:
|
||
begin
|
||
fPosition := offset;
|
||
if fposition >= fsize then
|
||
fsize := fposition;
|
||
end;
|
||
soFromCurrent:
|
||
begin
|
||
inc(fposition, offset);
|
||
if fposition >= fsize then
|
||
fsize := fposition;
|
||
end;
|
||
soFromEnd:
|
||
begin
|
||
fposition := fsize - abs(offset); // offset should be <= 0. Positive values handled as negative
|
||
end;
|
||
end;
|
||
result := fPosition;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEList
|
||
|
||
constructor TIEList.Create(OnGetCurrentValue: TIEListCurrentValueEvent = nil; OnSetCurrentValue: TIEListCurrentValueEvent = nil);
|
||
begin
|
||
inherited Create;
|
||
fData := nil;
|
||
fOnGetCurrentValue := OnGetCurrentValue;
|
||
fOnSetCurrentValue := OnSetCurrentValue;
|
||
Clear;
|
||
end;
|
||
|
||
destructor TIEList.Destroy;
|
||
begin
|
||
freemem(fData);
|
||
inherited Destroy;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEList.Clear
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Clear;
|
||
|
||
<FM>Description<FN>
|
||
Clear empties the Items array.
|
||
!!}
|
||
procedure TIEList.Clear;
|
||
begin
|
||
fCapacity := 0;
|
||
fCount := 0;
|
||
if assigned(fData) then
|
||
freemem(fData);
|
||
fData := nil;
|
||
fChanged := [];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEList.Count
|
||
|
||
<FM>Declaration<FC>
|
||
property Count: integer;
|
||
|
||
<FM>Description<FN>
|
||
Count contains the number of items in the Items array.
|
||
!!}
|
||
procedure TIEList.SetCount(v: integer);
|
||
var
|
||
xData: pointer;
|
||
begin
|
||
if fCapacity < v then
|
||
begin
|
||
fCapacity := imax(fCapacity * 2, v);
|
||
getmem(xData, fCapacity * fItemSize);
|
||
if assigned(fData) then
|
||
begin
|
||
move(pbyte(fData)^, pbyte(xData)^, imin(fCount, v) * fItemSize);
|
||
freemem(fData);
|
||
end;
|
||
fData := xData;
|
||
end;
|
||
fCount := v;
|
||
fChanged := fChanged + [ielItems];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEList.Delete
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Delete(idx: integer);
|
||
|
||
<FM>Description<FN>
|
||
Delete the idx value from the list.
|
||
!!}
|
||
procedure TIEList.Delete(idx: integer);
|
||
var
|
||
xData: pointer;
|
||
q: integer;
|
||
psrc, pdst: pbyte;
|
||
begin
|
||
if (idx >= 0) and (idx < fCount) then
|
||
begin
|
||
getmem(xData, (fCount - 1) * fItemSize);
|
||
psrc := fData;
|
||
pdst := xData;
|
||
for q := 0 to fCount - 1 do
|
||
begin
|
||
if q <> idx then
|
||
begin
|
||
// copy
|
||
move(psrc^, pdst^, fItemSize);
|
||
inc(pdst, fItemSize);
|
||
end;
|
||
inc(psrc, fItemSize);
|
||
end;
|
||
freemem(fData);
|
||
fData := xData;
|
||
dec(fCount);
|
||
fCapacity := fCount;
|
||
fChanged := fChanged + [ielItems];
|
||
end;
|
||
end;
|
||
|
||
procedure TIEList.InsertItem(idx: integer; v: pointer);
|
||
var
|
||
xData: pointer;
|
||
q: integer;
|
||
psrc, pdst: pbyte;
|
||
begin
|
||
if idx < fCount then
|
||
begin
|
||
inc(fCount);
|
||
fCapacity := fCount;
|
||
getmem(xData, fCount * fItemSize);
|
||
psrc := fData;
|
||
pdst := xData;
|
||
for q := 0 to fCount - 1 do
|
||
begin
|
||
if q <> idx then
|
||
begin
|
||
// copy
|
||
move(psrc^, pdst^, fItemSize);
|
||
inc(psrc, fItemSize);
|
||
end
|
||
else
|
||
// insert
|
||
move(pbyte(v)^, pdst^, fItemSize);
|
||
inc(pdst, fItemSize);
|
||
end;
|
||
freemem(fData);
|
||
fData := xData;
|
||
fChanged := fChanged + [ielItems];
|
||
end
|
||
else
|
||
AddItem(v);
|
||
end;
|
||
|
||
function TIEList.IndexOfItem(v: pointer): integer;
|
||
var
|
||
pp: pbyte;
|
||
begin
|
||
pp := fData;
|
||
for result := 0 to fCount - 1 do
|
||
begin
|
||
if CompareMem(pp, v, fItemSize) then
|
||
exit;
|
||
inc(pp, fItemSize);
|
||
end;
|
||
result := -1;
|
||
end;
|
||
|
||
function TIEList.AddItem(v: pointer): integer;
|
||
var
|
||
pb: pbyte;
|
||
begin
|
||
result := fCount;
|
||
SetCount(fCount + 1);
|
||
pb := fData;
|
||
inc(pb, result * fItemSize);
|
||
move(pbyte(v)^, pb^, fItemSize);
|
||
fChanged := fChanged + [ielItems];
|
||
end;
|
||
|
||
function TIEList.BaseGetItem(idx: integer): pointer;
|
||
var
|
||
pb: pbyte;
|
||
begin
|
||
pb := fData;
|
||
inc(pb, idx * fItemSize);
|
||
result := pb;
|
||
end;
|
||
|
||
procedure TIEList.BaseSetItem(idx: integer; v: pointer);
|
||
var
|
||
pb: pbyte;
|
||
begin
|
||
if idx < fCount then
|
||
begin
|
||
pb := fData;
|
||
inc(pb, idx * fItemSize);
|
||
move(pbyte(v)^, pb^, fItemSize);
|
||
fChanged := fChanged + [ielItems];
|
||
end;
|
||
end;
|
||
|
||
procedure TIEList.Assign(Source: TIEList);
|
||
begin
|
||
if assigned(Source) then
|
||
begin
|
||
fCount := Source.fCount;
|
||
fItemSize := Source.fItemSize;
|
||
fChanged := Source.fChanged;
|
||
if assigned(fData) then
|
||
begin
|
||
freemem(fData);
|
||
fData := nil;
|
||
end;
|
||
getmem(fData, fItemSize * fCount);
|
||
move(pbyte(Source.fData)^, pbyte(fData)^, fItemSize * fCount);
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEList.ExchangeItems
|
||
|
||
<FM>Declaration<FC>
|
||
procedure ExchangeItems(idx1, idx2: integer);
|
||
|
||
<FM>Description<FN>
|
||
Swap the position of items at idx1 and idx2.
|
||
!!}
|
||
procedure TIEList.ExchangeItems(idx1, idx2: integer);
|
||
var
|
||
temp: array of byte;
|
||
begin
|
||
if (idx1 < 0) or (idx1 >= FCount) then
|
||
raise EIEException.create( format( 'List index out of bounds (%d)', [ idx1 ]));
|
||
if (idx2 < 0) or (idx2 >= FCount) then
|
||
raise EIEException.create( format( 'List index out of bounds (%d)', [ idx2 ]));
|
||
|
||
SetLength( temp, fItemSize );
|
||
Move( pbyte(BaseGetItem(idx1))^, temp[0], fItemSize );
|
||
Move( pbyte(BaseGetItem(idx2))^, pbyte(BaseGetItem(idx1))^, fItemSize );
|
||
Move( temp[0], pbyte(BaseGetItem(idx2))^, fItemSize );
|
||
end;
|
||
|
||
procedure TIEList.ListQuickSort(L, R: Integer; SCompare: TIEListSortCompareFunc);
|
||
var
|
||
I, J: Integer;
|
||
P: Pointer;
|
||
begin
|
||
repeat
|
||
I := L;
|
||
J := R;
|
||
P := BaseGetItem(( L + R ) shr 1 );
|
||
repeat
|
||
while SCompare( BaseGetItem( I ), P ) < 0 do
|
||
Inc( I );
|
||
while SCompare( BaseGetItem( J ), P ) > 0 do
|
||
Dec( J );
|
||
if I <= J then
|
||
begin
|
||
if I <> J then
|
||
ExchangeItems(I, J);
|
||
Inc(I);
|
||
Dec(J);
|
||
end;
|
||
until I > J;
|
||
if L < J then
|
||
ListQuickSort( L, J, SCompare );
|
||
L := I;
|
||
until I >= R;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEList.Sort
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Sort(const Compare: <A TIEListSortCompareFunc>);
|
||
|
||
<FM>Description<FN>
|
||
Sorts the values of the list
|
||
!!}
|
||
procedure TIEList.Sort(Compare: TIEListSortCompareFunc);
|
||
begin
|
||
if Count > 1 then
|
||
ListQuickSort( 0, Count - 1, Compare);
|
||
end;
|
||
|
||
procedure TIEList.DoGetCurrentValue(value: pointer);
|
||
begin
|
||
if assigned(fOnGetCurrentValue) then
|
||
fOnGetCurrentValue(self, value);
|
||
end;
|
||
|
||
procedure TIEList.DoSetCurrentValue(value: pointer);
|
||
begin
|
||
if assigned(fOnSetCurrentValue) then
|
||
fOnSetCurrentValue(self, value);
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEDoubleList
|
||
|
||
constructor TIEDoubleList.Create(OnGetCurrentValue: TIEListCurrentValueEvent; OnSetCurrentValue: TIEListCurrentValueEvent);
|
||
begin
|
||
inherited Create(OnGetCurrentValue, OnSetCurrentValue);
|
||
end;
|
||
|
||
procedure TIEDoubleList.Assign(Source: TIEList);
|
||
begin
|
||
inherited;
|
||
if assigned(Source) then
|
||
begin
|
||
fRangeMin := (Source as TIEDoubleList).fRangeMin;
|
||
fRangeMax := (Source as TIEDoubleList).fRangeMax;
|
||
fRangeStep := (Source as TIEDoubleList).fRangeStep;
|
||
fCurrentValue := (Source as TIEDoubleList).fCurrentValue;
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.Add
|
||
|
||
<FM>Declaration<FC>
|
||
function Add(v: double): integer;
|
||
|
||
<FM>Description<FN>
|
||
Adds a new value to the list.
|
||
|
||
!!}
|
||
function TIEDoubleList.Add(v: double): integer;
|
||
begin
|
||
result := AddItem(@v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.Clear
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Clear;
|
||
|
||
<FM>Description<FN>
|
||
Removes all items.
|
||
!!}
|
||
procedure TIEDoubleList.Clear;
|
||
begin
|
||
inherited;
|
||
fItemSize := sizeof(double);
|
||
fRangeMin := 0;
|
||
fRangeMax := 0;
|
||
fRangeStep := 0;
|
||
fCurrentValue := 0;
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.Items
|
||
|
||
<FM>Declaration<FC>
|
||
property Items[index]: double;
|
||
|
||
<FM>Description<FN>
|
||
Items returns the double value of index element.
|
||
!!}
|
||
function TIEDoubleList.GetItem(idx: integer): double;
|
||
begin
|
||
result := PDouble(BaseGetItem(idx))^;
|
||
end;
|
||
|
||
procedure TIEDoubleList.SetItem(idx: integer; v: double);
|
||
begin
|
||
BaseSetItem(idx, @v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.Insert
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Insert(idx: integer; v: double);
|
||
|
||
<FM>Description<FN>
|
||
Insert a new value inside idx position.
|
||
!!}
|
||
procedure TIEDoubleList.Insert(idx: integer; v: double);
|
||
begin
|
||
InsertItem(idx, @v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.IndexOf
|
||
|
||
<FM>Declaration<FC>
|
||
function IndexOf(v: double): integer;
|
||
|
||
<FM>Description<FN>
|
||
IndexOf returns the index of v value. Returns -1 if not found.
|
||
!!}
|
||
function TIEDoubleList.IndexOf(v: double): integer;
|
||
begin
|
||
result := IndexOfItem(@v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.RangeMin
|
||
|
||
<FM>Declaration<FC>
|
||
property RangeMin: double;
|
||
|
||
<FM>Description<FN>
|
||
RangeMin is the minimum value that you can assign to <A TIEDoubleList.CurrentValue>.
|
||
!!}
|
||
procedure TIEDoubleList.SetRangeMin(v: double);
|
||
begin
|
||
fRangeMin := v;
|
||
fChanged := fChanged + [ielRange];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.RangeMax
|
||
|
||
<FM>Declaration<FC>
|
||
property RangeMax: double;
|
||
|
||
<FM>Description<FN>
|
||
RangeMax is the max value that you can assign to <A TIEDoubleList.CurrentValue>.
|
||
!!}
|
||
procedure TIEDoubleList.SetRangeMax(v: double);
|
||
begin
|
||
fRangeMax := v;
|
||
fChanged := fChanged + [ielRange];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.RangeStep
|
||
|
||
<FM>Declaration<FC>
|
||
property RangeStep: double;
|
||
|
||
<FM>Description<FN>
|
||
RangeStep defines the step from <A TIEDoubleList.RangeMin> to <A TIEDoubleList.RangeMax>.
|
||
!!}
|
||
procedure TIEDoubleList.SetRangeStep(v: double);
|
||
begin
|
||
fRangeStep := v;
|
||
fChanged := fChanged + [ielRange];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEDoubleList.CurrentValue
|
||
|
||
<FM>Declaration<FC>
|
||
property CurrentValue: double;
|
||
|
||
<FM>Description<FN>
|
||
CurrentValue returns the current value of the list. It isn't an index of <A TIEDoubleList.Items>, but a "powerup" value.
|
||
No control is made to values assigned to CurrentValue, but it should be one of the values in <A TIEDoubleList.Items> or inside of <A TIEDoubleList.RangeMin> and <A TIEDoubleList.RangeMax> (regarding <A TIEDoubleList.RangeStep> also).
|
||
!!}
|
||
procedure TIEDoubleList.SetCurrentValue(v: double);
|
||
begin
|
||
if fCurrentValue <> v then
|
||
begin
|
||
fCurrentValue := v;
|
||
fChanged := fChanged + [ielCurrentValue];
|
||
DoSetCurrentValue(@fCurrentValue);
|
||
end;
|
||
end;
|
||
|
||
function TIEDoubleList.GetCurrentValue(): double;
|
||
begin
|
||
DoGetCurrentValue(@fCurrentValue);
|
||
result := fCurrentValue;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEIntegerList
|
||
|
||
|
||
constructor TIEIntegerList.Create(OnGetCurrentValue: TIEListCurrentValueEvent; OnSetCurrentValue: TIEListCurrentValueEvent);
|
||
begin
|
||
inherited Create(OnGetCurrentValue, OnSetCurrentValue);
|
||
end;
|
||
|
||
procedure TIEIntegerList.Assign(Source: TIEList);
|
||
begin
|
||
inherited;
|
||
if assigned(Source) then
|
||
begin
|
||
fRangeMin := (Source as TIEIntegerList).fRangeMin;
|
||
fRangeMax := (Source as TIEIntegerList).fRangeMax;
|
||
fRangeStep := (Source as TIEIntegerList).RangeStep;
|
||
fCurrentValue := (Source as TIEIntegerList).fCurrentValue;
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.Add
|
||
|
||
<FM>Declaration<FC>
|
||
function Add(v: integer): integer;
|
||
|
||
<FM>Description<FN>
|
||
Adds a new value to the list.
|
||
!!}
|
||
function TIEIntegerList.Add(v: Integer): integer;
|
||
begin
|
||
result := AddItem(@v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.Clear
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Clear;
|
||
|
||
<FM>Description<FN>
|
||
Removes all items.
|
||
!!}
|
||
procedure TIEIntegerList.Clear;
|
||
begin
|
||
inherited;
|
||
fRangeMin := 0;
|
||
fRangeMax := 0;
|
||
fRangeStep := 0;
|
||
fCurrentValue := 0;
|
||
fItemSize := sizeof(Integer);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.Items
|
||
|
||
<FM>Declaration<FC>
|
||
property Items[index]: integer;
|
||
|
||
<FM>Description<FN>
|
||
<FC>Items<FN> returns the value of <FC>index<FN> element.
|
||
!!}
|
||
function TIEIntegerList.GetItem(idx: integer): Integer;
|
||
begin
|
||
result := PInteger(BaseGetItem(idx))^;
|
||
end;
|
||
|
||
procedure TIEIntegerList.SetItem(idx: integer; v: Integer);
|
||
begin
|
||
BaseSetItem(idx, @v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.Insert
|
||
|
||
<FM>Declaration<FC>
|
||
procedure Insert(idx: integer; v: integer);
|
||
|
||
<FM>Description<FN>
|
||
Insert a new value inside idx position.
|
||
!!}
|
||
procedure TIEIntegerList.Insert(idx: integer; v: Integer);
|
||
begin
|
||
InsertItem(idx, @v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.IndexOf
|
||
|
||
<FM>Declaration<FC>
|
||
function IndexOf(v: integer): integer;
|
||
|
||
<FM>Description<FN>
|
||
IndexOf returns the index of v value. Returns -1 if not found.
|
||
|
||
!!}
|
||
function TIEIntegerList.IndexOf(v: Integer): integer;
|
||
begin
|
||
result := IndexOfItem(@v);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.RangeMin
|
||
|
||
<FM>Declaration<FC>
|
||
property RangeMin: integer;
|
||
|
||
<FM>Description<FN>
|
||
RangeMin is the minimum value that you may assign to <A TIEIntegerList.CurrentValue>.
|
||
|
||
!!}
|
||
procedure TIEIntegerList.SetRangeMin(v: integer);
|
||
begin
|
||
fRangeMin := v;
|
||
fChanged := fChanged + [ielRange];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.RangeMax
|
||
|
||
<FM>Declaration<FC>
|
||
property RangeMax: integer;
|
||
|
||
<FM>Description<FN>
|
||
RangeMax is the maximum value you may assign to <A TIEIntegerList.CurrentValue>.
|
||
|
||
!!}
|
||
procedure TIEIntegerList.SetRangeMax(v: integer);
|
||
begin
|
||
fRangeMax := v;
|
||
fChanged := fChanged + [ielRange];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.RangeStep
|
||
|
||
<FM>Declaration<FC>
|
||
property RangeStep: integer;
|
||
|
||
<FM>Description<FN>
|
||
RangeStep specifies the step from <A TIEIntegerList.RangeMin> to <A TIEIntegerList.RangeMax>.
|
||
|
||
!!}
|
||
procedure TIEIntegerList.SetRangeStep(v: integer);
|
||
begin
|
||
fRangeStep := v;
|
||
fChanged := fChanged + [ielRange];
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIEIntegerList.CurrentValue
|
||
|
||
<FM>Declaration<FC>
|
||
property CurrentValue: integer;
|
||
|
||
<FM>Description<FN>
|
||
CurrentValue returns the current value of the list. It isn't an index of <A TIEIntegerList.Items>, but a "powerup" value.
|
||
|
||
No control is made to values assigned to CurrentValue, but it should be one of the values in <A TIEIntegerList.Items> or inside of <A TIEIntegerList.RangeMin> and <A TIEIntegerList.RangeMax> (regarding <A TIEIntegerList.RangeStep> also).
|
||
|
||
!!}
|
||
procedure TIEIntegerList.SetCurrentValue(v: integer);
|
||
begin
|
||
if fCurrentValue <> v then
|
||
begin
|
||
fCurrentValue := v;
|
||
fChanged := fChanged + [ielCurrentValue];
|
||
DoSetCurrentValue(@fCurrentValue);
|
||
end;
|
||
end;
|
||
|
||
function TIEIntegerList.GetCurrentValue(): integer;
|
||
begin
|
||
DoGetCurrentValue(@fCurrentValue);
|
||
result := fCurrentValue;
|
||
end;
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Prime numbers
|
||
|
||
function IEIsPrime(x: integer): boolean;
|
||
var
|
||
i, q: integer;
|
||
begin
|
||
result := true;
|
||
i := 3;
|
||
while true do
|
||
begin
|
||
q := x div i;
|
||
if (q < i) then
|
||
break;
|
||
if (x = q * i) then
|
||
begin
|
||
result := false;
|
||
break;
|
||
end;
|
||
inc(i, 2);
|
||
end;
|
||
end;
|
||
|
||
function IENextPrime(x: integer): integer;
|
||
begin
|
||
result := x + 1;
|
||
if (result <= 2) then
|
||
begin
|
||
result := 2;
|
||
exit;
|
||
end;
|
||
if (result and 1) = 0 then
|
||
inc(result);
|
||
while not IEIsPrime(result) do
|
||
inc(result, 2);
|
||
end;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
procedure QuickSort1(L, R: Integer; CompareFunction: TIECompareFunction; SwapFunction: TIESwapFunction);
|
||
var
|
||
I, J, P: Integer;
|
||
begin
|
||
repeat
|
||
I := L;
|
||
J := R;
|
||
P := L + (R - L) shr 1; // 3.0.4
|
||
repeat
|
||
while CompareFunction(I, P) < 0 do Inc(I);
|
||
while CompareFunction(J, P) > 0 do Dec(J);
|
||
if I <= J then
|
||
begin
|
||
if I=P then
|
||
P := J
|
||
else
|
||
if J=P then
|
||
P := I;
|
||
SwapFunction(I, J);
|
||
Inc(I);
|
||
Dec(J);
|
||
end;
|
||
until I > J;
|
||
if L < J then
|
||
QuickSort1(L, J, CompareFunction, SwapFunction);
|
||
L := I;
|
||
until I >= R;
|
||
end;
|
||
|
||
procedure IEQuickSort(ItemsCount: integer; CompareFunction: TIECompareFunction; SwapFunction: TIESwapFunction);
|
||
begin
|
||
if ItemsCount > 1 then
|
||
QuickSort1(0, ItemsCount - 1, CompareFunction, SwapFunction);
|
||
end;
|
||
|
||
// returns the full file path
|
||
// Directory must contain the last '\'
|
||
function IEGetTempFileName(const Descriptor: string; const Directory: string): string;
|
||
begin
|
||
repeat
|
||
result := Directory + Descriptor + '-' + IntToHex(random(MAXINT), 8) + '.tmp';
|
||
until not IEFileExists(result);
|
||
end;
|
||
|
||
// returns the full file path
|
||
function IEGetTempFileName2: string;
|
||
var
|
||
temppath: array[0..MAX_PATH] of Char;
|
||
tp: string;
|
||
begin
|
||
if IEGlobalSettings().DefTEMPPATH = '' then
|
||
begin
|
||
GetTempPath(250, temppath);
|
||
tp := string(temppath);
|
||
end
|
||
else
|
||
tp := IEGlobalSettings().DefTEMPPATH;
|
||
result := IEGetTempFileName('ietemp', tp);
|
||
end;
|
||
|
||
// Return a numbered filename that does not exist. I.e. returns sBaseFilename if the file does not already exist. Otherwise returns a numbered version of sBaseFilename
|
||
function IEGetNewFilename(const sBaseFilename: string; const sSepChar: Char = ' '): string;
|
||
var
|
||
I: Integer;
|
||
iCurrentSuffix: Integer;
|
||
iFileNumber: Integer;
|
||
sCurrentSuffix: string;
|
||
sExt: string;
|
||
sRootFilename: string;
|
||
begin
|
||
sRootFilename := IEAddBackSlash( ExtractFilePath( sBaseFilename )) + IEExtractFileNameWithoutExt( sBaseFilename );
|
||
sExt := IEExtractFileExtS( sBaseFilename );
|
||
iFileNumber := 1;
|
||
|
||
// Check if it already has a number extension
|
||
sCurrentSuffix := '';
|
||
if ( sSepChar <> '' ) and FileExists( sBaseFilename ) then
|
||
for I := Length( sRootFilename ) downto 1 do
|
||
begin
|
||
if sRootFilename[ I ] = sSepChar then
|
||
break
|
||
else
|
||
sCurrentSuffix := sRootFilename[ I ] + sCurrentSuffix;
|
||
if Length( sCurrentSuffix ) > 8 then
|
||
break; // Not a number
|
||
end;
|
||
|
||
// do we have a valid number suffix?
|
||
iCurrentSuffix := StrToIntDef( sCurrentSuffix, -1 );
|
||
if iCurrentSuffix > 0 then
|
||
begin
|
||
iFileNumber := iCurrentSuffix + 1;
|
||
SetLength( sRootFilename, Length( sRootFilename ) - Length( sSepChar + sCurrentSuffix ));
|
||
end;
|
||
|
||
// Find the first unique filename
|
||
for I := iFileNumber to MaxInt do
|
||
begin
|
||
if I = 1 then
|
||
result := sBaseFilename
|
||
else
|
||
result := sRootFilename + sSepChar + IntToStr( I ) + sExt;
|
||
if FileExists( result ) = False then
|
||
break;
|
||
end;
|
||
end;
|
||
|
||
|
||
function IEGetMem(ASize: dword): pointer;
|
||
begin
|
||
result := VirtualAlloc(nil, ASize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
|
||
end;
|
||
|
||
// Frees memory
|
||
procedure IEFreeMem(var P);
|
||
begin
|
||
VirtualFree(pointer(P), 0, MEM_RELEASE);
|
||
pointer(P) := nil;
|
||
end;
|
||
|
||
|
||
function IEFindNearestColor(color: TRGB; palette: TIEArrayOfTRGB; colorCount: integer): integer;
|
||
var
|
||
i: integer;
|
||
dstSqr: integer;
|
||
minDstSqr: integer;
|
||
dr, dg, db: integer;
|
||
begin
|
||
result := 0;
|
||
minDstSqr := 195076;
|
||
for i := 0 to colorCount - 1 do
|
||
begin
|
||
dr := integer(color.r) - integer(palette[i].r);
|
||
dg := integer(color.g) - integer(palette[i].g);
|
||
db := integer(color.b) - integer(palette[i].b);
|
||
dstSqr := dr * dr + dg * dg + db * db;
|
||
if dstSqr < minDstSqr then
|
||
begin
|
||
minDstSqr := dstSqr;
|
||
result := i;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
// Search a string from current stream position. Returns the start of string position (or -1 if not found)
|
||
// The stream position is one character after the end of the string
|
||
function IEStreamFindString(Stream: TStream; Text: AnsiString; StopAtPos: int64): int64;
|
||
var
|
||
spos: int64;
|
||
c: AnsiChar;
|
||
i: integer;
|
||
textLen: integer;
|
||
begin
|
||
textLen := length(Text);
|
||
while (Stream.Position < StopAtpos) do
|
||
begin
|
||
spos := Stream.Position;
|
||
for i := 1 to textLen do
|
||
begin
|
||
Stream.Read(c, 1);
|
||
if c <> Text[i] then
|
||
break
|
||
else
|
||
if i = textLen then
|
||
begin
|
||
result := spos;
|
||
exit;
|
||
end;
|
||
end;
|
||
end;
|
||
result := -1;
|
||
end;
|
||
|
||
|
||
// Executes a console command and returns its output
|
||
function IEGetDosOutput(CommandLine: AnsiString; Work: AnsiString = 'C:\'): AnsiString;
|
||
var
|
||
SA: TSecurityAttributes;
|
||
{$IFDEF UNICODE}
|
||
SI: TStartupInfoA;
|
||
{$ELSE}
|
||
SI: TStartupInfo;
|
||
{$ENDIF}
|
||
PI: TProcessInformation;
|
||
StdOutPipeRead, StdOutPipeWrite: THandle;
|
||
WasOK: Boolean;
|
||
Buffer: array [0..255] of AnsiChar;
|
||
BytesRead: Cardinal;
|
||
WorkDir: AnsiString;
|
||
Handle: Boolean;
|
||
begin
|
||
Result := '';
|
||
with SA do begin
|
||
nLength := SizeOf(SA);
|
||
bInheritHandle := True;
|
||
lpSecurityDescriptor := nil;
|
||
end;
|
||
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
|
||
try
|
||
with SI do
|
||
begin
|
||
FillChar(SI, SizeOf(SI), 0);
|
||
cb := SizeOf(SI);
|
||
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
|
||
wShowWindow := SW_HIDE;
|
||
hStdInput := GetStdHandle(STD_INPUT_HANDLE);
|
||
hStdOutput := StdOutPipeWrite;
|
||
hStdError := StdOutPipeWrite;
|
||
end;
|
||
WorkDir := Work;
|
||
Handle := CreateProcessA(nil, PAnsiChar('cmd.exe /C ' + CommandLine),
|
||
nil, nil, True, 0, nil,
|
||
PAnsiChar(WorkDir), SI, PI);
|
||
CloseHandle(StdOutPipeWrite);
|
||
if Handle then
|
||
try
|
||
repeat
|
||
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
|
||
if BytesRead > 0 then
|
||
begin
|
||
Buffer[BytesRead] := #0;
|
||
Result := Result + Buffer;
|
||
end;
|
||
until not WasOK or (BytesRead = 0);
|
||
WaitForSingleObject(PI.hProcess, INFINITE);
|
||
finally
|
||
CloseHandle(PI.hThread);
|
||
CloseHandle(PI.hProcess);
|
||
end;
|
||
finally
|
||
CloseHandle(StdOutPipeRead);
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
function IEGPSConvertDMSToDegDec(degrees: Double; minutes: Double; seconds: Double; ref: AnsiString): Double;
|
||
begin
|
||
result := degrees + minutes / 60.0 + seconds / 3600.0;
|
||
if (ref = 'W') or (ref = 'S') then
|
||
result := - result;
|
||
end;
|
||
|
||
// dir must be:
|
||
// 'SN' : latitude conversion
|
||
// 'WE' : longitude conversion
|
||
procedure IEGPSConvertDegDecToDMS(dir: AnsiString; value: Double; var degrees: Double; var minutes: Double; var seconds: Double; var ref: AnsiString);
|
||
begin
|
||
if value < 0 then
|
||
ref := dir[1]
|
||
else
|
||
ref := dir[2];
|
||
value := Abs(value);
|
||
degrees := Trunc(value);
|
||
value := Frac(value) * 60.0;
|
||
minutes := Trunc(value);
|
||
seconds := Frac(value) * 60.0;
|
||
end;
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
// IEGetCoresCount
|
||
|
||
const
|
||
|
||
// LOGICAL_PROCESSOR_RELATIONSHIP
|
||
RelationProcessorCore = 0;
|
||
RelationNumaNode = 1;
|
||
RelationCache = 2;
|
||
RelationProcessorPackage = 3;
|
||
|
||
// PROCESSOR_CACHE_TYPE
|
||
CacheUnified = 0;
|
||
CacheInstruction = 1;
|
||
CacheData = 2;
|
||
CacheTrace = 3;
|
||
|
||
type
|
||
|
||
CACHE_DESCRIPTOR = packed record
|
||
Level: BYTE;
|
||
Associativity: BYTE;
|
||
LineSize: WORD;
|
||
Size: DWORD;
|
||
Type_: DWORD; //PROCESSOR_CACHE_TYPE
|
||
end;
|
||
|
||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION = packed record
|
||
ProcessorMask: DWORD;
|
||
Relationship: DWORD; // LOGICAL_PROCESSOR_RELATIONSHIP
|
||
case integer of
|
||
0: (ProcessorCore : packed record Flags: BYTE; end);
|
||
1: (NumaNode : packed record NodeNumber: DWORD; end);
|
||
2: (Cache: CACHE_DESCRIPTOR);
|
||
3: (Reserved : packed record d1: int64; d2: int64; end);
|
||
end;
|
||
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION = ^SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
|
||
|
||
TIEGetLogicalProcessorInformation = function(buffer: PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; ReturnLength: PDWORD): longbool; stdcall;
|
||
|
||
function IEGetCoresCount(): integer;
|
||
var
|
||
buffer: pointer;
|
||
l, c: integer;
|
||
byteOff: integer;
|
||
curInfo: PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
|
||
hLib: THandle;
|
||
IEGetLogicalProcessorInformation: TIEGetLogicalProcessorInformation;
|
||
begin
|
||
if IEGlobalSettings().DefaultCoresCount = -1 then
|
||
begin
|
||
IEGlobalSettings().DefaultCoresCount := 1;
|
||
l := 0;
|
||
buffer := nil;
|
||
hLib := LoadLibrary('Kernel32.dll');
|
||
if hlib<>0 then
|
||
begin
|
||
@IEGetLogicalProcessorInformation := GetProcAddress(hLib, 'GetLogicalProcessorInformation');
|
||
if @IEGetLogicalProcessorInformation<>nil then
|
||
begin
|
||
IEGetLogicalProcessorInformation(buffer, @l); // get length of buffer to allocate
|
||
if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
|
||
begin
|
||
getmem(buffer, l);
|
||
if IEGetLogicalProcessorInformation(buffer, @l) then
|
||
begin
|
||
c := 0;
|
||
curInfo := PSYSTEM_LOGICAL_PROCESSOR_INFORMATION(buffer);
|
||
byteOff := 0;
|
||
while byteOff < l do
|
||
begin
|
||
if curInfo^.Relationship = RelationProcessorCore then
|
||
inc(c);
|
||
inc(curInfo);
|
||
inc(byteOff, sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||
end;
|
||
IEGlobalSettings().DefaultCoresCount := c;
|
||
end;
|
||
end;
|
||
end;
|
||
FreeLibrary(hLib);
|
||
end;
|
||
freemem(buffer);
|
||
end;
|
||
result := IEGlobalSettings().DefaultCoresCount;
|
||
end;
|
||
|
||
|
||
function IEGetRequiredThreads(ImageWidth, ImageHeight: integer): integer;
|
||
begin
|
||
if ImageWidth * ImageHeight >= IEGlobalSettings().ImageProcThreadsMinSize then
|
||
result := imin(IEGlobalSettings().ImageProcMaxThreads, IEGetCoresCount())
|
||
else
|
||
result := 1;
|
||
end;
|
||
|
||
|
||
// Returns true if the O/S is Vista, 7, 8 or something as yet undiscovered
|
||
function IEIsWindowsVistaOrNewer : Boolean;
|
||
begin
|
||
Result := IEGlobalSettings().OpSys in [ieosUnknown, ieosWinVista, ieosWin7, ieosWin8, ieosWin10];
|
||
end;
|
||
|
||
|
||
function IEIsKeyPressed(aKey: Word): Boolean;
|
||
begin
|
||
Result := ( GetKeyState( aKey ) and $8000 ) <> 0;
|
||
end;
|
||
|
||
|
||
// Returns a suitable font to use for Preview dialogs. Segoe UI 9 on Vista, 7. Tahoma 8 on XP, etc
|
||
function IEGetDefaultDialogFont() : TFont;
|
||
const
|
||
Vista_GUI_Font_Name = 'Segoe UI';
|
||
Vista_GUI_Font_Height = -12;
|
||
XP_GUI_Font_Name = 'Tahoma';
|
||
XP_GUI_Font_Height = -11;
|
||
begin
|
||
// Note: could use Screen.IconFont but our dialogs may not support unexpected fonts
|
||
if assigned(IEGlobalSettings().DefaultDialogFont) = False then
|
||
begin
|
||
IEGlobalSettings().DefaultDialogFont := TFont.Create;
|
||
|
||
IEGlobalSettings().DefaultDialogFont.Charset := DEFAULT_CHARSET;
|
||
IEGlobalSettings().DefaultDialogFont.Color := clWindowText;
|
||
IEGlobalSettings().DefaultDialogFont.Style := [];
|
||
|
||
if IEIsWindowsVistaOrNewer and (Screen.Fonts.IndexOf(Vista_GUI_Font_Name) >= 0) then
|
||
begin
|
||
IEGlobalSettings().DefaultDialogFont.Height := Vista_GUI_Font_Height;
|
||
IEGlobalSettings().DefaultDialogFont.Name := Vista_GUI_Font_Name;
|
||
end
|
||
else
|
||
begin
|
||
IEGlobalSettings().DefaultDialogFont.Height := XP_GUI_Font_Height;
|
||
IEGlobalSettings().DefaultDialogFont.Name := XP_GUI_Font_Name;
|
||
end
|
||
end;
|
||
|
||
Result := IEGlobalSettings().DefaultDialogFont;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
procedure IECenterWindow(Wnd: HWnd);
|
||
var
|
||
Rect: TRect;
|
||
Monitor: TMonitor;
|
||
begin
|
||
if assigned(IEGlobalSettings().DefDialogCenter) then
|
||
IEGlobalSettings().DefDialogCenter(Wnd)
|
||
else
|
||
begin
|
||
GetWindowRect(Wnd, Rect);
|
||
if Application.MainForm <> nil then
|
||
begin
|
||
if Assigned(Screen.ActiveForm) then
|
||
Monitor := Screen.ActiveForm.Monitor
|
||
else
|
||
Monitor := Application.MainForm.Monitor;
|
||
end
|
||
else
|
||
Monitor := Screen.Monitors[0];
|
||
SetWindowPos(Wnd, 0,
|
||
Monitor.Left + ((Monitor.Width - Rect.Right + Rect.Left) div 2),
|
||
Monitor.Top + ((Monitor.Height - Rect.Bottom + Rect.Top) div 3),
|
||
0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
type
|
||
TMEMORYSTATUSEX=packed record
|
||
dwLength: DWORD;
|
||
dwMemoryLoad: DWORD;
|
||
ullTotalPhys: int64;
|
||
ullAvailPhys: int64;
|
||
ullTotalPageFile: int64;
|
||
ullAvailPageFile: int64;
|
||
ullTotalVirtual: int64;
|
||
ullAvailVirtual: int64;
|
||
ullAvailExtendedVirtual: int64;
|
||
end;
|
||
PMEMORYSTATUSEX=^TMEMORYSTATUSEX;
|
||
|
||
TIEGlobalMemoryStatusEx = function(lpBuffer: PMEMORYSTATUSEX): longbool; stdcall;
|
||
|
||
// freememory = false -> total memory
|
||
// freememory = true -> free memory
|
||
function IEGetMemory(freememory: boolean): int64;
|
||
var
|
||
ms: TMemoryStatus;
|
||
msx: TMEMORYSTATUSEX;
|
||
h: THandle;
|
||
IEGlobalMemoryStatusEx: TIEGlobalMemoryStatusEx;
|
||
begin
|
||
h := LoadLibrary('Kernel32.dll');
|
||
if h <> 0 then
|
||
begin
|
||
@IEGlobalMemoryStatusEx := GetProcAddress(h, 'GlobalMemoryStatusEx');
|
||
if @IEGlobalMemoryStatusEx<>nil then
|
||
begin
|
||
FillChar(msx, sizeof(TMEMORYSTATUSEX), 0);
|
||
msx.dwLength := sizeof(TMEMORYSTATUSEX);
|
||
IEGlobalMemoryStatusEx(@msx);
|
||
if freememory then
|
||
result := msx.ullAvailPhys
|
||
else
|
||
result := msx.ullTotalPhys;
|
||
FreeLibrary(h);
|
||
exit;
|
||
end;
|
||
FreeLibrary(h);
|
||
end;
|
||
|
||
ms.dwLength := sizeof(ms);
|
||
GlobalMemoryStatus(ms);
|
||
if freememory then
|
||
result := ms.dwAvailPhys
|
||
else
|
||
result := ms.dwTotalPhys;
|
||
end;
|
||
|
||
|
||
|
||
procedure IECalcUnitsPerPixel(DpiX, DpiY: Integer; mu: TIEUnits; out cx, cy: double);
|
||
const
|
||
Inches_per_Foot = 12;
|
||
Inches_per_Yard = 36;
|
||
Inches_per_Mile = 63360;
|
||
begin
|
||
if mu = ieuPIXELS then
|
||
begin
|
||
cx := 1;
|
||
cy := 1;
|
||
end
|
||
else
|
||
if ( DpiX = 0 ) or ( DpiY = 0 ) then
|
||
begin
|
||
cx := 1;
|
||
cy := 1;
|
||
end
|
||
else
|
||
begin
|
||
cx := 1 / DpiX;
|
||
cy := 1 / DpiY;
|
||
case mu of
|
||
ieuKM:
|
||
begin
|
||
cx := (cx * CM_per_Inch) / 100000;
|
||
cy := (cy * CM_per_Inch) / 100000;
|
||
end;
|
||
ieuMETERS:
|
||
begin
|
||
cx := (cx * CM_per_Inch) / 100;
|
||
cy := (cy * CM_per_Inch) / 100;
|
||
end;
|
||
ieuCENTIMETERS:
|
||
begin
|
||
cx := cx * CM_per_Inch;
|
||
cy := cy * CM_per_Inch;
|
||
end;
|
||
ieuMILLIMETERS:
|
||
begin
|
||
cx := (cx * CM_per_Inch) * 10;
|
||
cy := (cy * CM_per_Inch) * 10;
|
||
end;
|
||
ieuMICRONS:
|
||
begin
|
||
cx := (cx * CM_per_Inch) * 10000;
|
||
cy := (cy * CM_per_Inch) * 10000;
|
||
end;
|
||
ieuNANOMETERS:
|
||
begin
|
||
cx := (cx * CM_per_Inch) * 10000000;
|
||
cy := (cy * CM_per_Inch) * 10000000;
|
||
end;
|
||
ieuFEET:
|
||
begin
|
||
cx := cx / Inches_per_Foot;
|
||
cy := cy / Inches_per_Foot;
|
||
end;
|
||
ieuYARDS:
|
||
begin
|
||
cx := cx / Inches_per_Yard;
|
||
cy := cy / Inches_per_Yard;
|
||
end;
|
||
ieuMILES:
|
||
begin
|
||
cx := cx / Inches_per_Mile;
|
||
cy := cy / Inches_per_Mile;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
procedure IESetPlim(var plim: trect; x, y: integer);
|
||
begin
|
||
if x < plim.Left then
|
||
plim.left := x;
|
||
if x > plim.Right then
|
||
plim.right := x;
|
||
if y < plim.Top then
|
||
plim.top := y;
|
||
if y > plim.Bottom then
|
||
plim.bottom := y;
|
||
end;
|
||
|
||
|
||
function IEArcCos(X: Extended): Extended;
|
||
begin
|
||
if (X = 1) or (X = -1) then
|
||
result := 0
|
||
else
|
||
Result := ArcTan2(Sqrt(1 - X * X), X);
|
||
end;
|
||
|
||
|
||
function IEDegreesToRadians(Angle: Double): Double;
|
||
begin
|
||
Result := Angle * PI / 180.0;
|
||
end;
|
||
|
||
function IERadiansToDegrees(Rad: Double): Double;
|
||
begin
|
||
Result := Rad * 180.0 / PI;
|
||
end;
|
||
|
||
|
||
// calculates the angle (rad) of the specified triangle. x2, y2 is the angle center
|
||
function IEAngle(x1, y1, x2, y2, x3, y3: double): double;
|
||
var
|
||
vx1, vy1, vx2, vy2: double;
|
||
d1, d2: double;
|
||
begin
|
||
vx1 := x2 - x1;
|
||
vy1 := y2 - y1;
|
||
vx2 := x3 - x2;
|
||
vy2 := y3 - y2;
|
||
try
|
||
d1 := sqrt(vx1 * vx1 + vy1 * vy1);
|
||
except
|
||
d1 := 0;
|
||
end;
|
||
try
|
||
d2 := sqrt(vx2 * vx2 + vy2 * vy2);
|
||
except
|
||
d2 := 0;
|
||
end;
|
||
if (d1 = 0) or (d2 = 0) then
|
||
result := 0
|
||
else
|
||
begin
|
||
d1 := (vx1 * vx2 + vy1 * vy2) / (d1 * d2);
|
||
if abs(d1) <= 1 then
|
||
result := IEArcCos(d1)
|
||
else
|
||
result := 0;
|
||
end;
|
||
end;
|
||
|
||
// Calc angle (rad) of segment x1, y1-x2, y2 relative to the X axis
|
||
function IEAngle2(x1, y1, x2, y2: integer): double;
|
||
begin
|
||
if (x1 < x2) and (y2 < y1) then // 1
|
||
result := pi - ieangle(x2, y2, x1, y1, x2, y1)
|
||
else
|
||
if (x1 < x2) and (y1 < y2) then // 4
|
||
result := pi + ieangle(x2, y1, x1, y1, x2, y2)
|
||
else
|
||
if (x2 < x1) and (y1 < y2) then // 3
|
||
result := 2 * pi - ieangle(x2, y1, x1, y1, x2, y2)
|
||
else
|
||
if (x2 < x1) and (y2 < y1) then // 2
|
||
result := ieangle(x2, y1, x1, y1, x2, y2)
|
||
else
|
||
if (x2 = x1) and (y1 > y2) then
|
||
result := pi / 2
|
||
else
|
||
if (x2 = x1) and (y1 < y2) then
|
||
result := 1.5 * pi
|
||
else
|
||
if (y1 = y2) and (x1 > x2) then
|
||
result := pi
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
function ccw(x0, y0, x1, y1, x2, y2: integer): integer;
|
||
var
|
||
dx1, dx2, dy1, dy2: integer;
|
||
begin
|
||
dx1 := x1 - x0;
|
||
dy1 := y1 - y0;
|
||
dx2 := x2 - x0;
|
||
dy2 := y2 - y0;
|
||
if dx1 * dy2 > dy1 * dx2 then
|
||
result := 1
|
||
else
|
||
if dx1 * dy2 < dy1 * dx2 then
|
||
result := -1
|
||
else
|
||
if (dx1 * dx2 < 0) or (dy1 * dy2 < 0) then
|
||
result := -1
|
||
else
|
||
if (dx1 * dx1 + dy1 * dy1) < (dx2 * dx2 + dy2 * dy2) then
|
||
result := 1
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
function IEAngle3(x1, y1, xc, yc, x2, y2: integer): double;
|
||
var
|
||
a, b, c: double;
|
||
begin
|
||
// a is (xc, yc)-(x2, y2)
|
||
// b is (x1, y1)-(x2, y2)
|
||
// c is (xc, yc)-(x1, y1)
|
||
a := sqrt(sqr(x2 - xc) + sqr(y2 - yc));
|
||
if a = 0 then
|
||
a := 1;
|
||
b := sqrt(sqr(x2 - x1) + sqr(y2 - y1));
|
||
if b = 0 then
|
||
b := 1;
|
||
c := sqrt(sqr(xc - x1) + sqr(yc - y1));
|
||
if c = 0 then
|
||
c := 1;
|
||
result := IEArcCos((sqr(a) + sqr(c) - sqr(b)) / (2 * a * c));
|
||
if ccw(x1, y1, xc, yc, x2, y2) = -1 then
|
||
result := 2 * PI - result;
|
||
end;
|
||
|
||
|
||
// returns reference angle (ex. 45.5 = 45.5, 361 = 1, 1000.5 =
|
||
// Angles in degrees
|
||
function IEGetReferenceAngle(Angle: double): double;
|
||
begin
|
||
result := Angle - Floor (Angle / 360.0) * 360.0;
|
||
if Angle < 0 then
|
||
result := - 360 + result;
|
||
end;
|
||
|
||
|
||
function IEExtractStylesFromLogFont(logfont: PLogFontA): TFontStyles;
|
||
begin
|
||
result := [];
|
||
if LogFont <> nil then
|
||
with LogFont^ do
|
||
begin
|
||
if lfItalic <> 0 then
|
||
include(result, fsItalic);
|
||
if lfUnderline <> 0 then
|
||
include(result, fsUnderline);
|
||
if lfStrikeOut <> 0 then
|
||
include(result, fsStrikeOut);
|
||
if lfWeight >= FW_BOLD then
|
||
include(result, fsBold);
|
||
end;
|
||
end;
|
||
|
||
|
||
function IEExtractStylesFromLogFontW(logfont: PLogFontW): TFontStyles;
|
||
begin
|
||
result := [];
|
||
if LogFont <> nil then
|
||
with LogFont^ do
|
||
begin
|
||
if lfItalic <> 0 then
|
||
include(result, fsItalic);
|
||
if lfUnderline <> 0 then
|
||
include(result, fsUnderline);
|
||
if lfStrikeOut <> 0 then
|
||
include(result, fsStrikeOut);
|
||
if lfWeight >= FW_BOLD then
|
||
include(result, fsBold);
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure IECopyLogFont(src: PLogFontA; dst: PLogFontW);
|
||
begin
|
||
dst^.lfHeight := src^.lfHeight;
|
||
dst^.lfWidth := src^.lfWidth;
|
||
dst^.lfEscapement := src^.lfEscapement;
|
||
dst^.lfOrientation := src^.lfOrientation;
|
||
dst^.lfWeight := src^.lfWeight;
|
||
dst^.lfItalic := src^.lfItalic;
|
||
dst^.lfUnderline := src^.lfUnderline;
|
||
dst^.lfStrikeOut := src^.lfStrikeOut;
|
||
dst^.lfCharSet := src^.lfCharSet;
|
||
dst^.lfOutPrecision := src^.lfOutPrecision;
|
||
dst^.lfClipPrecision := src^.lfClipPrecision;
|
||
dst^.lfQuality := src^.lfQuality;
|
||
dst^.lfPitchAndFamily := src^.lfPitchAndFamily;
|
||
IEStrPCopyW(@dst^.lfFaceName[0], WideString(AnsiString(src^.lfFaceName)));
|
||
end;
|
||
|
||
|
||
function CompareGUID(const g1, g2: TGuid): boolean;
|
||
begin
|
||
result := CompareMem(@g1, @g2, sizeof(TGuid));
|
||
end;
|
||
|
||
function IEConvertGUIDToString(g: PGUID): AnsiString;
|
||
var
|
||
p: pbyte;
|
||
i: integer;
|
||
begin
|
||
p := pbyte(g);
|
||
result := '{' + IEIntToHex(pinteger(p)^, 8) + '-';
|
||
inc(p, 4);
|
||
result := result + IEIntToHex(pword(p)^, 4) + '-';
|
||
inc(p, 2);
|
||
result := result + IEIntToHex(pword(p)^, 4) + '-';
|
||
inc(p, 2);
|
||
result := result + IEIntToHex(p^, 2);
|
||
inc(p);
|
||
result := result + IEIntToHex(p^, 2) + '-';
|
||
inc(p);
|
||
for i := 0 to 5 do
|
||
begin
|
||
result := result + IEIntToHex(p^, 2);
|
||
inc(p);
|
||
end;
|
||
result := IELowerCase(result) + '}';
|
||
end;
|
||
|
||
procedure IEConvertWStringToGUID(invar: WideString; gg: PGUID);
|
||
begin
|
||
IEConvertAStringToGUID(AnsiString(invar), gg);
|
||
end;
|
||
|
||
procedure IEConvertAStringToGUID(invar: AnsiString; gg: PGUID);
|
||
const
|
||
cv: array[48..70] of integer = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15);
|
||
mm: array[0..7] of integer = (268435456, 16777216, 1048576, 65536, 4096, 256, 16, 1);
|
||
var
|
||
i: integer;
|
||
v: cardinal;
|
||
begin
|
||
invar := IEUpperCase(invar);
|
||
v := 0;
|
||
for i := 2 to 9 do
|
||
v := v + cardinal(cv[ord(invar[i])] * mm[i - 2]);
|
||
gg^.D1 := v;
|
||
gg^.D2 := 0;
|
||
for i := 11 to 14 do
|
||
gg^.D2 := gg^.D2 + cv[ord(invar[i])] * mm[i - 11 + 4];
|
||
gg^.D3 := 0;
|
||
for i := 16 to 19 do
|
||
gg^.D3 := gg^.D3 + cv[ord(invar[i])] * mm[i - 16 + 4];
|
||
invar := IECopy(invar, 21, 4) + IECopy(invar, 26, 12);
|
||
for i := 0 to 7 do
|
||
begin
|
||
gg^.D4[i] := cv[ord(invar[i * 2 + 1])] * mm[6] + cv[ord(invar[i * 2 + 2])] * mm[7];
|
||
end;
|
||
end;
|
||
|
||
procedure IEResetPrinter;
|
||
var
|
||
Device, Driver, Port: pointer;
|
||
DevMode: THandle;
|
||
lCopies: integer;
|
||
lOrient: TPrinterOrientation;
|
||
lTitle: WideString;
|
||
begin
|
||
lCopies := Printer.Copies;
|
||
lOrient := Printer.Orientation;
|
||
lTitle := Printer.Title;
|
||
getmem(Device, 512);
|
||
getmem(Driver, 512);
|
||
getmem(Port, 512);
|
||
try
|
||
Printer.GetPrinter(Device, Driver, Port, DevMode);
|
||
Printer.SetPrinter(Device, Driver, Port, 0);
|
||
finally
|
||
freemem(Device);
|
||
freemem(Driver);
|
||
freemem(Port);
|
||
end;
|
||
Printer.Copies := lCopies;
|
||
Printer.Orientation := lOrient;
|
||
Printer.Title := lTitle;
|
||
end;
|
||
|
||
// Adjust the resampling size to match fwidth and fheight
|
||
// owidth, oheight: source image size
|
||
// fwidth, fheight: container box size
|
||
// rwidth, rheight: output - new size
|
||
// was: IEFitResample
|
||
procedure IEGetFitResampleSize(OWidth, OHeight, FWidth, FHeight: integer; out RWidth, RHeight: integer);
|
||
var
|
||
zz: double;
|
||
begin
|
||
if (owidth <> 0) and (oheight <> 0) then
|
||
begin
|
||
zz := dmin(fwidth / owidth, fheight / oheight);
|
||
rwidth := trunc(owidth * zz);
|
||
if rwidth = 0 then
|
||
rwidth := 1;
|
||
rheight := trunc(oheight * zz);
|
||
if rheight = 0 then
|
||
rheight := 1;
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
// Adjust the resampling size to match fwidth and fheight
|
||
// iImageWidth, iImageHeight: source image size
|
||
// iAvailableWidth, iAvailableHeight: container box size
|
||
// rwidth, rheight: output - new size
|
||
// if iAutoCropPercent > 0 then RAutoWidth, RAutoHeight will return an enlarged size that is bigger than the container box size (overlaps)
|
||
procedure IEGetFitResampleSizeWithAutoCrop(iImageWidth, iImageHeight, iAvailableWidth, iAvailableHeight: integer; out RWidth, RHeight: integer;
|
||
iAutoCropPercent : Integer; out RAutoWidth, RAutoHeight: integer);
|
||
var
|
||
dResizeRatio, dMaxResizeRatio: Double;
|
||
dCroppedWidth, dCroppedHeight: Double;
|
||
begin
|
||
if iAutoCropPercent > 100 then
|
||
iAutoCropPercent := 100;
|
||
if (iImageHeight = 0) or (iImageWidth = 0) or (iAvailableHeight = 0) or (iAvailableWidth = 0) then
|
||
begin
|
||
RWidth := 0;
|
||
RHeight := 0;
|
||
RAutoWidth := 0;
|
||
RAutoHeight := 0;
|
||
end
|
||
else
|
||
if (iImageHeight / iAvailableHeight) < (iImageWidth / iAvailableWidth) then
|
||
// WIDTH IS IMPORTANT
|
||
begin
|
||
// if we are allowing a percentage of the image to be auto-cropped then
|
||
// calculate the maximum possible ratio we can increase by without
|
||
// without the Height exceeding the available widht
|
||
if iAutoCropPercent > 0 then
|
||
begin
|
||
dCroppedWidth := iImageWidth * (100 - iAutoCropPercent) / 100;
|
||
if iAutoCropPercent = 100 then
|
||
dMaxResizeRatio := 1000
|
||
else
|
||
dMaxResizeRatio := iAvailableWidth / dCroppedWidth;
|
||
|
||
if round(iImageHeight * dMaxResizeRatio) > iAvailableHeight then
|
||
dMaxResizeRatio := iAvailableHeight / iImageHeight;
|
||
|
||
RAutoWidth := round(iImageWidth * dMaxResizeRatio);
|
||
RAutoHeight := round(iImageHeight * dMaxResizeRatio);
|
||
|
||
RWidth := imin(iAvailableWidth, RAutoWidth);
|
||
RHeight := imin(iAvailableHeight, RAutoHeight);
|
||
end
|
||
else
|
||
begin
|
||
dResizeRatio := iAvailableWidth / iImageWidth;
|
||
RWidth := round(iImageWidth * dResizeRatio);
|
||
RHeight := round(iImageHeight * dResizeRatio);
|
||
RAutoWidth := RWidth;
|
||
RAutoHeight := RHeight;
|
||
end;
|
||
end
|
||
ELSE
|
||
// HEIGHT IS IMPORTANT
|
||
begin
|
||
// if we are allowing a percentage of the image to be auto-cropped then
|
||
// calculate the maximum possible ratio we can increase by without
|
||
// without the width exceeding the available widht
|
||
if iAutoCropPercent > 0 then
|
||
begin
|
||
dCroppedHeight := iImageHeight * (100 - iAutoCropPercent) / 100;
|
||
if iAutoCropPercent = 100 then
|
||
dMaxResizeRatio := 1000
|
||
else
|
||
dMaxResizeRatio := iAvailableHeight / dCroppedHeight;
|
||
|
||
if round(iImageWidth * dMaxResizeRatio) > iAvailableWidth then
|
||
dMaxResizeRatio := iAvailableWidth / iImageWidth;
|
||
|
||
RAutoWidth := round(iImageWidth * dMaxResizeRatio);
|
||
RAutoHeight := round(iImageHeight * dMaxResizeRatio);
|
||
|
||
RWidth := imin(iAvailableWidth, RAutoWidth);
|
||
RHeight := imin(iAvailableHeight, RAutoHeight);
|
||
end
|
||
else
|
||
begin
|
||
dResizeRatio := iAvailableHeight / iImageHeight;
|
||
RWidth := round(iImageWidth * dResizeRatio);
|
||
RHeight := round(iImageHeight * dResizeRatio);
|
||
RAutoWidth := RWidth;
|
||
RAutoHeight := RHeight;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
// encode maximum 4 bytes (len can be 1 to 4)
|
||
// pad if len<4
|
||
// return chars wrote
|
||
function _IEASCII85Encode4(var inbytes: pbyte; inlen: integer; var outstr: PAnsiChar): integer;
|
||
var
|
||
c: array[1..5] of dword;
|
||
value: dword;
|
||
i: integer;
|
||
begin
|
||
value := 0;
|
||
for i := 0 to inlen-1 do
|
||
begin
|
||
value := value or (inbytes^ shl (24-i*8));
|
||
inc(inbytes);
|
||
end;
|
||
(*
|
||
value := inbytes^ shl 24;
|
||
inc(inbytes);
|
||
value := value or (inbytes^ shl 16);
|
||
inc(inbytes);
|
||
value := value or (inbytes^ shl 8);
|
||
inc(inbytes);
|
||
value := value or inbytes^;
|
||
inc(inbytes);
|
||
*)
|
||
|
||
if (value = 0) and (inlen = 4) then
|
||
begin
|
||
outstr^ := 'z';
|
||
inc(outstr);
|
||
result := 1;
|
||
end
|
||
else
|
||
begin
|
||
c[1] := value div 52200625;
|
||
value := value - c[1] * 52200625;
|
||
c[2] := value div 614125;
|
||
value := value - c[2] * 614125;
|
||
c[3] := value div 7225;
|
||
value := value - c[3] * 7225;
|
||
c[4] := value div 85;
|
||
value := value - c[4] * 85;
|
||
c[5] := value;
|
||
for i := 1 to inlen + 1 do
|
||
begin
|
||
outstr^ := AnsiChar(c[i] + 33);
|
||
inc(outstr);
|
||
end;
|
||
result := inlen + 1;
|
||
end;
|
||
end;
|
||
|
||
function IEASCII85EncodeBlock(var inbytes: pbyte; buflen: integer; var outstr: PAnsiChar; var asciilen: integer): integer;
|
||
var
|
||
w: integer;
|
||
row: integer;
|
||
begin
|
||
result := 0;
|
||
row := 0;
|
||
repeat
|
||
w := _IEASCII85Encode4(inbytes, imin(4, buflen), outstr);
|
||
inc(result, w);
|
||
inc(asciilen, w);
|
||
inc(row, w);
|
||
dec(buflen, 4);
|
||
if row >= 75 then
|
||
begin
|
||
outstr^ := #13;
|
||
inc(outstr);
|
||
outstr^ := #10;
|
||
inc(outstr);
|
||
inc(result, 2);
|
||
row := 0;
|
||
end;
|
||
until buflen <= 0;
|
||
outstr^ := '~';
|
||
inc(outstr);
|
||
outstr^ := '>';
|
||
inc(outstr);
|
||
outstr^ := #13;
|
||
inc(outstr);
|
||
outstr^ := #10;
|
||
inc(outstr);
|
||
inc(result, 4);
|
||
end;
|
||
|
||
// decode maximum 5 characters (inlen)
|
||
|
||
procedure _IEASCII85Decode5(var instr: PAnsiChar; inlen: integer; var outbytes: pbyte);
|
||
var
|
||
value: cardinal;
|
||
begin
|
||
if instr^ = 'z' then
|
||
begin
|
||
value := 0;
|
||
inc(instr);
|
||
end
|
||
else
|
||
begin
|
||
value := (ord(instr^) - 33) * 52200625;
|
||
inc(instr);
|
||
if inlen >= 2 then
|
||
begin
|
||
value := value + cardinal(ord(instr^) - 33) * 614125;
|
||
inc(instr);
|
||
end;
|
||
if inlen >= 3 then
|
||
begin
|
||
value := value + cardinal(ord(instr^) - 33) * 7225;
|
||
inc(instr);
|
||
end;
|
||
if inlen >= 4 then
|
||
begin
|
||
value := value + cardinal(ord(instr^) - 33) * 85;
|
||
inc(instr);
|
||
end;
|
||
if inlen >= 5 then
|
||
begin
|
||
value := value + cardinal(ord(instr^) - 33);
|
||
inc(instr);
|
||
end;
|
||
end;
|
||
outbytes^ := value div 16777216;
|
||
value := value - (outbytes^ * 16777216);
|
||
inc(outbytes);
|
||
outbytes^ := value div 65536;
|
||
value := value - (outbytes^ * 65536);
|
||
inc(outbytes);
|
||
outbytes^ := value div 256;
|
||
value := value - (outbytes^ * 256);
|
||
inc(outbytes);
|
||
outbytes^ := value;
|
||
inc(outbytes);
|
||
end;
|
||
|
||
// a block is terminates with a '~>' (EOD)
|
||
// buflen refers to instr length
|
||
// return output length
|
||
|
||
function IEASCII85DecodeBlock(var instr: PAnsiChar; buflen: integer; var outbytes: pbyte): integer;
|
||
var
|
||
i, l, flatlen: integer;
|
||
flatbuf, ptr, instr2: PAnsiChar;
|
||
begin
|
||
result := 0;
|
||
flatlen := 0;
|
||
getmem(flatbuf, buflen);
|
||
ptr := flatbuf;
|
||
i := 0;
|
||
while i < buflen do
|
||
begin
|
||
while ((ord(instr^) < 33) or (ord(instr^) > 117)) and (instr^ <> '~') and (instr^ <> '>') do
|
||
begin
|
||
inc(instr);
|
||
inc(i);
|
||
end;
|
||
if instr^ = '~' then
|
||
begin
|
||
instr2 := instr;
|
||
l := i;
|
||
inc(instr);
|
||
while ((ord(instr^) < 33) or (ord(instr^) > 117)) and (instr^ <> '~') and (instr^ <> '>') do
|
||
inc(instr);
|
||
if instr^ = '>' then
|
||
begin
|
||
inc(instr);
|
||
break;
|
||
end
|
||
else
|
||
begin
|
||
instr := instr2;
|
||
i := l;
|
||
end;
|
||
end;
|
||
ptr^ := instr^;
|
||
inc(instr);
|
||
inc(i);
|
||
inc(ptr);
|
||
inc(flatlen);
|
||
end;
|
||
ptr := flatbuf;
|
||
repeat
|
||
i := imin(flatlen, 5);
|
||
_IEASCII85Decode5(ptr, i, outbytes);
|
||
inc(result, i - 1);
|
||
dec(flatlen, i);
|
||
until flatlen <= 0;
|
||
freemem(flatbuf);
|
||
end;
|
||
|
||
// return the number of bytes actually written
|
||
|
||
function IEPSRunLengthEncode(inbytes: pbytearray; inlen: integer; outbytes: pbytearray): integer;
|
||
var
|
||
inpos, i, l, j: integer;
|
||
begin
|
||
result := 0; // this is output position
|
||
inpos := 0;
|
||
while inpos < inlen do
|
||
begin
|
||
|
||
// search for run lengths
|
||
|
||
i := inpos + 1;
|
||
while (i < inlen) and (inbytes[inpos] = inbytes[i]) and (i-inpos < 128) do
|
||
inc(i);
|
||
l := i - inpos;
|
||
if (l > 1) then
|
||
begin
|
||
// do run length
|
||
outbytes[result] := 257 - l;
|
||
inc(result);
|
||
outbytes[result] := inbytes[inpos];
|
||
inc(result);
|
||
inpos := i;
|
||
end
|
||
else
|
||
begin
|
||
|
||
// search for literals
|
||
|
||
i := inpos + 1;
|
||
while (i < inlen) and (inbytes[i-1] <> inbytes[i]) and (i-inpos < 128) do
|
||
inc(i);
|
||
l := i - inpos;
|
||
// do literals
|
||
outbytes[result] := l - 1;
|
||
inc(result);
|
||
for j := 0 to l - 1 do
|
||
begin
|
||
outbytes[result] := inbytes[inpos];
|
||
inc(result);
|
||
inc(inpos);
|
||
end;
|
||
|
||
end;
|
||
|
||
end;
|
||
|
||
// do EOD
|
||
outbytes[result] := 128;
|
||
inc(result);
|
||
|
||
end;
|
||
|
||
procedure IEWriteStrLn(s: TStream; ss: AnsiString);
|
||
begin
|
||
ss := ss + #13#10;
|
||
s.Write(PAnsiChar(ss)^, length(ss));
|
||
end;
|
||
|
||
|
||
function IEGetDecimalSeparator: Char;
|
||
begin
|
||
{$ifdef IEHASFORMATSETTINGS}
|
||
result := FormatSettings.DecimalSeparator;
|
||
{$else}
|
||
result := DecimalSeparator;
|
||
{$endif}
|
||
end;
|
||
|
||
procedure IESetDecimalSeparator(c: Char);
|
||
begin
|
||
{$ifdef IEHASFORMATSETTINGS}
|
||
FormatSettings.DecimalSeparator := c;
|
||
{$else}
|
||
DecimalSeparator := c;
|
||
{$endif}
|
||
end;
|
||
|
||
function IEFloatToStrA(Value: Extended): AnsiString;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := AnsiString(floattostr(Value));
|
||
for i := 1 to length(result) do
|
||
if (result[i]=',') or (result[i]=AnsiChar(IEGetDecimalSeparator)) then
|
||
result[i] := '.';
|
||
end;
|
||
|
||
function IEFloatToStrS(Value: Extended): string;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := FloatToStr(Value);
|
||
for i := 1 to length(result) do
|
||
if (result[i]=',') or (result[i]=IEGetDecimalSeparator()) then
|
||
result[i] := '.';
|
||
end;
|
||
|
||
function IEFloatToStrW(Value: Extended): WideString;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := floattostr(Value);
|
||
for i := 1 to length(result) do
|
||
if (result[i]=',') or (result[i]=WideString(IEGetDecimalSeparator())) then
|
||
result[i] := '.';
|
||
end;
|
||
|
||
function IEIsSpace(c: AnsiChar): boolean;
|
||
begin
|
||
result := (c = ' ') or (c = #8) or (c = #13) or (c = #10);
|
||
end;
|
||
|
||
function IERemoveCtrlCharsA(const text: AnsiString): AnsiString;
|
||
var
|
||
q: integer;
|
||
c: integer;
|
||
begin
|
||
result := '';
|
||
for q := 1 to length(text) do
|
||
begin
|
||
c := ord(text[q]);
|
||
if (c>31) and (c<>127) then
|
||
result := result+AnsiChar(c);
|
||
end;
|
||
end;
|
||
|
||
function IERemoveCtrlCharsS(const text: String): String;
|
||
begin
|
||
result := IERemoveCtrlCharsW(text);
|
||
end;
|
||
|
||
function IERemoveCtrlCharsW(const text: WideString): WideString;
|
||
var
|
||
q: integer;
|
||
c: integer;
|
||
begin
|
||
result := '';
|
||
for q := 1 to length(text) do
|
||
begin
|
||
c := ord(text[q]);
|
||
if (c>31) and (c<>127) then
|
||
result := result+WideChar(c);
|
||
end;
|
||
end;
|
||
|
||
|
||
// Returns true if rgb1, rgb2 are the equal (Tolerance = 0) or closely matched (Tolerance is between 1 and 255)
|
||
function IERGBColorsMatch(rgb1, rgb2 : TRGB; Tolerance : Integer = 0): Boolean;
|
||
var
|
||
dr, dg, db: Integer;
|
||
begin
|
||
dr := abs(rgb1.r - rgb2.r);
|
||
dg := abs(rgb1.g - rgb2.g);
|
||
db := abs(rgb1.b - rgb2.b);
|
||
result := (dr <= tolerance) and (dg <= tolerance) and (db <= tolerance);
|
||
end;
|
||
|
||
function IERGB2StrS(c: TRGB): string;
|
||
begin
|
||
with c do
|
||
result := IntToStr(r)+', '+IntToStr(g)+', '+IntToStr(b);
|
||
end;
|
||
|
||
function IERGB2StrW(c: TRGB): WideString;
|
||
begin
|
||
with c do
|
||
result := IntToStr(r)+', '+IntToStr(g)+', '+IntToStr(b);
|
||
end;
|
||
|
||
function IEBool2StrS(v: boolean): string;
|
||
begin
|
||
if v then
|
||
result := '1'
|
||
else
|
||
result := '0';
|
||
end;
|
||
|
||
function IEBool2StrW(v: boolean): WideString;
|
||
begin
|
||
if v then
|
||
result := '1'
|
||
else
|
||
result := '0';
|
||
end;
|
||
|
||
function IEStr2RGBW(const rgbstr: WideString): TRGB;
|
||
begin
|
||
result := IEStr2RGBS(string(rgbstr));
|
||
end;
|
||
|
||
function IEStr2RGBS(const rgbstr: string): TRGB;
|
||
var
|
||
p: integer;
|
||
ps1, q: integer;
|
||
ss: string;
|
||
l: integer;
|
||
begin
|
||
try
|
||
l := length(rgbstr);
|
||
ps1 := 1;
|
||
p := 0;
|
||
for q := 1 to l+1 do
|
||
begin
|
||
if (rgbstr[q]=',') or (q=l+1) then
|
||
begin
|
||
ss := Trim(copy(rgbstr, ps1, (q-ps1)));
|
||
case p of
|
||
0: result.r := StrToIntDef(ss, 0);
|
||
1: result.g := StrToIntDef(ss, 0);
|
||
2: result.b := StrToIntDef(ss, 0);
|
||
end;
|
||
inc(p);
|
||
ps1 := q+1;
|
||
end;
|
||
end;
|
||
except
|
||
result := creatergb(0, 0, 0);
|
||
end;
|
||
end;
|
||
|
||
function IEStr2BoolS(const v: string): boolean;
|
||
var
|
||
ss: string;
|
||
begin
|
||
ss := UpperCase(v);
|
||
result := (ss='1') or (ss='TRUE') or (ss='T');
|
||
end;
|
||
|
||
function IEStr2BoolW(const v: WideString): boolean;
|
||
begin
|
||
result := IEStr2BoolS(string(v));
|
||
end;
|
||
|
||
function IEStr2BoolA(const v: AnsiString): boolean;
|
||
begin
|
||
result := IEStr2BoolS(string(v));
|
||
end;
|
||
|
||
|
||
function IEStr2ColorDefS(const v : string; ADefault : TColor) : TColor;
|
||
begin
|
||
Try
|
||
Result := StringToColor(v);
|
||
except
|
||
Result := ADefault;
|
||
End;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
{!!
|
||
<FS>IESetTranslationWord
|
||
|
||
<FM>Declaration<FC>
|
||
procedure IESetTranslationWord(const lang: <A TMsgLanguage>; const msg: <A TMsgLanguageWords>; const trans: AnsiString);
|
||
procedure IESetTranslationWordU(const lang: <A TMsgLanguage>; const msg: <A TMsgLanguageWords>; const trans: String);
|
||
|
||
<FM>Description<FN>
|
||
IESetTranslationWord allows applications to set a customized word/sentence translation.
|
||
<FC>lang<FN> is the target language.
|
||
<FC>msg<FN> is the message to translate.
|
||
<FC>trans<FN> is the translated message.
|
||
|
||
See also: iewords.pas file.
|
||
!!}
|
||
procedure IESetTranslationWord(const lang: TMsgLanguage; const msg: TMsgLanguageWords; const trans: AnsiString);
|
||
{$ifdef UNICODE}
|
||
var
|
||
rbs: RawByteString;
|
||
begin
|
||
rbs := trans;
|
||
SetCodePage(rbs, IELANGUAGECHARINFO[lang].CodePage, false);
|
||
ieMessages[lang][msg] := string(rbs);
|
||
end;
|
||
{$else}
|
||
begin
|
||
ieMessages[lang][msg] := string(trans);
|
||
end;
|
||
{$endif}
|
||
|
||
procedure IESetTranslationWordU(const lang: TMsgLanguage; const msg: TMsgLanguageWords; const trans: string);
|
||
begin
|
||
ieMessages[lang][msg] := trans;
|
||
end;
|
||
|
||
|
||
// returns the message "msg" in current selected language
|
||
function iemsg(const msg: TMsgLanguageWords): WideString;
|
||
begin
|
||
if IEGlobalSettings().MsgLanguage = msSystem then
|
||
begin
|
||
case syslocale.PriLangID of
|
||
{$IFDEF IESUPPORTITALIAN}
|
||
LANG_ITALIAN: result := ieMessages[msItalian][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTPORTUGUESE}
|
||
LANG_PORTUGUESE: result := ieMessages[msPortuguese][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTENGLISH}
|
||
LANG_ENGLISH: result := ieMessages[msEnglish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTSPANISH}
|
||
LANG_SPANISH: result := ieMessages[msSpanish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTFRENCH}
|
||
LANG_FRENCH: result := ieMessages[msFrench][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTGERMAN}
|
||
LANG_GERMAN: result := ieMessages[msGerman][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTGREEK}
|
||
LANG_GREEK: result := ieMessages[msGreek][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTRUSSIAN}
|
||
LANG_RUSSIAN: result := ieMessages[msRussian][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTDUTCH}
|
||
LANG_DUTCH: result := ieMessages[msDutch][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTSWEDISH}
|
||
LANG_SWEDISH: result := ieMessages[msSwedish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTPOLISH}
|
||
LANG_POLISH: result := ieMessages[msPolish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTJAPANESE}
|
||
LANG_JAPANESE: result := ieMessages[msJapanese][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTCZECH}
|
||
LANG_CZECH: result := ieMessages[msCzech][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTFINNISH}
|
||
LANG_FINNISH: result := ieMessages[msFinnish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTFARSI}
|
||
LANG_FARSI: result := ieMessages[msFarsi][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTDANISH}
|
||
LANG_DANISH: result := ieMessages[msDanish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTTURKISH}
|
||
LANG_TURKISH: result := ieMessages[msTurkish][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTKOREAN}
|
||
LANG_KOREAN: result := ieMessages[msKorean][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTHUNGARIAN}
|
||
LANG_HUNGARIAN: result := ieMessages[msHungarian][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTARABIC}
|
||
LANG_ARABIC: result := ieMessages[msArabic][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTSERBIAN}
|
||
LANG_SERBIAN: result := ieMessages[msSerbian][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTNORWEGIAN}
|
||
LANG_NORWEGIAN: result := ieMessages[msNorwegian][msg];
|
||
{$ENDIF}
|
||
{$IFDEF IESUPPORTCHINESE}
|
||
LANG_CHINESE:
|
||
case syslocale.SubLangID of
|
||
SUBLANG_CHINESE_SIMPLIFIED: result := ieMessages[msChinese][msg];
|
||
SUBLANG_CHINESE_TRADITIONAL: result := ieMessages[msChineseTraditionalBig5][msg];
|
||
end;
|
||
{$ENDIF}
|
||
else
|
||
{$IFDEF IESUPPORTENGLISH}
|
||
result := ieMessages[msEnglish][msg];
|
||
{$ELSE}
|
||
result := ieMessages[TMsgLanguage(1)][msg];
|
||
{$ENDIF}
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
result := ieMessages[IEGlobalSettings().MsgLanguage][msg];
|
||
end;
|
||
|
||
// Fall back to English or whatever language is available
|
||
if result = '' then
|
||
{$IFDEF IESUPPORTENGLISH}
|
||
result := ieMessages[msEnglish][msg];
|
||
{$ELSE}
|
||
result := ieMessages[TMsgLanguage(1)][msg];
|
||
{$ENDIF}
|
||
end;
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
{
|
||
function CalcLineLenWithinRect(R: TRect; Angle: Integer): Double;
|
||
var
|
||
Pt1, Pt2: TPoint;
|
||
begin
|
||
CalcLineWithinRect( R, Angle, Pt1, Pt2 );
|
||
result := _DistPoint2Point( Pt1.x, Pt1.y, Pt2.x, Pt2.Y );
|
||
end;
|
||
}
|
||
|
||
// point to point distance
|
||
function _DistPoint2Point(x1, y1, x2, y2: integer): double;
|
||
begin
|
||
result := sqrt(sqr(x2 - x1) + sqr(y2 - y1));
|
||
end;
|
||
|
||
function IEDDistPoint2Point(x1, y1, x2, y2: double): double;
|
||
begin
|
||
result := sqrt(sqr(x2 - x1) + sqr(y2 - y1));
|
||
end;
|
||
|
||
|
||
// point to line distance
|
||
function _DistPoint2Line(xp, yp, x1, y1, x2, y2: integer): double;
|
||
var
|
||
a, b, c: double; // leave a, b, c as double (not integers! otherwise an overflow could occur)
|
||
begin
|
||
a := y1 - y2;
|
||
b := x2 - x1;
|
||
c := x1 * y2 - x2 * y1;
|
||
result := abs(a * xp + b * yp + c) / sqrt(a * a + b * b);
|
||
end;
|
||
|
||
// Point<->Segment distance
|
||
function _DistPoint2Seg(xp, yp, x1, y1, x2, y2: integer): double;
|
||
var
|
||
r: double;
|
||
begin
|
||
result := 1000000;
|
||
try
|
||
if (x1 = x2) and (y1 = y2) then
|
||
result := sqrt(sqr(xp - x1) + sqr(yp - y1))
|
||
else
|
||
begin
|
||
r := ((y1 - yp) * (y1 - y2) - (x1 - xp) * (x2 - x1)) / (sqr(x2 - x1) + sqr(y2 - y1));
|
||
if r > 1 then
|
||
begin
|
||
// distance from xp, yp to x2, y2
|
||
if abs(xp - x2) > 45000 then
|
||
exit;
|
||
if abs(yp - y2) > 45000 then
|
||
exit;
|
||
result := sqrt(sqr(xp - x2) + sqr(yp - y2));
|
||
end
|
||
else
|
||
if r < 0 then
|
||
begin
|
||
// distance from xp, yp to x1, y1
|
||
if abs(x1 - xp) > 45000 then
|
||
exit;
|
||
if abs(y1 - yp) > 45000 then
|
||
exit;
|
||
result := sqrt(sqr(x1 - xp) + sqr(y1 - yp))
|
||
end
|
||
else
|
||
begin
|
||
// distance from the line
|
||
result := _DistPoint2Line(xp, yp, x1, y1, x2, y2);
|
||
end;
|
||
end;
|
||
except
|
||
end;
|
||
end;
|
||
|
||
function _DistPoint2Polyline(x, y: integer; PolyPoints: PPointArray; PolyPointsCount: integer; ToSubX, ToSubY, ToAddX, ToAddY: integer; ToMulX, ToMulY: double; penWidth: integer; closed: boolean): double;
|
||
var
|
||
i: integer;
|
||
d: double;
|
||
x1, y1, x2, y2: integer;
|
||
|
||
procedure comp;
|
||
var
|
||
j, k: integer;
|
||
begin
|
||
d := _DistPoint2Seg(x, y, x1, y1, x2, y2);
|
||
if penWidth > 1 then
|
||
for j := -penWidth div 2 to penWidth div 2 do
|
||
for k := 2 to penWidth div 2 do
|
||
begin
|
||
d := dmin(d, _DistPoint2Seg(x, y, x1+j, y1+k, x2+j, y2+k));
|
||
end;
|
||
if d < result then
|
||
result := d;
|
||
iswap(x1, x2);
|
||
iswap(y1, y2);
|
||
end;
|
||
|
||
begin
|
||
result := 1000000;
|
||
if PolyPointsCount > 0 then
|
||
begin
|
||
x1 := round((PolyPoints^[0].x - ToSubX) * ToMulX + ToAddX);
|
||
y1 := round((PolyPoints^[0].y - ToSubY) * ToMulY + ToAddY);
|
||
for i := 1 to PolyPointsCount - 1 do
|
||
begin
|
||
x2 := round((PolyPoints^[i].x - ToSubX) * ToMulX + ToAddX);
|
||
y2 := round((PolyPoints^[i].y - ToSubY) * ToMulY + ToAddY);
|
||
comp;
|
||
end;
|
||
if closed then
|
||
begin
|
||
x2 := round((PolyPoints^[0].x - ToSubX) * ToMulX + ToAddX);
|
||
y2 := round((PolyPoints^[0].y - ToSubY) * ToMulY + ToAddY);
|
||
comp;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
function IEGetOpSys(): TIEOpSys;
|
||
var
|
||
ver: TOSVersionInfo;
|
||
begin
|
||
result := ieosUnknown;
|
||
ver.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
|
||
if not GetVersionEx(ver) then
|
||
Exit;
|
||
case ver.dwPlatformId of
|
||
VER_PLATFORM_WIN32_WINDOWS:
|
||
begin
|
||
if (ver.dwMajorVersion=4) then
|
||
begin
|
||
if (ver.dwMinorVersion=0) then
|
||
result := ieosWin95
|
||
else
|
||
if (ver.dwMinorVersion = 10) then
|
||
result := ieosWin98
|
||
else
|
||
if (ver.dwMinorVersion = 90) then
|
||
result := ieosWinME;
|
||
end;
|
||
end;
|
||
VER_PLATFORM_WIN32_NT:
|
||
begin
|
||
if (ver.dwMajorVersion=4) and (ver.dwMinorVersion=0) then
|
||
result := ieosWinNT4
|
||
else
|
||
if (ver.dwMajorVersion = 5) and (ver.dwMinorVersion = 0) then
|
||
result := ieosWin2000
|
||
else
|
||
if (ver.dwMajorVersion = 5) and (ver.dwMinorVersion = 1) then
|
||
result := ieosWinXP
|
||
else
|
||
if (ver.dwMajorVersion = 5) and (ver.dwMinorVersion = 2) then
|
||
result := ieosWin2003
|
||
else
|
||
if (ver.dwMajorVersion = 6) and (ver.dwMinorVersion = 0) then
|
||
result := ieosWinVista
|
||
else
|
||
if (ver.dwMajorVersion = 6) and (ver.dwMinorVersion = 1) then
|
||
result := ieosWin7
|
||
else
|
||
if (ver.dwMajorVersion = 6) and (ver.dwMinorVersion = 2) then
|
||
result := ieosWin8
|
||
else
|
||
if (ver.dwMajorVersion = 10) and (ver.dwMinorVersion = 0) then
|
||
result := ieosWin10;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
function IEGetDisplayOrientation(): integer;
|
||
var
|
||
devmode: TIEDeviceModeW;
|
||
begin
|
||
FillChar(devmode, sizeof(devmode), 0);
|
||
devmode.dmSize := sizeof(devmode);
|
||
IE_EnumDisplaySettingsExW(nil, DWORD(-1), devmode, 4);
|
||
result := devmode.dmDisplayOrientation * 90;
|
||
end;
|
||
|
||
|
||
function IEStrToFloatDefA(s: AnsiString; Def: extended): extended;
|
||
var
|
||
q: integer;
|
||
begin
|
||
if not IETextToFloat(PAnsiChar(s), result, fvExtended) then
|
||
begin
|
||
q := IEPos(',', s);
|
||
if q > 0 then
|
||
s[q] := '.'
|
||
else
|
||
begin
|
||
q := IEPos('.', s);
|
||
if q > 0 then
|
||
s[q] := ',';
|
||
end;
|
||
if not IETextToFloat(PAnsiChar(s), result, fvExtended) then
|
||
result := Def;
|
||
end;
|
||
end;
|
||
|
||
function IEStrToFloatDefW(s: WideString; Def: extended): extended;
|
||
begin
|
||
result := IEStrToFloatDefA(AnsiString(s), Def);
|
||
end;
|
||
|
||
function IEStrToFloatDefS(s: String; Def: extended): extended;
|
||
begin
|
||
result := IEStrToFloatDefA(AnsiString(s), Def);
|
||
end;
|
||
|
||
function IEStrToFloatDef(s: String; Def: extended): extended;
|
||
begin
|
||
result := IEStrToFloatDefA(AnsiString(s), Def);
|
||
end;
|
||
|
||
function IEStrLen(const Str: PAnsiChar): Cardinal;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.StrLen(Str);
|
||
{$else}
|
||
result := StrLen(Str);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEStrLenW(Str: PWideChar): Cardinal;
|
||
begin
|
||
result := 0;
|
||
while Str^ <> #0 do
|
||
begin
|
||
inc(result);
|
||
inc(Str);
|
||
end;
|
||
end;
|
||
|
||
function IEStrCopy(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.StrCopy(Dest, Source);
|
||
{$else}
|
||
result := StrCopy(Dest, Source);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEStrCopyW(Dest: PWideChar; Source: PWideChar): PWideChar;
|
||
begin
|
||
result := Dest;
|
||
while Source^ <> #0 do
|
||
begin
|
||
Dest^ := Source^;
|
||
inc(Dest);
|
||
inc(Source);
|
||
end;
|
||
Dest^ := #0;
|
||
end;
|
||
|
||
function IEStrPCopy(Dest: PAnsiChar; const Source: AnsiString): PAnsiChar;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.StrPCopy(Dest, Source);
|
||
{$else}
|
||
result := StrPCopy(Dest, Source);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEStrPCopyW(Dest: PWideChar; const Source: WideString): PWideChar;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := Dest;
|
||
for i := 1 to length(Source) do
|
||
begin
|
||
Dest^ := Source[i];
|
||
inc(Dest);
|
||
end;
|
||
Dest^ := #0;
|
||
end;
|
||
|
||
// Copies array of ansichar to PWideChar
|
||
function IEStrPCopyWA(Dest: PWideChar; Source: TIEArrayOfAnsiChar): PWideChar;
|
||
var
|
||
i: integer;
|
||
begin
|
||
result := Dest;
|
||
for i := 1 to length(Source) do
|
||
begin
|
||
Dest^ := WideChar(Source[i]);
|
||
inc(Dest);
|
||
end;
|
||
Dest^ := #0;
|
||
end;
|
||
|
||
function IEStrMove(Dest: PAnsiChar; const Source: PAnsiChar; Count: Cardinal): PAnsiChar;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.StrMove(Dest, Source, Count);
|
||
{$else}
|
||
result := StrMove(Dest, Source, Count);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEAnsiStrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.AnsiStrScan(Str, Chr);
|
||
{$else}
|
||
result := AnsiStrScan(Str, Chr);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEStrScan(const Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.StrScan(Str, Chr);
|
||
{$else}
|
||
result := StrScan(Str, Chr);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEStrRScan(const Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.StrRScan(Str, Chr);
|
||
{$else}
|
||
result := StrRScan(Str, Chr);
|
||
{$endif}
|
||
end;
|
||
|
||
function IETextToFloat(Buffer: PAnsiChar; var Value; ValueType: TFloatValue): Boolean;
|
||
begin
|
||
{$ifdef DelphiXE4orNewer}
|
||
result := AnsiStrings.TextToFloat(Buffer, Value, ValueType);
|
||
{$else}
|
||
result := TextToFloat(Buffer, Value, ValueType);
|
||
{$endif}
|
||
end;
|
||
|
||
|
||
function IECopyArrayOfByte(const Input: TIEArrayOfByte): TIEArrayOfByte;
|
||
begin
|
||
SetLength(result, length(Input));
|
||
move(Input[0], result[0], sizeof(byte) * length(Input));
|
||
end;
|
||
|
||
|
||
function IECopyArrayOfInteger(const Input: TIEArrayOfInteger): TIEArrayOfInteger;
|
||
begin
|
||
SetLength(result, length(Input));
|
||
move(Input[0], result[0], sizeof(integer) * length(Input));
|
||
end;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// L: 0..255
|
||
// A: -127...127
|
||
// B: -127...127
|
||
function IERGB2CIELAB(rgb: TRGB): TCIELAB;
|
||
var
|
||
X, Y, Z, fX, fY, fZ: double;
|
||
RR, GG, BB: double;
|
||
L: double;
|
||
begin
|
||
RR := rgb.r / 255.0;
|
||
GG := rgb.g / 255.0;
|
||
BB := rgb.b / 255.0;
|
||
|
||
if (RR > 0.04045) then
|
||
RR := IEPower2(((RR + 0.055) / 1.055), 2.4)
|
||
else
|
||
RR := RR / 12.92;
|
||
if (GG > 0.04045) then
|
||
GG := IEPower2(((GG + 0.055) / 1.055), 2.4)
|
||
else
|
||
GG := GG / 12.92;
|
||
if (BB > 0.04045) then
|
||
BB := IEPower2(((BB + 0.055) / 1.055), 2.4)
|
||
else
|
||
BB := BB / 12.92;
|
||
|
||
X := (0.412453*RR + 0.357580*GG + 0.180423*BB) / 0.95047;
|
||
Y := (0.212671*RR + 0.715160*GG + 0.072169*BB);
|
||
Z := (0.019334*RR + 0.119193*GG + 0.950227*BB) / 1.088883;
|
||
|
||
if (Y > 0.008856) then
|
||
begin
|
||
fY := IEPower2(Y, 1.0/3.0);
|
||
L := 116.0*fY - 16.0;
|
||
end
|
||
else
|
||
begin
|
||
fY := 7.787*Y + 16.0/116.0;
|
||
L := 903.3*Y;
|
||
end;
|
||
|
||
if (X > 0.008856) then
|
||
fX := IEPower2(X, 1.0/3.0)
|
||
else
|
||
fX := 7.787*X + 16.0/116.0;
|
||
|
||
if (Z > 0.008856) then
|
||
fZ := IEPower2(Z, 1.0/3.0)
|
||
else
|
||
fZ := 7.787*Z + 16.0/116.0;
|
||
|
||
result.L := trunc(L*2.55);
|
||
result.a := trunc(500.0*(fX - fY));
|
||
result.b := trunc(200.0*(fY - fZ));
|
||
end;
|
||
|
||
function IECIELAB2RGB(const lab: TCIELAB): TRGB;
|
||
var
|
||
var_R, var_G, var_B: double;
|
||
X, Y, Z: double;
|
||
begin
|
||
with lab do
|
||
begin
|
||
Y := ( L * 0.39215686275 + 16 ) / 116;
|
||
X := a / 500 + Y;
|
||
Z := Y - b / 200;
|
||
end;
|
||
|
||
if ( IEPower2(Y, 3) > 0.008856 ) then
|
||
Y := IEPower2(Y, 3)
|
||
else
|
||
Y := ( Y - 0.13793103448 ) / 7.787;
|
||
|
||
if ( IEPower2(X, 3) > 0.008856 ) then
|
||
X := IEPower2(X, 3)
|
||
else
|
||
X := ( X - 0.13793103448 ) / 7.787;
|
||
|
||
if ( IEPower2(Z, 3) > 0.008856 ) then
|
||
Z := IEPower2(Z, 3)
|
||
else
|
||
Z := ( Z - 0.13793103448 ) / 7.787;
|
||
|
||
X := X * 0.95047;
|
||
Z := Z * 1.08883;
|
||
|
||
var_R := X * 3.2406 + Y * (-1.5372) + Z * (-0.4986);
|
||
var_G := X * (-0.9689) + Y * 1.8758 + Z * 0.0415;
|
||
var_B := X * 0.0557 + Y * (-0.2040) + Z * 1.0570;
|
||
|
||
if ( var_R > 0.0031308 ) then
|
||
var_R := 1.055 * ( IEPower2(var_R, 0.41666666667) ) - 0.055
|
||
else
|
||
var_R := 12.92 * var_R;
|
||
|
||
if ( var_G > 0.0031308 ) then
|
||
var_G := 1.055 * ( IEPower2(var_G, 0.41666666667) ) - 0.055
|
||
else
|
||
var_G := 12.92 * var_G;
|
||
|
||
if ( var_B > 0.0031308 ) then
|
||
var_B := 1.055 * ( IEPower2(var_B, 0.41666666667) ) - 0.055
|
||
else
|
||
var_B := 12.92 * var_B;
|
||
|
||
with result do
|
||
begin
|
||
r := blimit(round(var_R * 255));
|
||
g := blimit(round(var_G * 255));
|
||
b := blimit(round(var_B * 255));
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
// draw a 3d rect
|
||
procedure IEDraw3DRect(Canvas: TCanvas; x1, y1, x2, y2: integer; cl1, cl2: TColor);
|
||
begin
|
||
with Canvas do
|
||
begin
|
||
Pen.Mode := pmCopy;
|
||
Pen.Style := psSolid;
|
||
Pen.Color := cl1;
|
||
Pen.Width := 1;
|
||
MoveTo(x1, y2);
|
||
LineTo(x1, y1);
|
||
LineTo(x2, y1);
|
||
Pen.Color := cl2;
|
||
MoveTo(x1, y2);
|
||
LineTo(x2, y2);
|
||
LineTo(x2, y1);
|
||
end;
|
||
end;
|
||
|
||
// Same as IEDraw3DRect but using TIECanvas
|
||
// Canvas must be TIECanvas
|
||
procedure IEDraw3DRect2(Canvas: TObject; x1, y1, x2, y2: integer; cl1, cl2: TColor);
|
||
begin
|
||
with Canvas as TIECanvas do
|
||
begin
|
||
Pen.Mode := pmCopy;
|
||
Pen.Style := psSolid;
|
||
Pen.Color := cl1;
|
||
MoveTo(x1, y2);
|
||
LineTo(x1, y1);
|
||
LineTo(x2, y1);
|
||
Pen.Color := cl2;
|
||
MoveTo(x1, y2);
|
||
LineTo(x2, y2);
|
||
LineTo(x2, y1);
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
procedure IEDrawHint(Canvas: TCanvas; var x, y: integer; const ss: string; Font: TFont; Brush: TBrush; var SaveBitmap: TBitmap; MaxWidth, MaxHeight: integer; Border1, Border2: TColor);
|
||
const
|
||
ox = 6;
|
||
oy = 6;
|
||
var
|
||
tw, th: integer;
|
||
begin
|
||
Canvas.Font.Assign(Font);
|
||
Canvas.Brush.Assign(Brush);
|
||
tw := Canvas.TextWidth(ss) + 6 + ox;
|
||
th := Canvas.TextHeight(ss) + 6 + oy;
|
||
if x < 0 then
|
||
x := 0;
|
||
if y < 0 then
|
||
y := 0;
|
||
x := imin(x, MaxWidth - 1 - tw);
|
||
y := imin(y, MaxHeight - 1 - th);
|
||
SaveBitmap.PixelFormat := pf24bit;
|
||
SaveBitmap.Width := tw;
|
||
SaveBitmap.Height := th;
|
||
SaveBitmap.Canvas.CopyMode := cmSrcCopy;
|
||
SaveBitmap.Canvas.CopyRect(rect(0, 0, tw, th), Canvas, rect(x, y, x + tw, y + th));
|
||
canvas.FillRect(rect(x + ox, y + oy, x + tw, y + th));
|
||
IEDraw3DRect(Canvas, x + ox, y + oy, x + tw - 1, y + th - 1, Border1, Border2);
|
||
Canvas.TextOut(x + 3 + ox, y + 3 + oy, string(ss));
|
||
end;
|
||
|
||
procedure IEDrawHint2(Canvas: TCanvas; var x, y: integer; const ss: string; const minText: string);
|
||
const
|
||
ox = 6;
|
||
oy = 6;
|
||
var
|
||
tw, th: integer;
|
||
iec: TIECanvas;
|
||
begin
|
||
iec := TIECanvas.Create(Canvas, true, true);
|
||
iec.Font.Name := 'Arial';
|
||
iec.Font.Size := 9;
|
||
iec.Font.Color := clBlack;
|
||
iec.Brush.Color := $0060FFFF;
|
||
iec.Brush.Style := bsSolid;
|
||
iec.Brush.Transparency := 128;
|
||
tw := imax( iec.TextWidth(ss) + 6 + ox , iec.TextWidth(minText) + 6 + ox );
|
||
th := iec.TextHeight(ss) + 6 + oy;
|
||
if x < 0 then
|
||
x := 0;
|
||
if y < 0 then
|
||
y := 0;
|
||
iec.FillRect(rect(x + ox, y + oy, x + tw, y + th));
|
||
IEDraw3DRect2(iec, x + ox, y + oy, x + tw - 1, y + th - 1, clWhite, clGray);
|
||
iec.Brush.Style := bsClear;
|
||
iec.TextOut(x + 3 + ox, y + 3 + oy, ss);
|
||
iec.Free;
|
||
end;
|
||
|
||
function IEDrawDibClose(hdd: hDrawDib): Boolean;
|
||
begin
|
||
result := DrawDibClose(hdd);
|
||
end;
|
||
|
||
function IEDrawDibDraw(hdd: hDrawDib; hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer; wFlags: UInt): Boolean;
|
||
begin
|
||
result := DrawDibDraw(hdd, hDC, xDst, yDst, dxDst, dyDst, lpbi, Bits, xSrc, ySrc, dxSrc, dySrc, wFlags);
|
||
end;
|
||
|
||
function IEDrawDibOpen: hDrawDib;
|
||
begin
|
||
result := DrawDibOpen;
|
||
end;
|
||
|
||
function IEDrawDibRealize(hdd: hDrawDib; hDC: THandle; fBackground: Bool): UInt;
|
||
begin
|
||
result := DrawDibRealize(hdd, hDC, fBackground);
|
||
end;
|
||
|
||
|
||
|
||
|
||
procedure SafeStreamWrite(Stream: TStream; var Aborting: boolean; const Buffer; Count: Longint);
|
||
begin
|
||
if Stream.Write(Buffer, Count) < Count then
|
||
Aborting := true;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
// DoPaletteDialog
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
{!!
|
||
<FS>TImageEnPaletteDialog.SetPalette
|
||
|
||
<FM>Declaration<FC>
|
||
procedure SetPalette(var Palette: array of <A TRGB>; NumCol: integer);
|
||
|
||
<FM>Description<FN>
|
||
Sets palette to show in the dialog.
|
||
|
||
<FM>Example<FC>
|
||
Var
|
||
fPalDial: TImageEnPaletteDialog;
|
||
Begin
|
||
fPalDial := TImageEnPaletteDialog.Create(self);
|
||
fPalDial.SetPalette(ImageEnIO1.Params.ColorMap^, ImageEnIO1.Params.ColorMapCount);
|
||
if fPalDial.Execute then
|
||
Panel1.Color := fPalDial.SelCol;
|
||
fPalDial.free;
|
||
End;
|
||
|
||
<FM>See Also<FN>
|
||
- <A CreateRGB>
|
||
- <A TRGB2TColor>
|
||
- <A TColor2TRGB>
|
||
!!}
|
||
procedure TImageEnPaletteDialog.SetPalette(var Palette: array of TRGB; NumCol: integer);
|
||
begin
|
||
fPalette := PRGBROW(@(Palette[0]));
|
||
fNumCol := NumCol;
|
||
end;
|
||
|
||
|
||
constructor TImageEnPaletteDialog.Create(AOwner: TComponent);
|
||
const
|
||
Right_Border = 8;
|
||
begin
|
||
inherited CreateNew(AOwner);
|
||
OnPaint := self.FormPaint;
|
||
OnMouseMove := self.FormMouseMove;
|
||
OnClick := self.FormClick;
|
||
BorderIcons := [biSystemMenu];
|
||
BorderStyle := bsDialog;
|
||
Caption := 'Palette';
|
||
Height := 199;
|
||
Position := poScreenCenter;
|
||
Width := 520;
|
||
ButtonCancel := TButton.Create(self);
|
||
with ButtonCancel do
|
||
begin
|
||
Parent := self;
|
||
ModalResult := mrCancel;
|
||
Caption := 'Cancel';
|
||
Cancel := true;
|
||
Top := 136;
|
||
end;
|
||
ButtonCancel.Left := ClientWidth - ButtonCancel.Width - Right_Border;
|
||
MouseCol := -1;
|
||
SelCol := -1;
|
||
end;
|
||
|
||
|
||
procedure TImageEnPaletteDialog.FormPaint(Sender: TObject);
|
||
var
|
||
c, x, y: integer;
|
||
begin
|
||
for c := 0 to fNumCol - 1 do
|
||
begin
|
||
y := 1 + (c div 32) * 16;
|
||
x := 1 + (c - (c div 32) * 32) * 16;
|
||
Canvas.Brush.Color := TRGB2TColor(fPalette^[c]);
|
||
if MouseCol = c then
|
||
Canvas.Pen.Color := clBlack
|
||
else
|
||
if Canvas.Brush.Color = SelCol then
|
||
Canvas.Pen.Color := $00555555
|
||
else
|
||
Canvas.Pen.Color := clWhite;
|
||
Canvas.Rectangle(x, y, x + 15, y + 15);
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure TImageEnPaletteDialog.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
||
var
|
||
c: integer;
|
||
begin
|
||
c := ((x - 1) div 16) + ((y - 1) div 16) * 32;
|
||
if (c >= 0) and (c < fNumCol) and (c <> MouseCol) then
|
||
begin
|
||
MouseCol := c;
|
||
FormPaint(self);
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure TImageEnPaletteDialog.FormClick(Sender: TObject);
|
||
begin
|
||
SelCol := TRGB2TCOLOR(fPalette^[MouseCol]);
|
||
modalresult := mrOK;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TImageEnPaletteDialog.Execute
|
||
|
||
<FM>Declaration<FC>
|
||
function Execute: boolean;
|
||
|
||
<FM>Description<FN>
|
||
Executes the dialog. Returns True if the user select a color, otherwise False if the user Cancel the dialog.
|
||
|
||
Use SelCol property to get the color selected as TColor or NumCol to get as integer index.
|
||
|
||
<FM>Example<FC>
|
||
Var
|
||
fPalDial: TImageEnPaletteDialog;
|
||
Begin
|
||
fPalDial := TImageEnPaletteDialog.Create(self);
|
||
fPalDial.SetPalette(ImageEnIO1.Params.ColorMap^, ImageEnIO1.Params.ColorMapCount);
|
||
if fPalDial.Execute then
|
||
Panel1.Color := fPalDial.SelCol;
|
||
fPalDial.free;
|
||
End;
|
||
|
||
!!}
|
||
function TImageEnPaletteDialog.Execute: boolean;
|
||
begin
|
||
if fPalette = nil then
|
||
raise EIEException.create('Invalid Palette!');
|
||
|
||
result := ShowModal = mrOK;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function IEDirectoryExists(const Name: string): Boolean;
|
||
var
|
||
Code: Integer;
|
||
begin
|
||
Code := GetFileAttributes(PChar(Name));
|
||
Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
|
||
end;
|
||
|
||
procedure IEForceDirectories(Dir: string);
|
||
begin
|
||
if Length(Dir) = 0 then
|
||
exit;
|
||
if (AnsiLastChar(Dir) <> nil) and (AnsiLastChar(Dir)^ = '\') then
|
||
Delete(Dir, Length(Dir), 1);
|
||
if (Length(Dir) < 3) or IEDirectoryExists(Dir) or (ExtractFilePath(Dir) = Dir) then
|
||
exit;
|
||
IEForceDirectories(ExtractFilePath(Dir));
|
||
CreateDir(Dir);
|
||
end;
|
||
|
||
// count consecutive bits
|
||
// ex 000111110000 return 5
|
||
function _GetBitCount(b: Integer): Integer;
|
||
var
|
||
i: Integer;
|
||
begin
|
||
i := 0;
|
||
while (i < 31) and (((1 shl i) and b) = 0) do
|
||
Inc(i);
|
||
Result := 0;
|
||
while (((1 shl i) and b) <> 0) and (i < 32) do
|
||
begin
|
||
Inc(i);
|
||
Inc(Result);
|
||
end;
|
||
end;
|
||
|
||
// return first set bit
|
||
// ex 000011100000 return 6 (first bit is "1")
|
||
// return 0 if no set bit found
|
||
function IEGetFirstSetBit(b: Integer): Integer;
|
||
var
|
||
i: Integer;
|
||
begin
|
||
i := 0;
|
||
while (i < 32) and (((1 shl i) and b) = 0) do
|
||
Inc(i);
|
||
if i = 32 then
|
||
result := 0
|
||
else
|
||
result := i + 1;
|
||
end;
|
||
|
||
// Converts colors count to needed bits per pixels (rounded)
|
||
function _NColToBitsPixel(NCol: integer): integer;
|
||
var
|
||
q: integer;
|
||
begin
|
||
result := -1;
|
||
for q := 0 to 31 do
|
||
if (NCol and (1 shl q)) <> 0 then
|
||
begin
|
||
if result <> -1 then
|
||
result := q + 1
|
||
else
|
||
result := q;
|
||
end;
|
||
end;
|
||
|
||
// return line length in bytes
|
||
// align is the number of bits of alignment. Allowed multiple of 8 bits (8, 16, 24, 32, 48...)
|
||
function IEBitmapRowLen(Width: integer; BitCount: integer; align: integer): int64;
|
||
begin
|
||
case align of
|
||
32:
|
||
// formula optimized for 32
|
||
result := (((Width * BitCount) + 31) shr 5) shl 2; // (((Width*BitCount)+31) div 32) * 4
|
||
else
|
||
// generic formula
|
||
result := (((Width * BitCount) + (align - 1)) div align) * (align div 8);
|
||
end;
|
||
end;
|
||
|
||
// Converts Pixelformat of TBitmap to BitCount
|
||
function IEVCLPixelFormat2BitCount(PixelFormat: TPixelFormat): integer;
|
||
const
|
||
conv: array[pfDevice..pfCustom] of integer = (0, 1, 4, 8, 15, 16, 24, 32, 0);
|
||
begin
|
||
case PixelFormat of
|
||
pf1bit: result := 1;
|
||
pf4bit: result := 4;
|
||
pf8bit: result := 8;
|
||
pf15bit: result := 15;
|
||
pf16bit: result := 16;
|
||
pf24bit: result := 24;
|
||
pf32bit: result := 32;
|
||
else
|
||
result := 0;
|
||
end;
|
||
end;
|
||
|
||
function IEVCLPixelFormat2ImageEnPixelFormat(PixelFormat: TPixelFormat): TIEPixelFormat;
|
||
begin
|
||
case PixelFormat of
|
||
pf1bit: result := ie1g;
|
||
pf4bit: result := ie8p;
|
||
pf8bit: result := ie8p;
|
||
pf15bit: result := ie24RGB;
|
||
pf16bit: result := ie24RGB;
|
||
pf24bit: result := ie24RGB;
|
||
pf32bit: result := ie24RGB;
|
||
else
|
||
result := ie24RGB;
|
||
end;
|
||
end;
|
||
|
||
// Get rowlen from PixelFormat
|
||
function IEVCLPixelFormat2RowLen(Width: integer; PixelFormat: TPixelFormat): integer;
|
||
begin
|
||
result := IEBitmapRowLen(Width, IEVCLPixelFormat2BitCount(PixelFormat), 32);
|
||
end;
|
||
|
||
// converts BitCount to PixelFormat (of TBitmap)
|
||
function IEBitCount2VCLPixelformat(Bitcount: integer): TPixelFormat;
|
||
begin
|
||
case BitCount of
|
||
1: result := pf1bit;
|
||
4: result := pf4bit;
|
||
8: result := pf8bit;
|
||
15: result := pf15bit;
|
||
16: result := pf16bit;
|
||
24: result := pf24bit;
|
||
32: result := pf32bit;
|
||
else
|
||
result := pfCustom;
|
||
end;
|
||
end;
|
||
|
||
function IEPixelFormat2BitCount(PixelFormat: TIEPixelFormat): integer;
|
||
const
|
||
PIXELFORMAT2BITCOUNT: array [TIEPixelFormat] of integer = ( 0, // ienull
|
||
1, // ie1g
|
||
8, // ie8p
|
||
8, // ie8g
|
||
16, // ie16g
|
||
24, // ie24RGB
|
||
32, // ie32f
|
||
32, // ieCMYK
|
||
48, // ie48RGB
|
||
24, // ieCIELab
|
||
32); // ie32RGB
|
||
begin
|
||
result := PIXELFORMAT2BITCOUNT[PixelFormat];
|
||
end;
|
||
|
||
function IEPixelFormat2ChannelCount(PixelFormat: TIEPixelFormat): integer;
|
||
const
|
||
PIXELFORMAT2CHANNELCOUNT: array [TIEPixelFormat] of integer = ( 0, // ienull
|
||
1, // ie1g
|
||
1, // ie8p
|
||
1, // ie8g
|
||
1, // ie16g
|
||
3, // ie24RGB
|
||
1, // ie32f
|
||
4, // ieCMYK
|
||
3, // ie48RGB
|
||
3, // ieCIELab
|
||
4); // ie32RGB
|
||
begin
|
||
result := PIXELFORMAT2CHANNELCOUNT[PixelFormat];
|
||
end;
|
||
|
||
|
||
|
||
|
||
const
|
||
invtab: array[0..255] of byte = ($00, $80, $40, $C0, $20, $A0, $60, $E0, $10, $90, $50, $D0, $30, $B0,
|
||
$70, $F0, $08, $88, $48, $C8, $28, $A8, $68, $E8, $18, $98, $58, $D8, $38, $B8, $78, $F8, $04, $84,
|
||
$44, $C4, $24, $A4, $64, $E4, $14, $94, $54, $D4, $34, $B4, $74, $F4, $0C, $8C, $4C, $CC, $2C, $AC,
|
||
$6C, $EC, $1C, $9C, $5C, $DC, $3C, $BC, $7C, $FC, $02, $82, $42, $C2, $22, $A2, $62, $E2, $12, $92,
|
||
$52, $D2, $32, $B2, $72, $F2, $0A, $8A, $4A, $CA, $2A, $AA, $6A, $EA, $1A, $9A, $5A, $DA, $3A, $BA,
|
||
$7A, $FA, $06, $86, $46, $C6, $26, $A6, $66, $E6, $16, $96, $56, $D6, $36, $B6, $76, $F6, $0E, $8E,
|
||
$4E, $CE, $2E, $AE, $6E, $EE, $1E, $9E, $5E, $DE, $3E, $BE, $7E, $FE, $01, $81, $41, $C1, $21, $A1,
|
||
$61, $E1, $11, $91, $51, $D1, $31, $B1, $71, $F1, $09, $89, $49, $C9, $29, $A9, $69, $E9, $19, $99,
|
||
$59, $D9, $39, $B9, $79, $F9, $05, $85, $45, $C5, $25, $A5, $65, $E5, $15, $95, $55, $D5, $35, $B5,
|
||
$75, $F5, $0D, $8D, $4D, $CD, $2D, $AD, $6D, $ED, $1D, $9D, $5D, $DD, $3D, $BD, $7D, $FD, $03, $83,
|
||
$43, $C3, $23, $A3, $63, $E3, $13, $93, $53, $D3, $33, $B3, $73, $F3, $0B, $8B, $4B, $CB, $2B, $AB,
|
||
$6B, $EB, $1B, $9B, $5B, $DB, $3B, $BB, $7B, $FB, $07, $87, $47, $C7, $27, $A7, $67, $E7, $17, $97,
|
||
$57, $D7, $37, $B7, $77, $F7, $0F, $8F, $4F, $CF, $2F, $AF, $6F, $EF, $1F, $9F, $5F, $DF, $3F, $BF,
|
||
$7F, $FF);
|
||
|
||
// reverse byte bits
|
||
procedure ReverseBitsB(var inp: byte);
|
||
begin
|
||
inp := invtab[inp];
|
||
end;
|
||
|
||
{$ifdef IEUSEASM}
|
||
procedure ReverseBits(var inp: dword); assembler;
|
||
asm
|
||
push esi
|
||
push ebx
|
||
mov esi, eax
|
||
mov eax, DWord Ptr [esi]
|
||
BSWAP EAX
|
||
MOV EDX, EAX
|
||
AND EAX, 0AAAAAAAAh
|
||
SHR EAX, 1
|
||
AND EDX, 055555555h
|
||
SHL EDX, 1
|
||
OR EAX, EDX
|
||
MOV EDX, EAX
|
||
AND EAX, 0CCCCCCCCh
|
||
SHR EAX, 2
|
||
AND EDX, 033333333h
|
||
SHL EDX, 2
|
||
OR EAX, EDX
|
||
MOV EDX, EAX
|
||
AND EAX, 0F0F0F0F0h
|
||
SHR EAX, 4
|
||
AND EDX, 00F0F0F0Fh
|
||
SHL EDX, 4
|
||
OR EAX, EDX
|
||
mov DWord Ptr [esi], eax
|
||
pop ebx
|
||
pop esi
|
||
end;
|
||
{$else}
|
||
procedure ReverseBits(var inp: dword);
|
||
begin
|
||
inp := (invtab[(inp shr 24) and $FF]) or
|
||
(invtab[(inp shr 16) and $FF] shl 8) or
|
||
(invtab[(inp shr 8) and $FF] shl 16) or
|
||
(invtab[(inp) and $FF] shl 24);
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
{$ifdef IEUSEASM}
|
||
function IEPower2(const Base, Exponent: Double): Double;
|
||
const
|
||
MAXINTFP : Extended = $7fffffff;
|
||
asm
|
||
sub esp,$14
|
||
//if (Abs(Exponent) <= MaxInt) then
|
||
fld MAXINTFP
|
||
fld Exponent
|
||
fld st(0)
|
||
fabs
|
||
fcomp st(2)
|
||
fstsw ax
|
||
sahf
|
||
ffree st(1)
|
||
jae @IfEnd1
|
||
//Y := Round(Exponent);
|
||
fld st(0)
|
||
frndint
|
||
fist dword ptr [esp]
|
||
fcomp st(1)
|
||
fstsw ax
|
||
sahf
|
||
ffree st(0)
|
||
jnz @IfEnd2
|
||
//Result := IntPowerDKCIA32_4e(Base, Y)
|
||
//if Base = 0 then
|
||
fldz
|
||
fld Base
|
||
fcom st(1)
|
||
fstsw ax
|
||
sahf
|
||
jnz @IntPowIfEnd2
|
||
//if Exponent = 0 then
|
||
mov ecx,[esp]
|
||
test ecx,ecx
|
||
jnz @IntPowElse2
|
||
//ResultX := 1
|
||
ffree st(1)
|
||
ffree st(0)
|
||
fld1
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElse2 :
|
||
//ResultX := 0;
|
||
fxch st(1)
|
||
ffree st(1)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowIfEnd2 :
|
||
//else if Exponent = 0 then
|
||
mov ecx,[esp]
|
||
test ecx,ecx
|
||
jnz @IntPowElseIf2
|
||
//ResultX := 1
|
||
ffree st(1)
|
||
ffree st(0)
|
||
fld1
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElseIf2 :
|
||
//else if Exponent = 1 then
|
||
cmp ecx,1
|
||
jnz @IntPowElseIf3
|
||
//ResultX := Base
|
||
ffree st(1)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElseIf3 :
|
||
//else if Exponent = 2 then
|
||
cmp ecx,2
|
||
jnz @IntPowElseIf4
|
||
//ResultX := Base * Base
|
||
ffree st(1)
|
||
fmul st(0),st(0)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElseIf4 :
|
||
//else if Exponent > 2 then
|
||
cmp ecx,2
|
||
jle @IntPowElseIf5
|
||
ffree st(1)
|
||
//ResultX2 := 1;
|
||
fld1
|
||
//ResultX := Base;
|
||
fxch st(1)
|
||
mov eax,ecx
|
||
//I := 2;
|
||
mov edx,2
|
||
//I2 := Exponent;
|
||
@IntPowRepeat1Start :
|
||
//I2 := I2 shr 1;
|
||
shr ecx,1
|
||
jnc @IntPowIfEnd8
|
||
//ResultX2 := ResultX2 * ResultX;
|
||
fmul st(1),st(0)
|
||
@IntPowIfEnd8 :
|
||
//ResultX := ResultX * ResultX;
|
||
fmul st(0),st(0)
|
||
//I := I * 2;
|
||
add edx,edx
|
||
//until(I > Exponent);
|
||
cmp eax,edx
|
||
jnl @IntPowRepeat1Start
|
||
//ResultX := ResultX * ResultX2;
|
||
fmulp st(1),st(0)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElseIf5 :
|
||
//else if Exponent = -1 then
|
||
cmp ecx,-1
|
||
jnz @IntPowElseIf6
|
||
ffree st(1)
|
||
//ResultX := 1/Base
|
||
fld1
|
||
fdivrp st(1),st(0)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElseIf6 :
|
||
//else if Exponent = -2 then
|
||
cmp ecx,-2
|
||
jnz @IntPowElse7
|
||
//ResultX := 1/(Base*Base)
|
||
ffree st(1)
|
||
fmul st(0),st(0)
|
||
fld1
|
||
fdivrp
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IntPowElse7 :
|
||
ffree st(1)
|
||
//else //if Exponent < -2 then
|
||
//I2 := -Exponent;
|
||
mov eax,ecx
|
||
neg eax
|
||
mov edx,eax
|
||
//I := 2;
|
||
mov ecx,2
|
||
//ResultX2 := 1;
|
||
fld1
|
||
//ResultX := Base;
|
||
fxch st(1)
|
||
@IntPowRepeat2Start :
|
||
//I2 := I2 shr 1;
|
||
shr eax,1
|
||
jnc @IntPowIfEnd7
|
||
//ResultX2 := ResultX2 * ResultX;
|
||
fmul st(1),st(0)
|
||
@IntPowIfEnd7 :
|
||
//ResultX := ResultX * ResultX;
|
||
fmul st(0),st(0)
|
||
//I := I * 2;
|
||
add ecx,ecx
|
||
//until(I > -Exponent);
|
||
cmp ecx,edx
|
||
jle @IntPowRepeat2Start
|
||
//ResultX := ResultX * ResultX2;
|
||
fmulp st(1),st(0)
|
||
//ResultX := 1 / ResultX;
|
||
fld1
|
||
fdivr
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IfEnd2 :
|
||
//Result := Exp(Exponent * Ln(Base))
|
||
fld Base
|
||
fldln2
|
||
fxch st(1)
|
||
fyl2x
|
||
fld Exponent
|
||
fmulp
|
||
fldl2e
|
||
fmulp
|
||
fld st(0)
|
||
frndint
|
||
fsub st(1),st(0)
|
||
fxch st(1)
|
||
f2xm1
|
||
fld1
|
||
faddp
|
||
fscale
|
||
ffree st(1)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IfEnd1 :
|
||
//if (Exponent > 0) and (Base <> 0) then
|
||
fldz
|
||
fcom st(1)
|
||
fstsw ax
|
||
sahf
|
||
jbe @IfEnd3
|
||
fld Base
|
||
fcom st(1)
|
||
fstsw ax
|
||
sahf
|
||
jz @IfEnd3
|
||
ffree st(1)
|
||
//Result := Exp(Exponent * Ln(Base))
|
||
fldln2
|
||
fxch st(1)
|
||
fyl2x
|
||
fmul st(0), st(2)
|
||
ffree st(2)
|
||
fldl2e
|
||
fmulp
|
||
fld st(0)
|
||
frndint
|
||
fsub st(1),st(0)
|
||
fxch st(1)
|
||
f2xm1
|
||
fld1
|
||
faddp
|
||
fscale
|
||
ffree st(1)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@IfEnd3 :
|
||
//else if Base = 0 then
|
||
fld Base
|
||
fcom st(1)
|
||
fstsw ax
|
||
sahf
|
||
ffree st(1)
|
||
jnz @ElseIfEnd4
|
||
//Result := 0
|
||
ffree st(2)
|
||
wait
|
||
mov esp,ebp
|
||
pop ebp
|
||
ret $10
|
||
@ElseIfEnd4 :
|
||
//Result := Exp(Exponent * Ln(Base))
|
||
fldln2
|
||
fxch st(1)
|
||
fyl2x
|
||
fmul st(0),st(2)
|
||
ffree st(2)
|
||
fldl2e
|
||
fmulp
|
||
fld st(0)
|
||
frndint
|
||
fsub st(1),st(0)
|
||
fxch st(1)
|
||
f2xm1
|
||
fld1
|
||
faddp
|
||
fscale
|
||
ffree st(1)
|
||
wait
|
||
mov esp,ebp
|
||
end;
|
||
{$else}
|
||
function IEPower2(const Base, Exponent: Double): Double;
|
||
begin
|
||
result := Power(Base, Exponent);
|
||
end;
|
||
{$endif}
|
||
|
||
// if hdd<>0 uses DibDrawDib otherwise StetchDIBits
|
||
// USE THIS ONLY ON PRINTING FUNCTION OF TIMAGEENIO
|
||
procedure DrawDibDrawEmu(hdd: THandle; hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer; wFlags: UInt);
|
||
var
|
||
fr: boolean;
|
||
begin
|
||
fr := (lpbi.biBitCount = 24) and (hdd = 0);
|
||
if fr then
|
||
hdd := drawdibopen;
|
||
if hdd = 0 then
|
||
begin
|
||
StretchDIBits(hDC, xDst, yDst, dxDst, dyDst, xSrc, ySrc, dxSrc, dySrc, Bits, PBITMAPINFO(@lpbi)^, DIB_RGB_COLORS, SRCCOPY);
|
||
end
|
||
else
|
||
DrawDibDraw(hdd, hDC, xDst, yDst, dxDst, dyDst, lpbi, Bits, xSrc, ySrc, dxSrc, dySrc, wFlags);
|
||
if fr then
|
||
drawdibclose(hdd);
|
||
end;
|
||
|
||
procedure DrawDib(hDC: THandle; xDst, yDst, dxDst, dyDst: Integer; var lpbi: TBitmapInfoHeader; Bits: Pointer; xSrc, ySrc, dxSrc, dySrc: Integer);
|
||
begin
|
||
SetStretchBltMode(hDC, HALFTONE);
|
||
StretchDIBits(hDC, xDst, yDst, dxDst, dyDst, xSrc, ySrc, dxSrc, dySrc, Bits, PBITMAPINFO(@lpbi)^, DIB_RGB_COLORS, SRCCOPY);
|
||
end;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////
|
||
// exchanges WORD [ ex result := hibyte(i) or (lobyte(i) shl 8); ]
|
||
{$ifdef IEUSEASM}
|
||
function IESwapWord(i: word): word; assembler;
|
||
asm
|
||
ror ax,8
|
||
end;
|
||
{$else}
|
||
function IESwapWord(i: word): word;
|
||
begin
|
||
result := (i and $FF shl 8) or (i and $FF00 shr 8);
|
||
end;
|
||
{$endif}
|
||
|
||
procedure IEChangeEndiannessWordArray(buffer: pword; items: integer);
|
||
begin
|
||
for items := items - 1 downto 0 do
|
||
begin
|
||
buffer^ := (buffer^ and $FF shl 8) or (buffer^ and $FF00 shr 8);
|
||
inc(buffer);
|
||
end;
|
||
end;
|
||
|
||
procedure IEChangeEndiannessDWordArray(buffer: pdword; items: integer);
|
||
begin
|
||
for items := items - 1 downto 0 do
|
||
begin
|
||
buffer^ := (buffer^ and $FF shl 24) or (buffer^ and $FF00 shl 8) or (buffer^ and $FF0000 shr 8) or (buffer^ and $FF000000 shr 24);
|
||
inc(buffer);
|
||
end;
|
||
end;
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////
|
||
// swap DWORD and int64
|
||
|
||
function IESwapDWord(i: integer): integer;
|
||
begin
|
||
{$ifdef IEUSEASM}
|
||
asm
|
||
mov EAX,i
|
||
bswap EAX
|
||
mov @result,EAX
|
||
end;
|
||
{$else}
|
||
PByteArray(@result)[0] := PByteArray(@i)[3];
|
||
PByteArray(@result)[1] := PByteArray(@i)[2];
|
||
PByteArray(@result)[2] := PByteArray(@i)[1];
|
||
PByteArray(@result)[3] := PByteArray(@i)[0];
|
||
{$endif}
|
||
end;
|
||
|
||
// cannot compile with Delphi 5 (internal error) if "result" and "i" are directly indexed
|
||
function IESwapInt64(i: int64): int64;
|
||
var
|
||
dst, src: PByteArray;
|
||
begin
|
||
dst := PByteArray(@result);
|
||
src := PByteArray(@i);
|
||
dst[0] := src[7];
|
||
dst[1] := src[6];
|
||
dst[2] := src[5];
|
||
dst[3] := src[4];
|
||
dst[4] := src[3];
|
||
dst[5] := src[2];
|
||
dst[6] := src[1];
|
||
dst[7] := src[0];
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// changes x2, y2 to make an angle of 45<34> or 90<39> with the line to x1, y1
|
||
// useful when CTRL is pressed
|
||
procedure _CastPolySelCC(const x1, y1: integer; var x2, y2: integer);
|
||
var
|
||
dx, dy: integer;
|
||
adx, ady: integer;
|
||
begin
|
||
dx := x1 - x2;
|
||
adx := abs(dx);
|
||
dy := y1 - y2;
|
||
ady := abs(dy);
|
||
if adx + 30 < ady then
|
||
x2 := x1
|
||
else
|
||
if adx - 30 > ady then
|
||
y2 := y1
|
||
else
|
||
begin
|
||
if (dx < 0) and (dy < 0) then
|
||
begin
|
||
if (adx < ady) then
|
||
inc(x2, abs(adx - ady))
|
||
else
|
||
inc(y2, abs(adx - ady));
|
||
end
|
||
else
|
||
if (dx > 0) and (dy > 0) then
|
||
begin
|
||
if (adx < ady) then
|
||
inc(y2, abs(adx - ady))
|
||
else
|
||
inc(x2, abs(adx - ady));
|
||
end
|
||
else
|
||
if (dx > 0) then
|
||
begin
|
||
if (adx < ady) then
|
||
dec(x2, abs(adx - ady))
|
||
else
|
||
inc(y2, abs(adx - ady));
|
||
end
|
||
else
|
||
if (dy > 0) then
|
||
begin
|
||
if (adx < ady) then
|
||
inc(x2, abs(adx - ady))
|
||
else
|
||
dec(y2, abs(adx - ady));
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
// Return true if the two rectangles have a common region
|
||
// The rectangles must have ordered coordinates
|
||
function _RectXRect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2: integer): boolean;
|
||
begin
|
||
result := not ((IMAX(ax1, ax2) < bx1) or (IMIN(ax1, ax2) > bx2) or
|
||
(IMAX(ay1, ay2) < by1) or (IMIN(ay1, ay2) > by2));
|
||
end;
|
||
|
||
// Return "How much" the rectangle "b" is included in "a"
|
||
// 0 = no common region
|
||
// 1 = common region (not all)
|
||
// 2 = common region
|
||
// The rectangles must have ordered coordinates
|
||
function _RectPRect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2: integer): integer;
|
||
var
|
||
vx1, vx2: boolean;
|
||
vy1, vy2: boolean;
|
||
begin
|
||
vx1 := (bx1 >= ax1) and (bx1 <= ax2);
|
||
vx2 := (bx2 >= ax1) and (bx2 <= ax2);
|
||
vy1 := (by1 >= ay1) and (by1 <= ay2);
|
||
vy2 := (by2 >= ay1) and (by2 <= ay2);
|
||
if (vx1 xor vx2) and (vy1 or vy2) then
|
||
result := 1 // partial x
|
||
else
|
||
if (vx1 or vx2) and (vy1 xor vy2) then
|
||
result := 1 // partial y
|
||
else
|
||
if (vx1 xor vx2) and (vy1 xor vy2) then
|
||
result := 1 // partial xy
|
||
else
|
||
if vx1 and vx2 and vy1 and vy2 then
|
||
result := 2 // full
|
||
else
|
||
result := 0; // null
|
||
end;
|
||
|
||
// return true if the point xx, yy is inside the rectangle x1, y1, x2, y2
|
||
// x1, y1, x2, y2 must be ordered
|
||
function IEPointInRect(xx, yy, x1, y1, x2, y2: integer): boolean;
|
||
begin
|
||
result := (xx >= x1) and (xx <= x2) and (yy >= y1) and (yy <= y2);
|
||
end;
|
||
|
||
function IEPointInRect(xx, yy : integer; ARect: TRect): boolean;
|
||
begin
|
||
Result := IEPointInRect(xx, yy, ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
|
||
end;
|
||
|
||
// return true if the point xx, yy is inside the rectangle x1, y1, x2, y2
|
||
// x1, y1, x2, y2 ordered or not ordered
|
||
function _InRectO(xx, yy, x1, y1, x2, y2: integer): boolean;
|
||
begin
|
||
OrdCor(x1, y1, x2, y2);
|
||
result := (xx >= x1) and (xx <= x2) and (yy >= y1) and (yy <= y2);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>IEGetFileSize
|
||
|
||
<FM>Declaration<FC>
|
||
function IEGetFileSize(const Filename: string): int64;
|
||
|
||
<FM>Description<FN>
|
||
Returns the size of a file (even if larger than 2GB). Result is 0 if an error occured.
|
||
|
||
<FM>See Also<FN>
|
||
- <A IEGetFileDetails>
|
||
!!}
|
||
function IEGetFileSize(const Filename: string): int64;
|
||
var
|
||
sr: TSearchRec;
|
||
begin
|
||
if FindFirst(filename, faAnyFile, sr) = 0 then
|
||
result := int64(sr.FindData.nFileSizeHigh) shl int64(32) + int64(sr.FindData.nFileSizeLow)
|
||
else
|
||
result := 0;
|
||
FindClose(sr);
|
||
end;
|
||
|
||
// Displays the TColorDialog so the user can select a color. Result is false if user cancels out
|
||
function PromptForColor(var AColor : TColor): Boolean;
|
||
var
|
||
cl: TColorDialog;
|
||
begin
|
||
Result := False;
|
||
cl := TColorDialog.Create(nil);
|
||
try
|
||
cl.CustomColors.Clear;
|
||
if IEGlobalSettings().ColorDialogCustomColors <> '' then
|
||
cl.CustomColors.Text := IEGlobalSettings().ColorDialogCustomColors
|
||
else
|
||
begin
|
||
cl.CustomColors.Add('ColorA=D670DA');
|
||
cl.CustomColors.Add('ColorB=8B3D48');
|
||
cl.CustomColors.Add('ColorC=FF901E');
|
||
cl.CustomColors.Add('ColorD=ED9564');
|
||
cl.CustomColors.Add('ColorE=EBCE87');
|
||
cl.CustomColors.Add('ColorF=908070');
|
||
cl.CustomColors.Add('ColorG=4F4F2F');
|
||
cl.CustomColors.Add('ColorH=2F6B55');
|
||
cl.CustomColors.Add('ColorI=008080');
|
||
cl.CustomColors.Add('ColorJ=7FFF00');
|
||
cl.CustomColors.Add('ColorK=00FC7C');
|
||
cl.CustomColors.Add('ColorL=32CD9A');
|
||
cl.CustomColors.Add('ColorM=B9DAFF');
|
||
cl.CustomColors.Add('ColorN=00D7FF');
|
||
cl.CustomColors.Add('ColorO=20A5DA');
|
||
cl.CustomColors.Add('ColorP=1E69D2');
|
||
end;
|
||
|
||
cl.Color := AColor;
|
||
|
||
If cl.Execute then
|
||
begin
|
||
AColor := cl.Color;
|
||
Result := True;
|
||
end;
|
||
IEGlobalSettings().ColorDialogCustomColors := cl.CustomColors.Text
|
||
finally
|
||
FreeAndNil(cl);
|
||
end;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
// search for the window handle that contains cmp, going back (start from cmp)
|
||
function IEFindHandle(cmp: TComponent): HWND;
|
||
var
|
||
xowner: TComponent;
|
||
begin
|
||
xowner := cmp;
|
||
while assigned(xowner) and not (xowner is TWinControl) do
|
||
xowner := xowner.owner;
|
||
if assigned(xowner) and (xowner as TWinControl).handleallocated then
|
||
result := (xowner as TWinControl).Handle
|
||
else
|
||
result := 0;
|
||
end;
|
||
|
||
|
||
procedure IERightShadow(Canvas: TCanvas; DestBitmap: TBitmap; x1, y1, x2, y2: integer; st: TIEShadowType; dstColor: TColor);
|
||
var
|
||
y, x, ww, hh: integer;
|
||
cl1, cl2, cl: integer;
|
||
o: integer;
|
||
cl_c, radius, Temp: double;
|
||
dstRGB: TRGB;
|
||
cl_r, cl_g, cl_b: integer;
|
||
//bmp: TIEBitmap;
|
||
px: PRGB;
|
||
bmpw, bmph: integer;
|
||
begin
|
||
ww := x2 - x1 + 1;
|
||
hh := y2 - y1 + 1;
|
||
case st of
|
||
iestSolid:
|
||
Canvas.FillRect(Rect(x1, y1 + ww, x2, y2 + 1));
|
||
iestSmooth1:
|
||
begin
|
||
bmpw := 0;
|
||
bmph := 0;
|
||
if assigned(DestBitmap) then
|
||
begin
|
||
bmpw := DestBitmap.Width;
|
||
bmph := DestBitmap.Height;
|
||
end;
|
||
radius := ww/3;
|
||
for x := 0 to ww - 1 do
|
||
begin
|
||
Temp := (ww-x) / radius;
|
||
cl_c := Exp(-0.1 - Temp * Temp / 6);
|
||
for y := y1+ww to y2-ww+x+3 do
|
||
begin
|
||
if assigned(DestBitmap) and (x+x1>=0) and (y>=0) and (x+x1<bmpw) and (y<bmph) then
|
||
begin
|
||
px := DestBitmap.Scanline[y]; inc(px, x+x1);
|
||
with px^ do
|
||
begin
|
||
r := trunc(cl_c*r);
|
||
g := trunc(cl_c*g);
|
||
b := trunc(cl_c*b);
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
dstRGB := TColor2TRGB( Canvas.Pixels[x1+x, y] );
|
||
cl_r := trunc(cl_c*dstRGB.r);
|
||
cl_g := trunc(cl_c*dstRGB.g);
|
||
cl_b := trunc(cl_c*dstRGB.b);
|
||
Canvas.Pixels[x1+x, y] := TColor((cl_r) + (cl_g shl 8) + (cl_b shl 16));
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
iestSmooth2:
|
||
begin
|
||
o := 0;
|
||
for y := 0 to hh do
|
||
begin
|
||
cl2 := blimit(trunc(exp((hh - y * 3) / hh) / exp(1) * 255));
|
||
if y > hh - ww + 1 then
|
||
inc(o);
|
||
for x := o to ww do
|
||
begin
|
||
cl1 := trunc(exp(x / ww) / exp(1) * 255);
|
||
cl := imax(cl1, cl2);
|
||
Canvas.Pixels[x1 + x, y1 + y] := TColor((cl) + (cl shl 8) + (cl shl 16));
|
||
end;
|
||
end;
|
||
end;
|
||
(*
|
||
iestSmooth3:
|
||
// EXPERIMENTAL!
|
||
begin
|
||
o := hh+20;
|
||
bmp := TIEBitmap.Create(o, o, ie8g);
|
||
bmp.Fill(0);
|
||
bmp.FillRect(10, 10, o-10, o-10, 255);
|
||
_IEGBlurRect8(bmp, 0, 0, o-1, o-1, 4);
|
||
for y := y1 to y2 do
|
||
begin
|
||
for x := x1 to x2 do
|
||
begin
|
||
dstRGB := TColor2TRGB(Canvas.Pixels[x, y]);
|
||
cl_c := 1-bmp.Pixels_ie8[x-x1+o-10, y-y1+10]/255;
|
||
cl_r := trunc(cl_c*dstRGB.r);
|
||
cl_g := trunc(cl_c*dstRGB.g);
|
||
cl_b := trunc(cl_c*dstRGB.b);
|
||
Canvas.pixels[x, y] := TColor((cl_r) + (cl_g shl 8) + (cl_b shl 16));
|
||
end;
|
||
end;
|
||
bmp.free;
|
||
end;
|
||
*)
|
||
end;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
procedure IEBottomShadow(Canvas: TCanvas; DestBitmap: TBitmap; x1, y1, x2, y2: integer; st: TIEShadowType; dstColor: TColor);
|
||
var
|
||
y, x, ww, hh: integer;
|
||
cl1, cl2, cl: integer;
|
||
o: integer;
|
||
cl_c, radius, Temp: double;
|
||
dstRGB: TRGB;
|
||
cl_r, cl_g, cl_b: integer;
|
||
bmpw, bmph: integer;
|
||
px: PRGB;
|
||
begin
|
||
ww := x2 - x1 + 1;
|
||
hh := y2 - y1 + 1;
|
||
case st of
|
||
iestSolid:
|
||
Canvas.FillRect(Rect(x1 + hh, y1, x2 + 1, y2));
|
||
iestSmooth1:
|
||
begin
|
||
bmpw := 0;
|
||
bmph := 0;
|
||
if assigned(DestBitmap) then
|
||
begin
|
||
bmpw := DestBitmap.Width;
|
||
bmph := DestBitmap.Height;
|
||
end;
|
||
px := nil;
|
||
radius := hh/3;
|
||
for y := 0 to hh - 1 do
|
||
begin
|
||
Temp := (y-hh) / radius;
|
||
cl_c := Exp(-0.1 - Temp * Temp / 6);
|
||
if assigned(DestBitmap) and (y+y1>0) and (y+y1<bmph) then
|
||
begin
|
||
px := DestBitmap.Scanline[y+y1];
|
||
inc(px, x1+hh);
|
||
end;
|
||
for x := x1+hh to x2-hh+y+1 do
|
||
begin
|
||
if assigned(DestBitmap) and (x>=0) and (y+y1>=0) and (x<bmpw) and (y+y1<bmph) then
|
||
begin
|
||
with px^ do
|
||
begin
|
||
r := trunc(cl_c*r);
|
||
g := trunc(cl_c*g);
|
||
b := trunc(cl_c*b);
|
||
end;
|
||
inc(px);
|
||
end
|
||
else
|
||
begin
|
||
dstRGB := TColor2TRGB( Canvas.Pixels[x, y1+y] );
|
||
cl_r := trunc(cl_c*dstRGB.r);
|
||
cl_g := trunc(cl_c*dstRGB.g);
|
||
cl_b := trunc(cl_c*dstRGB.b);
|
||
Canvas.Pixels[x, y1+y] := TColor((cl_r) + (cl_g shl 8) + (cl_b shl 16));
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
iestSmooth2:
|
||
begin
|
||
o := 0;
|
||
for x := 0 to ww do
|
||
begin
|
||
cl2 := blimit(trunc(exp((ww - x * 3) / ww) / exp(1) * 255));
|
||
if x > ww - hh + 1 then
|
||
inc(o);
|
||
for y := o to hh do
|
||
begin
|
||
cl1 := trunc(exp(y / hh) / exp(1) * 255);
|
||
cl := imax(cl1, cl2);
|
||
Canvas.Pixels[x1 + x, y1 + y] := TColor((cl) + (cl shl 8) + (cl shl 16));
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure IERectShadow(Bitmap: TBitmap; x1, y1, x2, y2: integer; dstColor: TColor);
|
||
var
|
||
ww, hh: integer;
|
||
bmp: TIEBitmap;
|
||
cl_c: double;
|
||
radius: integer;
|
||
bmpw, bmph: integer;
|
||
pb: pbyte;
|
||
px: PRGB;
|
||
x, y: integer;
|
||
offx, offy: integer;
|
||
begin
|
||
radius := 5;
|
||
offx := 2;
|
||
offy := 2;
|
||
|
||
bmpw := Bitmap.Width;
|
||
bmph := Bitmap.Height;
|
||
ww := x2 - x1 + 1;
|
||
hh := y2 - y1 + 1;
|
||
bmp := TIEBitmap.Create(ww+radius*2, hh+radius*2, ie8g);
|
||
bmp.Fill(0);
|
||
bmp.FillRect(radius, radius, ww+radius-1+offx, hh+radius-1+offy, 255);
|
||
_IEGBlurRect8(bmp, 0, 0, ww+radius*2-1, hh+radius*2-1, radius/2);
|
||
for y := y1-radius to y2+radius do
|
||
begin
|
||
if (y>=0) and (y<bmph) then
|
||
begin
|
||
px := Bitmap.Scanline[y]; inc(px, x1-radius);
|
||
pb := bmp.Scanline[y-y1+radius];
|
||
for x := x1-radius to x2+radius do
|
||
begin
|
||
if (x>=0) and (x<bmpw) and ((x<x1) or (x>=x2) or (y<y1) or (y>=y2)) then
|
||
begin
|
||
cl_c := 1-pb^/255;
|
||
with px^ do
|
||
begin
|
||
r := trunc(cl_c*r);
|
||
g := trunc(cl_c*g);
|
||
b := trunc(cl_c*b);
|
||
end;
|
||
end;
|
||
inc(px);
|
||
inc(pb);
|
||
end;
|
||
end;
|
||
end;
|
||
bmp.free;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// Saves the string ss to Stream. Saves the size (integer) then the string.
|
||
// Compatible with LoadStringFromStream
|
||
procedure IESaveStringToStream(Stream: TStream; const ss: AnsiString);
|
||
var
|
||
i: integer;
|
||
begin
|
||
i := length(ss);
|
||
Stream.Write(i, sizeof(integer));
|
||
Stream.Write(PAnsiChar(ss)^, i);
|
||
end;
|
||
|
||
// Loads a string from Stream. Compatible with SaveStringToStream
|
||
procedure IELoadStringFromStream(Stream: TStream; var ss: AnsiString);
|
||
var
|
||
i: integer;
|
||
begin
|
||
Stream.Read(i, sizeof(integer));
|
||
SetLength(ss, i);
|
||
Stream.Read(PAnsiChar(ss)^, i);
|
||
end;
|
||
|
||
{$IfDef UNICODE}
|
||
// Saves the string ss to Stream. Saves the size (integer) then the string.
|
||
// Compatible with LoadStringFromStream
|
||
procedure IESaveStringToStream(Stream: TStream; const ss: UnicodeString);
|
||
var
|
||
strLen: integer;
|
||
begin
|
||
strLen := Length( ss );
|
||
Stream.Write( strLen, sizeof( integer ));
|
||
if strLen > 0 then
|
||
Stream.Write( ss[1], strLen * SizeOf( ss[1] ));
|
||
end;
|
||
|
||
// Loads a string from Stream. Compatible with SaveStringToStream
|
||
procedure IELoadStringFromStream(Stream: TStream; var ss: UnicodeString);
|
||
var
|
||
strLen: integer;
|
||
begin
|
||
Stream.Read( strLen, sizeof(integer));
|
||
SetLength( ss, strLen );
|
||
if strLen > 0 then
|
||
Stream.Read( ss[1], strLen * SizeOf( ss[1] ));
|
||
end;
|
||
{$EndIf}
|
||
|
||
// Saves the string ss to Stream. Saves the size (integer) then the string.
|
||
// Compatible with LoadStringFromStreamW
|
||
procedure IESaveStringToStreamW(Stream: TStream; const ss: widestring);
|
||
var
|
||
i: integer;
|
||
begin
|
||
i := length(ss);
|
||
Stream.Write(i, sizeof(integer));
|
||
Stream.Write(ss[1], i*2);
|
||
end;
|
||
|
||
// Loads a string from Stream. Compatible with SaveStringToStreamW
|
||
procedure IELoadStringFromStreamW(Stream: TStream; var ss: widestring);
|
||
var
|
||
i: integer;
|
||
begin
|
||
Stream.Read(i, sizeof(integer));
|
||
SetLength(ss, i);
|
||
Stream.Read(ss[1], i*2);
|
||
end;
|
||
|
||
|
||
procedure IELoadStringFromStreamW(Stream: TStream; var ss: String);
|
||
var
|
||
ws: Widestring;
|
||
begin
|
||
IELoadStringFromStreamW( Stream, ws );
|
||
ss := ws;
|
||
end;
|
||
|
||
|
||
procedure IESaveStringListToStream(Stream: TStream; sl: TStringList);
|
||
var
|
||
i: integer;
|
||
begin
|
||
i := sl.Count;
|
||
Stream.Write(i, sizeof(integer));
|
||
for i := 0 to sl.Count - 1 do
|
||
IESaveStringToStream(Stream, AnsiString(sl[i]));
|
||
end;
|
||
|
||
procedure IELoadStringListFromStream(Stream: TStream; sl: TStringList);
|
||
var
|
||
i, w: integer;
|
||
ss: AnsiString;
|
||
begin
|
||
Stream.Read(w, sizeof(integer));
|
||
sl.Clear;
|
||
for i := 0 to w - 1 do
|
||
begin
|
||
IELoadStringFromStream(Stream, ss);
|
||
sl.Add(string(ss));
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure IELoadFontFromStream(Stream: TStream; var Font: TFont);
|
||
var
|
||
fontName : string;
|
||
fontCharset : TFontCharset;
|
||
fontColor : TColor;
|
||
fontHeight : Integer;
|
||
fontStyle : TFontStyles;
|
||
begin
|
||
IELoadStringFromStreamW(Stream, fontName);
|
||
Font.Name := fontName;
|
||
Stream.Read( fontCharset , SizeOf( TFontCharset ));
|
||
Font.Charset := fontCharset;
|
||
Stream.Read( fontColor , SizeOf( TColor ));
|
||
Font.Color := fontColor ;
|
||
Stream.Read( fontHeight , SizeOf( Integer ));
|
||
Font.Height := fontHeight;
|
||
Stream.Read( fontStyle , SizeOf( TFontStyles ));
|
||
Font.Style := fontStyle;
|
||
end;
|
||
|
||
procedure IESaveFontToStream(Stream: TStream; const Font: TFont);
|
||
var
|
||
fontName : string;
|
||
fontCharset : TFontCharset;
|
||
fontColor : TColor;
|
||
fontHeight : Integer;
|
||
fontStyle : TFontStyles;
|
||
begin
|
||
fontName := Font.Name;
|
||
IESaveStringToStreamW(Stream, fontName);
|
||
fontCharset := Font.Charset;
|
||
Stream.Write( fontCharset , SizeOf( TFontCharset ));
|
||
fontColor := Font.Color;
|
||
Stream.Write( fontColor , SizeOf( TColor ));
|
||
fontHeight := Font.Height;
|
||
Stream.Write( fontHeight , SizeOf( Integer ));
|
||
fontStyle := Font.Style;
|
||
Stream.Write( fontStyle , SizeOf( TFontStyles ));
|
||
end;
|
||
|
||
// Returns number of colors calculated from BitsPerSample and SamplesperPixel
|
||
function _GetNumCol(BitsPerSample: integer; SamplesPerPixel: integer): integer;
|
||
begin
|
||
result := 1;
|
||
while SamplesPerPixel > 0 do
|
||
begin
|
||
result := result * (1 shl BitsPerSample);
|
||
dec(SamplesPerPixel);
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure IEBlendRGBA(var src: TRGBA; var dst: TRGBA; RenderOperation: TIERenderOperation; row: integer);
|
||
var
|
||
osrc, odst: TRGB;
|
||
begin
|
||
osrc.r := src.r;
|
||
osrc.g := src.g;
|
||
osrc.b := src.b;
|
||
odst.r := dst.r;
|
||
odst.g := dst.g;
|
||
odst.b := dst.b;
|
||
IEBlend(osrc, odst, RenderOperation, row);
|
||
src.r := osrc.r;
|
||
src.g := osrc.g;
|
||
src.b := osrc.b;
|
||
dst.r := odst.r;
|
||
dst.g := odst.g;
|
||
dst.b := odst.b;
|
||
end;
|
||
|
||
|
||
procedure IEBlend(var src: TRGB; var dst: TRGB; RenderOperation: TIERenderOperation; row: integer);
|
||
// filters
|
||
function softlight(ib, ia: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
a, b, r: double;
|
||
begin
|
||
a := ia / 255;
|
||
b := ib / 255;
|
||
if b < 0.5 then
|
||
r := 2 * a * b + sqr(a) * (1 - 2 * b)
|
||
else
|
||
r := sqrt(a) * (2 * b - 1) + (2 * a) * (1 - b);
|
||
result := trunc(r * 255);
|
||
end;
|
||
|
||
function xfader(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
c := a * b shr 8;
|
||
result := c + a * (255 - ((255 - a) * (255 - b) shr 8) - c) shr 8;
|
||
end;
|
||
|
||
function coloredge(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if b = 255 then
|
||
result := 255
|
||
else
|
||
begin
|
||
c := (a shl 8) div (255 - b);
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function colorburn(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if b = 0 then
|
||
result := 0
|
||
else
|
||
begin
|
||
c := 255 - (((255 - a) shl 8) div b);
|
||
if c < 0 then
|
||
result := 0
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function inversecolordodge(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if a = 255 then
|
||
result := 255
|
||
else
|
||
begin
|
||
c := (b shl 8) div (255 - a);
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function inversecolorburn(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if a = 0 then
|
||
result := 0
|
||
else
|
||
begin
|
||
c := 255 - (((255 - b) shl 8) div a);
|
||
if c < 0 then
|
||
result := 0
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function softdodge(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if a + b < 256 then
|
||
begin
|
||
if b = 255 then
|
||
result := 255
|
||
else
|
||
begin
|
||
c := (a shl 7) div (255 - b);
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
c := 255 - (((255 - b) shl 7) div a);
|
||
if c < 0 then
|
||
result := 0
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function softburn(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if a + b < 256 then
|
||
begin
|
||
if a = 255 then
|
||
Result := 255
|
||
else
|
||
begin
|
||
c := (b shl 7) div (255 - a);
|
||
if c > 255 then
|
||
Result := 255
|
||
else
|
||
Result := c;
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
c := 255 - (((255 - a) shl 7) div b);
|
||
if c < 0 then
|
||
Result := 0
|
||
else
|
||
Result := c;
|
||
end;
|
||
end;
|
||
|
||
function reflect(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if b = 255 then
|
||
result := 255
|
||
else
|
||
begin
|
||
c := a * a div (255 - b);
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function glow(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if a = 255 then
|
||
result := 255
|
||
else
|
||
begin
|
||
c := b * b div (255 - a);
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function freeze(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if b = 0 then
|
||
result := 0
|
||
else
|
||
begin
|
||
c := 255 - sqr(255 - a) div b;
|
||
if c < 0 then
|
||
result := 0
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function eat(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
if a = 0 then
|
||
result := 0
|
||
else
|
||
begin
|
||
c := 255 - sqr(255 - b) div a;
|
||
if c < 0 then
|
||
result := 0
|
||
else
|
||
result := c;
|
||
end;
|
||
end;
|
||
|
||
function interpolation(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
c := IECosineTab[b] + IECosineTab[a];
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
|
||
function stamp(b, a: integer): integer; {$ifdef IESUPPORTINLINE} inline; {$endif}
|
||
var
|
||
c: integer;
|
||
begin
|
||
c := a + 2 * b - 256;
|
||
if c < 0 then
|
||
result := 0
|
||
else
|
||
if c > 255 then
|
||
result := 255
|
||
else
|
||
result := c;
|
||
end;
|
||
//
|
||
var
|
||
Ha, Sa, La: double;
|
||
Hb, Sb, Lb: double;
|
||
tmp: TRGB;
|
||
v1, v2: byte;
|
||
Y_1, Cb_1, Cr_1: integer;
|
||
Y_2, Cb_2, Cr_2: integer;
|
||
RedToGrayCoef, GreenToGrayCoef, BlueToGrayCoef: integer;
|
||
begin
|
||
case RenderOperation of
|
||
ielNormal:
|
||
begin
|
||
dst := src;
|
||
end;
|
||
ielAdd:
|
||
begin
|
||
dst.r := blimit(dst.r + src.r);
|
||
dst.g := blimit(dst.g + src.g);
|
||
dst.b := blimit(dst.b + src.b);
|
||
end;
|
||
ielSub:
|
||
begin
|
||
dst.r := abs(dst.r - src.r);
|
||
dst.g := abs(dst.g - src.g);
|
||
dst.b := abs(dst.b - src.b);
|
||
end;
|
||
ielDiv:
|
||
begin
|
||
dst.r := blimit(dst.r div ilimit(src.r, 1, 255));
|
||
dst.g := blimit(dst.g div ilimit(src.g, 1, 255));
|
||
dst.b := blimit(dst.b div ilimit(src.b, 1, 255));
|
||
end;
|
||
ielMul:
|
||
begin
|
||
dst.r := (dst.r * src.r) shr 8;
|
||
dst.g := (dst.g * src.g) shr 8;
|
||
dst.b := (dst.b * src.b) shr 8;
|
||
end;
|
||
ielOR:
|
||
begin
|
||
dst.r := blimit(dst.r or src.r);
|
||
dst.g := blimit(dst.g or src.g);
|
||
dst.b := blimit(dst.b or src.b);
|
||
end;
|
||
ielAND:
|
||
begin
|
||
dst.r := blimit(dst.r and src.r);
|
||
dst.g := blimit(dst.g and src.g);
|
||
dst.b := blimit(dst.b and src.b);
|
||
end;
|
||
ielXOR:
|
||
begin
|
||
dst.r := blimit(dst.r xor src.r);
|
||
dst.g := blimit(dst.g xor src.g);
|
||
dst.b := blimit(dst.b xor src.b);
|
||
end;
|
||
ielMAX:
|
||
begin
|
||
dst.r := imax(dst.r, src.r);
|
||
dst.g := imax(dst.g, src.g);
|
||
dst.b := imax(dst.b, src.b);
|
||
end;
|
||
ielMIN:
|
||
begin
|
||
dst.r := imin(dst.r, src.r);
|
||
dst.g := imin(dst.g, src.g);
|
||
dst.b := imin(dst.b, src.b);
|
||
end;
|
||
ielAverage:
|
||
begin
|
||
dst.r := (dst.r + src.r) shr 1;
|
||
dst.g := (dst.g + src.g) shr 1;
|
||
dst.b := (dst.b + src.b) shr 1;
|
||
end;
|
||
ielScreen:
|
||
begin
|
||
dst.r := trunc( 255 - ((255 - dst.r) * (255 - src.r) / 255) );
|
||
dst.g := trunc( 255 - ((255 - dst.g) * (255 - src.g) / 255) );
|
||
dst.b := trunc( 255 - ((255 - dst.b) * (255 - src.b) / 255) );
|
||
end;
|
||
ielNegation:
|
||
begin
|
||
dst.r := 255 - abs(255 - src.r - dst.r);
|
||
dst.g := 255 - abs(255 - src.g - dst.g);
|
||
dst.b := 255 - abs(255 - src.b - dst.b);
|
||
end;
|
||
ielExclusion:
|
||
begin
|
||
dst.r := src.r + dst.r - (src.r * dst.r shr 7);
|
||
dst.g := src.g + dst.g - (src.g * dst.g shr 7);
|
||
dst.b := src.b + dst.b - (src.b * dst.b shr 7);
|
||
end;
|
||
ielOverlay:
|
||
begin
|
||
if dst.r < 128 then
|
||
dst.r := (src.r * dst.r) shr 7
|
||
else
|
||
dst.r := 255 - ((255 - src.r) * (255 - dst.r) shr 7);
|
||
if dst.g < 128 then
|
||
dst.g := (src.g * dst.g) shr 7
|
||
else
|
||
dst.g := 255 - ((255 - src.g) * (255 - dst.g) shr 7);
|
||
if dst.b < 128 then
|
||
dst.b := (src.b * dst.b) shr 7
|
||
else
|
||
dst.b := 255 - ((255 - src.b) * (255 - dst.b) shr 7);
|
||
end;
|
||
ielHardLight:
|
||
begin
|
||
if src.r < 128 then
|
||
dst.r := (src.r * dst.r) shr 7
|
||
else
|
||
dst.r := 255 - ((255 - src.r) * (255 - dst.r) shr 7);
|
||
if src.g < 128 then
|
||
dst.g := (src.g * dst.g) shr 7
|
||
else
|
||
dst.g := 255 - ((255 - src.g) * (255 - dst.g) shr 7);
|
||
if src.b < 128 then
|
||
dst.b := (src.b * dst.b) shr 7
|
||
else
|
||
dst.b := 255 - ((255 - src.b) * (255 - dst.b) shr 7);
|
||
end;
|
||
ielSoftLight:
|
||
begin
|
||
dst.r := softlight(src.r, dst.r);
|
||
dst.g := softlight(src.r, dst.g);
|
||
dst.b := softlight(src.r, dst.b);
|
||
end;
|
||
ielXFader:
|
||
begin
|
||
dst.r := XFader(src.r, dst.r);
|
||
dst.g := XFader(src.g, dst.g);
|
||
dst.b := XFader(src.b, dst.b);
|
||
end;
|
||
ielColorEdge:
|
||
begin
|
||
dst.r := ColorEdge(src.r, dst.r);
|
||
dst.g := ColorEdge(src.g, dst.g);
|
||
dst.b := ColorEdge(src.b, dst.b);
|
||
end;
|
||
ielColorBurn:
|
||
begin
|
||
dst.r := ColorBurn(src.r, dst.r);
|
||
dst.g := ColorBurn(src.g, dst.g);
|
||
dst.b := ColorBurn(src.b, dst.b);
|
||
end;
|
||
ielInverseColorDodge:
|
||
begin
|
||
dst.r := InverseColorDodge(src.r, dst.r);
|
||
dst.g := InverseColorDodge(src.g, dst.g);
|
||
dst.b := InverseColorDodge(src.b, dst.b);
|
||
end;
|
||
ielInverseColorBurn:
|
||
begin
|
||
dst.r := InverseColorBurn(src.r, dst.r);
|
||
dst.g := InverseColorBurn(src.g, dst.g);
|
||
dst.b := InverseColorBurn(src.b, dst.b);
|
||
end;
|
||
ielSoftDodge:
|
||
begin
|
||
dst.r := SoftDodge(src.r, dst.r);
|
||
dst.g := SoftDodge(src.g, dst.g);
|
||
dst.b := SoftDodge(src.b, dst.b);
|
||
end;
|
||
ielSoftBurn:
|
||
begin
|
||
dst.r := SoftBurn(src.r, dst.r);
|
||
dst.g := SoftBurn(src.g, dst.g);
|
||
dst.b := SoftBurn(src.b, dst.b);
|
||
end;
|
||
ielReflect:
|
||
begin
|
||
dst.r := Reflect(src.r, dst.r);
|
||
dst.g := Reflect(src.g, dst.g);
|
||
dst.b := Reflect(src.b, dst.b);
|
||
end;
|
||
ielGlow:
|
||
begin
|
||
dst.r := Glow(src.r, dst.r);
|
||
dst.g := Glow(src.g, dst.g);
|
||
dst.b := Glow(src.b, dst.b);
|
||
end;
|
||
ielFreeze:
|
||
begin
|
||
dst.r := Freeze(src.r, dst.r);
|
||
dst.g := Freeze(src.g, dst.g);
|
||
dst.b := Freeze(src.b, dst.b);
|
||
end;
|
||
ielEat:
|
||
begin
|
||
dst.r := Eat(src.r, dst.r);
|
||
dst.g := Eat(src.g, dst.g);
|
||
dst.b := Eat(src.b, dst.b);
|
||
end;
|
||
ielSubtractive:
|
||
begin
|
||
dst.r := blimit(dst.r + src.r - 256);
|
||
dst.g := blimit(dst.g + src.g - 256);
|
||
dst.b := blimit(dst.b + src.b - 256);
|
||
end;
|
||
ielInterpolation:
|
||
begin
|
||
dst.r := Interpolation(src.r, dst.r);
|
||
dst.g := Interpolation(src.g, dst.g);
|
||
dst.b := Interpolation(src.b, dst.b);
|
||
end;
|
||
ielStamp:
|
||
begin
|
||
dst.r := Stamp(src.r, dst.r);
|
||
dst.g := Stamp(src.g, dst.g);
|
||
dst.b := Stamp(src.b, dst.b);
|
||
end;
|
||
ielRed:
|
||
begin
|
||
dst.r := src.r;
|
||
end;
|
||
ielGreen:
|
||
begin
|
||
dst.g := src.g;
|
||
end;
|
||
ielBlue:
|
||
begin
|
||
dst.b := src.b;
|
||
end;
|
||
ielHue:
|
||
begin
|
||
RGB2HSL(src, Ha, Sa, La);
|
||
RGB2HSL(dst, Hb, Sb, Lb);
|
||
HSL2RGB(dst, Ha, Sb, Lb);
|
||
end;
|
||
ielSaturation:
|
||
begin
|
||
RGB2HSL(src, Ha, Sa, La);
|
||
RGB2HSL(dst, Hb, Sb, Lb);
|
||
HSL2RGB(dst, Hb, Sa, Lb);
|
||
end;
|
||
ielColor:
|
||
begin
|
||
RGB2HSL(src, Ha, Sa, La);
|
||
RGB2HSL(dst, Hb, Sb, Lb);
|
||
HSL2RGB(dst, Ha, Sa, Lb);
|
||
end;
|
||
ielLuminosity:
|
||
begin
|
||
RGB2HSL(src, Ha, Sa, La);
|
||
RGB2HSL(dst, Hb, Sb, Lb);
|
||
HSL2RGB(dst, Hb, Sb, La);
|
||
end;
|
||
ielLuminosity2:
|
||
begin
|
||
IERGB2YCbCr(src, Y_1, Cb_1, Cr_1);
|
||
IERGB2YCbCr(dst, Y_2, Cb_2, Cr_2);
|
||
IEYCbCr2RGB(dst, Y_1, Cb_2, Cr_2);
|
||
end;
|
||
ielStereoBW: // black&white
|
||
begin
|
||
RedToGrayCoef := IEGlobalSettings().RedToGrayCoef;
|
||
GreenToGrayCoef := IEGlobalSettings().GreenToGrayCoef;
|
||
BlueToGrayCoef := IEGlobalSettings().BlueToGrayCoef;
|
||
v1 := (src.r * RedToGrayCoef + src.g * GreenToGrayCoef + src.b * BlueToGrayCoef) div 100;
|
||
v2 := (dst.r * RedToGrayCoef + dst.g * GreenToGrayCoef + dst.b * BlueToGrayCoef) div 100;
|
||
dst.r := v2;
|
||
dst.g := v1;
|
||
dst.b := v1;
|
||
end;
|
||
ielStereoColor:
|
||
begin
|
||
dst.r := dst.r;
|
||
dst.g := src.g;
|
||
dst.b := src.b;
|
||
end;
|
||
ielStereoColorDubois:
|
||
begin
|
||
tmp.r := blimit(round(
|
||
0.456100*dst.r
|
||
+0.500484*dst.g
|
||
+0.176381*dst.b
|
||
-0.0434706*src.r
|
||
-0.0879388*src.g
|
||
-0.00155529*src.b));
|
||
tmp.g := blimit(round(
|
||
-0.0400822*dst.r
|
||
-0.0378246*dst.g
|
||
-0.0157589*dst.b
|
||
+0.378476*src.r
|
||
+0.73364*src.g
|
||
-0.0184503*src.b));
|
||
tmp.b := blimit(round(
|
||
-0.0152161*dst.r
|
||
-0.0205971*dst.g
|
||
-0.00546856*dst.b
|
||
-0.0721527*src.r
|
||
-0.112961*src.g
|
||
+1.2264*src.b));
|
||
dst := tmp;
|
||
end;
|
||
ielStereoEven:
|
||
if not Odd(row) then
|
||
dst := src;
|
||
ielStereoOdd:
|
||
if Odd(row) then
|
||
dst := src; end;
|
||
end;
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEScrollBarParams
|
||
|
||
constructor TIEScrollBarParams.Create;
|
||
begin
|
||
inherited Create;
|
||
fLineStep := -1;
|
||
fPageStep := -1;
|
||
fTracking := true;
|
||
end;
|
||
|
||
destructor TIEScrollBarParams.Destroy;
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
constructor TIEMouseWheelParams.Create(DefaultAction : TIEMouseWheelParamsAction);
|
||
begin
|
||
inherited Create;
|
||
|
||
InvertDirection := false;
|
||
Action := DefaultAction;
|
||
Variation := iemwPercentage;
|
||
Value := 8;
|
||
ZoomPosition := iemwCenter;
|
||
end;
|
||
|
||
destructor TIEMouseWheelParams.Destroy;
|
||
begin
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEMouseWheelParams.Assign(Source: TPersistent);
|
||
begin
|
||
if Source is TIEMouseWheelParams then
|
||
begin
|
||
InvertDirection := TIEMouseWheelParams( Source ).InvertDirection;
|
||
Action := TIEMouseWheelParams( Source ).Action ;
|
||
Variation := TIEMouseWheelParams( Source ).Variation ;
|
||
Value := TIEMouseWheelParams( Source ).Value ;
|
||
ZoomPosition := TIEMouseWheelParams( Source ).ZoomPosition ;
|
||
end
|
||
else
|
||
inherited;
|
||
end;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function IEIsRemoteSession(): boolean;
|
||
const
|
||
SM_REMOTESESSION = $1000;
|
||
begin
|
||
result := Windows.GetSystemMetrics( SM_REMOTESESSION ) <> 0;
|
||
end;
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Base64 support
|
||
|
||
const
|
||
encoding_table: array [0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||
|
||
procedure IEEncodeBlock64(xin: pbytearray; xout: PAnsiChar; len: integer);
|
||
begin
|
||
xout[0] := encoding_table[ xin[0] shr 2 ];
|
||
xout[1] := encoding_table[ ((xin[0] and $03) shl 4) or ((xin[1] and $f0) shr 4) ];
|
||
if len > 1 then
|
||
xout[2] := encoding_table[ ((xin[1] and $0f) shl 2) or ((xin[2] and $c0) shr 6) ]
|
||
else
|
||
xout[2] := '=';
|
||
if len > 2 then
|
||
xout[3] := encoding_table[ xin[2] and $3f ]
|
||
else
|
||
xout[3] := '=';
|
||
end;
|
||
|
||
procedure IEEncode64(SrcStream: TStream; DstStream: TStream; linesize: integer);
|
||
var
|
||
xin: array [0..2] of byte;
|
||
xout: array [0..3] of AnsiChar;
|
||
i, len, blocksout: integer;
|
||
SrcStreamSize: int64;
|
||
begin
|
||
SrcStreamSize := SrcStream.Size;
|
||
blocksout := 0;
|
||
while SrcStream.Position < SrcStreamSize do
|
||
begin
|
||
len := 0;
|
||
for i := 0 to 2 do
|
||
begin
|
||
if SrcStream.Position < SrcStreamSize then
|
||
begin
|
||
SrcStream.Read(xin[i], 1);
|
||
inc(len);
|
||
end
|
||
else
|
||
xin[i] := 0;
|
||
end;
|
||
if len > 0 then
|
||
begin
|
||
IEEncodeBlock64(@xin, xout, len);
|
||
DstStream.Write(xout[0], 4);
|
||
inc(blocksout);
|
||
end;
|
||
if (blocksout >= (linesize / 4)) or (SrcStream.Position >= SrcStreamSize) then
|
||
begin
|
||
if blocksout > 0 then
|
||
IEStreamWriteLn(DstStream, '');
|
||
blocksout := 0;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function IEEncode64(SrcBuffer: pbyte; SrcBufferLength: integer; linesize: integer): AnsiString;
|
||
var
|
||
srcStream: TIEMemStream;
|
||
dstStream: TMemoryStream;
|
||
begin
|
||
srcStream := TIEMemStream.Create(SrcBuffer, SrcBufferLength);
|
||
dstStream := TMemoryStream.Create();
|
||
try
|
||
IEEncode64(srcStream, dstStream, linesize);
|
||
SetLength(result, dstStream.size);
|
||
CopyMemory(@result[1], dstStream.Memory, dstStream.Size);
|
||
finally
|
||
dstStream.Free();
|
||
srcStream.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure IEDecode64(SrcStream: TStream; DstStream: TStream);
|
||
const
|
||
mod_table: array [0..2] of integer = (0, 2, 1);
|
||
EQCHR: byte = ord('=');
|
||
var
|
||
decoding_table: array of byte;
|
||
i: integer;
|
||
input_length: int64;
|
||
data: TIEBufferedReadStream;
|
||
sextet_a: dword;
|
||
sextet_b: dword;
|
||
sextet_c: dword;
|
||
sextet_d: dword;
|
||
triple: dword;
|
||
b: byte;
|
||
|
||
procedure NextByte();
|
||
begin
|
||
while i < input_length do
|
||
begin
|
||
data.Read(b, 1);
|
||
inc(i);
|
||
if not IEIsSpace(AnsiChar(b)) then
|
||
break;
|
||
b := 0; // in case "i = input_length" we returns always 0
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
data := TIEBufferedReadStream.Create(SrcStream, 8192);
|
||
try
|
||
input_length := data.Size;
|
||
|
||
SetLength(decoding_table, 256);
|
||
for i := 0 to 63 do
|
||
decoding_table[ord(encoding_table[i])] := i;
|
||
decoding_table[EQCHR] := 0; // '=' -> 0
|
||
|
||
i := 0;
|
||
while i < input_length do
|
||
begin
|
||
NextByte();
|
||
sextet_a := decoding_table[b];
|
||
|
||
NextByte();
|
||
sextet_b := decoding_table[b];
|
||
|
||
NextByte();
|
||
sextet_c := decoding_table[b];
|
||
|
||
NextByte();
|
||
sextet_d := decoding_table[b];
|
||
|
||
triple := (sextet_a shl 18) + (sextet_b shl 12) + (sextet_c shl 6) + sextet_d;
|
||
|
||
IEStreamWriteByte(DstStream, (triple shr 16) and $FF);
|
||
IEStreamWriteByte(DstStream, (triple shr 8) and $FF);
|
||
IEStreamWriteByte(DstStream, triple and $FF);
|
||
end;
|
||
finally
|
||
data.Free();
|
||
end;
|
||
end;
|
||
|
||
function IEDecode64(SrcString: AnsiString): TIEArrayOfByte;
|
||
var
|
||
srcStream: TIEMemStream;
|
||
dstStream: TMemoryStream;
|
||
begin
|
||
srcStream := TIEMemStream.Create(@SrcString[1], length(SrcString));
|
||
dstStream := TMemoryStream.Create();
|
||
try
|
||
IEDecode64(srcStream, dstStream);
|
||
SetLength(result, dstStream.Size);
|
||
CopyMemory(@result[0], dstStream.Memory, dstStream.Size);
|
||
finally
|
||
dstStream.Free();
|
||
srcStream.Free();
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
// Base64 support
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
const
|
||
WSB_PROP_CYVSCROLL =$00000001;
|
||
WSB_PROP_CXHSCROLL =$00000002;
|
||
WSB_PROP_CYHSCROLL =$00000004;
|
||
WSB_PROP_CXVSCROLL =$00000008;
|
||
WSB_PROP_CXHTHUMB =$00000010;
|
||
WSB_PROP_CYVTHUMB =$00000020;
|
||
WSB_PROP_VBKGCOLOR =$00000040;
|
||
WSB_PROP_HBKGCOLOR =$00000080;
|
||
WSB_PROP_VSTYLE =$00000100;
|
||
WSB_PROP_HSTYLE =$00000200;
|
||
WSB_PROP_WINSTYLE =$00000400;
|
||
WSB_PROP_PALETTE =$00000800;
|
||
WSB_PROP_MASK =$00000FFF;
|
||
|
||
FSB_FLAT_MODE = 2;
|
||
FSB_ENCARTA_MODE = 1;
|
||
FSB_REGULAR_MODE = 0;
|
||
|
||
procedure IESetScrollBar(hWnd: HWND; nBar: integer; nMinPos: integer; nMaxPos: integer; PageSize: integer; nPos: integer; bRedraw: boolean; flat: boolean = False);
|
||
var
|
||
ScrollInfo: TScrollInfo;
|
||
begin
|
||
FillChar(ScrollInfo, sizeof(ScrollInfo), 0);
|
||
ScrollInfo.cbSize := SizeOf(ScrollInfo);
|
||
ScrollInfo.fMask := SIF_RANGE or SIF_POS or SIF_PAGE;
|
||
ScrollInfo.nMin := nMinPos;
|
||
ScrollInfo.nMax := nMaxPos;
|
||
ScrollInfo.nPos := nPos;
|
||
ScrollInfo.nPage := PageSize;
|
||
IESetScrollInfo(hWnd, nBar, ScrollInfo, bRedraw, flat);
|
||
end;
|
||
|
||
|
||
// 3.0.3
|
||
function IESetScrollRange(hWnd: HWND; nBar, nMinPos, nMaxPos: Integer; bRedraw: BOOL; flat: boolean): BOOL;
|
||
var
|
||
ScrollInfo: TScrollInfo;
|
||
begin
|
||
FillChar(ScrollInfo, sizeof(ScrollInfo), 0);
|
||
ScrollInfo.cbSize := SizeOf(ScrollInfo);
|
||
ScrollInfo.fMask := SIF_RANGE;
|
||
ScrollInfo.nMin := nMinPos;
|
||
ScrollInfo.nMax := nMaxPos;
|
||
IESetScrollInfo(hWnd, nBar, ScrollInfo, bRedraw, flat);
|
||
result := true;
|
||
end;
|
||
|
||
// 3.0.3
|
||
function IESetScrollPos(hWnd: HWND; nBar, nPos: Integer; bRedraw: BOOL; flat: boolean): Integer;
|
||
var
|
||
ScrollInfo: TScrollInfo;
|
||
begin
|
||
FillChar(ScrollInfo, sizeof(ScrollInfo), 0);
|
||
ScrollInfo.cbSize := SizeOf(ScrollInfo);
|
||
ScrollInfo.fMask := SIF_POS;
|
||
ScrollInfo.nPos := nPos;
|
||
result := IESetScrollInfo(hWnd, nBar, ScrollInfo, bRedraw, flat);
|
||
end;
|
||
|
||
// Set cursor size (pagesize) of a scroll bar
|
||
// fnBar can be SB_HORZ or SB_VERT
|
||
procedure IESetSBPageSize(HScrollBar: THandle; fnBar: integer; PageSize: Integer; Redraw: boolean; flat: boolean);
|
||
var
|
||
ScrollInfo: TScrollInfo;
|
||
begin
|
||
FillChar(ScrollInfo, sizeof(ScrollInfo), 0);
|
||
ScrollInfo.cbSize := Sizeof(ScrollInfo);
|
||
ScrollInfo.fMask := SIF_PAGE;
|
||
ScrollInfo.nPage := PageSize;
|
||
IESetScrollInfo(HScrollBar, fnBar, ScrollInfo, Redraw, flat);
|
||
end;
|
||
|
||
function IESetScrollInfo(hWnd: HWND; BarFlag: Integer; const ScrollInfo: TScrollInfo; Redraw: BOOL; flat: boolean): Integer;
|
||
begin
|
||
{$ifdef IEINCLUDEFLATSB}
|
||
if flat then
|
||
result := FlatSB_SetScrollInfo(hWnd, BarFlag, ScrollInfo, Redraw)
|
||
else
|
||
result := SetScrollInfo(hWnd, BarFlag, ScrollInfo, Redraw);
|
||
{$else}
|
||
result := SetScrollInfo(hWnd, BarFlag, ScrollInfo, Redraw);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEEnableScrollBar(hWnd: HWND; wSBflags, wArrows: UINT; flat: boolean = False): BOOL;
|
||
begin
|
||
{$ifdef IEINCLUDEFLATSB}
|
||
if flat then
|
||
begin
|
||
result := FlatSB_EnableScrollBar(hWnd, wSBflags, wArrows);
|
||
end
|
||
else
|
||
result := EnableScrollBar(hWnd, wSBflags, wArrows);
|
||
{$else}
|
||
result := EnableScrollBar(hWnd, wSBflags, wArrows);
|
||
{$endif}
|
||
end;
|
||
|
||
function IEShowScrollBar(hWnd: HWND; wBar: Integer; bShow: BOOL; flat: boolean = False): BOOL;
|
||
begin
|
||
{$ifdef IEINCLUDEFLATSB}
|
||
if flat then
|
||
begin
|
||
result := FlatSB_ShowScrollBar(hWnd, wBar, bShow);
|
||
end
|
||
else
|
||
result := ShowScrollBar(hWnd, wBar, bShow);
|
||
{$else}
|
||
result := ShowScrollBar(hWnd, wBar, bShow);
|
||
{$endif}
|
||
end;
|
||
|
||
|
||
|
||
|
||
|
||
{!!
|
||
<FS>GetImageSizeWithinArea
|
||
|
||
<FM>Declaration<FC>
|
||
function GetImageSizeWithinArea(iImageWidth, iImageHeight : integer;
|
||
iAvailableWidth, iAvailableHeight : integer;
|
||
bAllowStretching : boolean = TRUE;
|
||
FitMethod: <A TFitMethod> = _fmFitWithinRect
|
||
): TPoint;
|
||
|
||
<FM>Description<FN>
|
||
Return the new size of an image we wish to fit within an area of size iAvailableWidth x iAvailableHeight while maintaining the original aspect ratio
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>iImageWidth, iImageHeight<FN></C> <C>The dimensions of the image</C> </R>
|
||
<R> <C><FC>iAvailableWidth, iAvailableHeight<FN></C> <C>The space available for the image (e.g. the client area of a display control, such as a TImageEnView)</C> </R>
|
||
<R> <C><FC>bAllowStretching<FN></C> <C>If the image is smaller than the available area it will be stretched to the full available size (otherwise result is the original width/height)</C> </R>
|
||
<R> <C><FC>FitMethod<FN></C> <C>Generally _fmFitWithinRect, but _fmFillRect_WithOverlap will return an image that makes the image as large as possible without any border area (so one dimension will match the available size, and the other will generally be larger)</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>See Also<FN>
|
||
- <A GetImageRectWithinArea>
|
||
- <A IEAdjustRectToAspectRatio>
|
||
!!}
|
||
function GetImageSizeWithinArea(iImageWidth, iImageHeight : integer; // height and width of object
|
||
iAvailableWidth, iAvailableHeight : integer; // the space available
|
||
bAllowStretching : boolean = TRUE; // if the image is smaller than the available area it will be stretched to the full available size;
|
||
FitMethod: TFitMethod = _fmFitWithinRect
|
||
): TPoint;
|
||
// NPC: 24/10/11
|
||
var
|
||
TempRect : TRect;
|
||
begin
|
||
TempRect := GetImageRectWithinArea(iImageWidth, iImageHeight,
|
||
iAvailableWidth, iAvailableHeight,
|
||
0, 0,
|
||
bAllowStretching, True,
|
||
false, False, 0,
|
||
FitMethod);
|
||
result.x := TempRect.Right;
|
||
result.y := TempRect.Bottom;
|
||
end;
|
||
|
||
|
||
// Estimate aspect ratio of rectified rectangle having four perspective quadrilater points
|
||
// tech report: "Whiteboard Scanning and Image Enhancement", Zhengyou Zhang
|
||
// x0, y0 = top-left
|
||
// x1, y1 = top-right
|
||
// x2, y2 = bottom-right
|
||
// x3, y3 = bottom-left
|
||
// cx, cy = center of image (Bitmap.Width / 2, Bitmap.Height / 2)
|
||
function IERectifiedRectangleAspectRatio(x0, y0, x1, y1, x2, y2, x3, y3, cx, cy: double): double;
|
||
var
|
||
k2, k3: double;
|
||
f2: double;
|
||
r2: double;
|
||
begin
|
||
x0 := x0 - cx;
|
||
y0 := y0 - cy;
|
||
x1 := x1 - cx;
|
||
y1 := y1 - cy;
|
||
x2 := x2 - cx;
|
||
y2 := y2 - cy;
|
||
x3 := x3 - cx;
|
||
y3 := y3 - cy;
|
||
|
||
k2 := ((y3 - y1) * x0 - (x3 - x1) * y0 + x3 * y1 - y3 * x1) / ((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1) ;
|
||
k3 := ((y3 - y1) * x2 - (x3 - x1) * y2 + x3 * y1 - y3 * x1) / ((y0 - y1) * x2 - (x0 - x1) * y2 + x0 * y1 - y0 * x1) ;
|
||
|
||
result := 0;
|
||
|
||
if (k2 <> 1) and (k3 <> 1) then
|
||
begin
|
||
f2 := -((k3 * y0 - y3) * (k2 * y2 - y3) + (k3 * x0 - x3) * (k2 * x2 - x3)) / ((k3 - 1) * (k2 - 1));
|
||
r2 := (sqr(k2 - 1) + sqr(k2 * y2 - y3) / f2 + sqr(k2 * x2 - x3) / f2) / (sqr(k3 - 1) + sqr(k3 * y0 - y3) / f2 + sqr(k3 * x0 - x3) / f2);
|
||
if r2 > 0 then
|
||
result := sqrt(r2);
|
||
end;
|
||
|
||
if result = 0 then
|
||
result := sqrt((sqr(y2 - y3) + sqr(x2 - x3)) / (sqr(y0 - y3) + sqr(x0 - x3)));
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>GetImageRectWithinArea
|
||
|
||
<FM>Declaration<FC>
|
||
function GetImageRectWithinArea(iImageWidth, iImageHeight : Integer;
|
||
iAvailableWidth, iAvailableHeight : Integer;
|
||
iHorzOffset : Integer = 0;
|
||
iVertOffset : integer = 0;
|
||
bAllowStretching : boolean = true;
|
||
bAllowShrinking : boolean = true;
|
||
bCenterHorz : boolean = true;
|
||
bCenterVert : boolean = true;
|
||
iAutoCropPercent : Integer = 0;
|
||
FitMethod: <A TFitMethod> = _fmFitWithinRect) : TRect; overload;
|
||
|
||
function GetImageRectWithinArea(iImageWidth, iImageHeight: Integer;
|
||
ADestRect : TRect;
|
||
bAllowStretching : boolean = true;
|
||
bAllowShrinking : boolean = true;
|
||
bCenterHorz : boolean = true;
|
||
bCenterVert : boolean = true;
|
||
iAutoCropPercent : Integer = 0;
|
||
FitMethod: <A TFitMethod> = _fmFitWithinRect) : TRect; overload;
|
||
|
||
<FM>Description<FN>
|
||
Return the new size and position of an image within an area assuming that we maintain the aspect ratio of the image.
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>iImageWidth/iImageHeight<FN></C> <C>The dimensions of the image</C> </R>
|
||
<R> <C><FC>iAvailableWidth/iAvailableHeight or ADestRect<FN></C> <C>The space available for the image (e.g. the client area of a display control, such as a TImageEnView)</C> </R>
|
||
<R> <C><FC>iHorzOffset/iVertOffset<FN></C> <C>Added to the left/top of the image position, e.g. to add a margin</C> </R>
|
||
<R> <C><FC>bAllowStretching<FN></C> <C>If image is smaller than iAvailableWidth/iAvailableHeight its dimensions will be enlarged</C> </R>
|
||
<R> <C><FC>bAllowShrinking<FN></C> <C>If image is larger than iAvailableWidth/iAvailableHeight its dimensions will be reduced</C> </R>
|
||
<R> <C><FC>bCenterHorz<FN></C> <C>Image is positioned in the horizontal center (Otherwise result.Left will be zero)</C> </R>
|
||
<R> <C><FC>bCenterVert<FN></C> <C>Image is positioned in the vertical center (Otherwise result.Top will be zero)</C> </R>
|
||
<R> <C><FC>iAutoCropPercent<FN></C> <C>An advanced parameter that allows the image to be positioned outside of the display area to that it appears larger (i.e. part of the image is cropped). For example, if a portrait image is shown on screen generally there are wide side borders. An autocrop value of 10% would see (up to) 5% of the image not shown at the top and bottom so the border areas are reduced</C> </R>
|
||
<R> <C><FC>FitMethod<FN></C> <C>Generally _fmFitWithinRect, but _fmFillRect_WithOverlap will return an image that makes the image as large as possible without any border area (but with part of the image offscreen). This is the same as using an iAutoCropPercent of 100</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Examples<FC>
|
||
// Stretch Draw an image centered within a TIEBitmap
|
||
aRect := GetImageRectWithinArea( SrcBMP.Width, SrcBMP.Height, DestBMP.Width, DestBMP.Height);
|
||
SrcBMP.DrawToTIEBitmap( DestBMP, IERectangle( aRect ), IERectangle( 0, 0, SrcBMP.Width, SrcBMP.Height ) );
|
||
|
||
// Col 1 of a TStringGrid displays a thumbnail drawn from a TImageEnMView
|
||
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Longint;
|
||
Rect: TRect; State: TGridDrawState);
|
||
var
|
||
aIEBitmap: IEBitmap;
|
||
aCanvas: TCanvas;
|
||
idx: Integer;
|
||
begin
|
||
// Col 1 contains thumbnail. Row 0 is fixed header row
|
||
if (ACol <> 1) or (ARow = 0) then
|
||
Exit;
|
||
|
||
idx := ARow;
|
||
aCanvas := (Sender as TStringGrid).Canvas;
|
||
|
||
// Clear current cell rect
|
||
aCanvas.FillRect( Rect );
|
||
|
||
// Get our image
|
||
// Note: don't need to create or free the TIEBitmap
|
||
aIEBitmap := ImageEnMView1.GetIEBitmap( idx );
|
||
|
||
// Adjust our rect to maintain the image aspect ratio
|
||
Rect := GetImageRectWithinArea( Rect, aIEBitmap.Width, aIEBitmap.Height );
|
||
|
||
// Draw the image
|
||
aIEBitmap := RenderToCanvas( aCanvas, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, rfFastLinear, 0 );
|
||
|
||
// Release our image
|
||
ImageEnMView1.ReleaseBitmap( idx, False );
|
||
end;
|
||
|
||
<FM>See Also<FN>
|
||
- <A GetImageSizeWithinArea>
|
||
- <A IEAdjustRectToAspectRatio>
|
||
!!}
|
||
// pass the dimensions of an image and the space available to display it
|
||
// Result will be a rectangle to with the position and size to show the image within that area (with aspect ratio maintained)
|
||
function GetImageRectWithinArea(iImageWidth, iImageHeight : Integer; // height and widht of object being put within the space
|
||
iAvailableWidth, iAvailableHeight : Integer; // the space available
|
||
iHorzOffset : Integer = 0; // Added to the left of the object
|
||
iVertOffset : integer = 0; // Added to the top of the object
|
||
bAllowStretching : boolean = true; // if the image is smaller than the available area it will be stretched to the full available size
|
||
bAllowShrinking : boolean = true; // if the image is larger than the available area it will be shrunk to the full available size
|
||
bCenterHorz : boolean = true; // center the image horizontally if it is narrower than the available area (otherwise placed on the left)
|
||
bCenterVert : boolean = true; // center the image vertically if it is shorter than the available area (otherwise placed on the Top)
|
||
iAutoCropPercent : Integer = 0; // if > 0 then that percentage of the image will be be placed OUTSIDE the available area (for cropping) to better match the aspect ratio of the available area
|
||
FitMethod: TFitMethod = _fmFitWithinRect // See TFitMethod declaration
|
||
) : TRect; overload;
|
||
var
|
||
iNewObjHeight, iNewObjWidth: integer;
|
||
bWidthIsCloserRatioMatch: Boolean;
|
||
bSizeToWidth: Boolean;
|
||
|
||
procedure SetImageNoChange; // no change to size of object
|
||
begin
|
||
iNewObjWidth := iImageWidth;
|
||
iNewObjHeight := iImageHeight;
|
||
end;
|
||
|
||
procedure SetImageToWidth; // object Width is set to max, Height is calculated
|
||
var
|
||
dResizeRatio, dMaxResizeRatio: Double;
|
||
dCroppedWidth: Double;
|
||
begin
|
||
dResizeRatio := iAvailableWidth / iImageWidth;
|
||
|
||
// if we are allowing a percentage of the image to be auto-cropped then
|
||
// calculate the maximum possible ratio we can increase by without
|
||
// without the Height exceeding the available widht
|
||
if iAutoCropPercent > 0 then
|
||
begin
|
||
dCroppedWidth := iImageWidth * (100 - iAutoCropPercent) / 100;
|
||
if iAutoCropPercent = 100 then
|
||
dMaxResizeRatio := 1000
|
||
else
|
||
dMaxResizeRatio := iAvailableWidth / dCroppedWidth;
|
||
|
||
if round(iImageHeight * dMaxResizeRatio) > iAvailableHeight then
|
||
dMaxResizeRatio := iAvailableHeight / iImageHeight;
|
||
|
||
dResizeRatio := dMaxResizeRatio;
|
||
end;
|
||
|
||
iNewObjHeight := round(iImageHeight * dResizeRatio);
|
||
iNewObjWidth := round(iImageWidth * dResizeRatio);
|
||
end;
|
||
|
||
procedure SetImageToHeight; // object height is set to max, width is calculated
|
||
var
|
||
dResizeRatio, dMaxResizeRatio: Double;
|
||
dCroppedHeight: Double;
|
||
begin
|
||
dResizeRatio := iAvailableHeight / iImageHeight;
|
||
|
||
// if we are allowing a percentage of the image to be auto-cropped then
|
||
// calculate the maximum possible ratio we can increase by without
|
||
// without the width exceeding the available widht
|
||
if iAutoCropPercent > 0 then
|
||
begin
|
||
dCroppedHeight := iImageHeight * (100 - iAutoCropPercent) / 100;
|
||
if iAutoCropPercent = 100 then
|
||
dMaxResizeRatio := 1000
|
||
else
|
||
dMaxResizeRatio := iAvailableHeight / dCroppedHeight;
|
||
|
||
if round(iImageWidth * dMaxResizeRatio) > iAvailableWidth then
|
||
dMaxResizeRatio := iAvailableWidth / iImageWidth;
|
||
|
||
dResizeRatio := dMaxResizeRatio;
|
||
end;
|
||
|
||
iNewObjWidth := round(iImageWidth * dResizeRatio);
|
||
iNewObjHeight := round(iImageHeight * dResizeRatio);
|
||
end;
|
||
|
||
begin
|
||
if ( iImageWidth = 0 ) or ( iImageHeight = 0 ) or ( iAvailableHeight = 0 ) or ( iAvailableWidth = 0 ) then
|
||
begin
|
||
result := rect(iHorzOffset, iVertOffset, 0, 0);
|
||
exit;
|
||
end;
|
||
|
||
bWidthIsCloserRatioMatch := (iImageHeight / iAvailableHeight)<(iImageWidth / iAvailableWidth);
|
||
if FitMethod = _fmFitWithinRect then
|
||
bSizeToWidth := bWidthIsCloserRatioMatch
|
||
else
|
||
bSizeToWidth := not bWidthIsCloserRatioMatch;
|
||
|
||
if bSizeToWidth then
|
||
// WIDTH IS IMPORTANT
|
||
begin
|
||
if iImageWidth > iAvailableWidth then
|
||
begin
|
||
if bAllowShrinking = False then
|
||
SetImageNoChange
|
||
else
|
||
SetImageToWidth;
|
||
end
|
||
else
|
||
begin
|
||
if bAllowStretching = False then
|
||
SetImageNoChange
|
||
else
|
||
SetImageToWidth;
|
||
end;
|
||
end
|
||
ELSE
|
||
// HEIGHT IS IMPORTANT
|
||
begin
|
||
if iImageHeight > iAvailableHeight then
|
||
begin
|
||
if bAllowShrinking=False then
|
||
SetImageNoChange
|
||
else
|
||
SetImageToHeight;
|
||
end
|
||
else
|
||
begin
|
||
if bAllowStretching = False then
|
||
SetImageNoChange
|
||
else
|
||
SetImageToHeight;
|
||
end;
|
||
end;
|
||
|
||
result.Left := iHorzOffset;
|
||
result.Top := iVertOffset;
|
||
|
||
// center image in the available area
|
||
if bCenterHorz then
|
||
result.left := (trunc((iAvailableWidth /2)-(iNewObjWidth /2)))+iHorzOffset;
|
||
if bCenterVert then
|
||
result.top := (trunc((iAvailableHeight / 2)-(iNewObjHeight / 2)))+iVertOffset;
|
||
|
||
result.right := result.left + iNewObjWidth;
|
||
result.bottom := result.top + iNewObjHeight;
|
||
end;
|
||
|
||
|
||
// pass the dimensions of an image and the Rect where it will be displayed
|
||
// Result will be a rectangle to with the position and size to show the image within that area (with aspect ratio maintained)
|
||
function GetImageRectWithinArea(iImageWidth, iImageHeight: Integer; // height and width of object being put within the space
|
||
ADestRect : TRect; // The rect that iImageWidth/iImageHeight must fit within
|
||
bAllowStretching : boolean = true; // if the image is smaller than the available area it will be stretched to the full available size
|
||
bAllowShrinking : boolean = true; // if the image is larger than the available area it will be shrunk to the full available size
|
||
bCenterHorz : boolean = true; // center the image horizontally if it is narrower than the available area (otherwise placed on the left)
|
||
bCenterVert : boolean = true; // center the image vertically if it is shorter than the available area (otherwise placed on the Top)
|
||
iAutoCropPercent : Integer = 0; // if > 0 then that percentage of the image will be be placed OUTSIDE the available area (for cropping) to better match the aspect ratio of the available area
|
||
FitMethod: TFitMethod = _fmFitWithinRect // See TFitMethod declaration
|
||
) : TRect; overload;
|
||
var
|
||
iRectWidth, iRectHeight : Integer;
|
||
begin
|
||
iRectWidth := ADestRect.Right - ADestRect.Left;
|
||
iRectHeight := ADestRect.Bottom - ADestRect.Top;
|
||
|
||
Result := GetImageRectWithinArea(iImageWidth, iImageHeight,
|
||
iRectWidth, iRectHeight,
|
||
ADestRect.Left, ADestRect.Top,
|
||
bAllowStretching,
|
||
bAllowShrinking,
|
||
bCenterHorz,
|
||
bCenterVert,
|
||
iAutoCropPercent,
|
||
FitMethod);
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>IEAdjustRectToAspectRatio
|
||
|
||
<FM>Declaration<FC>
|
||
function IEAdjustRectToAspectRatio(InRect : TRect;
|
||
iImageWidth, iImageHeight: Integer;
|
||
iDisplayWidth, iDisplayHeight : Integer;
|
||
FitMethod: <A TFitMethod> = _fmFitWithinRect ) : TRect;
|
||
|
||
<FM>Description<FN>
|
||
Adjusts the past rect so that it matches the aspect ratio of an image. For example, if InRect specifies a selected area where you want to draw an image, you can adjust the selection so that the image is not stretched (maintains its aspect ratio).
|
||
|
||
<TABLE>
|
||
<R> <H>Parameter</H> <H>Description</H> </R>
|
||
<R> <C><FC>InRect<FN></C> <C>The source rect (to be adjusted)</C> </R>
|
||
<R> <C><FC>iImageWidth, iImageHeight<FN></C> <C>The dimensions of the image (to which inRect will be adjusted)</C> </R>
|
||
<R> <C><FC>iDisplayWidth, iDisplayHeight<FN></C> <C>The maximum width/height for the rect (typically the client area of a display control, such as a TImageEnView)</C> </R>
|
||
<R> <C><FC>FitMethod<FN></C> <C>Rather than reducing the area of InRect, it is increased. The returned rect will cover the entire passed rect</C> </R>
|
||
</TABLE>
|
||
|
||
Assuming InRect does not already match the ratio of iImageWidth/iImageHeight then IEAdjustRectToAspectRatio will return a rect with either:
|
||
- Left and Right unchanged but Top increased and Bottom decreased
|
||
- Top and Bottom unchanged but Left increased and Right decreased
|
||
|
||
But if FitMethod is _fmFillRect_WithOverlap then result wil be either:
|
||
- Left and Right unchanged but Top decreased and Bottom increased
|
||
- Top and Bottom unchanged but Left decreased and Right increased
|
||
|
||
<FM>Compatibility Notes<FN>
|
||
This is the same as the AdjustRectToAspectRatio() method in versions prior to v6.0.0 but note the change of parameter order
|
||
|
||
<FM>See Also<FN>
|
||
- <A GetImageRectWithinArea>
|
||
- <A GetImageSizeWithinArea>
|
||
!!}
|
||
function IEAdjustRectToAspectRatio(InRect : TRect;
|
||
iImageWidth, iImageHeight: Integer;
|
||
iDisplayWidth, iDisplayHeight : Integer;
|
||
FitMethod: TFitMethod = _fmFitWithinRect ) : TRect;
|
||
var
|
||
bAdjustWidth: Boolean;
|
||
iNewLeft, iNewTop, iNewWidth, iNewHeight: Integer;
|
||
iObjLeft, iObjTop, iObjHeight, iObjWidth: Integer;
|
||
begin
|
||
iObjLeft := imax(0, InRect.left);
|
||
iObjTop := imax(0, InRect.Top);
|
||
iObjWidth := imin(iImageWidth, InRect.Right-InRect.Left);
|
||
iObjHeight := imin(iImageHeight, InRect.Bottom-InRect.Top);
|
||
|
||
if FitMethod = _fmFillRect_WithOverlap then
|
||
bAdjustWidth := iObjHeight / iDisplayHeight < iObjWidth / iDisplayWidth
|
||
else
|
||
bAdjustWidth := iObjHeight / iDisplayHeight > iObjWidth / iDisplayWidth;
|
||
|
||
|
||
if bAdjustWidth then
|
||
// ADJUST WIDTH
|
||
begin
|
||
iNewHeight := iObjHeight;
|
||
iNewTop := iObjTop;
|
||
iNewWidth := round(iObjHeight * iDisplayWidth / iDisplayHeight);
|
||
iNewLeft := iObjLeft-((iNewWidth-iObjWidth) div 2);
|
||
|
||
if FitMethod = _fmFillRect_WithOverlap then
|
||
begin
|
||
if iNewLeft < 0 then
|
||
iNewLeft := 0;
|
||
if iNewWidth > iImageWidth then
|
||
begin
|
||
iNewWidth := iImageWidth;
|
||
iNewHeight := round(iNewWidth * iDisplayHeight / iDisplayWidth);
|
||
iNewTop := iObjTop - ((iNewHeight - iObjHeight) div 2);
|
||
end;
|
||
end;
|
||
end
|
||
ELSE
|
||
// ADJUST HEIGHT
|
||
begin
|
||
iNewWidth := iObjWidth;
|
||
iNewLeft := iObjLeft;
|
||
iNewHeight := round(iObjWidth * iDisplayHeight / iDisplayWidth);
|
||
iNewTop := iObjTop - ((iNewHeight - iObjHeight) div 2);
|
||
|
||
if FitMethod = _fmFillRect_WithOverlap then
|
||
begin
|
||
if iNewTop < 0 then
|
||
iNewTop := 0;
|
||
if iNewHeight>iImageHeight then
|
||
begin
|
||
iNewHeight := iImageHeight;
|
||
iNewWidth := round(iNewHeight * iDisplayWidth / iDisplayHeight);
|
||
iNewLeft := iObjLeft-((iNewWidth-iObjWidth) div 2);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
if FitMethod = _fmFillRect_WithOverlap then
|
||
begin
|
||
if iNewLeft + iNewWidth > iImageWidth then
|
||
iNewLeft := iImageWidth - iNewWidth;
|
||
if iNewTop + iNewHeight > iImageHeight then
|
||
iNewTop := iNewHeight - iImageHeight;
|
||
end;
|
||
|
||
result := rect(iNewLeft, iNewTop, iNewLeft + iNewWidth, iNewTop + iNewHeight);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>AngleToImageEnRotateAngle
|
||
|
||
<FM>Declaration<FC>
|
||
function AngleToImageEnRotateAngle(Angle: Double): Double;
|
||
|
||
<FM>Description<FN>
|
||
ImageEn's <L TImageEnProc.Rotate>rotation parameter</L> requires a value specified negative or positive degrees counter-clockwise. This method converts a standard positive clockwise value to an ImageEn value.
|
||
|
||
See also: <A ImageEnRotateAngleToAngle>
|
||
|
||
<FM>Example<FC>
|
||
// Rotate image 90 deg. clockwise
|
||
ImageEnView1.Proc.Rotate( AngleToImageEnRotateAngle( 90 ) );
|
||
!!}
|
||
function AngleToImageEnRotateAngle(Angle: Double): Double;
|
||
begin
|
||
result := abs( 360 - Angle );
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>ImageEnRotateAngleToAngle
|
||
|
||
<FM>Declaration<FC>
|
||
function AngleToImageEnRotateAngle(Angle: Double): Double;
|
||
|
||
<FM>Description<FN>
|
||
ImageEn's <L TImageEnProc.Rotate>rotation parameter</L> requires a value specified negative or positive degrees counter-clockwise. This method converts an ImageEn rotation value to a value between -180 and +180.
|
||
|
||
See also: <A AngleToImageEnRotateAngle>
|
||
|
||
<FM>Example<FC>
|
||
ImageEnView1.Proc.Rotate( 90 );
|
||
ShowMessage( Format( 'Rotated by %d degrees', [ ImageEnRotateAngleToAngle( 90 )]);
|
||
!!}
|
||
function ImageEnRotateAngleToAngle(Angle: Double): Double;
|
||
begin
|
||
result := -1 * Angle;
|
||
if Result > 180 then
|
||
Result := Result - 360
|
||
else
|
||
if Result <= 180 then
|
||
Result := Result + 360;
|
||
end;
|
||
|
||
|
||
|
||
function IEBilinear(needX, needY: Double; centerValue, rightValue, bottomValue, BottomRightValue: integer): integer;
|
||
var
|
||
m0, m1: Double;
|
||
begin
|
||
needX := needX - trunc(needX);
|
||
needY := needY - trunc(needY);
|
||
if (needX < 0) then
|
||
needX := needX + 1.0;
|
||
if (needY < 0) then
|
||
needY := needY + 1.0;
|
||
m0 := (1.0 - needX) * centerValue + needX * rightValue;
|
||
m1 := (1.0 - needX) * bottomValue + needX * BottomRightValue;
|
||
result := trunc((1.0 - needY) * m0 + needY * m1);
|
||
end;
|
||
|
||
|
||
// Adjust the size of ItemHeight for ComboBox Items to cope with windows font scaling
|
||
// Can call for any combo box, but only needed for csOwnerDrawFixed
|
||
procedure IEInitializeComboBox(AComboBox : TComboBox);
|
||
var
|
||
TM : Windows.TTextMetric;
|
||
iSize: Integer;
|
||
begin
|
||
if AComboBox.Style = csOwnerDrawFixed then
|
||
try
|
||
GetTextMetrics(AComboBox.Canvas.Handle, TM);
|
||
iSize := GetSystemMetrics(SM_CYBORDER) * 2 + TM.tmHeight;
|
||
if iSize > AComboBox.ItemHeight then
|
||
AComboBox.ItemHeight := iSize;
|
||
except
|
||
// UNEXPECTED FAILURE
|
||
end;
|
||
end;
|
||
|
||
|
||
{
|
||
Typical Usage:
|
||
|
||
procedure TfrmMain.cmbSourcesDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
|
||
begin
|
||
IEDrawComboListBoxItem( TCombobox(Control).Canvas, Rect, Control.Enabled, TCombobox(Control).Items[ Index ], ImageList1, Drive_Glyph_Index );
|
||
end;
|
||
|
||
Code that was
|
||
IEDrawComboListBoxItem( TCombobox(Control), Rect, TCombobox(Control).Items[ Index ], ImageList1, Drive_Glyph_Index );
|
||
|
||
Should change to:
|
||
IEDrawComboListBoxItem( TCombobox(Control).Canvas, Rect, Control.Enabled, TCombobox(Control).Items[ Index ], ImageList1, Drive_Glyph_Index );
|
||
}
|
||
procedure IEDrawComboListBoxItem(ControlCanvas : TCanvas;
|
||
CanvasRect : trect;
|
||
ControlEnabled: Boolean;
|
||
const Text : string;
|
||
AnImageList : TImageList = nil;
|
||
iGlyph : Short = -1);
|
||
const
|
||
DRAW_GLYPH_LEFT = 2;
|
||
DRAW_GLYPH_TEXT_MARGIN = 3;
|
||
DRAW_TEXT_LEFT_NO_GLYPH = 4;
|
||
var
|
||
AColor: TColor;
|
||
textX : Integer;
|
||
textY : Integer;
|
||
glyphX : Integer;
|
||
glyphY : Integer;
|
||
begin
|
||
ControlCanvas.FillRect(CanvasRect);
|
||
if ControlEnabled = False then
|
||
ControlCanvas.font.color := clGrayText;
|
||
|
||
if assigned(AnImageList) and (iGlyph >= 0) then
|
||
begin
|
||
glyphX := DRAW_GLYPH_LEFT;
|
||
glyphY := ((CanvasRect.Bottom - CanvasRect.Top) - AnImageList.Height) div 2;
|
||
textX := DRAW_GLYPH_LEFT + AnImageList.Width + DRAW_GLYPH_TEXT_MARGIN;
|
||
textY := ((CanvasRect.Bottom - CanvasRect.Top) - ControlCanvas.TextHeight(Text)) div 2;
|
||
|
||
ControlCanvas.TextOut(CanvasRect.left + textX, CanvasRect.top + textY, Text);
|
||
|
||
AColor := ControlCanvas.Brush.Color;
|
||
AnImageList.Draw(ControlCanvas, CanvasRect.Left + glyphX, CanvasRect.Top + glyphY, iGlyph, ControlEnabled );
|
||
ControlCanvas.Brush.Color := AColor;
|
||
end
|
||
else
|
||
begin
|
||
textX := DRAW_TEXT_LEFT_NO_GLYPH;
|
||
textY := ((CanvasRect.Bottom - CanvasRect.Top) - ControlCanvas.TextHeight(Text)) div 2;
|
||
|
||
ControlCanvas.TextOut(CanvasRect.left + textX, CanvasRect.top + textY, Text);
|
||
end;
|
||
end;
|
||
|
||
|
||
// Useful to get a suitable next zoom step when clicking a "Zoom In" or "Zoom Out" button
|
||
// bZoomIn: true if a "Zoom In" button was pressed or false for "Zoom Out"
|
||
// iIdealZoom: Optionally specify the zoom level required to fit to window (i.e. ieImage.GetIdealZoom) and it will be offered as a zoom step
|
||
// E.g. ieImage.Zoom := GetNextZoomValue(ieImage.Zoom, Sender = btnZoomIn, ieImage.GetIdealZoom);
|
||
function GetNextZoomValue(iCurrentZoom: double;
|
||
bZoomIn: boolean;
|
||
iIdealZoom: double = 0) : double;
|
||
var
|
||
iZoomInc: integer;
|
||
begin
|
||
result := iCurrentZoom;
|
||
|
||
if bZoomIn then
|
||
begin
|
||
iZoomInc := 25;
|
||
result := result + 1;
|
||
end
|
||
else
|
||
begin
|
||
if result < 6 then
|
||
begin
|
||
Result := 1;
|
||
exit
|
||
end
|
||
else
|
||
begin
|
||
iZoomInc := 0;
|
||
result := result - 1;
|
||
end;
|
||
end;
|
||
|
||
if result < 26 then
|
||
result := ((trunc(result) div 5) * 5) + (iZoomInc div 5)
|
||
else
|
||
if result < 300 then
|
||
result := ((trunc(result) div 25) * 25) + iZoomInc
|
||
else
|
||
result := ((trunc(result) div 100) * 100) + (iZoomInc * 4);
|
||
|
||
if (iIdealZoom > 0) and
|
||
(iIdealZoom <> iCurrentZoom) and
|
||
(trunc(iIdealZoom) <> trunc(iCurrentZoom)) and
|
||
(iIdealZoom > Min(trunc(result), trunc(iCurrentZoom))) and
|
||
(iIdealZoom < Max(trunc(result), trunc(iCurrentZoom))) then
|
||
result := iIdealZoom; // snap to fit
|
||
end;
|
||
|
||
|
||
(*
|
||
CCIR Recommendation 601-1 (lumaRed=0.299, lumaGreen=0.587, lumaBlue=0.114)
|
||
|
||
R = Y + 1.40200 * Cr
|
||
G = Y - 0.34414 * Cb - 0.71414 * Cr
|
||
B = Y + 1.77200 * Cb
|
||
|
||
Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
|
||
Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + 128
|
||
Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + 128
|
||
*)
|
||
procedure IERGB2YCbCr(rgb: TRGB; var Y, Cb, Cr: integer);
|
||
begin
|
||
with rgb do
|
||
begin
|
||
Y := blimit(trunc(0.29900 * R + 0.58700 * G + 0.11400 * B));
|
||
Cb := blimit(trunc(-0.16874 * R - 0.33126 * G + 0.50000 * B + 128));
|
||
Cr := blimit(trunc(0.50000 * R - 0.41869 * G - 0.08131 * B + 128));
|
||
end;
|
||
end;
|
||
|
||
procedure IEYCbCr2RGB(var rgb: TRGB; Y, Cb, Cr: integer);
|
||
begin
|
||
Cb := Cb-128;
|
||
Cr := Cr-128;
|
||
rgb.r := blimit(trunc(Y + 1.40200 * Cr));
|
||
rgb.g := blimit(trunc(Y - 0.34414 * Cb - 0.71414 * Cr));
|
||
rgb.b := blimit(trunc(Y + 1.77200 * Cb));
|
||
end;
|
||
|
||
function IESystemAlloc(ASize: int64): pointer;
|
||
begin
|
||
result := pointer(GlobalAlloc(GPTR, ASize));
|
||
end;
|
||
|
||
// Frees memory
|
||
procedure IESystemFree(var P);
|
||
begin
|
||
GlobalFree(THandle(pointer(P)));
|
||
pointer(P) := nil;
|
||
end;
|
||
|
||
const IEMINSYSALLOC = 1048576;
|
||
|
||
function IEAutoAlloc(ASize: int64): pointer;
|
||
begin
|
||
if ASize >= IEMINSYSALLOC then
|
||
begin
|
||
result := IESystemAlloc(ASize + 4);
|
||
if result = nil then
|
||
exit; // FAIL
|
||
pboolean(result)^ := true;
|
||
end
|
||
else
|
||
begin
|
||
try
|
||
GetMem(result, ASize + 4);
|
||
pboolean(result)^ := false;
|
||
except
|
||
result := IESystemAlloc(ASize + 4);
|
||
if result = nil then
|
||
exit; // FAIL
|
||
pboolean(result)^ := true;
|
||
end;
|
||
end;
|
||
inc(pboolean(result));
|
||
end;
|
||
|
||
procedure IEAutoFree(var P);
|
||
begin
|
||
dec(pboolean(P));
|
||
if pboolean(P)^ then
|
||
IESystemFree(P)
|
||
else
|
||
FreeMem(pointer(P));
|
||
end;
|
||
|
||
procedure IESilentGetMem(var P; Size: Integer);
|
||
begin
|
||
try
|
||
GetMem(pointer(P), Size);
|
||
except
|
||
pointer(P) := nil;
|
||
end;
|
||
end;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
// check if mmx available
|
||
function IEMMXSupported: bytebool;
|
||
begin
|
||
result := false;
|
||
{$ifdef IEUSEASM}
|
||
asm
|
||
push ebx
|
||
// check if the cpuid instruction is available
|
||
pushfd
|
||
pushfd
|
||
pop eax
|
||
mov ecx, eax
|
||
xor eax, 200000h
|
||
push eax
|
||
popfd
|
||
pushfd
|
||
pop eax
|
||
popfd
|
||
xor eax, ecx
|
||
jz @nocpuid
|
||
// cpuid supported, check MMX
|
||
mov eax, 1
|
||
Dw $A20F // CPUID
|
||
test edx, 800000h
|
||
setnz result
|
||
@nocpuid:
|
||
pop ebx
|
||
end;
|
||
{$endif}
|
||
end;
|
||
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Extra backgrounds
|
||
|
||
(*
|
||
f(x)=(1/(sqrt(2*pi)*var))*e^((-1/2*(var^2))*(x-mean)^2)
|
||
mean: center of highest value. 0=centered on zero
|
||
var: width of the curve. 0.1=maximum width, 1=minimum, ref=0.2
|
||
*)
|
||
procedure IECreateGaussCurve(variance: double; curveCount: integer; curveMin, curveMax: integer; var curve: array of double);
|
||
const
|
||
mean=0;
|
||
var
|
||
i: integer;
|
||
x: double;
|
||
mx: double;
|
||
begin
|
||
mx := -100000;
|
||
for i := 0 to curveCount-1 do
|
||
begin
|
||
x := (i/curveCount)*2-1;
|
||
curve[i] := (1/(sqrt(2*pi)*variance))*exp((-1/2*(Power(variance, 2)))*Power(x-mean, 2));
|
||
if curve[i]>mx then
|
||
mx := curve[i];
|
||
end;
|
||
for i := 0 to curveCount-1 do
|
||
curve[i] := curveMin+ curve[i]/mx*(curveMax-curveMin);
|
||
end;
|
||
|
||
procedure IECreateOSXBackgroundPaper(bmp: TBitmap; width, height: integer);
|
||
var
|
||
px: PRGB;
|
||
col: TRGB;
|
||
x, y: integer;
|
||
c: integer;
|
||
gauss: array [0..3] of double;
|
||
begin
|
||
bmp.Width := width;
|
||
bmp.Height := height;
|
||
bmp.PixelFormat := pf24bit;
|
||
IECreateGaussCurve(0.5, 4, 130, 255, gauss);
|
||
c := 0;
|
||
for y := 0 to bmp.Height-1 do
|
||
begin
|
||
px := bmp.Scanline[y];
|
||
col.r := trunc(gauss[c]);
|
||
col.g := col.r;
|
||
col.b := col.r;
|
||
for x := 0 to bmp.Width-1 do
|
||
begin
|
||
px^ := col;
|
||
inc(px);
|
||
end;
|
||
inc(c);
|
||
if c=4 then
|
||
c := 0;
|
||
end;
|
||
end;
|
||
|
||
procedure IECreateOSXBackgroundMetal(bmp: TBitmap; width, height: integer);
|
||
var
|
||
px: PRGB;
|
||
x, y: integer;
|
||
c, a: integer;
|
||
gauss: pdoublearray;
|
||
bmpWidth, bmpHeight: integer;
|
||
begin
|
||
bmp.Width := width;
|
||
bmp.Height := height;
|
||
bmp.PixelFormat := pf24bit;
|
||
bmpWidth := bmp.Width;
|
||
bmpHeight := bmp.Height;
|
||
getmem(gauss, bmpWidth*sizeof(double));
|
||
IECreateGaussCurve(3, bmpWidth, 160, 208, gauss^);
|
||
a := 0;
|
||
for y := 0 to bmpHeight-1 do
|
||
begin
|
||
c := 0;
|
||
px := bmp.Scanline[y];
|
||
for x := 0 to bmpWidth-1 do
|
||
begin
|
||
px^.r := trunc(gauss[x])+a;
|
||
px^.g := px^.r;
|
||
px^.b := px^.r;
|
||
inc(px);
|
||
inc(c);
|
||
if c>(100+random(bmpWidth)) then
|
||
begin
|
||
c := 0;
|
||
a := random(11);
|
||
end;
|
||
end;
|
||
end;
|
||
freemem(gauss);
|
||
end;
|
||
|
||
// Extra backgrounds
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Clipboard helper functions
|
||
|
||
// you must call OpenClipboard before call this function
|
||
function IEEnumClipboardNames: TStringList;
|
||
const
|
||
MX=512;
|
||
var
|
||
cf: cardinal;
|
||
pc: PChar;
|
||
len: integer;
|
||
begin
|
||
getmem(pc, (MX+1)*sizeof(Char));
|
||
result := TStringList.Create;
|
||
cf := 0;
|
||
while true do
|
||
begin
|
||
cf := EnumClipboardFormats(cf);
|
||
if cf=0 then
|
||
break;
|
||
len := GetClipboardFormatName(cf, pc, MX);
|
||
if len > 0 then
|
||
result.AddObject( copy(pc, 1, len), pointer(cf) );
|
||
end;
|
||
freemem(pc);
|
||
end;
|
||
|
||
// you must call OpenClipboard before call this function
|
||
function IEGetClipboardDataByName(const name: string): THandle;
|
||
var
|
||
l: TStringList;
|
||
i: integer;
|
||
begin
|
||
result := 0;
|
||
l := IEEnumClipboardNames;
|
||
i := l.IndexOf(name);
|
||
if i>-1 then
|
||
result := cardinal(l.Objects[i]);
|
||
l.free;
|
||
end;
|
||
|
||
// Clipboard helper functions
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// Sometimes OpenClipboard fails. In particular when big images are just copied in and a paste is done immediately.
|
||
function IEOpenClipboard: boolean;
|
||
var
|
||
i: integer;
|
||
begin
|
||
for i := 1 to 10 do
|
||
begin
|
||
if OpenClipboard(0) then
|
||
begin
|
||
result := true;
|
||
exit;
|
||
end;
|
||
sleep(20); // up to 200 ms (20*10)
|
||
end;
|
||
result := false;
|
||
end;
|
||
|
||
{!!
|
||
<FS>IEAlphaToOpacity
|
||
|
||
<FM>Declaration<FC>
|
||
function IEAlphaToOpacity(Alpha: integer ): integer;
|
||
|
||
<FM>Description<FN>
|
||
COnverts an alpha value (in range of 0 - 255) to an opacity percentage (0 - 100).
|
||
Opacity is generally referred to as percent. (e.g. Alpha of 255 would return Opacity of 100% )
|
||
|
||
See also: <A IEOpacityToAlpha>
|
||
!!}
|
||
function IEAlphaToOpacity(Alpha: integer ): integer;
|
||
begin
|
||
result := Round( Alpha / 255 * 100 );
|
||
end;
|
||
|
||
{!!
|
||
<FS>IEOpacityToAlpha
|
||
|
||
<FM>Declaration<FC>
|
||
function IEOpacityToAlpha(Opacity: integer): integer;
|
||
|
||
<FM>Description<FN>
|
||
COnverts a opacity percentage (0 - 100) to an alpha value (in range of 0 - 255). For example Opacity of 100% would return Alpha of 255.
|
||
|
||
See also: <A IEAlphaToOpacity>
|
||
!!}
|
||
function IEOpacityToAlpha(Opacity: integer): integer;
|
||
begin
|
||
result := ( Opacity * 255 ) div 100;
|
||
end;
|
||
|
||
|
||
// calculates coordinates of intersection of two perpendicular lines
|
||
// First line is specified by slope and one point
|
||
// Second line is specified by a single point
|
||
function IECalcOrthogonalLinesIntersectingPoint(FirstLinePoint: TIE2DPoint; FirstLineSlope: double; SecondLinePoint: TIE2DPoint): TIE2DPoint;
|
||
var
|
||
A, B, C: double;
|
||
z: double;
|
||
begin
|
||
// equation of first line
|
||
A := -FirstLineSlope;
|
||
B := 1;
|
||
C := -FirstLinePoint.Y + FirstLineSlope * FirstLinePoint.X;
|
||
|
||
// dropping a perpendicular and find intersection point
|
||
z := (A * SecondLinePoint.X + B * SecondLInePoint.Y + C) / (sqr(A) + sqr(B));
|
||
result := IE2DPoint(SecondLinePoint.X - A * z, SecondLinePoint.Y - B * z);
|
||
end;
|
||
|
||
|
||
function IECalcPolygonCentroid(polygon: array of TIE2DPoint): TIE2DPoint;
|
||
var
|
||
i, j: integer;
|
||
ai, atmp, xtmp, ytmp: double;
|
||
xi, yi, xj, yj: double;
|
||
begin
|
||
result.X := 0;
|
||
result.Y := 0;
|
||
atmp := 0;
|
||
xtmp := 0;
|
||
ytmp := 0;
|
||
i := length(polygon) - 1;
|
||
j := 0;
|
||
while j < length(polygon) do
|
||
begin
|
||
xi := polygon[i].x;
|
||
yi := polygon[i].y;
|
||
xj := polygon[j].x;
|
||
yj := polygon[j].y;
|
||
ai := xi * yj - xj * yi;
|
||
atmp := atmp + ai;
|
||
xtmp := xtmp + (xj + xi) * ai;
|
||
ytmp := ytmp + (yj + yi) * ai;
|
||
i := j;
|
||
inc(j);
|
||
end;
|
||
if (atmp <> 0) then
|
||
begin
|
||
result.x := xtmp / (3 * atmp);
|
||
result.y := ytmp / (3 * atmp);
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure IERotatePoints(var rpt: array of TPoint; PointCount: Integer; angle: double; CenterX, CenterY: integer);
|
||
var
|
||
aa: double;
|
||
i, x, y: integer;
|
||
begin
|
||
aa := -angle * pi / 180;
|
||
for i := 0 to PointCount - 1 do
|
||
begin
|
||
x := rpt[i].X;
|
||
y := rpt[i].Y;
|
||
rpt[i].X := CenterX + trunc( (x-CenterX)*cos(aa) - (y-CenterY)*sin(aa) );
|
||
rpt[i].Y := CenterY + trunc( (x-CenterX)*sin(aa) + (y-CenterY)*cos(aa) );
|
||
end;
|
||
end;
|
||
|
||
procedure IEDRotatePointsWithCenter(var rpt: array of TIE2DPoint; angle: double; CenterX, CenterY: double);
|
||
var
|
||
i: integer;
|
||
aa: double;
|
||
x, y: double;
|
||
begin
|
||
aa := -angle * pi / 180;
|
||
for i := 0 to High(rpt) do
|
||
begin
|
||
x := rpt[i].X;
|
||
y := rpt[i].Y;
|
||
rpt[i].X := CenterX + (x - CenterX) * cos(aa) - (y - CenterY) * sin(aa);
|
||
rpt[i].Y := CenterY + (x - CenterX) * sin(aa) + (y - CenterY) * cos(aa);
|
||
end;
|
||
end;
|
||
|
||
procedure IEDRotatePoints(var rpt: array of TIE2DPoint; angle: double);
|
||
var
|
||
center: TIE2DPoint;
|
||
begin
|
||
center := IECalcPolygonCentroid(rpt);
|
||
IEDRotatePointsWithCenter(rpt, angle, Center.X, Center.Y);
|
||
end;
|
||
|
||
procedure IEDRotateTwoPoints(Angle: double; const P1: TIE2DPoint; const P2: TIE2DPoint; out OutP1: TIE2DPoint; out OutP2: TIE2DPoint);
|
||
var
|
||
radAngle: double;
|
||
centerX, centerY: double;
|
||
begin
|
||
radAngle := -Angle * PI / 180;
|
||
centerX := (P1.X + P2.X) / 2.0;
|
||
centerY := (P1.Y + P2.Y) / 2.0;
|
||
OutP1.X := centerX + (P1.X - centerX) * cos(radAngle) - (P1.Y - centerY) * sin(radAngle);
|
||
OutP1.Y := centerY + (P1.X - centerX) * sin(radAngle) + (P1.Y - centerY) * cos(radAngle);
|
||
OutP2.X := centerX + (P2.X - centerX) * cos(radAngle) - (P2.Y - centerY) * sin(radAngle);
|
||
OutP2.Y := centerY + (P2.X - centerX) * sin(radAngle) + (P2.Y - centerY) * cos(radAngle);
|
||
end;
|
||
|
||
procedure IERotatePoint(var px, py: integer; angle: double; CenterX, CenterY: integer);
|
||
var
|
||
aa: double;
|
||
x, y: integer;
|
||
begin
|
||
aa := -angle * pi / 180;
|
||
x := px;
|
||
y := py;
|
||
px := CenterX + trunc( (x-CenterX)*cos(aa) - (y-CenterY)*sin(aa) );
|
||
py := CenterY + trunc( (x-CenterX)*sin(aa) + (y-CenterY)*cos(aa) );
|
||
end;
|
||
|
||
procedure IEDRotatePoint(var px, py: double; angle: double; CenterX, CenterY: double);
|
||
var
|
||
aa: double;
|
||
x, y: double;
|
||
begin
|
||
aa := -angle * pi / 180;
|
||
x := px;
|
||
y := py;
|
||
px := CenterX + (x - CenterX) * cos(aa) - (y - CenterY) * sin(aa);
|
||
py := CenterY + (x - CenterX) * sin(aa) + (y - CenterY) * cos(aa);
|
||
end;
|
||
|
||
function IECalcRotatedRectBoundingBox(Rectangle: TIEDRectangle; RotationCenter: TIE2DPoint; RotationAngle: double): TIEDRectangle;
|
||
var
|
||
rotRect: array [0..4] of TIE2DPoint;
|
||
i: integer;
|
||
begin
|
||
rotRect[0] := IE2DPoint(Rectangle[0].X, Rectangle[0].Y);
|
||
rotRect[1] := IE2DPoint(Rectangle[1].X, Rectangle[0].Y);
|
||
rotRect[2] := IE2DPoint(Rectangle[1].X, Rectangle[1].Y);
|
||
rotRect[3] := IE2DPoint(Rectangle[0].X, Rectangle[1].Y);
|
||
for i := 0 to 3 do
|
||
IEDRotatePoint(rotRect[i].X, rotRect[i].Y, RotationAngle, RotationCenter.X, RotationCenter.Y);
|
||
result[0] := rotRect[0];
|
||
result[1] := rotRect[0];
|
||
for i := 1 to 3 do
|
||
begin
|
||
result[0].X := dmin(result[0].X, rotRect[i].X);
|
||
result[0].Y := dmin(result[0].Y, rotRect[i].Y);
|
||
result[1].X := dmax(result[1].X, rotRect[i].X);
|
||
result[1].Y := dmax(result[1].Y, rotRect[i].Y);
|
||
end;
|
||
end;
|
||
|
||
procedure IECalcRotatedBitmapSizes(Width, Height: integer; RotationCenter: TIE2DPoint; RotationAngle: double; out NewWidth: integer; out NewHeight: integer);
|
||
var
|
||
rc: TIEDRectangle;
|
||
bbox: TIEDRectangle;
|
||
begin
|
||
rc[0].X := 0;
|
||
rc[0].Y := 0;
|
||
rc[1].X := Width - 1;
|
||
rc[1].Y := Height - 1;
|
||
bbox := IECalcRotatedRectBoundingBox(rc, RotationCenter, RotationAngle);
|
||
NewWidth := round(bbox[1].X - bbox[0].X + 1);
|
||
NewHeight := round(bbox[1].Y - bbox[0].Y + 1);
|
||
end;
|
||
|
||
// RotationAngle in degrees
|
||
// Background can be 0 or 1
|
||
procedure IERotateBits(Bits: TIEArrayOfByte; Width, Height: integer; RowAlignment: integer; RotationCenter: TIE2DPoint; RotationAngle: double; Background: integer; MaintainOriginalSize: boolean; out outBits: TIEArrayOfByte; out outWidth: integer; out outHeight: integer);
|
||
var
|
||
i, j: integer;
|
||
radAngle: double;
|
||
rowlen, outRowlen: integer;
|
||
deltaX, deltaY: double;
|
||
rotX, rotY: integer;
|
||
dstRow, srcRow: pbyte;
|
||
newWidth, newHeight: integer;
|
||
offX, offY: integer;
|
||
row, col: integer;
|
||
begin
|
||
if RotationAngle = 0.0 then
|
||
begin
|
||
// no rotation
|
||
outWidth := Width;
|
||
outHeight := Height;
|
||
SetLength(outBits, length(Bits));
|
||
for i := 0 to high(Bits) do
|
||
outBits[i] := Bits[i];
|
||
exit;
|
||
end;
|
||
|
||
radAngle := RotationAngle * PI / 180.0;
|
||
|
||
IECalcRotatedBitmapSizes(Width, Height, RotationCenter, RotationAngle, newWidth, newHeight);
|
||
|
||
if MaintainOriginalSize then
|
||
begin
|
||
outWidth := Width;
|
||
outHeight := Height;
|
||
offX := (outWidth - Width) div 2;
|
||
offY := (outHeight - Height) div 2;
|
||
end
|
||
else
|
||
begin
|
||
outWidth := newWidth;
|
||
outHeight := newHeight;
|
||
offX := 0;
|
||
offY := 0;
|
||
end;
|
||
|
||
rowlen := IEBitmapRowLen(Width, 1, RowAlignment);
|
||
outRowlen := IEBitmapRowLen(outWidth, 1, RowAlignment);
|
||
|
||
SetLength(outBits, outRowlen * outHeight);
|
||
|
||
dstRow := @outBits[0];
|
||
for i := 0 to outHeight - 1 do
|
||
begin
|
||
for j := 0 to outWidth - 1 do
|
||
begin
|
||
col := offX + j;
|
||
row := offY + i;
|
||
deltaY := col - RotationCenter.X;
|
||
deltaX := row - RotationCenter.Y;
|
||
rotX := round(RotationCenter.X + deltaX * sin(radAngle) + deltaY * cos(radAngle));
|
||
rotY := round(RotationCenter.Y + deltaX * cos(radAngle) - deltaY * sin(radAngle));
|
||
if (rotX >= 0) and (rotX < Width) and (rotY >= 0) and (rotY < Height) then
|
||
begin
|
||
srcRow := @Bits[0];
|
||
inc(srcRow, rowlen * rotY);
|
||
_SetPixelbw(dstRow, col, _GetPixelbw(srcRow, rotX));
|
||
end
|
||
else
|
||
begin
|
||
_SetPixelbw(dstRow, col, Background);
|
||
end;
|
||
end;
|
||
inc(dstRow, outRowlen);
|
||
end;
|
||
|
||
end;
|
||
|
||
// RotationAngle in degrees around cursor hotspot
|
||
// No need to call DestroyCursor when assigned to Screen.Cursors[]
|
||
function IECreateRotatedCursor(CursorIntResource: integer; RotationAngle: double): HCURSOR;
|
||
var
|
||
hresInfo: HRSRC;
|
||
hres: THandle;
|
||
buf: pbyte;
|
||
bufLen: integer;
|
||
ms: TIEMemStream;
|
||
hotSpotX, hotSpotY: word;
|
||
rotationCenter: TIE2DPoint;
|
||
infoHead: TBITMAPINFOHEADER;
|
||
width, height: integer;
|
||
colorMap: array of TRGBQUAD;
|
||
plane: TIEArrayOfByte;
|
||
XORplane: TIEArrayOfByte;
|
||
ANDplane: TIEArrayOfByte;
|
||
rowlen: integer;
|
||
newWidth, newHeight: integer;
|
||
begin
|
||
result := 0;
|
||
|
||
hresInfo := FindResource(HInstance, MakeIntResource(CursorIntResource), RT_CURSOR);
|
||
hres := LoadResource(HInstance, hresInfo);
|
||
bufLen := SizeOfResource(HInstance, hresInfo);
|
||
buf := LockResource(hres);
|
||
|
||
if (buf <> nil) and (buflen > 0) then
|
||
begin
|
||
ms := TIEMemStream.Create(buf, bufLen);
|
||
|
||
// hot spot
|
||
ms.Read(hotSpotX, sizeof(word));
|
||
ms.Read(hotSpotY, sizeof(word));
|
||
|
||
// rotate around hotsport
|
||
rotationCenter.X := hotSpotX;
|
||
rotationCenter.Y := hotSpotY;
|
||
|
||
// Bitmap info header
|
||
FillChar(InfoHead, sizeof(InfoHead), 0);
|
||
ms.Read(infoHead, sizeof(TBITMAPINFOHEADER));
|
||
|
||
// here only black/white cursor are supported
|
||
if infoHead.biBitCount = 1 then
|
||
begin
|
||
// color map
|
||
SetLength(colorMap, 2);
|
||
ms.Read(colorMap[0], sizeof(TRGBQUAD) * length(colorMap));
|
||
|
||
width := infoHead.biWidth;
|
||
height := infoHead.biHeight div 2;
|
||
|
||
// allocate buffer to contain source XOR and AND planes
|
||
rowlen := IEBitmapRowLen(width, 1, 32);
|
||
SetLength(plane, rowlen * height);
|
||
|
||
// load and rotate XOR plane
|
||
ms.Read(plane[0], length(plane));
|
||
IERotateBits(plane, width, height, 32, rotationCenter, RotationAngle, 0, true, XORplane, newWidth, newHeight);
|
||
|
||
// load and rotate AND plane
|
||
ms.Read(plane[0], length(plane));
|
||
IERotateBits(plane, width, height, 32, rotationCenter, RotationAngle, 1, true, ANDplane, newWidth, newHeight);
|
||
|
||
// creates the new cursor
|
||
result := CreateCursor(HInstance, hotSpotX, hotSpotY, newWidth, newHeight, @ANDplane[0], @XORplane[0]);
|
||
end;
|
||
|
||
ms.Free();
|
||
end;
|
||
|
||
UnlockResource(hres);
|
||
FreeResource(hres);
|
||
end;
|
||
|
||
// Return the max and min x and y in a point array
|
||
procedure IEGetPointsRange(rpt: array of TPoint; PointCount: Integer; out MinX: Integer; out MinY: Integer; out MaxX: Integer; out MaxY: Integer);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
MinX := 0;
|
||
MaxX := 0;
|
||
MinY := 0;
|
||
MaxY := 0;
|
||
|
||
if PointCount < 1 then
|
||
exit;
|
||
|
||
MinX := MaxInt;
|
||
MaxX := - MaxInt;
|
||
MinY := MaxInt;
|
||
MaxY := - MaxInt;
|
||
|
||
for i := 0 to PointCount - 1 do
|
||
begin
|
||
if rpt[i].X > MaxX then
|
||
MaxX := rpt[i].X;
|
||
if rpt[i].X < MinX then
|
||
MinX := rpt[i].X;
|
||
if rpt[i].Y > MaxY then
|
||
MaxY := rpt[i].Y;
|
||
if rpt[i].Y < MinY then
|
||
MinY := rpt[i].Y;
|
||
end;
|
||
end;
|
||
|
||
// Scale all points so they are in the range minx to maxx and miny to maxy
|
||
procedure IEScalePoints(var rpt: array of TPoint; PointCount: Integer; MinX, MinY, MaxX, MaxY: Integer; MaintainAR: Boolean = False);
|
||
var
|
||
i, currMinX, currMinY, currMaxX, currMaxY : Integer;
|
||
addX, addY: Integer;
|
||
scaleX, ScaleY: Double;
|
||
rightMostX, bottomMostY: Integer;
|
||
begin
|
||
if PointCount < 1 then
|
||
exit;
|
||
|
||
IEGetPointsRange(rpt, PointCount, currMinX, currMinY, currMaxX, currMaxY );
|
||
|
||
addX := MinX - currMinX;
|
||
scaleX := ( MaxX - MinX ) / (( currMaxX - CurrMinX ));
|
||
addY := MinY - currMinY;
|
||
scaleY := ( MaxY - MinY ) / (( currMaxY - CurrMinY ));
|
||
|
||
if MaintainAR then
|
||
begin
|
||
if scaleX < ScaleY then
|
||
begin
|
||
bottomMostY := Round(( currMaxY - currMinY ) * ScaleX ) + addY + currMinY;
|
||
inc( addY, ( MaxY - bottomMostY ) div 2 );
|
||
ScaleY := scaleX;
|
||
end
|
||
else
|
||
begin
|
||
rightMostX := Round(( currMaxX - currMinX ) * ScaleY ) + addX + currMinX;
|
||
inc( addX, ( MaxX - rightMostX ) div 2 );
|
||
scaleX := ScaleY;
|
||
end;
|
||
end;
|
||
|
||
for i := 0 to PointCount - 1 do
|
||
begin
|
||
rpt[i].X := Round(( rpt[i].X - currMinX ) * ScaleX ) + addX + currMinX;
|
||
rpt[i].Y := Round(( rpt[i].Y - currMinY ) * ScaleY ) + addY + currMinY;
|
||
end;
|
||
end;
|
||
|
||
|
||
function IEDISPointInPoly(x, y: double; poly: array of TIE2DPoint): boolean;
|
||
var
|
||
i, j: integer;
|
||
begin
|
||
result := false;
|
||
j := High(poly);
|
||
for i := Low(poly) to High(poly) do
|
||
begin
|
||
if ((((poly[i].y <= y) and (y < poly[j].y)) or ((poly[j].y <= y) and (y < poly[i].y)) ) and (x < ((poly[j].x - poly[i].x) * (y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x))) then
|
||
result := not result;
|
||
j := i
|
||
end;
|
||
end;
|
||
|
||
function IEISPointInPoly(x, y: integer; poly: array of TPoint): boolean;
|
||
var
|
||
i, j: integer;
|
||
begin
|
||
result := false;
|
||
j := High(poly);
|
||
for i := Low(poly) to High(poly) do
|
||
begin
|
||
if ((((poly[i].y <= y) and (y < poly[j].y)) or ((poly[j].y <= y) and (y < poly[i].y)) ) and (x < ((poly[j].x - poly[i].x) * (y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x))) then
|
||
result := not result;
|
||
j := i
|
||
end;
|
||
end;
|
||
|
||
function IEISPointInPoly2(x, y: integer; PolyPoints: PPointArray; PolyPointsCount: integer; ToSubX, ToSubY, ToAddX, ToAddY: integer; ToMulX, ToMulY: double): boolean;
|
||
var
|
||
i, j: integer;
|
||
xi, yi, xj, yj: double;
|
||
begin
|
||
result := false;
|
||
j := PolyPointsCount-1;
|
||
for i := 0 to PolyPointsCount-1 do
|
||
begin
|
||
xi := (PolyPoints[i].x-ToSubX)*ToMulX+ToAddX;
|
||
yi := (PolyPoints[i].y-ToSubY)*ToMulY+ToAddY;
|
||
xj := (PolyPoints[j].x-ToSubX)*ToMulX+ToAddX;
|
||
yj := (PolyPoints[j].y-ToSubY)*ToMulY+ToAddY;
|
||
if ((((yi <= y) and (y < yj)) or ((yj <= y) and (y < yi)) ) and (x < ((xj - xi) * (y - yi) / (yj - yi) + xi))) then
|
||
result := not result;
|
||
j := i
|
||
end;
|
||
end;
|
||
|
||
procedure IECenterRectInRect(OuterRectX1, OuterRectY1, OuterRectX2, OuterRectY2: integer; var InnerRectX1: integer; var InnerRectY1: integer; var InnerRectX2: integer; var InnerRectY2: integer);
|
||
var
|
||
outerWidth, outerHeight: integer;
|
||
innerWidth, innerHeight: integer;
|
||
offX, offY: integer;
|
||
begin
|
||
outerWidth := OuterRectX2 - OuterRectX1 + 1;
|
||
outerHeight := OuterRectY2 - OuterRectY1 + 1;
|
||
innerWidth := InnerRectX2 - InnerRectX1 + 1;
|
||
innerHeight := InnerRectY2 - InnerRectY1 + 1;
|
||
offX := (outerWidth - innerWidth) div 2;
|
||
offY := (outerHeight - innerHeight) div 2;
|
||
InnerRectX1 := OuterRectX1 + offX;
|
||
InnerRectY1 := OuterRectY1 + offY;
|
||
InnerRectX2 := InnerRectX1 + innerWidth - 1;
|
||
InnerRectY2 := InnerRectY1 + innerHeight - 1;
|
||
end;
|
||
|
||
|
||
// Given a rect and an angle, for a line passing through the center, where would it intersect with the rect edges?
|
||
procedure CalcLineWithinRect(R: TRect; Angle: Integer; out Pt1, Pt2: TPoint);
|
||
var
|
||
baseAngle: Integer;
|
||
x1gr, y1gr: Boolean;
|
||
w2, h2 : Double;
|
||
|
||
procedure _FitTopAndBottom();
|
||
var
|
||
a: Double;
|
||
xOffset: Double;
|
||
begin
|
||
// Intersects on top and bottom edges
|
||
Pt1.Y := R.Top;
|
||
Pt2.Y := R.Bottom;
|
||
a := IEDegreesToRadians( 90 - angle );
|
||
xOffset := Abs( Tan( a ) * h2 );
|
||
|
||
if Angle > 45 then
|
||
xOffset := -1 * xOffset;
|
||
Pt1.X := Round( R.Left + w2 - xOffset );
|
||
Pt2.X := Round( R.Left + w2 + xOffset );
|
||
end;
|
||
|
||
procedure _FitLeftAndRight();
|
||
var
|
||
a: Double;
|
||
yOffset: Double;
|
||
begin
|
||
// Intersects on left and right side
|
||
Pt1.X := R.Left;
|
||
Pt2.X := R.Right;
|
||
|
||
a := IEDegreesToRadians( angle );
|
||
yOffset := Abs( Tan( a ) * w2 );
|
||
|
||
if Angle < 0 then
|
||
yOffset := -1 * yOffset;
|
||
Pt1.Y := Round( R.Top + h2 + yOffset );
|
||
Pt2.Y := Round( R.Top + h2 - yOffset );
|
||
end;
|
||
|
||
procedure _SwapX();
|
||
var
|
||
tempX: Integer;
|
||
begin
|
||
tempX := pt1.X;
|
||
pt1.X := pt2.X;
|
||
pt2.X := tempX;
|
||
end;
|
||
|
||
procedure _SwapY();
|
||
var
|
||
tempY: Integer;
|
||
begin
|
||
tempY := pt1.Y;
|
||
pt1.Y := pt2.Y;
|
||
pt2.Y := tempY;
|
||
end;
|
||
|
||
begin
|
||
if ( R.Left > R.Right ) or
|
||
( R.Top > R.Bottom ) then
|
||
begin
|
||
Pt1 := Point( -1, -1 );
|
||
Pt2 := Point( -1, -1 );
|
||
exit;
|
||
end;
|
||
|
||
|
||
baseAngle := Angle;
|
||
while baseAngle < 0 do
|
||
baseAngle := baseAngle + 360;
|
||
|
||
// Want angle to be in range -90 - 90
|
||
While Angle <= -90 do
|
||
Angle := Angle + 180;
|
||
While Angle > 90 do
|
||
Angle := Angle - 180;
|
||
|
||
w2 := ( R.Right - R.Left ) / 2;
|
||
h2 := ( R.Bottom - R.Top ) / 2;
|
||
|
||
if ( Angle < -45 ) or ( Angle > 45 ) then
|
||
begin
|
||
_FitTopAndBottom();
|
||
x1gr := ( Pt1.X > Pt2.X );
|
||
y1gr := ( Pt1.Y > Pt2.Y );
|
||
if ( Pt1.X < R.Left ) or ( Pt2.X < R.Left ) then
|
||
_FitLeftAndRight();
|
||
end
|
||
else
|
||
// > -45 and < 45
|
||
begin
|
||
_FitLeftAndRight();
|
||
x1gr := ( Pt1.X > Pt2.X );
|
||
y1gr := ( Pt1.Y > Pt2.Y );
|
||
if ( Pt1.Y < R.Top ) or ( Pt2.Y < R.Top ) then
|
||
_FitTopAndBottom();
|
||
end;
|
||
|
||
// Correct for refits
|
||
if x1gr and ( Pt2.X > Pt1.X ) then
|
||
_SwapX()
|
||
else
|
||
if ( x1gr = False ) and ( Pt1.X > Pt2.X ) then
|
||
_SwapX();
|
||
|
||
if y1gr and ( Pt2.Y > Pt1.Y ) then
|
||
_SwapY()
|
||
else
|
||
if ( y1gr = False ) and ( Pt1.Y > Pt2.Y ) then
|
||
_SwapY();
|
||
|
||
|
||
if ( baseAngle > 45 ) and (baseAngle <= 225 )then
|
||
IESwap( Pt1, Pt2 );
|
||
end;
|
||
|
||
|
||
// Given a distance and an angle from a point, what would be the new position?
|
||
function OffsetPoint(Pt: TPoint; Dist: Double; Angle: Double) : TPoint;
|
||
var
|
||
aa: Double;
|
||
begin
|
||
aa := -angle * pi / 180;
|
||
Result.X := Pt.X + trunc(( Dist * cos( aa )));
|
||
Result.Y := Pt.Y + trunc(( Dist * sin( aa )));
|
||
end;
|
||
|
||
|
||
function IEIsLeftMouseButtonPressed: boolean;
|
||
begin
|
||
result := (((GetAsyncKeyState(VK_LBUTTON) and $8000)<>0) and (GetSystemMetrics(SM_SWAPBUTTON)=0)) or
|
||
(((GetAsyncKeyState(VK_RBUTTON) and $8000)<>0) and (GetSystemMetrics(SM_SWAPBUTTON)<>0));
|
||
end;
|
||
|
||
function IERGBToStr(rgb: TRGB): AnsiString;
|
||
begin
|
||
with rgb do
|
||
result := IEIntToStr(r)+', '+IEIntToStr(g)+', '+IEIntToStr(b);
|
||
end;
|
||
|
||
function IEGetURLTypeW(const URL: WideString): TIEURLType;
|
||
begin
|
||
result := IEGetURLTypeA(AnsiString(URL));
|
||
end;
|
||
|
||
function IEGetURLTypeA(const URL: AnsiString): TIEURLType;
|
||
var
|
||
tmp: AnsiString;
|
||
begin
|
||
tmp := IELowerCase(URL);
|
||
if IECopy(tmp, 1, 7) = 'http://' then
|
||
result := ieurlHTTP
|
||
else
|
||
if IECopy(tmp, 1, 8) = 'https://' then
|
||
result := ieurlHTTPS
|
||
else
|
||
if IECopy(tmp, 1, 6) = 'ftp://' then
|
||
result := ieurlFTP
|
||
else
|
||
result := ieurlUNKNOWN;
|
||
end;
|
||
|
||
// Return distance between (x, y) and the ellipse inside x1, y1, x2, y2
|
||
// Coordinates x1, y1, x2, y2 must be ordered
|
||
// 3.0.2 (penWidth)
|
||
function IEDistPoint2Ellipse(x, y, x1, y1, x2, y2: integer; filled: boolean; penWidth: integer): double;
|
||
var
|
||
g, xr1, yr1, xr2, yr2, rx, ry, p, pw, ox, oy: integer;
|
||
d: double;
|
||
begin
|
||
result := 2147483647;
|
||
for pw := -penWidth div 2 to penWidth div 2 do
|
||
begin
|
||
rx := (x2 - x1) div 2 + pw; // ray x
|
||
ry := (y2 - y1) div 2 + pw; // ray y
|
||
ox := x - (x1 + rx)+pw;
|
||
oy := y - (y1 + ry)+pw;
|
||
if filled then
|
||
p := trunc(2 * pi * imin(rx, ry))
|
||
else
|
||
p := trunc(2 * pi * imin(rx, ry)) shr 3;
|
||
|
||
if p<2 then p := 2;
|
||
|
||
xr1 := rx;
|
||
yr1 := 0;
|
||
for g := 1 to p - 1 do
|
||
begin
|
||
xr2 := trunc(cos((2 * pi / p) * g) * rx);
|
||
yr2 := trunc(sin((2 * pi / p) * g) * ry);
|
||
if filled then
|
||
d := trunc(_DistPoint2Seg(ox, oy, 0, 0, xr2, yr2))
|
||
else
|
||
d := _DistPoint2Seg(ox, oy, xr1, yr1, xr2, yr2);
|
||
if d < result then
|
||
result := d;
|
||
xr1 := xr2;
|
||
yr1 := yr2;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
// 3.0.2 (penWidth)
|
||
function IEDist2Box(x, y, x1, y1, x2, y2: integer; filled: boolean; penWidth: integer): double;
|
||
var
|
||
pw: integer;
|
||
begin
|
||
result := 2147483647;
|
||
for pw := -penWidth div 2 to penWidth div 2 do
|
||
begin
|
||
result := dmin(result, dmin(_DistPoint2Seg(x, y, x1+pw, y1+pw, x2+pw, y1+pw),
|
||
dmin(_DistPoint2Seg(x, y, x2+pw, y1+pw, x2+pw, y2+pw),
|
||
dmin(_DistPoint2Seg(x, y, x2+pw, y2+pw, x1+pw, y2+pw),
|
||
_DistPoint2Seg(x, y, x1+pw, y2+pw, x1+pw, y1+pw)))));
|
||
if filled and IEPointInRect(x, y, x1+pw, y1+pw, x2+pw, y2+pw) then
|
||
begin
|
||
result := 0;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
// calculate the distance of two parallel lines
|
||
// line A: defined by two points (FirstLinePointA, FirstLinePointB)
|
||
// line B: defined by one point (SecondLinePoint)
|
||
function IEDistParallelLines(FirstLinePointA: TIE2DPoint; FirstLinePointB: TIE2DPoint; SecondLinePoint: TIE2DPoint): double;
|
||
var
|
||
AB, BC, AC: double;
|
||
p: double;
|
||
S: double;
|
||
begin
|
||
AB := IEDDistPoint2Point(FirstLinePointA.X, FirstLinePointA.Y, FirstLinePointB.X, FirstLinePointB.Y);
|
||
BC := IEDDistPoint2Point(FirstLinePointB.X, FirstLinePointB.Y, SecondLinePoint.X, SecondLinePoint.Y);
|
||
AC := IEDDistPoint2Point(FirstLinePointA.X, FirstLinePointA.Y, SecondLinePoint.X, SecondLinePoint.Y);
|
||
p := (AB + BC + AC) / 2.0; // perimeter / 2
|
||
S := sqrt(p * (p - AB) * (p - BC) * (p - AC)); // area (Heron's formula)
|
||
result := 2.0 * S / AB; // triangle height
|
||
end;
|
||
|
||
|
||
// calculate the signed area of triangle
|
||
function IESignedTriangleArea(Point1: TIE2DPoint; Point2: TIE2DPoint; Point3: TIE2DPoint): double;
|
||
begin
|
||
result := (-Point2.X * Point1.Y + Point3.X * Point1.Y + Point1.X * Point2.Y - Point3.X * Point2.Y - Point1.X * Point3.Y + Point2.X * Point3.Y) / 2.0;
|
||
end;
|
||
|
||
|
||
// calculate the offsets to translate a segment such that it passes by a given point, respecting the original orientation and direction (that is "to offset the coordinates in the orthogonal direction")
|
||
// "P" (Point) can be any point in the translated line (even out of segment)
|
||
// P
|
||
// /
|
||
// / /
|
||
// / /
|
||
// /
|
||
procedure IEOrthogonalTranslate(OrigSegmentA, OrigSegmentB: TIE2DPoint; Point: TIE2DPoint; out OffsetX: double; out OffsetY: double);
|
||
var
|
||
L, offsetPixels: double;
|
||
begin
|
||
offsetPixels := IEDistParallelLines(OrigSegmentA, OrigSegmentB, Point);
|
||
if IESignedTriangleArea(OrigSegmentA, OrigSegmentB, Point) > 0 then
|
||
offsetPixels := -offsetPixels;
|
||
L := sqrt((OrigSegmentA.X - OrigSegmentB.X) * (OrigSegmentA.X - OrigSegmentB.X) + (OrigSegmentA.Y - OrigSegmentB.Y) * (OrigSegmentA.Y - OrigSegmentB.Y));
|
||
OffsetX := offsetPixels * (OrigSegmentB.Y - OrigSegmentA.Y) / L;
|
||
OffsetY := offsetPixels * (OrigSegmentA.X - OrigSegmentB.X) / L;
|
||
end;
|
||
|
||
|
||
|
||
|
||
function IETrim(const v: AnsiString): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(trim(string(v)));
|
||
{$ELSE}
|
||
result := trim(v);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IEExtractFileExtS(const FileName: string; includeDot: boolean=true): string;
|
||
begin
|
||
result := ExtractFileExt(LowerCase(FileName));
|
||
if not includeDot then
|
||
result := Copy(result, 2, length(result)-1);
|
||
end;
|
||
|
||
function IEExtractFileExtA(const FileName: AnsiString; includeDot: boolean): AnsiString;
|
||
begin
|
||
{$ifdef IEHASANSISTRINGBUG}
|
||
result := IEExtractFileExtS(string(FileName), includeDot);
|
||
{$else}
|
||
result := AnsiString(IEExtractFileExtS(string(FileName), includeDot));
|
||
{$endif}
|
||
end;
|
||
|
||
function IEExtractFileExtW(const FileName: WideString; includeDot: boolean): WideString;
|
||
begin
|
||
result := WideString(IEExtractFileExtS(string(FileName), includeDot));
|
||
end;
|
||
|
||
|
||
// = IncludeTrailingBackSlash, but if path is '' it returns ''
|
||
function IEAddBackSlash(const Path: String): String;
|
||
begin
|
||
Result := '';
|
||
if Path <> '' then
|
||
Result := IncludeTrailingBackSlash( Path );
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>IEFilenameInExtensions
|
||
|
||
<FM>Declaration<FC>
|
||
function IEFilenameInExtensions(const sFileName, sExtensions : String) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the filename has an extension listed in those passed (in format '*.jpeg;*.jpg;*.gif;');
|
||
|
||
For example: IEFilenameInExtensions('C:\File.avi', '*.AVI;*.mpg;*.mpeg') would return true
|
||
|
||
<FM>See Also<FN>
|
||
- <A General Helper Functions>
|
||
!!}
|
||
function IEFilenameInExtensions(const sFileName, sExtensions : String) : Boolean;
|
||
begin
|
||
Result := IEFileExtInExtensions(ExtractFileExt(sFilename), sExtensions);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>IEFileExtInExtensions
|
||
|
||
<FM>Declaration<FC>
|
||
function IEFileExtInExtensions(sFileExt : String; const sExtensions : String) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the extension (with or without the dot) is listed in those passed (in format '*.jpeg;*.jpg;*.gif;');
|
||
|
||
For example: IEFilenameInExtensions('.avi', '*.AVI;*.mpg;*.mpeg') would return true
|
||
|
||
Note: <FC>sExtensions<FN> can be '*.*';
|
||
|
||
<FM>See Also<FN>
|
||
- <A General Helper Functions>
|
||
!!}
|
||
function IEFileExtInExtensions(sFileExt : String; const sExtensions : String) : Boolean;
|
||
begin
|
||
Result := False;
|
||
|
||
sFileExt := Lowercase(sFileExt);
|
||
if (sFileExt <> '') and (sFileExt[1] <> '.') then
|
||
sFileExt := '.' + sFileExt;
|
||
|
||
if ( sExtensions = '*.*' ) or ( sExtensions = '*.*;' ) then
|
||
result := True
|
||
else
|
||
if ( Length( sFileExt ) > 1 ) and ( pos( sFileExt + ';', Lowercase( sExtensions + ';' )) > 0 ) then
|
||
result := True;
|
||
end;
|
||
|
||
|
||
|
||
function IEUpperCase(const v: AnsiString): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(UpperCase(string(v)));
|
||
{$ELSE}
|
||
result := UpperCase(v);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IELowerCase(const v: AnsiString): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(LowerCase(string(v)));
|
||
{$ELSE}
|
||
result := LowerCase(v);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IEIntToStr(v: integer): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(IntToStr(v));
|
||
{$ELSE}
|
||
result := IntToStr(v);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
|
||
// iMaxDigitsOfPrecision: Specifies number of leading digits that are non zero, e.g. 3 woudl make 123,456 return 123,000
|
||
function IEIntToFormattedStr(v: integer; iMaxDigitsOfPrecision: Integer = 0): AnsiString;
|
||
var
|
||
iRoundTo: Integer;
|
||
begin
|
||
if iMaxDigitsOfPrecision > 0 then
|
||
begin
|
||
iRoundTo := Length( IntToStr( v )) - iMaxDigitsOfPrecision;
|
||
if iRoundTo > 0 then
|
||
v := Trunc( RoundTo( v, iRoundTo ));
|
||
end;
|
||
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(format('%.0n', [v * 1.0]));
|
||
{$ELSE}
|
||
result := format('%.0n', [v * 1.0]);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
// MAX VALUE: 2GB!!!
|
||
function IEBytesToStr(v: integer; iThreshold: Integer = 100 * 1024) : AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
if v < iThreshold then
|
||
Result := IEIntToFormattedStr(v) + AnsiString(' bytes')
|
||
else
|
||
Result := IEIntToFormattedStr(v div 1024) + AnsiString(' KB');
|
||
{$ELSE}
|
||
if v < iThreshold then
|
||
Result := IEIntToFormattedStr(v) + ' bytes'
|
||
else
|
||
Result := IEIntToFormattedStr(v div 1024) + ' KB';
|
||
{$ENDIF}
|
||
end;
|
||
|
||
// Handles very big sizes which may include files in KB, MB or FB
|
||
function IEBytesToStr2(iBytes: Int64) : AnsiString;
|
||
const
|
||
ONE_KB = 1024;
|
||
ONE_MB = ONE_KB * ONE_KB;
|
||
ONE_GB = ONE_MB * ONE_KB;
|
||
|
||
function _FloatToFormatString(Value: Real;
|
||
iDecimalCount: Integer;
|
||
bStripZeros: boolean = True): AnsiString;
|
||
begin
|
||
result := AnsiString(Format('%.' + inttostr(iDecimalCount) + 'f', [Value]));
|
||
|
||
if bStripZeros and (IEPos('.', result) > 0) then
|
||
begin
|
||
while result[length(result)] = '0' do
|
||
setlength(result, length(result) - 1);
|
||
|
||
if result[length(result)] = '.' then
|
||
setlength(result, length(result) - 1);
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
if iBytes < 10 * ONE_MB then
|
||
Result := IEBytesToStr(iBytes, ONE_KB)
|
||
else
|
||
if iBytes < 1 * ONE_GB then
|
||
result := _FloatToFormatString(iBytes / ONE_MB, 2) + AnsiString(' MB')
|
||
else
|
||
result := _FloatToFormatString(iBytes / ONE_GB, 2) + AnsiString(' GB');
|
||
{$ELSE}
|
||
if iBytes < 10 * ONE_MB then
|
||
Result := IEBytesToStr(iBytes, ONE_KB)
|
||
else
|
||
if iBytes < 1 * ONE_GB then
|
||
result := _FloatToFormatString(iBytes / ONE_MB, 2) + ' MB'
|
||
else
|
||
result := _FloatToFormatString(iBytes / ONE_GB, 2) + ' GB';
|
||
{$ENDIF}
|
||
end;
|
||
|
||
|
||
|
||
|
||
function IEStrToIntDef(const s: AnsiString; def: integer): integer;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := StrToIntDef(string(s), def);
|
||
{$ELSE}
|
||
result := StrToIntDef(s, def);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IECopy(S: AnsiString; Index, Count: Integer): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(Copy(string(S), Index, Count));
|
||
{$ELSE}
|
||
result := Copy(S, Index, Count);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IEFloatToStrFA(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): AnsiString;
|
||
begin
|
||
result := AnsiString(FloatToStrF(Value, Format, Precision, Digits));
|
||
end;
|
||
|
||
function IEFloatToStrFS(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): string;
|
||
begin
|
||
result := FloatToStrF(Value, Format, Precision, Digits);
|
||
end;
|
||
|
||
function IEIntToHex(Value: Integer; Digits: Integer): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(IntToHex(Value, Digits));
|
||
{$ELSE}
|
||
result := IntToHex(Value, Digits);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IEPos(Substr: AnsiString; S: AnsiString): Integer;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := Pos(string(Substr), string(S));
|
||
{$ELSE}
|
||
result := Pos(Substr, S);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IEExtractFilePathA(const FileName: AnsiString): AnsiString;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
result := AnsiString(ExtractFilePath(string(FileName)));
|
||
{$ELSE}
|
||
result := ExtractFilePath(FileName);
|
||
{$ENDIF}
|
||
end;
|
||
|
||
function IEExtractFilePathW(const FileName: WideString): WideString;
|
||
var
|
||
I: Integer;
|
||
begin
|
||
I := LastDelimiter('\:', FileName);
|
||
Result := Copy(FileName, 1, I);
|
||
end;
|
||
|
||
function IEExtractFileNameW(const FileName: WideString): WideString;
|
||
var
|
||
I: Integer;
|
||
begin
|
||
I := LastDelimiter('\:', FileName);
|
||
Result := Copy(FileName, I + 1, MaxInt);
|
||
end;
|
||
|
||
|
||
function IEExtractFileNameWithoutExt(const FileName: String): String;
|
||
var
|
||
iExtLen: integer;
|
||
begin
|
||
Result := ExtractFilename( FileName );
|
||
iExtLen := length( IEExtractFileExtW( Result ));
|
||
if ( iExtLen > 0 ) and
|
||
( iExtLen < Length( Result )) then // avoid issues with folder names with a leading period
|
||
Delete( Result, Length( Result ) - iExtLen + 1, iExtLen );
|
||
end;
|
||
|
||
|
||
function IEStrDup(s: PAnsiChar): PAnsiChar;
|
||
begin
|
||
if s <> nil then
|
||
begin
|
||
getmem(result, IEStrLen(s) + 1);
|
||
IEStrCopy(result, s);
|
||
end
|
||
else
|
||
result := nil;
|
||
end;
|
||
|
||
|
||
function IEStrDupW(s: PWideChar): PWideChar;
|
||
begin
|
||
if s <> nil then
|
||
begin
|
||
getmem(result, IEStrLenW(s) * 2 + 2);
|
||
IEStrCopyW(result, s);
|
||
end
|
||
else
|
||
result := nil;
|
||
end;
|
||
|
||
|
||
function IEFileExists(const FileName: string): Boolean;
|
||
var
|
||
Attr: Cardinal;
|
||
begin
|
||
if IEGlobalSettings().UseDefaultFileExists then
|
||
result := FileExists(FileName)
|
||
else
|
||
begin
|
||
// FileGetSize is very slow, GetFileAttributes is much faster
|
||
Attr := GetFileAttributes(Pointer(Filename));
|
||
Result := (Attr <> $FFFFFFFF) and (Attr and FILE_ATTRIBUTE_DIRECTORY = 0);
|
||
end;
|
||
end;
|
||
|
||
function IEFileExistsW(const FileName: WideString): Boolean;
|
||
var
|
||
Attr: Cardinal;
|
||
begin
|
||
{$IFDEF UNICODE}
|
||
if IEGlobalSettings().UseDefaultFileExists then
|
||
result := FileExists(string(FileName))
|
||
else
|
||
begin
|
||
{$ENDIF}
|
||
if IEGlobalSettings().UnicodeOS then
|
||
Attr := GetFileAttributesW(PWideChar(Filename))
|
||
else
|
||
Attr := GetFileAttributesA(PAnsiChar(AnsiString(Filename)));
|
||
Result := (Attr <> $FFFFFFFF) and (Attr and FILE_ATTRIBUTE_DIRECTORY = 0);
|
||
{$IFDEF UNICODE}
|
||
end;
|
||
{$ENDIF}
|
||
end;
|
||
|
||
|
||
procedure IEDrawGrayedOut(Canvas: TCanvas; XDst, YDst, WidthDst, HeightDst: integer; SX1, SY1, SX2, SY2: integer);
|
||
var
|
||
iec: TIECanvas;
|
||
begin
|
||
if (SX1 < SX2) and (SY1 < SY2) then
|
||
begin
|
||
iec := TIECanvas.Create(Canvas, false);
|
||
|
||
iec.Brush.Color := clBlack;
|
||
iec.Brush.Style := bsSolid;
|
||
iec.Brush.Transparency := 150;
|
||
|
||
inc(WidthDst);
|
||
inc(HeightDst);
|
||
|
||
inc(SX1);
|
||
inc(SY1);
|
||
inc(SX2);
|
||
inc(SY2);
|
||
|
||
iec.FillRect(Rect(XDst, YDst, SX1+1, YDst+HeightDst));
|
||
iec.FillRect(Rect(SX2-1, YDst, XDst+WidthDst, YDst+HeightDst));
|
||
iec.FillRect(Rect(SX1, YDst, SX2, SY1+1));
|
||
iec.FillRect(Rect(SX1, SY2, SX2, YDst+HeightDst));
|
||
|
||
iec.Free;
|
||
end;
|
||
end;
|
||
|
||
// A TStream.CopyFrom that adjusts "Count" (or autocalculated Count) to source size without raising exceptions
|
||
function IECopyFrom(Dest: TStream; Source: TStream; Count: int64): int64;
|
||
const
|
||
MaxBufSize = $2FFFF;
|
||
var
|
||
BufSize, N: Integer;
|
||
Buffer: pbyte;
|
||
begin
|
||
if Count = 0 then
|
||
begin
|
||
Source.Position := 0;
|
||
Count := Source.Size;
|
||
end;
|
||
|
||
if not (Source is TZDecompressionStream)
|
||
and not (Source is TZCompressionStream)
|
||
and not (Source is TIEHashStream)
|
||
then
|
||
begin
|
||
Count := i64max(0, i64min(Count, Source.Size-Source.Position));
|
||
end;
|
||
|
||
Result := Count;
|
||
|
||
if Count > MaxBufSize then
|
||
BufSize := MaxBufSize
|
||
else
|
||
BufSize := Count;
|
||
|
||
GetMem(Buffer, BufSize);
|
||
try
|
||
while Count <> 0 do
|
||
begin
|
||
if Count > BufSize then N := BufSize else N := Count;
|
||
Source.ReadBuffer(Buffer^, N);
|
||
Dest.WriteBuffer(Buffer^, N);
|
||
Dec(Count, N);
|
||
end;
|
||
finally
|
||
FreeMem(Buffer, BufSize);
|
||
end;
|
||
end;
|
||
|
||
procedure IEDecimalToFraction(value: double; var numerator: integer; var denominator: integer; accuracy: double);
|
||
var
|
||
z: double;
|
||
prevDen, sign, sVal: int64;
|
||
anum, aden: int64;
|
||
num, den: int64;
|
||
begin
|
||
if value < 0.0 then
|
||
sign := -1
|
||
else
|
||
sign := +1;
|
||
value := abs(value);
|
||
if value = trunc(value) then
|
||
begin
|
||
numerator := trunc(value * sign);
|
||
denominator := 1;
|
||
exit
|
||
end;
|
||
if value < 1.0E-19 then
|
||
begin
|
||
numerator := sign;
|
||
denominator := 999999999;
|
||
exit
|
||
end;
|
||
if value > 1.0E+19 then
|
||
begin
|
||
numerator := 999999999 * sign;
|
||
denominator := 1;
|
||
exit
|
||
end;
|
||
|
||
// in case of failure
|
||
num := trunc(value);
|
||
den := 1;
|
||
|
||
z := value;
|
||
prevDen := 0;
|
||
aden := 1;
|
||
repeat
|
||
z := 1.0 / (z - trunc(z));
|
||
sVal := aden;
|
||
aden := aden * trunc(z) + prevDen;
|
||
prevDen := sVal;
|
||
anum := trunc(value * aden + 0.5);
|
||
if (anum > 2147483647) or (aden > 2147483647) then
|
||
break;
|
||
num := anum;
|
||
den := aden;
|
||
until (abs((value - (anum / aden))) < accuracy) or (z = trunc(z));
|
||
numerator := sign * num;
|
||
denominator := den;
|
||
end;
|
||
|
||
|
||
procedure IECopyTList(source: TList; dest: TList);
|
||
var
|
||
i: integer;
|
||
begin
|
||
dest.Count := source.Count;
|
||
for i := 0 to source.Count-1 do
|
||
dest[i] := source[i];
|
||
end;
|
||
|
||
|
||
function IESendMessageTimeout(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM; fuFlags, uTimeout: UINT; lpdwResult: pointer): LRESULT;
|
||
begin
|
||
{$ifdef IEUSENEWSENDMESSAGETIMEOUT}
|
||
result := SendMessageTimeout(hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult);
|
||
{$else}
|
||
result := SendMessageTimeout(hWnd, Msg, wParam, lParam, fuFlags, uTimeout, PDWORD(lpdwResult)^);
|
||
{$endif}
|
||
end;
|
||
|
||
|
||
|
||
function IETextWidthW(Canvas: TCanvas; const Text: WideString): integer;
|
||
var
|
||
Size: TSize;
|
||
begin
|
||
Size.cx := 0;
|
||
Size.cy := 0;
|
||
Windows.GetTextExtentPoint32W(Canvas.Handle, PWideChar(Text), Length(Text), Size);
|
||
result := Size.cx;
|
||
end;
|
||
|
||
function IETextHeightW(Canvas: TCanvas; const Text: WideString): integer;
|
||
var
|
||
Size: TSize;
|
||
begin
|
||
Size.cx := 0;
|
||
Size.cy := 0;
|
||
Windows.GetTextExtentPoint32W(Canvas.Handle, PWideChar(Text), Length(Text), Size);
|
||
result := Size.cy;
|
||
end;
|
||
|
||
function IETruncateStr(sCaption : WideString; TruncSide: TIEMTruncSide; ACanvas : TCanvas; iMaxWidth : Integer) : Widestring;
|
||
var
|
||
tw: integer;
|
||
ws1: WideString;
|
||
q: Integer;
|
||
begin
|
||
Result := sCaption;
|
||
case TruncSide of
|
||
iemtsLeft:
|
||
begin
|
||
q := 1;
|
||
repeat
|
||
tw := IETextWidthW(ACanvas, Result);
|
||
if (tw <= iMaxWidth) or (length(Result) < 2) then
|
||
break;
|
||
inc(q);
|
||
ws1 := TrimRight( Copy(sCaption, 1, length(sCaption) - q ));
|
||
if ws1 = '' then
|
||
break;
|
||
Result := ws1 + '...';
|
||
until false;
|
||
end;
|
||
iemtsRight:
|
||
begin
|
||
q := 1;
|
||
repeat
|
||
tw := IETextWidthW(ACanvas, Result);
|
||
if (tw <= iMaxWidth) or (length(Result) < 2) then
|
||
break;
|
||
inc(q);
|
||
ws1 := TrimLeft( Copy(sCaption, q, length(sCaption)));
|
||
if ws1 = '' then
|
||
break;
|
||
Result := '...' + ws1;
|
||
until false;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
function IEFileTimeToDateTime(ft: TFileTime): TDateTime;
|
||
var
|
||
LocalFileTime: TFileTime;
|
||
iDosDT: integer;
|
||
begin
|
||
Result := 0.0;
|
||
if ft.dwLowDateTime + ft.dwHighDateTime = 0 then
|
||
EXIT;
|
||
|
||
if not FileTimeToLocalFileTime(ft, LocalFileTime) then
|
||
EXIT;
|
||
|
||
if not FileTimeToDosDateTime(LocalFileTime, longRec(iDosDT).hi, longRec(iDosDT).lo) then
|
||
EXIT;
|
||
|
||
if iDosDT <> -1 then
|
||
Result := FileDateToDateTime(iDosDT);
|
||
end;
|
||
|
||
|
||
function IELargeFileSize(nFileSizeHigh, nFileSizeLow: DWORD) : Int64;
|
||
begin
|
||
Int64Rec(Result).Lo := nFileSizeLow;
|
||
Int64Rec(Result).Hi := nFileSizeHigh;
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>IEGetFileDetails
|
||
|
||
<FM>Declaration<FC>
|
||
function IEGetFileDetails(const sFilename: string;
|
||
out iFileSizeBytes: Int64;
|
||
out dtCreateDate: TDateTime;
|
||
out dtEditDate: TDateTime
|
||
): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Return the size, create date and last edit date of a file. Result is false if an error occured.
|
||
|
||
<FM>See Also<FN>
|
||
- <A IEGetFileSize>
|
||
!!}
|
||
function IEGetFileDetails(const sFilename: string;
|
||
out iFileSizeBytes: Int64;
|
||
out dtCreateDate: TDateTime;
|
||
out dtEditDate: TDateTime
|
||
): boolean;
|
||
var
|
||
Data: TWin32FindData;
|
||
H: THandle;
|
||
ErrorMode: word;
|
||
begin
|
||
result := true;
|
||
iFileSizeBytes := 0;
|
||
dtCreateDate := 0;
|
||
dtEditdate := 0;
|
||
{ turn off critical errors }
|
||
ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
|
||
try
|
||
try
|
||
H := FindFirstFile(PCHAR(sFilename), Data);
|
||
if H <> INVALID_HANDLE_VALUE then
|
||
try
|
||
iFileSizeBytes := IELargeFileSize(Data.nFileSizeHigh, Data.nFileSizeLow);
|
||
dtEditDate := IEFileTimeToDateTime(Data.ftLastWriteTime);
|
||
try
|
||
dtCreateDate := IEFileTimeToDateTime(Data.ftCreationTime);
|
||
except
|
||
dtCreateDate := dtEditDate;
|
||
end;
|
||
finally
|
||
Windows.FindClose(H);
|
||
end
|
||
else
|
||
Result := false;
|
||
except
|
||
result := false;
|
||
end;
|
||
finally
|
||
{ restore old error mode }
|
||
SetErrorMode(ErrorMode);
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>IEFileSetDate
|
||
|
||
<FM>Declaration<FC>
|
||
function FileSetDate(const sFilename: string; DateTime: TDateTime): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Same as sysutils.FileSetDate but takes a TDateTime as a parameter.
|
||
!!}
|
||
function IEFileSetDate(const sFilename: string; DateTime: TDateTime): boolean;
|
||
var
|
||
liHandle: INTEGER;
|
||
begin
|
||
result := False;
|
||
|
||
if DateTime <> 0 then
|
||
try
|
||
liHandle := FileOpen(sFileName, fmOpenReadWrite or fmShareDenyNone);
|
||
if liHandle > 0 then
|
||
begin
|
||
result := FileSetDate(liHandle, DateTimeToFileDate(DateTime)) <> 0;
|
||
FileClose(liHandle);
|
||
end;
|
||
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
// convert a real value into a string with decimal places
|
||
function IEFloatToFormatString(Value: Extended;
|
||
iDecimalCount: Integer;
|
||
bStripZeros: boolean): string;
|
||
begin
|
||
result := Format('%.' + inttostr( imax(0, iDecimalCount )) + 'f', [Value]);
|
||
|
||
if bStripZeros and (pos('.', result) > 0) then
|
||
while result[length(result)] = '0' do
|
||
setlength(result, length(result) - 1);
|
||
|
||
if result[length(result)] = '.' then
|
||
setlength(result, length(result) - 1);
|
||
end;
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
|
||
function IE2DPoint(X, Y: double): TIE2DPoint;
|
||
begin
|
||
result.X := X;
|
||
result.Y := Y;
|
||
end;
|
||
|
||
|
||
{$ifndef IEHASUINT64}
|
||
function UInt64(v : Pointer) : int64;
|
||
begin
|
||
result := int64(DWORD(v));
|
||
end;
|
||
|
||
function UInt64(v : Integer) : int64;
|
||
begin
|
||
result := int64(DWORD(v));
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
{$ifndef IEHASNATIVEINT}
|
||
function Nativeint(v: Pointer): DWORD;
|
||
begin
|
||
result := DWORD(v);
|
||
end;
|
||
|
||
function Nativeint(v: Char): DWORD;
|
||
begin
|
||
result := DWORD(v);
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
|
||
{$IfNDef Delphi6orNewer}
|
||
function Get8087CW: Word; // for D5
|
||
asm
|
||
PUSH 0
|
||
FNSTCW [ESP].Word
|
||
POP EAX
|
||
end;
|
||
{$ENDIF}
|
||
|
||
|
||
{$ifdef IEVISION}
|
||
function IEVisionBGR8ToTRGB(visionBGR8: TIEVisionBGR8): TRGB;
|
||
begin
|
||
result.b := visionBGR8.b;
|
||
result.g := visionBGR8.g;
|
||
result.r := visionBGR8.r;
|
||
end;
|
||
|
||
function IETRGBToVisionBGR8(rgb: TRGB): TIEVisionBGR8;
|
||
begin
|
||
result.b := rgb.b;
|
||
result.g := rgb.g;
|
||
result.r := rgb.r;
|
||
end;
|
||
|
||
// from PixleFormat to IEVision channelFormat/channelCount
|
||
procedure IEVisionConvPixelFormat(PixelFormat: TIEPixelFormat; out channelFormat: TIEVisionChannelFormat; out channelCount: integer);
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 0;
|
||
case PixelFormat of
|
||
ie1g:
|
||
begin
|
||
channelFormat := ievUINT1;
|
||
channelCount := 1;
|
||
end;
|
||
ie8p:
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 1;
|
||
end;
|
||
ie8g:
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 1;
|
||
end;
|
||
ie16g:
|
||
begin
|
||
channelFormat := ievUINT16;
|
||
channelCount := 1;
|
||
end;
|
||
ie24RGB:
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 3;
|
||
end;
|
||
ie32f:
|
||
begin
|
||
channelFormat := ievFLOAT32;
|
||
channelCount := 1;
|
||
end;
|
||
ieCMYK:
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 4;
|
||
end;
|
||
ie48RGB:
|
||
begin
|
||
channelFormat := ievUINT16;
|
||
channelCount := 3;
|
||
end;
|
||
ieCIELab:
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 3;
|
||
end;
|
||
ie32RGB:
|
||
begin
|
||
channelFormat := ievUINT8;
|
||
channelCount := 4;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
// from IEVision channelFormat/channelCount to PixleFormat
|
||
function IEVisionConvPixelFormat(channelFormat: TIEVisionChannelFormat; channelCount: integer): TIEPixelFormat;
|
||
begin
|
||
result := ienull; // invalid
|
||
case channelFormat of
|
||
ievUINT1:
|
||
begin
|
||
case channelCount of
|
||
1: result := ie1g;
|
||
end;
|
||
end;
|
||
ievUINT8:
|
||
begin
|
||
case channelCount of
|
||
1: result := ie8g;
|
||
3: result := ie24RGB;
|
||
4: result := ie32RGB;
|
||
end;
|
||
end;
|
||
ievUINT16:
|
||
begin
|
||
case channelCount of
|
||
1: result := ie16g;
|
||
3: result := ie48RGB;
|
||
end;
|
||
end;
|
||
ievFLOAT32:
|
||
begin
|
||
case channelCount of
|
||
1: result := ie32f;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Swaps two values
|
||
|
||
procedure IESwap(var a: integer; var b: integer);
|
||
var
|
||
t: integer;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: double; var b: double);
|
||
var
|
||
t: double;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: boolean; var b: boolean);
|
||
var
|
||
t: boolean;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TIELayerMagnification; var b: TIELayerMagnification);
|
||
var
|
||
t: TIELayerMagnification;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TIERenderOperation; var b: TIERenderOperation);
|
||
var
|
||
t: TIERenderOperation;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: pointer; var b: pointer);
|
||
var
|
||
t: pointer;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TResampleFilter; var b: TResampleFilter);
|
||
var
|
||
t: TResampleFilter;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: AnsiString; var b: AnsiString);
|
||
var
|
||
t: AnsiString;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
{$IfDef UNICODE}
|
||
procedure IESwap(var a: UnicodeString; var b: UnicodeString);
|
||
var
|
||
t: UnicodeString;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
{$EndIf}
|
||
|
||
procedure IESwap(var a: TGuid; var b: TGuid);
|
||
var
|
||
t: TGuid;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
|
||
procedure IESwap(var a: TRGB; var b: TRGB);
|
||
var
|
||
t: TRGB;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TIEArrayOfTRGB; var b: TIEArrayOfTRGB);
|
||
var
|
||
t: TIEArrayOfTRGB;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TRect; var b: TRect);
|
||
var
|
||
t: TRect;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TIEShape; var b: TIEShape);
|
||
var
|
||
t: TIEShape;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TColor; var b: TColor);
|
||
var
|
||
t: TColor;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
procedure IESwap(var a: TFont; var b: TFont);
|
||
var
|
||
tmpCharset: TFontCharset;
|
||
tmpColor: TColor;
|
||
tmpHeight: Integer;
|
||
tmpName: TFontName;
|
||
tmpStyle: TFontStyles;
|
||
begin
|
||
tmpCharset := a.Charset;
|
||
a.Charset := b.Charset;
|
||
b.Charset := tmpCharset;
|
||
|
||
tmpColor := a.Color;
|
||
a.Color := b.Color;
|
||
b.Color := tmpColor;
|
||
|
||
tmpHeight := a.Height;
|
||
a.Height := b.Height;
|
||
b.Height := tmpHeight;
|
||
|
||
tmpName := a.Name;
|
||
a.Name := b.Name;
|
||
b.Name := tmpName;
|
||
|
||
tmpStyle := a.Style;
|
||
a.Style := b.Style;
|
||
b.Style := tmpStyle;
|
||
end;
|
||
|
||
procedure IESwap(var a: TPoint; var b: TPoint);
|
||
var
|
||
t: TPoint;
|
||
begin
|
||
t := a; a := b; b := t;
|
||
end;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// timeout support
|
||
|
||
function IESetupTimeout(): dword;
|
||
begin
|
||
result := GetTickCount();
|
||
end;
|
||
|
||
function IEIsTimeoutExpired(startTime: dword; timeout: dword): boolean;
|
||
var
|
||
diff: dword;
|
||
curr: dword;
|
||
begin
|
||
curr := GetTickCount();
|
||
if startTime > curr then
|
||
// overflow
|
||
diff := $FFFFFFFF - startTime + curr
|
||
else
|
||
diff := curr - startTime;
|
||
result := diff >= timeout;
|
||
end;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
{!!
|
||
<FS>IERectangle
|
||
|
||
<FM>Declaration<FC>
|
||
function IERectangle(x, y, width, height: integer): <A TIERectangle>; overload;
|
||
function IERectangle(Rect: TRect): <A TIERectangle>; overload;
|
||
|
||
<FM>Description<FN>
|
||
Create a TIERectangle structure.
|
||
!!}
|
||
function IERectangle(x, y, width, height: integer): TIERectangle;
|
||
begin
|
||
result.x := x;
|
||
result.y := y;
|
||
result.width := width;
|
||
result.height := height;
|
||
end;
|
||
|
||
function IERectangle(Rect: TRect): TIERectangle;
|
||
begin
|
||
with Rect do
|
||
begin
|
||
result.x := Left;
|
||
result.y := Top;
|
||
result.width := Right - Left;
|
||
result.height := Bottom - Top;
|
||
end;
|
||
end;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// TIEClientSocket
|
||
|
||
|
||
const
|
||
|
||
WSADESCRIPTION_LEN = 256;
|
||
WSASYS_STATUS_LEN = 128;
|
||
INVALID_SOCKET = pointer(-1);
|
||
SOCKET_ERROR = -1;
|
||
AF_INET = 2;
|
||
SOCK_STREAM = 1;
|
||
AF_UNSPEC = 0;
|
||
IPPROTO_TCP = 6;
|
||
TCP_NODELAY = $0001;
|
||
SD_BOTH = 2;
|
||
|
||
type
|
||
|
||
TWSAData = record
|
||
wVersion: Word;
|
||
wHighVersion: Word;
|
||
szDescription: array[0..WSADESCRIPTION_LEN] of AnsiChar;
|
||
szSystemStatus: array[0..WSASYS_STATUS_LEN] of AnsiChar;
|
||
iMaxSockets: Word;
|
||
iMaxUdpDg: Word;
|
||
lpVendorInfo: PAnsiChar;
|
||
end;
|
||
|
||
SunB = packed record
|
||
s_b1, s_b2, s_b3, s_b4: byte;
|
||
end;
|
||
|
||
SunW = packed record
|
||
s_w1, s_w2: word;
|
||
end;
|
||
|
||
in_addr = record
|
||
case integer of
|
||
0: (S_un_b: SunB);
|
||
1: (S_un_w: SunW);
|
||
2: (S_addr: dword);
|
||
end;
|
||
|
||
TInAddr = in_addr;
|
||
|
||
sockaddr_in = record
|
||
case Integer of
|
||
0: (sin_family: word;
|
||
sin_port: word;
|
||
sin_addr: TInAddr;
|
||
sin_zero: array[0..7] of AnsiChar);
|
||
1: (sa_family: word;
|
||
sa_data: array[0..13] of AnsiChar)
|
||
end;
|
||
|
||
TSockAddr = sockaddr_in;
|
||
PSOCKADDR = ^TSockAddr;
|
||
|
||
paddrinfoA = ^addrinfoA;
|
||
addrinfoA = packed record
|
||
ai_flags: integer;
|
||
ai_family: integer;
|
||
ai_socktype: integer;
|
||
ai_protocol: integer;
|
||
ai_addrlen: TIESizeT;
|
||
ai_canonname: PAnsiChar;
|
||
ai_addr: PSOCKADDR;
|
||
ai_next: paddrinfoA;
|
||
end;
|
||
|
||
TIE_WSAStartup = function(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;
|
||
TIE_WSACleanup = function(): Integer; stdcall;
|
||
TIE_recv = function(s: pointer; var Buf; len, flags: Integer): Integer; stdcall;
|
||
TIE_send = function(s: pointer; var Buf; len, flags: Integer): Integer; stdcall;
|
||
TIE_socket = function(af, Struct, protocol: Integer): pointer; stdcall;
|
||
TIE_getaddrinfo = function(nodename: PAnsiChar; servname: PAnsiChar; hints: paddrinfoA; var res: paddrinfoA): integer; stdcall;
|
||
TIE_freeaddrinfo = procedure(addr: paddrinfoA); stdcall;
|
||
TIE_connect = function(s: pointer; var name: TSockAddr; namelen: Integer): Integer; stdcall;
|
||
TIE_setsockopt = function(s: pointer; level, optname: Integer; optval: PAnsiChar; optlen: Integer): Integer; stdcall;
|
||
TIE_shutdown = function(s: pointer; how: Integer): Integer; stdcall;
|
||
TIE_closesocket = function(s: pointer): Integer; stdcall;
|
||
|
||
var
|
||
IE_SockLibInitCS: TCriticalSection;
|
||
IE_SockLib: THandle = 0;
|
||
IE_SockLibCount: integer = 0;
|
||
IE_WSAStartup: TIE_WSAStartup = nil;
|
||
IE_WSACleanup: TIE_WSACleanup = nil;
|
||
IE_recv: TIE_recv = nil;
|
||
IE_send: TIE_send = nil;
|
||
IE_socket: TIE_socket = nil;
|
||
IE_getaddrinfo: TIE_getaddrinfo = nil;
|
||
IE_freeaddrinfo: TIE_freeaddrinfo = nil;
|
||
IE_connect: TIE_connect = nil;
|
||
IE_setsockopt: TIE_setsockopt = nil;
|
||
IE_shutdown: TIE_shutdown = nil;
|
||
IE_closesocket: TIE_closesocket = nil;
|
||
|
||
|
||
|
||
function IEInitializeSocketLib: boolean;
|
||
begin
|
||
IE_SockLibInitCS.Enter();
|
||
result := true;
|
||
try
|
||
if IE_SockLibCount = 0 then
|
||
begin
|
||
result := false;
|
||
IE_SockLib := LoadLibrary('Ws2_32.dll');
|
||
if IE_SockLib<>0 then
|
||
begin
|
||
IE_WSAStartup := GetProcAddress(IE_SockLib, 'WSAStartup');
|
||
IE_WSACleanup := GetProcAddress(IE_SockLib, 'WSACleanup');
|
||
IE_recv := GetProcAddress(IE_SockLib, 'recv');
|
||
IE_send := GetProcAddress(IE_SockLib, 'send');
|
||
IE_socket := GetProcAddress(IE_SockLib, 'socket');
|
||
IE_getaddrinfo := GetProcAddress(IE_SockLib, 'getaddrinfo');
|
||
IE_freeaddrinfo := GetProcAddress(IE_SockLib, 'freeaddrinfo');
|
||
IE_connect := GetProcAddress(IE_SockLib, 'connect');
|
||
IE_setsockopt := GetProcAddress(IE_SockLib, 'setsockopt');
|
||
IE_shutdown := GetProcAddress(IE_SockLib, 'shutdown');
|
||
IE_closesocket := GetProcAddress(IE_SockLib, 'closesocket');
|
||
result := assigned(@IE_WSAStartup) and assigned(@IE_WSACleanup) and assigned(@IE_recv) and
|
||
assigned(@IE_send) and assigned(@IE_socket) and assigned(@IE_getaddrinfo) and assigned(@IE_freeaddrinfo) and
|
||
assigned(@IE_connect) and assigned(@IE_setsockopt) and assigned(@IE_shutdown) and assigned(@IE_closesocket);
|
||
if not result then
|
||
FreeLibrary(IE_SockLib);
|
||
end;
|
||
end;
|
||
if result then
|
||
inc(IE_SockLibCount);
|
||
finally
|
||
IE_SockLibInitCS.Leave();
|
||
end;
|
||
end;
|
||
|
||
procedure IEFinalizeSocketLib;
|
||
begin
|
||
IE_SockLibInitCS.Enter();
|
||
try
|
||
dec(IE_SockLibCount);
|
||
if IE_SockLibCount = 0 then
|
||
begin
|
||
FreeLibrary(IE_SockLib);
|
||
IE_SockLib := 0;
|
||
end;
|
||
finally
|
||
IE_SockLibInitCS.Leave();
|
||
end;
|
||
end;
|
||
|
||
constructor TIEClientSocket.Create;
|
||
var
|
||
versionRequired: word;
|
||
WSData: TWSAData;
|
||
begin
|
||
inherited;
|
||
|
||
m_socket := INVALID_SOCKET;
|
||
m_littleEndian := false;
|
||
|
||
versionRequired := 2 or (2 shl 8);
|
||
if not IEInitializeSocketLib() or (IE_WSAStartUp(versionRequired, WSData)<>0) then
|
||
raise EIERFBError.Create('Failed to startup WinSock');
|
||
end;
|
||
|
||
destructor TIEClientSocket.Destroy;
|
||
begin
|
||
IE_WSACleanUp();
|
||
IEFinalizeSocketLib();
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEClientSocket.ReceiveBuffer(buf: pointer; len: integer);
|
||
var
|
||
r, tr: integer;
|
||
begin
|
||
tr := 0;
|
||
while tr < len do
|
||
begin
|
||
r := IE_recv(m_socket, pbyte(buf)^, len-tr, 0);
|
||
if r = 0 then
|
||
raise EIERFBError.Create('Connection closed')
|
||
else
|
||
if r = SOCKET_ERROR then
|
||
raise EIERFBError.Create('Receive error');
|
||
inc(tr, r);
|
||
inc(pbyte(buf), r);
|
||
end;
|
||
end;
|
||
|
||
function TIEClientSocket.ReceiveBufferSilent(buf: pointer; len: integer): Boolean;
|
||
var
|
||
r, tr: integer;
|
||
begin
|
||
result := true;
|
||
tr := 0;
|
||
while tr < len do
|
||
begin
|
||
r := IE_recv(m_socket, pbyte(buf)^, len-tr, 0);
|
||
if (r = 0) or (r = SOCKET_ERROR) then
|
||
begin
|
||
result := false;
|
||
break;
|
||
end;
|
||
inc(tr, r);
|
||
inc(pbyte(buf), r);
|
||
end;
|
||
end;
|
||
|
||
procedure TIEClientSocket.SendBuffer(buf: pointer; len: integer);
|
||
var
|
||
s, ts: integer;
|
||
begin
|
||
ts := 0;
|
||
while ts < len do
|
||
begin
|
||
s := IE_send(m_socket, pbyte(buf)^, len-ts, 0);
|
||
if s = SOCKET_ERROR then
|
||
raise EIERFBError.Create('Send error');
|
||
inc(ts, s);
|
||
inc(pbyte(buf), s);
|
||
end;
|
||
end;
|
||
|
||
function TIEClientSocket.ReceiveByte(): byte;
|
||
begin
|
||
ReceiveBuffer(@result, 1);
|
||
end;
|
||
|
||
function TIEClientSocket.ReceiveByteSilent(var b: Byte): Boolean;
|
||
begin
|
||
result := ReceiveBufferSilent(@b, 1);
|
||
end;
|
||
|
||
procedure TIEClientSocket.ReceivePad(len: integer);
|
||
begin
|
||
while len>0 do
|
||
begin
|
||
ReceiveByte();
|
||
dec(len);
|
||
end;
|
||
end;
|
||
|
||
function TIEClientSocket.ReceiveWord(): word;
|
||
begin
|
||
ReceiveBuffer(@result, 2);
|
||
if not m_littleEndian then
|
||
result := IESwapWord(result);
|
||
end;
|
||
|
||
function TIEClientSocket.ReceiveDWord(): dword;
|
||
begin
|
||
ReceiveBuffer(@result, 4);
|
||
if not m_littleEndian then
|
||
result := IESwapDWord(result);
|
||
end;
|
||
|
||
procedure TIEClientSocket.SendByte(value: byte);
|
||
begin
|
||
SendBuffer(@value, 1);
|
||
end;
|
||
|
||
procedure TIEClientSocket.SendPad(len: integer);
|
||
begin
|
||
while len>0 do
|
||
begin
|
||
SendByte(0);
|
||
dec(len);
|
||
end;
|
||
end;
|
||
|
||
procedure TIEClientSocket.SendWord(value: word);
|
||
begin
|
||
if not m_littleEndian then
|
||
value := IESwapWord(value);
|
||
SendBuffer(@value, 2);
|
||
end;
|
||
|
||
procedure TIEClientSocket.SendDWord(value: dword);
|
||
begin
|
||
if not m_littleEndian then
|
||
value := IESwapDWord(value);
|
||
SendBuffer(@value, 4);
|
||
end;
|
||
|
||
procedure TIEClientSocket.Connect(const Address: string; Port: word);
|
||
var
|
||
addr: paddrinfoA;
|
||
hints: addrinfoA;
|
||
PortStr: AnsiString;
|
||
i: integer;
|
||
dw: dword;
|
||
begin
|
||
try
|
||
m_socket := IE_socket(AF_INET, SOCK_STREAM, 0);
|
||
if m_socket = INVALID_SOCKET then
|
||
raise EIERFBError.Create('Failed to open socket');
|
||
|
||
addr := nil;
|
||
ZeroMemory(@hints, sizeof(addrinfoA));
|
||
hints.ai_family := AF_UNSPEC;
|
||
hints.ai_socktype := SOCK_STREAM;
|
||
hints.ai_protocol := IPPROTO_TCP;
|
||
PortStr := IEIntToStr(Port);
|
||
if IE_getaddrinfo(PAnsiChar(AnsiString(Address)), PAnsiChar(PortStr), @hints, addr) <> 0 then
|
||
raise EIERFBError.Create('Cannot resolve host name');
|
||
i := IE_connect(m_socket, addr^.ai_addr^, addr^.ai_addrlen);
|
||
IE_freeaddrinfo(addr);
|
||
if i = SOCKET_ERROR then
|
||
raise EIERFBError.Create('Connection error');
|
||
|
||
dw := 1;
|
||
IE_setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, PAnsiChar(@dw), sizeof(BOOL));
|
||
except
|
||
if m_socket<>INVALID_SOCKET then
|
||
begin
|
||
IE_shutdown(m_socket, SD_BOTH);
|
||
IE_closesocket(m_socket);
|
||
m_socket := INVALID_SOCKET;
|
||
end;
|
||
raise;
|
||
end;
|
||
end;
|
||
|
||
procedure TIEClientSocket.Disconnect();
|
||
begin
|
||
if Connected then
|
||
begin
|
||
IE_shutdown(m_socket, SD_BOTH);
|
||
IE_closesocket(m_socket);
|
||
m_socket := INVALID_SOCKET;
|
||
end;
|
||
end;
|
||
|
||
function TIEClientSocket.GetConnected: boolean;
|
||
begin
|
||
result := m_socket <> INVALID_SOCKET;
|
||
end;
|
||
|
||
// TIEClientSocket
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
constructor TIEByteArray.Create(InitBlockSize: integer);
|
||
begin
|
||
inherited Create;
|
||
fBlockSize := InitBlockSize;
|
||
fSize := 0;
|
||
fRSize := fBlockSize;
|
||
getmem(Data, fRSize);
|
||
end;
|
||
|
||
destructor TIEByteArray.Destroy;
|
||
begin
|
||
freemem(Data);
|
||
inherited;
|
||
end;
|
||
|
||
procedure TIEByteArray.AddByte(v: byte);
|
||
begin
|
||
SetSize(fSize + 1);
|
||
Data^[fSize - 1] := v;
|
||
end;
|
||
|
||
procedure TIEByteArray.Clear;
|
||
begin
|
||
freemem(Data);
|
||
fSize := 0;
|
||
fRSize := fBlockSize;
|
||
getmem(Data, fRSize);
|
||
end;
|
||
|
||
procedure TIEByteArray.SetSize(v: integer);
|
||
var
|
||
tmp: pbytearray;
|
||
begin
|
||
if v > fSize then
|
||
begin
|
||
// increase
|
||
if v > fRSize then
|
||
begin
|
||
fRSize := v + fBlockSize;
|
||
getmem(tmp, fRSize);
|
||
CopyMemory(tmp, Data, fSize);
|
||
freemem(Data);
|
||
Data := tmp;
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
// decrease
|
||
if v < (fRSize - fBlockSize) then
|
||
begin
|
||
fRSize := v + fBlockSize;
|
||
getmem(tmp, fRSize);
|
||
CopyMemory(tmp, Data, v);
|
||
freemem(Data);
|
||
Data := tmp;
|
||
end;
|
||
end;
|
||
fSize := v;
|
||
end;
|
||
|
||
// returns number of bytes written
|
||
function TIEByteArray.AppendFromStream(Stream: TStream; Count: integer): integer;
|
||
var
|
||
l: integer;
|
||
begin
|
||
l := fSize;
|
||
SetSize(fSize + Count);
|
||
result := Stream.Read(Data^[l], Count);
|
||
if result < Count then
|
||
SetSize(l + result);
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Gestures support
|
||
|
||
var
|
||
IEGesturesUser32Lib: THandle = 0;
|
||
|
||
|
||
|
||
procedure IEInitialize_gestures();
|
||
begin
|
||
IEGesturesUser32Lib := LoadLibrary('User32.dll');
|
||
if IEGesturesUser32Lib <> 0 then
|
||
begin
|
||
IEGetGestureInfo := GetProcAddress(IEGesturesUser32Lib, 'GetGestureInfo');
|
||
IECloseGestureInfoHandle := GetProcAddress(IEGesturesUser32Lib, 'CloseGestureInfoHandle');
|
||
IESetGestureConfig := GetProcAddress(IEGesturesUser32Lib, 'SetGestureConfig');
|
||
IEUnregisterTouchWindow := GetProcAddress(IEGesturesUser32Lib, 'UnregisterTouchWindow');
|
||
if @IEGetGestureInfo = nil then
|
||
IEFinalize_gestures();
|
||
end;
|
||
end;
|
||
|
||
procedure IEFinalize_gestures();
|
||
begin
|
||
if IEGesturesUser32Lib <> 0 then
|
||
begin
|
||
FreeLibrary(IEGesturesUser32Lib);
|
||
IEGesturesUser32Lib := 0;
|
||
end;
|
||
end;
|
||
|
||
function IEHasGestures(): boolean;
|
||
begin
|
||
result := IEGesturesUser32Lib <> 0;
|
||
end;
|
||
|
||
// Gestures support
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
procedure InitIECosineTab;
|
||
var
|
||
i: integer;
|
||
begin
|
||
for i := 0 to 255 do
|
||
IECosineTab[i] := Round(64 - Cos(i * Pi / 255) * 64);
|
||
end;
|
||
|
||
procedure IEBezier2D4Controls(p0: TPoint; c0: TPoint; c1: TPoint; p1: TPoint; pResultArray: PPointArray; nSteps: integer);
|
||
var
|
||
t, t_sq, t_cb, incr, r1, r2, r3, r4: double ;
|
||
i: integer ;
|
||
begin
|
||
incr := 1.0/nSteps;
|
||
t := incr;
|
||
for i := 0 to nSteps-1 do
|
||
begin
|
||
t_sq := t * t;
|
||
t_cb := t * t_sq;
|
||
r1 := 1 - 3*t + 3*t_sq - t_cb;
|
||
r2 := 3*t - 6*t_sq + 3*t_cb;
|
||
r3 := 3*t_sq - 3*t_cb;
|
||
r4 := t_cb;
|
||
pResultArray[i].x := round(r1*p0.x + r2*c0.x + r3*c1.x + r4*p1.x);
|
||
pResultArray[i].y := round(r1*p0.y + r2*c0.y + r3*c1.y + r4*p1.y);
|
||
t := t+incr;
|
||
end;
|
||
end;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/// GRADIENT
|
||
|
||
const
|
||
GRADIENT_FILL_RECT_V = $00000001;
|
||
GRADIENT_FILL_RECT_H = $00000000;
|
||
|
||
type
|
||
Trivertex = packed record
|
||
X, Y: DWORD;
|
||
Red, Green, Blue, Alpha: Word;
|
||
end;
|
||
|
||
TGradientFill = function(DC: HDC; pVertex: Pointer; dwNumVertex: DWORD; pMesh: Pointer; dwNumMesh, dwMode: DWORD): LongBool; stdcall;
|
||
|
||
TRGBRec = packed record
|
||
case Integer of
|
||
1: (RGBVal: LongInt);
|
||
0: (Red, Green, Blue, None: Byte);
|
||
end;
|
||
|
||
TGradientRect = packed record
|
||
UpperLeft: ULONG;
|
||
LowerRight: ULONG;
|
||
end;
|
||
|
||
|
||
var
|
||
FhGradientFill: HMODULE;
|
||
FGradientFill: TGradientFill;
|
||
|
||
function LoadGradLibrary: boolean;
|
||
begin
|
||
result := True;
|
||
if FhGradientFill = 0 then
|
||
begin
|
||
FhGradientFill := LoadLibrary('MSIMG32.DLL');
|
||
if FhGradientFill > 0 then
|
||
FGradientFill := GetProcAddress(FhGradientFill, 'GradientFill')
|
||
else
|
||
result := false; // MSIMG32 could not be loaded
|
||
end;
|
||
end;
|
||
|
||
function IEDrawGradient(R: TRect; DC: HDC; ColorStart, ColorStop: TColor; bVertical: boolean): Boolean;
|
||
var
|
||
Gr: TGradientRect;
|
||
Vert: array[0..1] of Trivertex;
|
||
StartColor, StopColor: TRGBRec;
|
||
begin
|
||
result := LoadGradLibrary;
|
||
if not result then
|
||
exit;
|
||
StartColor.RGBVal := ColorToRGB(ColorStart);
|
||
StopColor.RGBVal := ColorToRGB(ColorStop);
|
||
|
||
Gr.UpperLeft := 0;
|
||
Gr.LowerRight := 1;
|
||
|
||
Vert[0].x := r.TopLeft.x;
|
||
Vert[0].y := r.TopLeft.y;
|
||
Vert[0].Red := StartColor.Red shl 8;
|
||
Vert[0].Green := StartColor.Green shl 8;
|
||
Vert[0].Blue := StartColor.Blue shl 8;
|
||
Vert[0].Alpha := $0000;
|
||
|
||
Vert[1].x := r.BottomRight.x;
|
||
Vert[1].y := r.BottomRight.y;
|
||
Vert[1].Red := StopColor.Red shl 8;
|
||
Vert[1].Green := StopColor.Green shl 8;
|
||
Vert[1].Blue := StopColor.Blue shl 8;
|
||
Vert[1].Alpha := $0000;
|
||
|
||
if bVertical then
|
||
Result := FGradientFill(DC, @Vert, 2, @Gr, 1, GRADIENT_FILL_RECT_V)
|
||
else
|
||
Result := FGradientFill(DC, @Vert, 2, @Gr, 1, GRADIENT_FILL_RECT_H);
|
||
end;
|
||
|
||
// Return the standard BitsPerSample and SamplesPerPixel for a PixelFormat
|
||
procedure IEPixelFormatToBPSAndSPP(PixelFormat: TIEPixelFormat; out iBitsPerSample: Integer; out iSamplesPerPixel: Integer);
|
||
begin
|
||
case PixelFormat of
|
||
|
||
ie1g:
|
||
begin
|
||
iBitsPerSample := 1;
|
||
iSamplesPerPixel := 1;
|
||
end;
|
||
|
||
ie8p, ie8g:
|
||
begin
|
||
iBitsPerSample := 8;
|
||
iSamplesPerPixel := 1;
|
||
end;
|
||
|
||
ie16g:
|
||
begin
|
||
iBitsPerSample := 16;
|
||
iSamplesPerPixel := 1;
|
||
end;
|
||
|
||
else { ie24RGB }
|
||
begin
|
||
iBitsPerSample := 8;
|
||
iSamplesPerPixel := 3;
|
||
end;
|
||
|
||
end;
|
||
end;
|
||
|
||
// Return the standard BitsPerSample and SamplesPerPixel for a BitCount
|
||
// bAllow32bit=False: 32 bit return the same as 24bit
|
||
procedure BitCountToBPSAndSPP(BitCount: Integer; bAllow32bit: Boolean; out iBitsPerSample: Integer; out iSamplesPerPixel: Integer);
|
||
begin
|
||
case BitCount of
|
||
|
||
1:
|
||
begin
|
||
iBitsPerSample := 1;
|
||
iSamplesPerPixel := 1;
|
||
end;
|
||
|
||
4:
|
||
begin
|
||
iBitsPerSample := 4;
|
||
iSamplesPerPixel := 1;
|
||
end;
|
||
|
||
8:
|
||
begin
|
||
iBitsPerSample := 8;
|
||
iSamplesPerPixel := 1;
|
||
end;
|
||
|
||
15:
|
||
begin
|
||
iBitsPerSample := 5;
|
||
iSamplesPerPixel := 3;
|
||
end;
|
||
|
||
32:
|
||
if bAllow32bit then
|
||
begin
|
||
iBitsPerSample := 8;
|
||
iSamplesPerPixel := 4;
|
||
end
|
||
else
|
||
begin
|
||
iBitsPerSample := 8;
|
||
iSamplesPerPixel := 3;
|
||
end;
|
||
|
||
else { 16, 24 }
|
||
begin
|
||
iBitsPerSample := 8;
|
||
iSamplesPerPixel := 3;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function ProgressRec(Sender: TObject; OnProgress: TIEProgressEvent; var bAborting: Boolean) : TProgressRec;
|
||
begin
|
||
Result.Sender := Sender;
|
||
Result.fOnProgress := OnProgress;
|
||
Result.Aborting := @bAborting;
|
||
end;
|
||
|
||
function ProgressRec(Sender: TObject; OnProgress: TIEProgressEvent; pAborting: PBoolean) : TProgressRec;
|
||
begin
|
||
Result.Sender := Sender;
|
||
Result.fOnProgress := OnProgress;
|
||
Result.Aborting := pAborting;
|
||
end;
|
||
|
||
|
||
function NullProgressRec(var bAborting: Boolean; bResetAborting : Boolean = true) : TProgressRec;
|
||
begin
|
||
if bResetAborting then
|
||
bAborting := False;
|
||
Result.Sender := nil;
|
||
Result.fOnProgress := nil;
|
||
Result.Aborting := @bAborting;
|
||
end;
|
||
|
||
function NullProgressRec(pAborting: PBoolean; bResetAborting : Boolean = true) : TProgressRec;
|
||
begin
|
||
if bResetAborting and ( pAborting <> nil ) then
|
||
pAborting^ := False;
|
||
Result.Sender := nil;
|
||
Result.fOnProgress := nil;
|
||
Result.Aborting := pAborting;
|
||
end;
|
||
|
||
|
||
{$IfNdef Delphi6orNewer}
|
||
function RoundTo(const AValue: Double; ADigit: Integer): Double;
|
||
var
|
||
LFactor: Double;
|
||
begin
|
||
LFactor := IntPower(10, ADigit);
|
||
Result := Round(AValue / LFactor) * LFactor;
|
||
end;
|
||
{$endif}
|
||
|
||
{$IfNdef Delphi6orNewer}
|
||
function Sign(const AValue: Double): Integer;
|
||
begin
|
||
if AValue < 0 then
|
||
Result := -1
|
||
else
|
||
if AValue > 0 then
|
||
Result := 1
|
||
else
|
||
Result := 0;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
procedure IESetStringA(var S: AnsiString; Buffer: PAnsiChar; Length: Integer);
|
||
begin
|
||
SetLength(S, Length);
|
||
CopyMemory(@S[1], Buffer, Length);
|
||
end;
|
||
|
||
|
||
{$IfNdef Delphi7orNewer}
|
||
function BoolToStr(B: Boolean): string;
|
||
const
|
||
cSimpleBoolStrs: array [boolean] of String = ('0', '-1');
|
||
begin
|
||
Result := cSimpleBoolStrs[B];
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
function IECreateRect(Left, Top, Right, Bottom: Integer): TRect;
|
||
begin
|
||
{$IfNdef Delphi7orNewer}
|
||
Result.Left := Left;
|
||
Result.Top := Top;
|
||
Result.Right := Right;
|
||
Result.Bottom := Bottom;
|
||
{$else}
|
||
Result := Types.Rect(Left, Top, Right, Bottom);
|
||
{$endif}
|
||
end;
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
var
|
||
ieImageEnInitializedMagik: AnsiString;
|
||
ieImageEnInitialized: integer; // 0=not inizialized >0 initialized n times
|
||
ieImageEnInit_CS: TCriticalSection;
|
||
|
||
|
||
// IEInitializeImageEn and IEFinalizeImageEn must be called in initialization/finalization section only of hyieutils
|
||
// or in constructor/descructors of objects, or in functions, but not in initialization/finalization section of other units.
|
||
// Attention to deadlocks (for example you cannot call IEInitializeImageEn in TImageEnIO creator).
|
||
|
||
procedure IEInitializeImageEn;
|
||
begin
|
||
if ieImageEnInitializedMagik <> 'STATICINIT' then
|
||
begin
|
||
// static variables not still intialized, do it here
|
||
ieImageEnInitializedMagik := 'STATICINIT';
|
||
ieImageEnInitialized := 0;
|
||
ieImageEnInit_CS := TCriticalSection.Create();
|
||
end;
|
||
ieImageEnInit_CS.Enter();
|
||
try
|
||
if ieImageEnInitialized = 0 then
|
||
begin
|
||
// initialize
|
||
IEInitialize_iegdiplus();
|
||
IEInitialize_hyiedefs();
|
||
IEInitialize_hyieutils();
|
||
IEInitialize_ievect();
|
||
IEInitialize_imageenio();
|
||
IEInitialize_iexBitmaps;
|
||
IEInitialize_imageenproc();
|
||
IEInitialize_imageenview();
|
||
IEInitialize_tifccitt();
|
||
IEInitialize_ietextc();
|
||
IEInitialize_iepresetim();
|
||
IEInitialize_gestures();
|
||
end;
|
||
inc(ieImageEnInitialized);
|
||
finally
|
||
ieImageEnInit_CS.Leave();
|
||
end;
|
||
end;
|
||
|
||
procedure IEFinalizeImageEn;
|
||
var
|
||
freecriticalsec: boolean;
|
||
begin
|
||
if ieImageEnInitializedMagik<>'STATICINIT' then
|
||
exit;
|
||
freecriticalsec := false;
|
||
ieImageEnInit_CS.Enter();
|
||
try
|
||
dec(ieImageEnInitialized);
|
||
if ieImageEnInitialized = 0 then
|
||
begin
|
||
// finalize
|
||
IEFinalize_gestures();
|
||
IEFinalize_iepresetim();
|
||
IEFinalize_ietextc();
|
||
IEFinalize_tifccitt();
|
||
IEFinalize_imageenview();
|
||
IEFinalize_imageenproc();
|
||
IEFinalize_imageenio();
|
||
IEFinalize_iexBitmaps;
|
||
IEFinalize_ievect();
|
||
{$IFDEF IEINCLUDEJPEG2000}
|
||
IEFinalize_iej2000(); // initialized in iej2000 reading/writing functions (not in IEInitializeImageEn)
|
||
{$ENDIF}
|
||
IEFinalize_hyieutils();
|
||
IEFinalize_hyiedefs();
|
||
IEFinalize_iegdiplus();
|
||
{$IFDEF IEVISION}
|
||
// note: initialization done in IEVisionAvailable() and IELibAvailable() instead of IEInitializeImageEn()
|
||
IEFinalize_ielib();
|
||
IEFinalize_ievision();
|
||
{$ENDIF}
|
||
{$IFDEF IEINCLUDEMISCPLUGINS}
|
||
TIEMiscPluginsImageMagick.Finalize();
|
||
{$ENDIF}
|
||
IEGlobalSettings().DestroySingletonInstance();
|
||
|
||
ieImageEnInitializedMagik := '';
|
||
freecriticalsec := true;
|
||
end;
|
||
finally
|
||
ieImageEnInit_CS.Leave();
|
||
if freecriticalsec then
|
||
FreeAndNil(ieImageEnInit_CS);
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
|
||
procedure IEPrintLogWrite(const ss: String);
|
||
begin
|
||
if iegPrintLogFileName <> '' then
|
||
begin
|
||
closefile(iegPrintLogFile);
|
||
assignfile(iegPrintLogFile, string(iegPrintLogFileName));
|
||
append(iegPrintLogFile);
|
||
WriteLn(iegPrintLogFile, datetostr(date) + ' ' + timetostr(time) + ' : ' + ss);
|
||
Flush(iegPrintLogFile);
|
||
end;
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
procedure iedswap(var d1, d2: Double);
|
||
var
|
||
v: Double;
|
||
begin
|
||
v := d1;
|
||
d1 := d2;
|
||
d2 := v;
|
||
end;
|
||
|
||
procedure i64swap(var v1, v2: int64);
|
||
var
|
||
v: int64;
|
||
begin
|
||
v := v1;
|
||
v1 := v2;
|
||
v2 := v;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function Floor(X: Extended): Integer;
|
||
begin
|
||
Result := Trunc(X);
|
||
if Frac(X) < 0 then
|
||
Dec(Result);
|
||
end;
|
||
|
||
|
||
function CreateCMYK(c, m, y, k: byte): TCMYK;
|
||
begin
|
||
result.c := c;
|
||
result.m := m;
|
||
result.y := y;
|
||
result.k := k;
|
||
end;
|
||
|
||
function CreateRGB(r, g, b: byte): TRGB;
|
||
begin
|
||
result.r := r;
|
||
result.g := g;
|
||
result.b := b;
|
||
end;
|
||
|
||
function CreateRGB48(r, g, b: word): TRGB48;
|
||
begin
|
||
result.r := r;
|
||
result.g := g;
|
||
result.b := b;
|
||
end;
|
||
|
||
|
||
function CreateRGBA(r, g, b, a: byte): TRGBA;
|
||
begin
|
||
result.r := r;
|
||
result.g := g;
|
||
result.b := b;
|
||
result.a := a;
|
||
end;
|
||
|
||
function CreateRGBFromInt(r, g, b: Integer): TRGB;
|
||
begin
|
||
result.r := blimit(r);
|
||
result.g := blimit(g);
|
||
result.b := blimit(b);
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function TRGB2TColor(rgb: TRGB): TColor;
|
||
begin
|
||
with rgb do
|
||
result := r or (g shl 8) or (b shl 16);
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function RGB2TColor(r, g, b: Integer): TColor;
|
||
begin
|
||
result := r or (g shl 8) or (b shl 16);
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function TColor2TRGB(cl: TColor): TRGB;
|
||
var
|
||
rgb: longint;
|
||
begin
|
||
rgb := colortorgb(cl);
|
||
result.r := $FF and rgb;
|
||
result.g := ($FF00 and rgb) shr 8;
|
||
result.b := ($FF0000 and rgb) shr 16;
|
||
end;
|
||
|
||
function TColor2TRGBA(cl: TColor; transparency: Integer): TRGBA;
|
||
var
|
||
rgb: longint;
|
||
begin
|
||
rgb := colortorgb(cl);
|
||
result.r := $FF and rgb;
|
||
result.g := ($FF00 and rgb) shr 8;
|
||
result.b := ($FF0000 and rgb) shr 16;
|
||
result.a := transparency;
|
||
end;
|
||
|
||
// gets alpha from TColor
|
||
// Cannot accept colors like clRed
|
||
function TColor2TRGBA(cl: TColor): TRGBA;
|
||
var
|
||
rgb: longint;
|
||
begin
|
||
rgb := colortorgb(cl);
|
||
result.r := $FF and rgb;
|
||
result.g := ($FF00 and rgb) shr 8;
|
||
result.b := ($FF0000 and rgb) shr 16;
|
||
result.a := ($FF000000 and rgb) shr 24;
|
||
end;
|
||
|
||
|
||
function IEApplyAlphaToColor(rgb: TRGB; Alpha: Integer): TRGB;
|
||
begin
|
||
Result := rgb;
|
||
|
||
if (Result.r = 255) and (Result.g = 255) and (Result.b = 255) then
|
||
begin
|
||
// All white
|
||
Result.r := Alpha;
|
||
Result.g := Alpha;
|
||
Result.b := Alpha;
|
||
end
|
||
else
|
||
begin
|
||
Result.r := Trunc( Alpha / 255 * Result.r ) + ( 255 - Alpha );
|
||
Result.g := Trunc( Alpha / 255 * Result.g ) + ( 255 - Alpha );
|
||
Result.b := Trunc( Alpha / 255 * Result.b ) + ( 255 - Alpha );
|
||
end;
|
||
end;
|
||
|
||
function IEApplyAlphaToColor(Color: TColor; Alpha: Integer): TColor;
|
||
begin
|
||
Result := TRGB2TColor( IEApplyAlphaToColor( TColor2TRGB( Color ), Alpha ));
|
||
end;
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function dmin(v1, v2: Double): Double;
|
||
begin
|
||
if v1 < v2 then
|
||
dmin := v1
|
||
else
|
||
dmin := v2;
|
||
end;
|
||
|
||
function dmax(v1, v2: Double): Double;
|
||
begin
|
||
if v1 > v2 then
|
||
dmax := v1
|
||
else
|
||
dmax := v2;
|
||
end;
|
||
|
||
function dwmax(v1, v2: DWord): DWord;
|
||
begin
|
||
if v1 > v2 then
|
||
result := v1
|
||
else
|
||
result := v2;
|
||
end;
|
||
|
||
function imax(v1, v2: Integer): Integer;
|
||
{$ifdef IEUSEASM}
|
||
asm
|
||
cmp edx,eax
|
||
jng @1
|
||
mov eax,edx
|
||
@1:
|
||
end;
|
||
{$else}
|
||
begin
|
||
if v1 > v2 then
|
||
result := v1
|
||
else
|
||
result := v2;
|
||
end;
|
||
{$endif}
|
||
|
||
function imin(v1, v2: Integer): Integer;
|
||
{$ifdef IEUSEASM}
|
||
asm
|
||
cmp eax,edx
|
||
jng @1
|
||
mov eax,edx
|
||
@1:
|
||
end;
|
||
{$else}
|
||
begin
|
||
if v1 < v2 then
|
||
result := v1
|
||
else
|
||
result := v2;
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
{$ifdef IEHASUINT64}
|
||
function u64min(v1, v2: uint64): uint64;
|
||
begin
|
||
if v1 < v2 then
|
||
result := v1
|
||
else
|
||
result := v2;
|
||
end;
|
||
{$endif}
|
||
|
||
function i64min(v1, v2: int64): int64;
|
||
begin
|
||
if v1 < v2 then
|
||
result := v1
|
||
else
|
||
result := v2;
|
||
end;
|
||
|
||
function i64max(v1, v2: int64): int64;
|
||
begin
|
||
if v1 > v2 then
|
||
result := v1
|
||
else
|
||
result := v2;
|
||
end;
|
||
|
||
|
||
// vv=eax result=eax
|
||
// min=edx
|
||
// max=ecx
|
||
function ilimit(vv, min, max: Integer): Integer;
|
||
{$ifdef IEUSEASM}
|
||
asm
|
||
cmp eax,edx
|
||
jg @1 // vv>min
|
||
mov eax,edx
|
||
ret
|
||
@1:
|
||
cmp eax,ecx
|
||
jl @2 // vv<min
|
||
mov eax,ecx
|
||
ret
|
||
@2:
|
||
end;
|
||
{$else}
|
||
begin
|
||
if vv < min then
|
||
result := min
|
||
else
|
||
if vv > max then
|
||
result := max
|
||
else
|
||
result := vv;
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
// limit 0 between 255
|
||
function blimit(vv: Integer): Integer;
|
||
{$ifdef IEUSEASM}
|
||
asm
|
||
OR EAX, EAX
|
||
JNS @@plus
|
||
XOR EAX, EAX
|
||
RET
|
||
|
||
@@plus:
|
||
CMP EAX, 255
|
||
JBE @@END
|
||
MOV EAX, 255
|
||
@@END:
|
||
end;
|
||
{$else}
|
||
begin
|
||
if vv < 0 then
|
||
result := 0
|
||
else
|
||
if vv > 255 then
|
||
result := 255
|
||
else
|
||
result := vv;
|
||
end;
|
||
{$endif}
|
||
|
||
function wlimit(vv: Integer): word;
|
||
begin
|
||
if vv < 0 then
|
||
result := 0
|
||
else
|
||
if vv>65535 then
|
||
result := 65535
|
||
else
|
||
result := vv;
|
||
end;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
{$ifdef IEUSEASM}
|
||
procedure iswap(var B1, B2: LongInt); assembler;
|
||
asm
|
||
push EBX
|
||
mov ecx, [EAX];
|
||
mov ebx, [EDX];
|
||
mov [EDX], ecx
|
||
mov [EAX], ebx
|
||
pop EBX
|
||
end;
|
||
{$else}
|
||
procedure iswap(var B1, B2: LongInt);
|
||
var
|
||
temp: LongInt;
|
||
begin
|
||
temp := B1;
|
||
B1 := B2;
|
||
B2 := temp;
|
||
end;
|
||
{$endif}
|
||
|
||
{$ifdef IEUSEASM}
|
||
procedure dwswap(var B1, B2: dword); assembler;
|
||
asm
|
||
push EBX
|
||
mov ecx, [EAX];
|
||
mov ebx, [EDX];
|
||
mov [EDX], ecx
|
||
mov [EAX], ebx
|
||
pop EBX
|
||
end;
|
||
{$else}
|
||
procedure dwswap(var B1, B2: dword);
|
||
var
|
||
temp: dword;
|
||
begin
|
||
temp := B1;
|
||
B1 := B2;
|
||
B2 := temp;
|
||
end;
|
||
{$endif}
|
||
|
||
procedure dswap(var v1, v2: Double);
|
||
var
|
||
t: Double;
|
||
begin
|
||
t := v1;
|
||
v1 := v2;
|
||
v2 := t;
|
||
end;
|
||
|
||
function EqualRGB(rgb1, rgb2: TRGB): Boolean;
|
||
begin
|
||
result := (rgb1.r = rgb2.r) and (rgb1.g = rgb2.g) and (rgb1.b = rgb2.b);
|
||
end;
|
||
|
||
|
||
function IEAverageColor(c1, c2 : TColor): TColor;
|
||
begin
|
||
Result := TRGB2TCOLOR( IEAverageColor( TColor2TRGB( c1 ), TColor2TRGB( c2 ) ));
|
||
end;
|
||
|
||
function IEAverageColor(rgb1, rgb2 : TRGB): TRGB;
|
||
begin
|
||
Result := CreateRGB( ( rgb1.r + rgb2.r ) div 2,
|
||
( rgb1.g + rgb2.g ) div 2,
|
||
( rgb1.b + rgb2.b ) div 2 );
|
||
end;
|
||
|
||
|
||
{$ifdef IEUSEASM}
|
||
procedure bswap(var B1, B2: Byte); assembler;
|
||
asm
|
||
mov cl, Byte Ptr [EAX];
|
||
mov ch, Byte Ptr [EDX];
|
||
mov Byte Ptr [EDX], cl
|
||
mov Byte Ptr [EAX], ch
|
||
end;
|
||
{$else}
|
||
procedure bswap(var B1, B2: byte);
|
||
var
|
||
temp: byte;
|
||
begin
|
||
temp := B1;
|
||
B1 := B2;
|
||
B2 := temp;
|
||
end;
|
||
{$endif}
|
||
|
||
// order two coordinates, putting the first as top-left
|
||
procedure OrdCor(var x1, y1, x2, y2: Integer);
|
||
begin
|
||
if x1 > x2 then
|
||
iswap(x1, x2);
|
||
if y1 > y2 then
|
||
iswap(y1, y2);
|
||
end;
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
// Hue, Sat, Lum from 0 to 1
|
||
procedure ColorToHSL(cl: TColor; var Hue, Sat, Lum: Double);
|
||
var
|
||
RGB: TRGB;
|
||
begin
|
||
RGB := TColor2TRGB( cl );
|
||
RGB2HSL( RGB, Hue, Sat, Lum );
|
||
end;
|
||
|
||
// Hue, Sat, Lum from 0 to 1
|
||
procedure RGB2HSL(px: TRGB; var Hue, Sat, Lum: Double);
|
||
var
|
||
delta, r, g, b, cmax, cmin: Double;
|
||
begin
|
||
r := px.r / 255;
|
||
g := px.g / 255;
|
||
b := px.b / 255;
|
||
cmax := dmax(r, dmax(g, b));
|
||
cmin := dmin(r, dmin(g, b));
|
||
Lum := (cmax + cmin) / 2;
|
||
if cmax = cmin then
|
||
begin
|
||
Sat := 0;
|
||
Hue := 0;
|
||
end
|
||
else
|
||
begin
|
||
if Lum < 0.5 then
|
||
Sat := (cmax - cmin) / (cmax + cmin)
|
||
else
|
||
Sat := (cmax - cmin) / (2 - cmax - cmin);
|
||
delta := cmax - cmin;
|
||
if r = cmax then
|
||
Hue := (g - b) / delta
|
||
else
|
||
if g = cmax then
|
||
Hue := 2 + (b - r) / delta
|
||
else
|
||
Hue := 4 + (r - g) / delta;
|
||
Hue := Hue / 6;
|
||
if Hue < 0 then
|
||
Hue := Hue + 1;
|
||
end;
|
||
end;
|
||
|
||
|
||
// Hue, Sat, Lum: 0..1
|
||
function HSLToColor(Hue, Sat, Lum: Double) : TColor;
|
||
var
|
||
RGB: TRGB;
|
||
begin
|
||
HSL2RGB( RGB, Hue, Sat, Lum );
|
||
Result := TRGB2TColor( RGB );
|
||
end;
|
||
|
||
|
||
// Hue, Sat, Lum: 0..1
|
||
procedure HSL2RGB(var px: TRGB; Hue, Sat, Lum: Double);
|
||
|
||
function HueToRGB(m1, m2, h: Double): Double;
|
||
const
|
||
C1 = 2 / 3;
|
||
begin
|
||
if h < 0 then
|
||
h := h + 1
|
||
else
|
||
if h > 1 then
|
||
h := h - 1;
|
||
if 6 * h < 1 then
|
||
result := (m1 + (m2 - m1) * h * 6)
|
||
else
|
||
if 2 * h < 1 then
|
||
result := m2
|
||
else
|
||
if 3 * h < 2 then
|
||
result := (m1 + (m2 - m1) * (C1 - h) * 6)
|
||
else
|
||
result := m1;
|
||
end;
|
||
|
||
const
|
||
C1 = 1 / 3;
|
||
var
|
||
r, g, b: Double;
|
||
m1, m2: Double;
|
||
begin
|
||
// check limits
|
||
if Hue < 0 then
|
||
Hue := 1 + Hue
|
||
else
|
||
if Hue > 1 then
|
||
Hue := Hue - 1;
|
||
if Sat < 0 then
|
||
Sat := 0
|
||
else
|
||
if Sat > 1 then
|
||
Sat := 1;
|
||
if Lum < 0 then
|
||
Lum := 0
|
||
else
|
||
if Lum > 1 then
|
||
Lum := 1;
|
||
//
|
||
if Sat = 0 then
|
||
begin
|
||
r := Lum;
|
||
g := Lum;
|
||
b := Lum;
|
||
end
|
||
else
|
||
begin
|
||
if Lum <= 0.5 then
|
||
m2 := Lum * (1 + Sat)
|
||
else
|
||
m2 := Lum + Sat - Lum * Sat;
|
||
m1 := 2 * Lum - m2;
|
||
r := HueToRGB(m1, m2, Hue + C1);
|
||
g := HueToRGB(m1, m2, Hue);
|
||
b := HueToRGB(m1, m2, Hue - C1);
|
||
end;
|
||
px.r := blimit(round(r * 255));
|
||
px.g := blimit(round(g * 255));
|
||
px.b := blimit(round(b * 255));
|
||
end;
|
||
|
||
// HSV to RGB.
|
||
// H = 0 to 359 (corresponding to 0..359 degrees around hexcone)
|
||
// S = 0 (shade of gray) to 99 (pure color)
|
||
// V = 0 (black) to 99 {white)
|
||
//
|
||
// Based on C Code in "Computer Graphics -- Principles and Practice"
|
||
// Foley et al, 1996, p. 594. Floating point fractions, 0..1, replaced with
|
||
// integer values, 0..99.
|
||
|
||
procedure HSV2RGB(var px: TRGB; H, S, V: Integer);
|
||
const
|
||
divisor: Integer = 99 * 60;
|
||
var
|
||
f: Integer;
|
||
hTemp: Integer;
|
||
p, q, t: Integer;
|
||
VS: Integer;
|
||
begin
|
||
// check limits (changed at 2.1.1)
|
||
if H < 0 then
|
||
H := 360 + H
|
||
else
|
||
if H > 359 then
|
||
H := H - 360;
|
||
if S < 0 then
|
||
S := 0
|
||
else
|
||
if S > 99 then
|
||
S := 99;
|
||
if V < 0 then
|
||
V := 0
|
||
else
|
||
if V > 99 then
|
||
V := 99;
|
||
//
|
||
if S = 0 then
|
||
begin
|
||
px.r := v;
|
||
px.g := v;
|
||
px.b := v;
|
||
end
|
||
else
|
||
begin
|
||
if H = 360 then
|
||
hTemp := 0
|
||
else
|
||
hTemp := H;
|
||
f := hTemp mod 60;
|
||
hTemp := hTemp div 60;
|
||
VS := V * S;
|
||
p := V - VS div 99;
|
||
q := V - (VS * f) div divisor;
|
||
t := V - (VS * (60 - f)) div divisor;
|
||
with px do
|
||
begin
|
||
case hTemp of
|
||
0:
|
||
begin
|
||
R := V;
|
||
G := t;
|
||
B := p
|
||
end;
|
||
1:
|
||
begin
|
||
R := q;
|
||
G := V;
|
||
B := p
|
||
end;
|
||
2:
|
||
begin
|
||
R := p;
|
||
G := V;
|
||
B := t
|
||
end;
|
||
3:
|
||
begin
|
||
R := p;
|
||
G := q;
|
||
B := V
|
||
end;
|
||
4:
|
||
begin
|
||
R := t;
|
||
G := p;
|
||
B := V
|
||
end;
|
||
5:
|
||
begin
|
||
R := V;
|
||
G := p;
|
||
B := q
|
||
end;
|
||
end
|
||
end
|
||
end;
|
||
px.r := round(px.r / 99 * 255);
|
||
px.g := round(px.g / 99 * 255);
|
||
px.b := round(px.b / 99 * 255);
|
||
end;
|
||
|
||
|
||
function HSVToColor(h, s, v: Integer): TColor;
|
||
var
|
||
RGB: TRGB;
|
||
begin
|
||
HSV2RGB( RGB, h, s, v );
|
||
Result := TRGB2TColor( RGB );
|
||
end;
|
||
|
||
// RGB, each 0 to 255, to HSV.
|
||
// H = 0 to 359 (corresponding to 0..359 degrees around hexcone)
|
||
// S = 0 (shade of gray) to 99 (pure color)
|
||
// V = 0 (black) to 99 {white)
|
||
//
|
||
// Based on C Code in "Computer Graphics -- Principles and Practice"
|
||
// Foley et al, 1996, p. 592. Floating point fractions, 0..1, replaced with
|
||
// integer values, 0..99.
|
||
|
||
procedure RGB2HSV(RGB: TRGB; var h, s, v: Integer);
|
||
|
||
procedure MinMaxInt(const i, j, k: Integer; var min, max: Integer);
|
||
begin
|
||
if i > j then
|
||
begin
|
||
if i > k then
|
||
max := i
|
||
else
|
||
max := k;
|
||
if j < k then
|
||
min := j
|
||
else
|
||
min := k
|
||
end
|
||
else
|
||
begin
|
||
if j > k then
|
||
max := j
|
||
else
|
||
max := k;
|
||
if i < k then
|
||
min := i
|
||
else
|
||
min := k
|
||
end;
|
||
end;
|
||
|
||
var
|
||
Delta: Integer;
|
||
MinValue: Integer;
|
||
r, g, b: Integer;
|
||
begin
|
||
r := round(RGB.r / 255 * 99);
|
||
g := round(RGB.g / 255 * 99);
|
||
b := round(RGB.b / 255 * 99);
|
||
MinMaxInt(R, G, B, MinValue, V);
|
||
Delta := V - MinValue;
|
||
if V = 0 then
|
||
S := 0
|
||
else
|
||
S := (99 * Delta) div V;
|
||
if S = 0 then
|
||
H := 0
|
||
else
|
||
begin
|
||
if R = V then
|
||
h := (60 * (G - B)) div Delta
|
||
else
|
||
if G = V then
|
||
h := 120 + (60 * (B - R)) div Delta
|
||
else
|
||
if B = V then
|
||
h := 240 + (60 * (R - G)) div Delta;
|
||
if H < 0 then
|
||
H := H + 360;
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure ColorToHSV(cl: TColor; var h, s, v: Integer);
|
||
var
|
||
RGB: TRGB;
|
||
begin
|
||
RGB := TColor2TRGB( cl );
|
||
RGB2HSV( RGB, h, s, v );
|
||
end;
|
||
|
||
|
||
// HTML Color
|
||
function ColorToHex(Color : TColor): string;
|
||
begin
|
||
Result := '#' +
|
||
{ red value }
|
||
IntToHex( GetRValue( Color ), 2 ) +
|
||
{ green value }
|
||
IntToHex( GetGValue( Color ), 2 ) +
|
||
{ blue value }
|
||
IntToHex( GetBValue( Color ), 2 );
|
||
end;
|
||
|
||
|
||
|
||
procedure YUV2RGB(y, u, v: Integer; var RGB: TRGB);
|
||
begin
|
||
with RGB do
|
||
begin
|
||
b := blimit(round(1.164 * (y - 16) + 2.018 * (u - 128)));
|
||
g := blimit(round(1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128)));
|
||
r := blimit(round(1.164 * (y - 16) + 1.596 * (v - 128)));
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Thanks to Roy Klever
|
||
|
||
procedure IERGBtoHSB(const cRed, cGreen, cBlue: byte; var H, S, B: word);
|
||
|
||
procedure MinMaxByte(const i, j, k: byte; var min: Integer; var max: word);
|
||
begin
|
||
if i > j then
|
||
begin
|
||
if i > k then
|
||
max := i
|
||
else
|
||
max := k;
|
||
if j < k then
|
||
min := j
|
||
else
|
||
min := k
|
||
end
|
||
else
|
||
begin
|
||
if j > k then
|
||
max := j
|
||
else
|
||
max := k;
|
||
if i < k then
|
||
min := i
|
||
else
|
||
min := k
|
||
end;
|
||
end;
|
||
|
||
var
|
||
Delta: Integer;
|
||
MinValue: Integer;
|
||
tmpH: Integer;
|
||
begin
|
||
tmpH := 0;
|
||
MinMaxByte(cRed, cGreen, cBlue, MinValue, B);
|
||
Delta := B - MinValue;
|
||
if B = 0 then
|
||
S := 0
|
||
else
|
||
S := (255 * Delta) div B;
|
||
if S = 0 then
|
||
tmpH := 0
|
||
else
|
||
begin
|
||
if cRed = B then
|
||
tmpH := (60 * (cGreen - cBlue)) div Delta
|
||
else
|
||
if cGreen = B then
|
||
tmpH := 120 + (60 * (cBlue - cRed)) div Delta
|
||
else
|
||
if cBlue = B then
|
||
tmpH := 240 + (60 * (cRed - cGreen)) div Delta;
|
||
if tmpH < 0 then
|
||
tmpH := tmpH + 360;
|
||
end;
|
||
H := tmpH;
|
||
end;
|
||
|
||
procedure IEHSBtoRGB(const H, S, B: word; var cRed, cGreen, cBlue: byte);
|
||
const
|
||
divisor: Integer = 255 * 60;
|
||
var
|
||
f: Integer;
|
||
hTemp: Integer;
|
||
p, q, t: Integer;
|
||
VS: Integer;
|
||
begin
|
||
if s = 0 then
|
||
begin
|
||
cRed := B;
|
||
cGreen := B;
|
||
cBlue := B;
|
||
end
|
||
else
|
||
begin
|
||
if H = 360 then
|
||
hTemp := 0
|
||
else
|
||
hTemp := H;
|
||
f := hTemp mod 60;
|
||
hTemp := hTemp div 60;
|
||
VS := B * S;
|
||
p := B - VS div 255;
|
||
q := B - (VS * f) div divisor;
|
||
t := B - (VS * (60 - f)) div divisor;
|
||
|
||
case hTemp of
|
||
0:
|
||
begin
|
||
cRed := B;
|
||
cGreen := t;
|
||
cBlue := p
|
||
end;
|
||
1:
|
||
begin
|
||
cRed := q;
|
||
cGreen := B;
|
||
cBlue := p
|
||
end;
|
||
2:
|
||
begin
|
||
cRed := p;
|
||
cGreen := B;
|
||
cBlue := t
|
||
end;
|
||
3:
|
||
begin
|
||
cRed := p;
|
||
cGreen := q;
|
||
cBlue := B
|
||
end;
|
||
4:
|
||
begin
|
||
cRed := t;
|
||
cGreen := p;
|
||
cBlue := B
|
||
end;
|
||
5:
|
||
begin
|
||
cRed := B;
|
||
cGreen := p;
|
||
cBlue := q
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
procedure IEInitialize_hyieutils;
|
||
begin
|
||
begin
|
||
IEGlobalSettings(); // just to create global settings object now
|
||
IESetDefaultTranslationWords();
|
||
mscms := 0;
|
||
InitIECosineTab();
|
||
{$ifdef IERFBPROTOCOL}
|
||
IE_SockLibInitCS := TCriticalSection.Create();
|
||
{$endif}
|
||
end;
|
||
end;
|
||
|
||
procedure IEFinalize_hyieutils;
|
||
begin
|
||
{$ifdef IERFBPROTOCOL}
|
||
FreeAndNil(IE_SockLibInitCS);
|
||
{$endif}
|
||
if assigned(IEGlobalSettings().DefaultDialogFont) then
|
||
begin
|
||
IEGlobalSettings().DefaultDialogFont.Free();
|
||
IEGlobalSettings().DefaultDialogFont := nil;
|
||
end;
|
||
if mscms <> 0 then
|
||
FreeLibrary(mscms);
|
||
end;
|
||
|
||
|
||
|
||
initialization
|
||
FhGradientFill := 0;
|
||
IEInitializeImageEn();
|
||
|
||
finalization
|
||
IEFinalizeImageEn();
|
||
try
|
||
if FhGradientFill > 0 then
|
||
FreeLibrary(fhGradientFill);
|
||
except
|
||
end;
|
||
|
||
|
||
end.
|
||
|
||
|
||
|
||
|
||
|