1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915 |
- unit GR32_Transforms;
- (* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1 or LGPL 2.1 with linking exception
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * Alternatively, the contents of this file may be used under the terms of the
- * Free Pascal modified version of the GNU Lesser General Public License
- * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
- * of this license are applicable instead of those above.
- * Please see the file LICENSE.txt for additional information concerning this
- * license.
- *
- * The Original Code is Graphics32
- *
- * The Initial Developer of the Original Code is
- * Alex A. Denisov
- *
- * Portions created by the Initial Developer are Copyright (C) 2000-2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Andre Beckedorf <[email protected]>
- * Mattias Andersson <[email protected]>
- * J. Tulach <[email protected]>
- * Michael Hansen <[email protected]>
- * Peter Larson
- *
- * ***** END LICENSE BLOCK ***** *)
- interface
- {$I GR32.inc}
- uses
- System.Types,
- SysUtils, Classes, GR32, GR32_VectorMaps, GR32_Rasterizers;
- type
- ETransformError = class(Exception);
- ETransformNotImplemented = class(Exception);
- type
- TFloatMatrix = array [0..2, 0..2] of TFloat; // 3x3 TFloat precision
- TFixedMatrix = array [0..2, 0..2] of TFixed; // 3x3 fixed precision
- const
- IdentityMatrix: TFloatMatrix = (
- (1, 0, 0),
- (0, 1, 0),
- (0, 0, 1));
- type
- TVector3f = array [0..2] of TFloat;
- TVector3i = array [0..2] of Integer;
- // Matrix conversion routines
- function FixedMatrix(const FloatMatrix: TFloatMatrix): TFixedMatrix; overload;
- function FloatMatrix(const FixedMatrix: TFixedMatrix): TFloatMatrix; overload;
- procedure Adjoint(var M: TFloatMatrix);
- function Determinant(const M: TFloatMatrix): TFloat;
- procedure Scale(var M: TFloatMatrix; Factor: TFloat);
- procedure Invert(var M: TFloatMatrix);
- function Mult(const M1, M2: TFloatMatrix): TFloatMatrix;
- function VectorTransform(const M: TFloatMatrix; const V: TVector3f): TVector3f;
- type
- TTransformation = class(TNotifiablePersistent)
- private
- FSrcRect: TFloatRect;
- procedure SetSrcRect(const Value: TFloatRect);
- protected
- TransformValid: Boolean;
- procedure PrepareTransform; virtual;
- procedure ReverseTransformInt(DstX, DstY: Integer; out SrcX, SrcY: Integer); virtual;
- procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); virtual;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); virtual;
- procedure TransformInt(SrcX, SrcY: Integer; out DstX, DstY: Integer); virtual;
- procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); virtual;
- procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); virtual;
- public
- procedure Changed; override;
- function HasTransformedBounds: Boolean; virtual;
- function GetTransformedBounds: TFloatRect; overload;
- function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; overload; virtual;
- function ReverseTransform(const P: TPoint): TPoint; overload; virtual;
- function ReverseTransform(const P: TFixedPoint): TFixedPoint; overload; virtual;
- function ReverseTransform(const P: TFloatPoint): TFloatPoint; overload; virtual;
- function Transform(const P: TPoint): TPoint; overload; virtual;
- function Transform(const P: TFixedPoint): TFixedPoint; overload; virtual;
- function Transform(const P: TFloatPoint): TFloatPoint; overload; virtual;
- property SrcRect: TFloatRect read FSrcRect write SetSrcRect;
- end;
- TTransformationClass = class of TTransformation;
- TNestedTransformation = class(TTransformation)
- private
- FItems: TList;
- FOwner: TPersistent;
- function GetCount: Integer;
- function GetItem(Index: Integer): TTransformation;
- procedure SetItem(Index: Integer; const Value: TTransformation);
- protected
- procedure PrepareTransform; override;
- procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); override;
- procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
- public
- constructor Create;
- destructor Destroy; override;
- function Add(ItemClass: TTransformationClass): TTransformation;
- procedure Clear;
- procedure Delete(Index: Integer);
- function Insert(Index: Integer; ItemClass: TTransformationClass): TTransformation;
- property Owner: TPersistent read FOwner;
- property Count: Integer read GetCount;
- property Items[Index: Integer]: TTransformation read GetItem write SetItem; default;
- end;
- T3x3Transformation = class(TTransformation)
- protected
- FMatrix, FInverseMatrix: TFloatMatrix;
- FFixedMatrix, FInverseFixedMatrix: TFixedMatrix;
- procedure PrepareTransform; override;
- procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); override;
- procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
- public
- property Matrix: TFloatMatrix read FMatrix;
- end;
- TAffineTransformation = class(T3x3Transformation)
- private
- FStack: ^TFloatMatrix;
- FStackLevel: Integer;
- public
- constructor Create; virtual;
- function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
- procedure Push;
- procedure Pop;
- procedure Clear; overload;
- procedure Clear(BaseMatrix: TFloatMatrix); overload;
- procedure Rotate(Alpha: TFloat); overload; // degrees
- procedure Rotate(Cx, Cy, Alpha: TFloat); overload; // degrees
- procedure Skew(Fx, Fy: TFloat);
- procedure Scale(Sx, Sy: TFloat); overload;
- procedure Scale(Value: TFloat); overload;
- procedure Translate(Dx, Dy: TFloat);
- end;
- TProjectiveTransformation = class(T3x3Transformation)
- private
- FQuadX: array [0..3] of TFloat;
- FQuadY: array [0..3] of TFloat;
- procedure SetX0(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetX1(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetX2(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetX3(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetY0(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetY1(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetY2(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- procedure SetY3(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
- protected
- procedure PrepareTransform; override;
- procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); override;
- procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
- public
- function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
- published
- property X0: TFloat read FQuadX[0] write SetX0;
- property X1: TFloat read FQuadX[1] write SetX1;
- property X2: TFloat read FQuadX[2] write SetX2;
- property X3: TFloat read FQuadX[3] write SetX3;
- property Y0: TFloat read FQuadY[0] write SetY0;
- property Y1: TFloat read FQuadY[1] write SetY1;
- property Y2: TFloat read FQuadY[2] write SetY2;
- property Y3: TFloat read FQuadY[3] write SetY3;
- end;
- TTwirlTransformation = class(TTransformation)
- private
- Frx, Fry: TFloat;
- FTwirl: TFloat;
- procedure SetTwirl(const Value: TFloat);
- protected
- procedure PrepareTransform; override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- public
- constructor Create; virtual;
- function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
- published
- property Twirl: TFloat read FTwirl write SetTwirl;
- end;
- TBloatTransformation = class(TTransformation)
- private
- FBloatPower: TFloat;
- FBP: TFloat;
- FPiW, FPiH: TFloat;
- procedure SetBloatPower(const Value: TFloat);
- protected
- procedure PrepareTransform; override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- procedure TransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- public
- constructor Create; virtual;
- published
- property BloatPower: TFloat read FBloatPower write SetBloatPower;
- end;
- TDisturbanceTransformation = class(TTransformation)
- private
- FDisturbance: TFloat;
- procedure SetDisturbance(const Value: TFloat);
- protected
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- public
- function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
- published
- property Disturbance: TFloat read FDisturbance write SetDisturbance;
- end;
- TFishEyeTransformation = class(TTransformation)
- private
- Frx, Fry: TFloat;
- Faw, Fsr: TFloat;
- Sx, Sy: TFloat;
- FMinR: TFloat;
- protected
- procedure PrepareTransform; override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- end;
- TPolarTransformation = class(TTransformation)
- private
- FDstRect: TFloatRect;
- FPhase: TFloat;
- Sx, Sy, Cx, Cy, Dx, Dy, Rt, Rt2, Rr, Rcx, Rcy: TFloat;
- procedure SetDstRect(const Value: TFloatRect);
- procedure SetPhase(const Value: TFloat);
- protected
- procedure PrepareTransform; override;
- procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- public
- property DstRect: TFloatRect read FDstRect write SetDstRect;
- property Phase: TFloat read FPhase write SetPhase;
- end;
- TPathTransformation = class(TTransformation)
- private
- FTopLength: TFloat;
- FBottomLength: TFloat;
- FBottomCurve: TArrayOfFloatPoint;
- FTopCurve: TArrayOfFloatPoint;
- FTopHypot, FBottomHypot: array of record Dist, RecDist: TFloat end;
- procedure SetBottomCurve(const Value: TArrayOfFloatPoint);
- procedure SetTopCurve(const Value: TArrayOfFloatPoint);
- protected
- rdx, rdy: TFloat;
- procedure PrepareTransform; override;
- procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
- public
- destructor Destroy; override;
- property TopCurve: TArrayOfFloatPoint read FTopCurve write SetTopCurve;
- property BottomCurve: TArrayOfFloatPoint read FBottomCurve write SetBottomCurve;
- end;
- TRemapTransformation = class(TTransformation)
- private
- FVectorMap : TVectorMap;
- FScalingFixed: TFixedVector;
- FScalingFloat: TFloatVector;
- FCombinedScalingFixed: TFixedVector;
- FCombinedScalingFloat: TFloatVector;
- FSrcTranslationFixed: TFixedVector;
- FSrcScaleFixed: TFixedVector;
- FDstTranslationFixed: TFixedVector;
- FDstScaleFixed: TFixedVector;
- FSrcTranslationFloat: TFloatVector;
- FSrcScaleFloat: TFloatVector;
- FDstTranslationFloat: TFloatVector;
- FDstScaleFloat: TFloatVector;
- FOffsetFixed : TFixedVector;
- FOffsetInt : TPoint;
- FMappingRect: TFloatRect;
- FOffset: TFloatVector;
- procedure SetMappingRect(Rect: TFloatRect);
- procedure SetOffset(const Value: TFloatVector);
- protected
- procedure PrepareTransform; override;
- procedure ReverseTransformInt(DstX, DstY: Integer; out SrcX, SrcY: Integer); override;
- procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
- procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
- public
- constructor Create; virtual;
- destructor Destroy; override;
- function HasTransformedBounds: Boolean; override;
- function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
- procedure Scale(Sx, Sy: TFloat);
- property MappingRect: TFloatRect read FMappingRect write SetMappingRect;
- property Offset: TFloatVector read FOffset write SetOffset;
- property VectorMap: TVectorMap read FVectorMap write FVectorMap;
- end;
- function TransformPoints(Points: TArrayOfArrayOfFixedPoint; Transformation: TTransformation): TArrayOfArrayOfFixedPoint;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation); overload;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
- const DstClip: TRect); overload;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
- Rasterizer: TRasterizer); overload;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
- Rasterizer: TRasterizer; const DstClip: TRect); overload;
- procedure RasterizeTransformation(Vectormap: TVectormap;
- Transformation: TTransformation; DstRect: TRect;
- CombineMode: TVectorCombineMode = vcmAdd;
- CombineCallback: TVectorCombineEvent = nil);
- procedure SetBorderTransparent(ABitmap: TCustomBitmap32; ARect: TRect);
- { FullEdge controls how the bitmap is resampled }
- var
- FullEdge: Boolean = True;
- resourcestring
- RCStrReverseTransformationNotImplemented = 'Reverse transformation is not implemented in %s.';
- RCStrForwardTransformationNotImplemented = 'Forward transformation is not implemented in %s.';
- RCStrTopBottomCurveNil = 'Top or bottom curve is nil';
- implementation
- uses
- Math, GR32_Blend, GR32_LowLevel, GR32_Math, GR32_Bindings,
- GR32_Resamplers;
- resourcestring
- RCStrSrcRectIsEmpty = 'SrcRect is empty!';
- RCStrMappingRectIsEmpty = 'MappingRect is empty!';
- RStrStackEmpty = 'Stack empty';
- type
- {provides access to proctected members of TCustomBitmap32 by typecasting}
- TTransformationAccess = class(TTransformation);
- var
- DET32: function(a1, a2, b1, b2: Single): Single;
- DET64: function(a1, a2, b1, b2: Double): Double;
- { A bit of linear algebra }
- function DET32_Pas(a1, a2, b1, b2: Single): Single; overload;
- begin
- Result := a1 * b2 - a2 * b1;
- end;
- function DET64_Pas(a1, a2, b1, b2: Double): Double; overload;
- begin
- Result := a1 * b2 - a2 * b1;
- end;
- {$IFNDEF PUREPASCAL}
- function DET32_ASM(a1, a2, b1, b2: Single): Single; overload;
- asm
- {$IFDEF CPU64}
- MULSS XMM0, XMM3
- MULSS XMM1, XMM2
- ADDSS XMM0, XMM1
- {$ELSE}
- FLD A1.Single
- FMUL B2.Single
- FLD A2.Single
- FMUL B1.Single
- FSUBP
- {$ENDIF}
- end;
- function DET64_ASM(a1, a2, b1, b2: Double): Double; overload;
- asm
- {$IFDEF CPU64}
- MULSD XMM0, XMM3
- MULSD XMM1, XMM2
- ADDSD XMM0, XMM1
- {$ELSE}
- FLD A1.Double
- FMUL B2.Double
- FLD A2.Double
- FMUL B1.Double
- FSUBP
- {$ENDIF}
- end;
- {$ENDIF}
- { implementation of detereminant for TFloat precision }
- function _DET(a1, a2, b1, b2: TFloat): TFloat; overload; {$IFDEF UseInlining} inline; {$ENDIF}
- begin
- Result := a1 * b2 - a2 * b1;
- end;
- function _DET(a1, a2, a3, b1, b2, b3, c1, c2, c3: TFloat): TFloat; overload; {$IFDEF UseInlining} inline; {$ENDIF}
- begin
- Result :=
- a1 * (b2 * c3 - b3 * c2) -
- b1 * (a2 * c3 - a3 * c2) +
- c1 * (a2 * b3 - a3 * b2);
- end;
- procedure Adjoint(var M: TFloatMatrix);
- var
- Tmp: TFloatMatrix;
- begin
- Tmp := M;
- M[0,0] := _DET(Tmp[1,1], Tmp[1,2], Tmp[2,1], Tmp[2,2]);
- M[0,1] := -_DET(Tmp[0,1], Tmp[0,2], Tmp[2,1], Tmp[2,2]);
- M[0,2] := _DET(Tmp[0,1], Tmp[0,2], Tmp[1,1], Tmp[1,2]);
- M[1,0] := -_DET(Tmp[1,0], Tmp[1,2], Tmp[2,0], Tmp[2,2]);
- M[1,1] := _DET(Tmp[0,0], Tmp[0,2], Tmp[2,0], Tmp[2,2]);
- M[1,2] := -_DET(Tmp[0,0], Tmp[0,2], Tmp[1,0], Tmp[1,2]);
- M[2,0] := _DET(Tmp[1,0], Tmp[1,1], Tmp[2,0], Tmp[2,1]);
- M[2,1] := -_DET(Tmp[0,0], Tmp[0,1], Tmp[2,0], Tmp[2,1]);
- M[2,2] := _DET(Tmp[0,0], Tmp[0,1], Tmp[1,0], Tmp[1,1]);
- end;
- function Determinant(const M: TFloatMatrix): TFloat;
- begin
- Result := _DET(M[0,0], M[1,0], M[2,0],
- M[0,1], M[1,1], M[2,1],
- M[0,2], M[1,2], M[2,2]);
- end;
- procedure Scale(var M: TFloatMatrix; Factor: TFloat);
- var
- i, j: Integer;
- begin
- for i := 0 to 2 do
- for j := 0 to 2 do
- M[i,j] := M[i,j] * Factor;
- end;
- procedure Invert(var M: TFloatMatrix);
- var
- Det: TFloat;
- begin
- Det := Determinant(M);
- if Abs(Det) < 1E-5 then M := IdentityMatrix
- else
- begin
- Adjoint(M);
- Scale(M, 1 / Det);
- end;
- end;
- function Mult(const M1, M2: TFloatMatrix): TFloatMatrix;
- var
- i, j: Integer;
- begin
- for i := 0 to 2 do
- for j := 0 to 2 do
- Result[i, j] :=
- M1[0, j] * M2[i, 0] +
- M1[1, j] * M2[i, 1] +
- M1[2, j] * M2[i, 2];
- end;
- function VectorTransform(const M: TFloatMatrix; const V: TVector3f): TVector3f;
- begin
- Result[0] := M[0,0] * V[0] + M[1,0] * V[1] + M[2,0] * V[2];
- Result[1] := M[0,1] * V[0] + M[1,1] * V[1] + M[2,1] * V[2];
- Result[2] := M[0,2] * V[0] + M[1,2] * V[1] + M[2,2] * V[2];
- end;
- { Transformation functions }
- function TransformPoints(Points: TArrayOfArrayOfFixedPoint; Transformation: TTransformation): TArrayOfArrayOfFixedPoint;
- var
- I, J: Integer;
- begin
- if Points = nil then
- Result := nil
- else
- begin
- SetLength(Result, Length(Points));
- Transformation.PrepareTransform;
- for I := 0 to High(Result) do
- begin
- SetLength(Result[I], Length(Points[I]));
- if Length(Result[I]) > 0 then
- for J := 0 to High(Result[I]) do
- Transformation.TransformFixed(Points[I][J].X, Points[I][J].Y, Result[I][J].X, Result[I][J].Y);
- end;
- end;
- end;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation);
- var
- Rasterizer: TRasterizer;
- begin
- Rasterizer := DefaultRasterizerClass.Create;
- try
- Transform(Dst, Src, Transformation, Rasterizer);
- finally
- Rasterizer.Free;
- end;
- end;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation; const DstClip: TRect);
- var
- Rasterizer: TRasterizer;
- begin
- Rasterizer := DefaultRasterizerClass.Create;
- try
- Transform(Dst, Src, Transformation, Rasterizer, DstClip);
- finally
- Rasterizer.Free;
- end;
- end;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
- Rasterizer: TRasterizer);
- begin
- Transform(Dst, Src, Transformation, Rasterizer, Dst.BoundsRect);
- end;
- procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
- Rasterizer: TRasterizer; const DstClip: TRect);
- var
- DstRect: TRect;
- Transformer: TTransformer;
- begin
- GR32.IntersectRect(DstRect, DstClip, Dst.ClipRect);
- if (DstRect.Right < DstRect.Left) or (DstRect.Bottom < DstRect.Top) then Exit;
- if not Dst.MeasuringMode then
- begin
- Transformer := TTransformer.Create(Src.Resampler, Transformation);
- try
- Rasterizer.Sampler := Transformer;
- Rasterizer.Rasterize(Dst, DstRect, Src);
- finally
- EMMS;
- Transformer.Free;
- end;
- end;
- Dst.Changed(DstRect);
- end;
- procedure SetBorderTransparent(ABitmap: TCustomBitmap32; ARect: TRect);
- var
- I: Integer;
- begin
- GR32.IntersectRect(ARect, ARect, ABitmap.BoundsRect);
- with ARect, ABitmap do
- if (Right > Left) and (Bottom > Top) and
- (Left < ClipRect.Right) and (Top < ClipRect.Bottom) and
- (Right > ClipRect.Left) and (Bottom > ClipRect.Top) then
- begin
- Dec(Right);
- Dec(Bottom);
- for I := Left to Right do
- begin
- ABitmap[I, Top] := ABitmap[I, Top] and $00FFFFFF;
- ABitmap[I, Bottom] := ABitmap[I, Bottom] and $00FFFFFF;
- end;
- for I := Top to Bottom do
- begin
- ABitmap[Left, I] := ABitmap[Left, I] and $00FFFFFF;
- ABitmap[Right, I] := ABitmap[Right, I] and $00FFFFFF;
- end;
- Changed;
- end;
- end;
- { TTransformation }
- function TTransformation.GetTransformedBounds: TFloatRect;
- begin
- Result := GetTransformedBounds(FSrcRect);
- end;
- procedure TTransformation.Changed;
- begin
- TransformValid := False;
- inherited;
- end;
- function TTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
- begin
- Result := ASrcRect;
- end;
- function TTransformation.HasTransformedBounds: Boolean;
- begin
- Result := True;
- end;
- procedure TTransformation.PrepareTransform;
- begin
- // Dummy
- end;
- function TTransformation.ReverseTransform(const P: TFloatPoint): TFloatPoint;
- begin
- if not TransformValid then PrepareTransform;
- ReverseTransformFloat(P.X, P.Y, Result.X, Result.Y);
- end;
- function TTransformation.ReverseTransform(const P: TFixedPoint): TFixedPoint;
- begin
- if not TransformValid then PrepareTransform;
- ReverseTransformFixed(P.X, P.Y, Result.X, Result.Y);
- end;
- function TTransformation.ReverseTransform(const P: TPoint): TPoint;
- begin
- if not TransformValid then PrepareTransform;
- ReverseTransformInt(P.X, P.Y, Result.X, Result.Y);
- end;
- procedure TTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
- out SrcX, SrcY: TFixed);
- var
- X, Y: TFloat;
- begin
- ReverseTransformFloat(DstX * FixedToFloat, DstY * FixedToFloat, X, Y);
- SrcX := Fixed(X);
- SrcY := Fixed(Y);
- end;
- procedure TTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- begin
- // ReverseTransformFloat is the top precisionlevel, all decendants must override at least this level!
- raise ETransformNotImplemented.CreateFmt(RCStrReverseTransformationNotImplemented, [Self.Classname]);
- end;
- procedure TTransformation.ReverseTransformInt(DstX, DstY: Integer;
- out SrcX, SrcY: Integer);
- var
- X, Y: TFixed;
- begin
- ReverseTransformFixed(DstX shl 16, DstY shl 16, X, Y);
- SrcX := FixedRound(X);
- SrcY := FixedRound(Y);
- end;
- procedure TTransformation.SetSrcRect(const Value: TFloatRect);
- begin
- FSrcRect := Value;
- Changed;
- end;
- function TTransformation.Transform(const P: TFloatPoint): TFloatPoint;
- begin
- if not TransformValid then PrepareTransform;
- TransformFloat(P.X, P.Y, Result.X, Result.Y);
- end;
- function TTransformation.Transform(const P: TFixedPoint): TFixedPoint;
- begin
- if not TransformValid then PrepareTransform;
- TransformFixed(P.X, P.Y, Result.X, Result.Y);
- end;
- function TTransformation.Transform(const P: TPoint): TPoint;
- begin
- if not TransformValid then PrepareTransform;
- TransformInt(P.X, P.Y, Result.X, Result.Y);
- end;
- procedure TTransformation.TransformFixed(SrcX, SrcY: TFixed; out DstX,
- DstY: TFixed);
- var
- X, Y: TFloat;
- begin
- TransformFloat(SrcX * FixedToFloat, SrcY * FixedToFloat, X, Y);
- DstX := Fixed(X);
- DstY := Fixed(Y);
- end;
- procedure TTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat);
- begin
- // TransformFloat is the top precisionlevel, all decendants must override at least this level!
- raise ETransformNotImplemented.CreateFmt(RCStrForwardTransformationNotImplemented, [Self.Classname]);
- end;
- procedure TTransformation.TransformInt(SrcX, SrcY: Integer; out DstX, DstY: Integer);
- var
- X, Y: TFixed;
- begin
- TransformFixed(SrcX shl 16, SrcY shl 16, X, Y);
- DstX := FixedRound(X);
- DstY := FixedRound(Y);
- end;
- { TNestedTransformation }
- constructor TNestedTransformation.Create;
- begin
- FItems := TList.Create;
- end;
- destructor TNestedTransformation.Destroy;
- begin
- if Assigned(FItems) then Clear;
- FItems.Free;
- inherited;
- end;
- function TNestedTransformation.Add(
- ItemClass: TTransformationClass): TTransformation;
- begin
- Result := ItemClass.Create;
- FItems.Add(Result);
- end;
- procedure TNestedTransformation.Clear;
- begin
- BeginUpdate;
- try
- while FItems.Count > 0 do
- Delete(FItems.Count - 1);
- finally
- EndUpdate;
- end;
- end;
- procedure TNestedTransformation.Delete(Index: Integer);
- begin
- TTransformation(FItems[Index]).Free;
- FItems.Delete(Index);
- end;
- function TNestedTransformation.GetCount: Integer;
- begin
- Result := FItems.Count;
- end;
- function TNestedTransformation.GetItem(Index: Integer): TTransformation;
- begin
- Result := FItems[Index];
- end;
- function TNestedTransformation.Insert(Index: Integer;
- ItemClass: TTransformationClass): TTransformation;
- begin
- BeginUpdate;
- try
- Result := Add(ItemClass);
- finally
- EndUpdate;
- end;
- end;
- procedure TNestedTransformation.PrepareTransform;
- var
- Index: Integer;
- begin
- for Index := 0 to Count - 1 do
- TTransformation(FItems[Index]).PrepareTransform;
- end;
- procedure TNestedTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
- out SrcX, SrcY: TFixed);
- var
- Index: Integer;
- begin
- for Index := 0 to Count - 1 do
- begin
- TTransformation(FItems[Index]).ReverseTransformFixed(DstX, DstY, SrcX,
- SrcY);
- DstX := SrcX;
- DstY := SrcY;
- end;
- end;
- procedure TNestedTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- var
- Index: Integer;
- begin
- for Index := 0 to Count - 1 do
- begin
- TTransformation(FItems[Index]).ReverseTransformFloat(DstX, DstY, SrcX,
- SrcY);
- DstX := SrcX;
- DstY := SrcY;
- end;
- end;
- procedure TNestedTransformation.SetItem(Index: Integer;
- const Value: TTransformation);
- begin
- TCollectionItem(FItems[Index]).Assign(Value);
- end;
- procedure TNestedTransformation.TransformFixed(SrcX, SrcY: TFixed; out DstX,
- DstY: TFixed);
- var
- Index: Integer;
- begin
- for Index := 0 to Count - 1 do
- begin
- TTransformation(FItems[Index]).TransformFixed(SrcX, SrcY, DstX, DstY);
- SrcX := DstX;
- SrcY := DstY;
- end;
- end;
- procedure TNestedTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
- DstY: TFloat);
- var
- Index: Integer;
- begin
- for Index := 0 to Count - 1 do
- begin
- TTransformation(FItems[Index]).TransformFloat(SrcX, SrcY, DstX, DstY);
- SrcX := DstX;
- SrcY := DstY;
- end;
- end;
- { T3x3Transformation }
- procedure T3x3Transformation.PrepareTransform;
- begin
- FInverseMatrix := Matrix;
- Invert(FInverseMatrix);
- // calculate a fixed point (65536) factors
- FInverseFixedMatrix := FixedMatrix(FInverseMatrix);
- FFixedMatrix := FixedMatrix(Matrix);
- TransformValid := True;
- end;
- procedure T3x3Transformation.ReverseTransformFixed(DstX, DstY: TFixed; out SrcX,
- SrcY: TFixed);
- begin
- SrcX := FixedMul(DstX, FInverseFixedMatrix[0, 0]) +
- FixedMul(DstY, FInverseFixedMatrix[1, 0]) + FInverseFixedMatrix[2, 0];
- SrcY := FixedMul(DstX, FInverseFixedMatrix[0, 1]) +
- FixedMul(DstY, FInverseFixedMatrix[1, 1]) + FInverseFixedMatrix[2, 1];
- end;
- procedure T3x3Transformation.ReverseTransformFloat(DstX, DstY: TFloat; out SrcX,
- SrcY: TFloat);
- begin
- SrcX := DstX * FInverseMatrix[0, 0] + DstY * FInverseMatrix[1, 0] +
- FInverseMatrix[2, 0];
- SrcY := DstX * FInverseMatrix[0, 1] + DstY * FInverseMatrix[1, 1] +
- FInverseMatrix[2, 1];
- end;
- procedure T3x3Transformation.TransformFixed(SrcX, SrcY: TFixed; out DstX,
- DstY: TFixed);
- begin
- DstX := FixedMul(SrcX, FFixedMatrix[0, 0]) +
- FixedMul(SrcY, FFixedMatrix[1, 0]) + FFixedMatrix[2, 0];
- DstY := FixedMul(SrcX, FFixedMatrix[0, 1]) +
- FixedMul(SrcY, FFixedMatrix[1, 1]) + FFixedMatrix[2, 1];
- end;
- procedure T3x3Transformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
- DstY: TFloat);
- begin
- DstX := SrcX * Matrix[0, 0] + SrcY * Matrix[1, 0] + Matrix[2, 0];
- DstY := SrcX * Matrix[0, 1] + SrcY * Matrix[1, 1] + Matrix[2, 1];
- end;
- { TAffineTransformation }
- constructor TAffineTransformation.Create;
- begin
- FStackLevel := 0;
- FStack := nil;
- Clear;
- end;
- procedure TAffineTransformation.Clear;
- begin
- FMatrix := IdentityMatrix;
- Changed;
- end;
- procedure TAffineTransformation.Clear(BaseMatrix: TFloatMatrix);
- begin
- FMatrix := BaseMatrix;
- Changed;
- end;
- function TAffineTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
- var
- V1, V2, V3, V4: TVector3f;
- begin
- V1[0] := ASrcRect.Left; V1[1] := ASrcRect.Top; V1[2] := 1;
- V2[0] := ASrcRect.Right; V2[1] := V1[1]; V2[2] := 1;
- V3[0] := V1[0]; V3[1] := ASrcRect.Bottom; V3[2] := 1;
- V4[0] := V2[0]; V4[1] := V3[1]; V4[2] := 1;
- V1 := VectorTransform(Matrix, V1);
- V2 := VectorTransform(Matrix, V2);
- V3 := VectorTransform(Matrix, V3);
- V4 := VectorTransform(Matrix, V4);
- Result.Left := Min(Min(V1[0], V2[0]), Min(V3[0], V4[0]));
- Result.Right := Max(Max(V1[0], V2[0]), Max(V3[0], V4[0]));
- Result.Top := Min(Min(V1[1], V2[1]), Min(V3[1], V4[1]));
- Result.Bottom := Max(Max(V1[1], V2[1]), Max(V3[1], V4[1]));
- end;
- procedure TAffineTransformation.Push;
- begin
- Inc(FStackLevel);
- ReallocMem(FStack, FStackLevel * SizeOf(TFloatMatrix));
- Move(FMatrix, FStack^[FStackLevel - 1], SizeOf(TFloatMatrix));
- end;
- procedure TAffineTransformation.Pop;
- begin
- if FStackLevel <= 0 then
- raise Exception.Create(RStrStackEmpty);
- Move(FStack^[FStackLevel - 1], FMatrix, SizeOf(TFloatMatrix));
- Dec(FStackLevel);
- Changed;
- end;
- procedure TAffineTransformation.Rotate(Alpha: TFloat);
- var
- S, C: TFloat;
- M: TFloatMatrix;
- begin
- Alpha := DegToRad(Alpha);
- GR32_Math.SinCos(Alpha, S, C);
- M := IdentityMatrix;
- M[0, 0] := C; M[1, 0] := S;
- M[0, 1] := -S; M[1, 1] := C;
- FMatrix := Mult(M, Matrix);
- Changed;
- end;
- procedure TAffineTransformation.Rotate(Cx, Cy, Alpha: TFloat);
- var
- S, C: TFloat;
- M: TFloatMatrix;
- begin
- if (Cx <> 0) or (Cy <> 0) then Translate(-Cx, -Cy);
- Alpha := DegToRad(Alpha);
- GR32_Math.SinCos(Alpha, S, C);
- M := IdentityMatrix;
- M[0, 0] := C; M[1, 0] := S;
- M[0, 1] := -S; M[1, 1] := C;
- FMatrix := Mult(M, Matrix);
- if (Cx <> 0) or (Cy <> 0) then Translate(Cx, Cy);
- Changed;
- end;
- procedure TAffineTransformation.Scale(Sx, Sy: TFloat);
- var
- M: TFloatMatrix;
- begin
- M := IdentityMatrix;
- M[0, 0] := Sx;
- M[1, 1] := Sy;
- FMatrix := Mult(M, Matrix);
- Changed;
- end;
- procedure TAffineTransformation.Scale(Value: TFloat);
- var
- M: TFloatMatrix;
- begin
- M := IdentityMatrix;
- M[0, 0] := Value;
- M[1, 1] := Value;
- FMatrix := Mult(M, Matrix);
- Changed;
- end;
- procedure TAffineTransformation.Skew(Fx, Fy: TFloat);
- var
- M: TFloatMatrix;
- begin
- M := IdentityMatrix;
- M[1, 0] := Fx;
- M[0, 1] := Fy;
- FMatrix := Mult(M, Matrix);
- Changed;
- end;
- procedure TAffineTransformation.Translate(Dx, Dy: TFloat);
- var
- M: TFloatMatrix;
- begin
- M := IdentityMatrix;
- M[2, 0] := Dx;
- M[2, 1] := Dy;
- FMatrix := Mult(M, Matrix);
- Changed;
- end;
- { TProjectiveTransformation }
- function TProjectiveTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
- begin
- Result.Left := Min(Min(FQuadX[0], FQuadX[1]), Min(FQuadX[2], FQuadX[3]));
- Result.Right := Max(Max(FQuadX[0], FQuadX[1]), Max(FQuadX[2], FQuadX[3]));
- Result.Top := Min(Min(FQuadY[0], FQuadY[1]), Min(FQuadY[2], FQuadY[3]));
- Result.Bottom := Max(Max(FQuadY[0], FQuadY[1]), Max(FQuadY[2], FQuadY[3]));
- end;
- procedure TProjectiveTransformation.PrepareTransform;
- var
- dx1, dx2, px, dy1, dy2, py: TFloat;
- g, h, k: TFloat;
- R: TFloatMatrix;
- begin
- px := FQuadX[0] - FQuadX[1] + FQuadX[2] - FQuadX[3];
- py := FQuadY[0] - FQuadY[1] + FQuadY[2] - FQuadY[3];
- if (px = 0) and (py = 0) then
- begin
- // affine mapping
- FMatrix[0, 0] := FQuadX[1] - FQuadX[0];
- FMatrix[1, 0] := FQuadX[2] - FQuadX[1];
- FMatrix[2, 0] := FQuadX[0];
- FMatrix[0, 1] := FQuadY[1] - FQuadY[0];
- FMatrix[1, 1] := FQuadY[2] - FQuadY[1];
- FMatrix[2, 1] := FQuadY[0];
- FMatrix[0, 2] := 0;
- FMatrix[1, 2] := 0;
- FMatrix[2, 2] := 1;
- end
- else
- begin
- // projective mapping
- dx1 := FQuadX[1] - FQuadX[2];
- dx2 := FQuadX[3] - FQuadX[2];
- dy1 := FQuadY[1] - FQuadY[2];
- dy2 := FQuadY[3] - FQuadY[2];
- k := dx1 * dy2 - dx2 * dy1;
- if k <> 0 then
- begin
- k := 1 / k;
- g := (px * dy2 - py * dx2) * k;
- h := (dx1 * py - dy1 * px) * k;
- FMatrix[0, 0] := FQuadX[1] - FQuadX[0] + g * FQuadX[1];
- FMatrix[1, 0] := FQuadX[3] - FQuadX[0] + h * FQuadX[3];
- FMatrix[2, 0] := FQuadX[0];
- FMatrix[0, 1] := FQuadY[1] - FQuadY[0] + g * FQuadY[1];
- FMatrix[1, 1] := FQuadY[3] - FQuadY[0] + h * FQuadY[3];
- FMatrix[2, 1] := FQuadY[0];
- FMatrix[0, 2] := g;
- FMatrix[1, 2] := h;
- FMatrix[2, 2] := 1;
- end
- else
- begin
- FillChar(FMatrix, SizeOf(FMatrix), 0);
- end;
- end;
- // denormalize texture space (u, v)
- R := IdentityMatrix;
- R[0, 0] := 1 / (SrcRect.Right - SrcRect.Left);
- R[1, 1] := 1 / (SrcRect.Bottom - SrcRect.Top);
- FMatrix := Mult(FMatrix, R);
- R := IdentityMatrix;
- R[2, 0] := -SrcRect.Left;
- R[2, 1] := -SrcRect.Top;
- FMatrix := Mult(FMatrix, R);
- inherited;
- end;
- procedure TProjectiveTransformation.SetX0(Value: TFloat);
- begin
- FQuadX[0] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetX1(Value: TFloat);
- begin
- FQuadX[1] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetX2(Value: TFloat);
- begin
- FQuadX[2] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetX3(Value: TFloat);
- begin
- FQuadX[3] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetY0(Value: TFloat);
- begin
- FQuadY[0] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetY1(Value: TFloat);
- begin
- FQuadY[1] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetY2(Value: TFloat);
- begin
- FQuadY[2] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.SetY3(Value: TFloat);
- begin
- FQuadY[3] := Value;
- Changed;
- end;
- procedure TProjectiveTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
- out SrcX, SrcY: TFixed);
- var
- Z: TFixed;
- Zf: TFloat;
- begin
- Z := FixedMul(FInverseFixedMatrix[0, 2], DstX) +
- FixedMul(FInverseFixedMatrix[1, 2], DstY) + FInverseFixedMatrix[2, 2];
- if Z = 0 then Exit;
- {$IFDEF UseInlining}
- SrcX := FixedMul(DstX, FInverseFixedMatrix[0, 0]) +
- FixedMul(DstY, FInverseFixedMatrix[1, 0]) + FInverseFixedMatrix[2, 0];
- SrcY := FixedMul(DstX, FInverseFixedMatrix[0,1]) +
- FixedMul(DstY, FInverseFixedMatrix[1, 1]) + FInverseFixedMatrix[2, 1];
- {$ELSE}
- inherited;
- {$ENDIF}
- if Z <> FixedOne then
- begin
- EMMS;
- Zf := FixedOne / Z;
- SrcX := Round(SrcX * Zf);
- SrcY := Round(SrcY * Zf);
- end;
- end;
- procedure TProjectiveTransformation.ReverseTransformFloat(
- DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- var
- Z: TFloat;
- begin
- EMMS;
- Z := FInverseMatrix[0, 2] * DstX + FInverseMatrix[1, 2] * DstY +
- FInverseMatrix[2, 2];
- if Z = 0 then Exit;
- {$IFDEF UseInlining}
- SrcX := DstX * FInverseMatrix[0, 0] + DstY * FInverseMatrix[1, 0] +
- FInverseMatrix[2, 0];
- SrcY := DstX * FInverseMatrix[0, 1] + DstY * FInverseMatrix[1, 1] +
- FInverseMatrix[2, 1];
- {$ELSE}
- inherited;
- {$ENDIF}
- if Z <> 1 then
- begin
- Z := 1 / Z;
- SrcX := SrcX * Z;
- SrcY := SrcY * Z;
- end;
- end;
- procedure TProjectiveTransformation.TransformFixed(SrcX, SrcY: TFixed;
- out DstX, DstY: TFixed);
- var
- Z: TFixed;
- Zf: TFloat;
- begin
- Z := FixedMul(FFixedMatrix[0, 2], SrcX) +
- FixedMul(FFixedMatrix[1, 2], SrcY) + FFixedMatrix[2, 2];
- if Z = 0 then Exit;
- {$IFDEF UseInlining}
- DstX := FixedMul(SrcX, FFixedMatrix[0, 0]) +
- FixedMul(SrcY, FFixedMatrix[1, 0]) + FFixedMatrix[2, 0];
- DstY := FixedMul(SrcX, FFixedMatrix[0, 1]) +
- FixedMul(SrcY, FFixedMatrix[1, 1]) + FFixedMatrix[2, 1];
- {$ELSE}
- inherited;
- {$ENDIF}
- if Z <> FixedOne then
- begin
- EMMS;
- Zf := FixedOne / Z;
- DstX := Round(DstX * Zf);
- DstY := Round(DstY * Zf);
- end;
- end;
- procedure TProjectiveTransformation.TransformFloat(SrcX, SrcY: TFloat;
- out DstX, DstY: TFloat);
- var
- Z: TFloat;
- begin
- EMMS;
- Z := FMatrix[0, 2] * SrcX + FMatrix[1, 2] * SrcY + FMatrix[2, 2];
- if Z = 0 then Exit;
- {$IFDEF UseInlining}
- DstX := SrcX * Matrix[0, 0] + SrcY * Matrix[1, 0] + Matrix[2, 0];
- DstY := SrcX * Matrix[0, 1] + SrcY * Matrix[1, 1] + Matrix[2, 1];
- {$ELSE}
- inherited;
- {$ENDIF}
- if Z <> 1 then
- begin
- Z := 1 / Z;
- DstX := DstX * Z;
- DstY := DstY * Z;
- end;
- end;
- { TTwirlTransformation }
- constructor TTwirlTransformation.Create;
- begin
- FTwirl := 0.03;
- end;
- function TTwirlTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
- var
- Cx, Cy, R: TFloat;
- const
- CPiHalf: TFloat = 0.5 * Pi;
- begin
- Cx := (ASrcRect.Left + ASrcRect.Right) * 0.5;
- Cy := (ASrcRect.Top + ASrcRect.Bottom) * 0.5;
- R := Max(Cx - ASrcRect.Left, Cy - ASrcRect.Top);
- Result.Left := Cx - R * CPiHalf;
- Result.Right := Cx + R * CPiHalf;
- Result.Top := Cy - R * CPiHalf;
- Result.Bottom := Cy + R * CPiHalf;
- end;
- procedure TTwirlTransformation.PrepareTransform;
- begin
- with FSrcRect do
- begin
- Frx := (Right - Left) * 0.5;
- Fry := (Bottom - Top) * 0.5;
- end;
- TransformValid := True;
- end;
- procedure TTwirlTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- var
- xf, yf, r, t: Single;
- begin
- xf := DstX - Frx;
- yf := DstY - Fry;
- r := GR32_Math.Hypot(xf, yf);
- t := ArcTan2(yf, xf) + r * FTwirl;
- GR32_Math.SinCos(t, yf, xf);
- SrcX := Frx + r * xf;
- SrcY := Fry + r * yf;
- end;
- procedure TTwirlTransformation.SetTwirl(const Value: TFloat);
- begin
- FTwirl := Value;
- Changed;
- end;
- { TBloatTransformation }
- constructor TBloatTransformation.Create;
- begin
- FBloatPower := 0.3;
- end;
- procedure TBloatTransformation.PrepareTransform;
- begin
- FPiW := (Pi / (FSrcRect.Right - FSrcRect.Left));
- FPiH := (Pi / (FSrcRect.Bottom - FSrcRect.Top));
- FBP := FBloatPower * Max(FSrcRect.Right - FSrcRect.Left, FSrcRect.Bottom - FSrcRect.Top);
- TransformValid := True;
- end;
- procedure TBloatTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- var
- SinY, CosY, SinX, CosX, t: Single;
- begin
- GR32_Math.SinCos(FPiH * DstY, SinY, CosY);
- GR32_Math.SinCos(FPiW * DstX, SinX, CosX);
- t := FBP * SinY * SinX;
- SrcX := DstX + t * CosX;
- SrcY := DstY + t * CosY;
- end;
- procedure TBloatTransformation.TransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- var
- SinY, CosY, SinX, CosX, t: Single;
- begin
- GR32_Math.SinCos(-FPiH * DstY, SinY, CosY);
- GR32_Math.SinCos(-FPiW * DstX, SinX, CosX);
- t := FBP * SinY * SinX;
- SrcX := DstX + t * CosX;
- SrcY := DstY + t * CosY;
- end;
- procedure TBloatTransformation.SetBloatPower(const Value: TFloat);
- begin
- FBloatPower := Value;
- Changed;
- end;
- { TFishEyeTransformation }
- procedure TFishEyeTransformation.PrepareTransform;
- begin
- with FSrcRect do
- begin
- Frx := (Right - Left) * 0.5;
- Fry := (Bottom - Top) * 0.5;
- if Frx <= Fry then
- begin
- FMinR := Frx;
- Sx := 1;
- Sy:= Frx / Fry;
- end
- else
- begin
- FMinR := Fry;
- Sx:= Fry / Frx;
- Sy := 1;
- end;
- Fsr := 1 / FMinR;
- Faw := ArcSin(Constrain(FMinR * Fsr, -1, 1));
- if Faw <> 0 then Faw := 1 / Faw;
- Faw := Faw * FMinR
- end;
- TransformValid := True;
- end;
- procedure TFishEyeTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- var
- d, Xrx, Yry: TFloat;
- begin
- Yry := (DstY - Fry) * sy;
- Xrx := (DstX - Frx) * sx;
- d := GR32_Math.Hypot(Xrx, Yry);
- if (d < FMinR) and (d > 0) then
- begin
- d := ArcSin(d * Fsr) * Faw / d;
- SrcX := Frx + Xrx * d;
- SrcY := Fry + Yry * d;
- end
- else
- begin
- SrcX := DstX;
- SrcY := DstY;
- end;
- end;
- { TPolarTransformation }
- procedure TPolarTransformation.PrepareTransform;
- begin
- Sx := SrcRect.Right - SrcRect.Left;
- Sy := SrcRect.Bottom - SrcRect.Top;
- Cx := (DstRect.Left + DstRect.Right) * 0.5;
- Cy := (DstRect.Top + DstRect.Bottom) * 0.5;
- Dx := DstRect.Right - Cx;
- Dy := DstRect.Bottom - Cy;
- Rt := (1 / (PI * 2)) * Sx;
- Rt2 := Sx;
- if Rt2 <> 0 then Rt2 := 1 / Sx else Rt2 := 0.00000001;
- Rt2 := Rt2 * 2 * Pi;
- Rr := Sy;
- if Rr <> 0 then Rr := 1 / Rr else Rr := 0.00000001;
- Rcx := Cx;
- if Rcx <> 0 then Rcx := 1 / Rcx else Rcx := 0.00000001;
- Rcy := Cy;
- if Rcy <> 0 then Rcy := 1 / Rcy else Rcy := 0.00000001;
- TransformValid := True;
- end;
- procedure TPolarTransformation.SetDstRect(const Value: TFloatRect);
- begin
- FDstRect := Value;
- Changed;
- end;
- procedure TPolarTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
- DstY: TFloat);
- var
- R, Theta, S, C: TFloat;
- begin
- Theta := (SrcX - SrcRect.Left) * Rt2 + Phase;
- R := (SrcY - SrcRect.Bottom) * Rr;
- GR32_Math.SinCos(Theta, S, C);
- DstX := Dx * R * C + Cx;
- DstY := Dy * R * S + Cy;
- end;
- procedure TPolarTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- const
- PI2 = 2 * PI;
- var
- Dcx, Dcy, Theta: TFloat;
- begin
- Dcx := (DstX - Cx) * Rcx;
- Dcy := (DstY - Cy) * Rcy;
- Theta := ArcTan2(Dcy, Dcx) + Pi - Phase;
- if Theta < 0 then Theta := Theta + PI2;
- SrcX := SrcRect.Left + Theta * Rt;
- SrcY := SrcRect.Bottom - GR32_Math.Hypot(Dcx, Dcy) * Sy;
- end;
- procedure TPolarTransformation.SetPhase(const Value: TFloat);
- begin
- FPhase := Value;
- Changed;
- end;
- { TPathTransformation }
- destructor TPathTransformation.Destroy;
- begin
- FTopHypot := nil;
- FBottomHypot := nil;
- inherited;
- end;
- procedure TPathTransformation.PrepareTransform;
- var
- I: Integer;
- L, DDist: TFloat;
- begin
- if not (Assigned(FTopCurve) and Assigned(FBottomCurve)) then
- raise ETransformError.Create(RCStrTopBottomCurveNil);
- SetLength(FTopHypot, Length(FTopCurve));
- SetLength(FBottomHypot, Length(FBottomCurve));
- L := 0;
- for I := 0 to High(FTopCurve) - 1 do
- begin
- FTopHypot[I].Dist := L;
- with FTopCurve[I + 1] do
- L := L + GR32_Math.Hypot(FTopCurve[I].X - X, FTopCurve[I].Y - Y);
- end;
- FTopLength := L;
- for I := 1 to High(FTopCurve) do
- with FTopHypot[I] do
- begin
- DDist := Dist - FTopHypot[I - 1].Dist;
- if DDist <> 0 then
- RecDist := 1 / DDist
- else if I > 1 then
- RecDist := FTopHypot[I - 1].RecDist
- else
- RecDist := 0;
- end;
- L := 0;
- for I := 0 to High(FBottomCurve) - 1 do
- begin
- FBottomHypot[I].Dist := L;
- with FBottomCurve[I + 1] do
- L := L + GR32_Math.Hypot(FBottomCurve[I].X - X, FBottomCurve[I].Y - Y);
- end;
- FBottomLength := L;
- for I := 1 to High(FBottomCurve) do
- with FBottomHypot[I] do
- begin
- DDist := Dist - FBottomHypot[I - 1].Dist;
- if DDist <> 0 then
- RecDist := 1 / DDist
- else if I > 1 then
- RecDist := FBottomHypot[I - 1].RecDist
- else
- RecDist := 0;
- end;
- rdx := 1 / (SrcRect.Right - SrcRect.Left);
- rdy := 1 / (SrcRect.Bottom - SrcRect.Top);
- TransformValid := True;
- end;
- procedure TPathTransformation.SetBottomCurve(const Value: TArrayOfFloatPoint);
- begin
- FBottomCurve := Value;
- Changed;
- end;
- procedure TPathTransformation.SetTopCurve(const Value: TArrayOfFloatPoint);
- begin
- FTopCurve := Value;
- Changed;
- end;
- procedure TPathTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
- DstY: TFloat);
- var
- I, H: Integer;
- X, Y, fx, dx, dy, r, Tx, Ty, Bx, By: TFloat;
- begin
- X := (SrcX - SrcRect.Left) * rdx;
- Y := (SrcY - SrcRect.Top) * rdy;
- fx := X * FTopLength;
- I := 1;
- H := High(FTopHypot);
- while (FTopHypot[I].Dist < fx) and (I < H) do Inc(I);
- with FTopHypot[I] do
- r := (Dist - fx) * RecDist;
- dx := (FTopCurve[I - 1].X - FTopCurve[I].X);
- dy := (FTopCurve[I - 1].Y - FTopCurve[I].Y);
- Tx := FTopCurve[I].X + r * dx;
- Ty := FTopCurve[I].Y + r * dy;
- fx := X * FBottomLength;
- I := 1;
- H := High(FBottomHypot);
- while (FBottomHypot[I].Dist < fx) and (I < H) do Inc(I);
- with FBottomHypot[I] do
- r := (Dist - fx) * RecDist;
- dx := (FBottomCurve[I - 1].X - FBottomCurve[I].X);
- dy := (FBottomCurve[I - 1].Y - FBottomCurve[I].Y);
- Bx := FBottomCurve[I].X + r * dx;
- By := FBottomCurve[I].Y + r * dy;
- DstX := Tx + Y * (Bx - Tx);
- DstY := Ty + Y * (By - Ty);
- end;
- { TDisturbanceTransformation }
- function TDisturbanceTransformation.GetTransformedBounds(
- const ASrcRect: TFloatRect): TFloatRect;
- begin
- Result := ASrcRect;
- InflateRect(Result, 0.5 * FDisturbance, 0.5 * FDisturbance);
- end;
- procedure TDisturbanceTransformation.ReverseTransformFloat(DstX,
- DstY: TFloat; out SrcX, SrcY: TFloat);
- begin
- SrcX := DstX + (Random - 0.5) * FDisturbance;
- SrcY := DstY + (Random - 0.5) * FDisturbance;
- end;
- procedure TDisturbanceTransformation.SetDisturbance(const Value: TFloat);
- begin
- FDisturbance := Value;
- Changed;
- end;
- { TRemapTransformation }
- constructor TRemapTransformation.Create;
- begin
- inherited;
- FScalingFixed := FixedPoint(1, 1);
- FScalingFloat := FloatPoint(1, 1);
- FOffset := FloatPoint(0,0);
- FVectorMap := TVectorMap.Create;
- //Ensuring initial setup to avoid exceptions
- FVectorMap.SetSize(1, 1);
- end;
- destructor TRemapTransformation.Destroy;
- begin
- FVectorMap.Free;
- inherited;
- end;
- function TRemapTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
- const
- InfRect: TFloatRect = (Left: -Infinity; Top: -Infinity; Right: Infinity; Bottom: Infinity);
- begin
- // We can't predict the ultimate bounds without transforming each vector in
- // the vector map, return the absolute biggest possible transformation bounds
- Result := InfRect;
- end;
- function TRemapTransformation.HasTransformedBounds: Boolean;
- begin
- Result := False;
- end;
- procedure TRemapTransformation.PrepareTransform;
- begin
- if IsRectEmpty(SrcRect) then raise Exception.Create(RCStrSrcRectIsEmpty);
- if IsRectEmpty(FMappingRect) then raise Exception.Create(RCStrMappingRectIsEmpty);
- with SrcRect do
- begin
- FSrcTranslationFloat.X := Left;
- FSrcTranslationFloat.Y := Top;
- FSrcScaleFloat.X := (Right - Left) / (FVectorMap.Width - 1);
- FSrcScaleFloat.Y := (Bottom - Top) / (FVectorMap.Height - 1);
- FSrcTranslationFixed := FixedPoint(FSrcTranslationFloat);
- FSrcScaleFixed := FixedPoint(FSrcScaleFloat);
- end;
- with FMappingRect do
- begin
- FDstTranslationFloat.X := Left;
- FDstTranslationFloat.Y := Top;
- FDstScaleFloat.X := (FVectorMap.Width - 1) / (Right - Left);
- FDstScaleFloat.Y := (FVectorMap.Height - 1) / (Bottom - Top);
- FCombinedScalingFloat.X := FDstScaleFloat.X * FScalingFloat.X;
- FCombinedScalingFloat.Y := FDstScaleFloat.Y * FScalingFloat.Y;
- FCombinedScalingFixed := FixedPoint(FCombinedScalingFloat);
- FDstTranslationFixed := FixedPoint(FDstTranslationFloat);
- FDstScaleFixed := FixedPoint(FDstScaleFloat);
- end;
- TransformValid := True;
- end;
- procedure TRemapTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
- out SrcX, SrcY: TFixed);
- begin
- with FVectorMap.FixedVectorX[DstX - FOffsetFixed.X, DstY - FOffsetFixed.Y] do
- begin
- DstX := DstX - FDstTranslationFixed.X;
- DstX := FixedMul(DstX , FDstScaleFixed.X);
- DstX := DstX + FixedMul(X, FCombinedScalingFixed.X);
- DstX := FixedMul(DstX, FSrcScaleFixed.X);
- SrcX := DstX + FSrcTranslationFixed.X;
- DstY := DstY - FDstTranslationFixed.Y;
- DstY := FixedMul(DstY, FDstScaleFixed.Y);
- DstY := DstY + FixedMul(Y, FCombinedScalingFixed.Y);
- DstY := FixedMul(DstY, FSrcScaleFixed.Y);
- SrcY := DstY + FSrcTranslationFixed.Y;
- end;
- end;
- procedure TRemapTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
- out SrcX, SrcY: TFloat);
- begin
- with FVectorMap.FloatVectorF[DstX - FOffset.X, DstY - FOffset.Y] do
- begin
- DstX := DstX - FDstTranslationFloat.X;
- DstY := DstY - FDstTranslationFloat.Y;
- DstX := DstX * FDstScaleFloat.X;
- DstY := DstY * FDstScaleFloat.Y;
- DstX := DstX + X * FCombinedScalingFloat.X;
- DstY := DstY + Y * FCombinedScalingFloat.Y;
- DstX := DstX * FSrcScaleFloat.X;
- DstY := DstY * FSrcScaleFloat.Y;
- SrcX := DstX + FSrcTranslationFloat.X;
- SrcY := DstY + FSrcTranslationFloat.Y;
- end;
- end;
- procedure TRemapTransformation.ReverseTransformInt(DstX, DstY: Integer;
- out SrcX, SrcY: Integer);
- begin
- with FVectorMap.FixedVector[DstX - FOffsetInt.X, DstY - FOffsetInt.Y] do
- begin
- DstX := DstX * FixedOne - FDstTranslationFixed.X;
- DstY := DstY * FixedOne - FDstTranslationFixed.Y;
- DstX := FixedMul(DstX, FDstScaleFixed.X);
- DstY := FixedMul(DstY, FDstScaleFixed.Y);
- DstX := DstX + FixedMul(X, FCombinedScalingFixed.X);
- DstY := DstY + FixedMul(Y, FCombinedScalingFixed.Y);
- DstX := FixedMul(DstX, FSrcScaleFixed.X);
- DstY := FixedMul(DstY, FSrcScaleFixed.Y);
- SrcX := FixedRound(DstX + FSrcTranslationFixed.X);
- SrcY := FixedRound(DstY + FSrcTranslationFixed.Y);
- end;
- end;
- procedure TRemapTransformation.Scale(Sx, Sy: TFloat);
- begin
- FScalingFixed.X := Fixed(Sx);
- FScalingFixed.Y := Fixed(Sy);
- FScalingFloat.X := Sx;
- FScalingFloat.Y := Sy;
- Changed;
- end;
- procedure TRemapTransformation.SetMappingRect(Rect: TFloatRect);
- begin
- FMappingRect := Rect;
- Changed;
- end;
- procedure TRemapTransformation.SetOffset(const Value: TFloatVector);
- begin
- FOffset := Value;
- FOffsetInt := Point(Value);
- FOffsetFixed := FixedPoint(Value);
- Changed;
- end;
- procedure RasterizeTransformation(Vectormap: TVectormap;
- Transformation: TTransformation; DstRect: TRect;
- CombineMode: TVectorCombineMode = vcmAdd;
- CombineCallback: TVectorCombineEvent = nil);
- var
- I, J: Integer;
- P, Q, Progression: TFixedVector;
- ProgressionX, ProgressionY: TFixed;
- MapPtr: PFixedPointArray;
- begin
- GR32.IntersectRect(DstRect, VectorMap.BoundsRect, DstRect);
- if GR32.IsRectEmpty(DstRect) then Exit;
- if not TTransformationAccess(Transformation).TransformValid then
- TTransformationAccess(Transformation).PrepareTransform;
- case CombineMode of
- vcmAdd:
- begin
- with DstRect do
- for I := Top to Bottom - 1 do
- begin
- MapPtr := @VectorMap.Vectors[I * VectorMap.Width];
- for J := Left to Right - 1 do
- begin
- P := FixedPoint(Integer(J - Left), Integer(I - Top));
- Q := Transformation.ReverseTransform(P);
- Inc(MapPtr[J].X, Q.X - P.X);
- Inc(MapPtr[J].Y, Q.Y - P.Y);
- end;
- end;
- end;
- vcmReplace:
- begin
- with DstRect do
- for I := Top to Bottom - 1 do
- begin
- MapPtr := @VectorMap.Vectors[I * VectorMap.Width];
- for J := Left to Right - 1 do
- begin
- P := FixedPoint(Integer(J - Left), Integer(I - Top));
- Q := Transformation.ReverseTransform(P);
- MapPtr[J].X := Q.X - P.X;
- MapPtr[J].Y := Q.Y - P.Y;
- end;
- end;
- end;
- else // vcmCustom
- ProgressionX := Fixed(1 / (DstRect.Right - DstRect.Left - 1));
- ProgressionY := Fixed(1 / (DstRect.Bottom - DstRect.Top - 1));
- Progression.Y := 0;
- with DstRect do for I := Top to Bottom - 1 do
- begin
- Progression.X := 0;
- MapPtr := @VectorMap.Vectors[I * VectorMap.Width];
- for J := Left to Right - 1 do
- begin
- P := FixedPoint(Integer(J - Left), Integer(I - Top));
- Q := Transformation.ReverseTransform(P);
- Q.X := Q.X - P.X;
- Q.Y := Q.Y - P.Y;
- CombineCallback(Q, Progression, MapPtr[J]);
- Inc(Progression.X, ProgressionX);
- end;
- Inc(Progression.Y, ProgressionY);
- end;
- end;
- end;
- { Matrix conversion routines }
- function FixedMatrix(const FloatMatrix: TFloatMatrix): TFixedMatrix;
- begin
- Result[0,0] := Round(FloatMatrix[0,0] * FixedOne);
- Result[0,1] := Round(FloatMatrix[0,1] * FixedOne);
- Result[0,2] := Round(FloatMatrix[0,2] * FixedOne);
- Result[1,0] := Round(FloatMatrix[1,0] * FixedOne);
- Result[1,1] := Round(FloatMatrix[1,1] * FixedOne);
- Result[1,2] := Round(FloatMatrix[1,2] * FixedOne);
- Result[2,0] := Round(FloatMatrix[2,0] * FixedOne);
- Result[2,1] := Round(FloatMatrix[2,1] * FixedOne);
- Result[2,2] := Round(FloatMatrix[2,2] * FixedOne);
- end;
- function FloatMatrix(const FixedMatrix: TFixedMatrix): TFloatMatrix;
- begin
- Result[0,0] := FixedMatrix[0,0] * FixedToFloat;
- Result[0,1] := FixedMatrix[0,1] * FixedToFloat;
- Result[0,2] := FixedMatrix[0,2] * FixedToFloat;
- Result[1,0] := FixedMatrix[1,0] * FixedToFloat;
- Result[1,1] := FixedMatrix[1,1] * FixedToFloat;
- Result[1,2] := FixedMatrix[1,2] * FixedToFloat;
- Result[2,0] := FixedMatrix[2,0] * FixedToFloat;
- Result[2,1] := FixedMatrix[2,1] * FixedToFloat;
- Result[2,2] := FixedMatrix[2,2] * FixedToFloat;
- end;
- {CPU target and feature Function templates}
- const
- FID_DETERMINANT32 = 0;
- FID_DETERMINANT64 = 1;
- {Complete collection of unit templates}
- var
- Registry: TFunctionRegistry;
- procedure RegisterBindings;
- begin
- Registry := NewRegistry('GR32_Transforms bindings');
- Registry.RegisterBinding(FID_DETERMINANT32, @@DET32);
- Registry.Add(FID_DETERMINANT32, @DET32_Pas, []);
- {$IFNDEF PUREPASCAL}
- Registry.Add(FID_DETERMINANT32, @DET32_ASM, []);
- // Registry.Add(FID_DETERMINANT32, @DET32_SSE2, [ciSSE2]);
- {$ENDIF}
- Registry.RegisterBinding(FID_DETERMINANT64, @@DET64);
- Registry.Add(FID_DETERMINANT64, @DET64_Pas, []);
- {$IFNDEF PUREPASCAL}
- Registry.Add(FID_DETERMINANT64, @DET64_ASM, []);
- // Registry.Add(FID_DETERMINANT64, @DET64_SSE2, [ciSSE2]);
- {$ENDIF}
- Registry.RebindAll;
- end;
- initialization
- RegisterBindings;
- finalization
- end.
|