| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473 |
- // SPDX-License-Identifier: GPL-3.0-only
- unit UToolVectorial;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, LCLType, BGRABitmap, BGRABitmapTypes,
- BGRALayerOriginal, BGRAGraphics, LCVectorOriginal, LCVectorialFill,
- UTool, UImageType, ULayerAction, LCVectorRectShapes, LCVectorMultishape,
- BGRAGradientOriginal, UStateType;
- type
- TToolSplineMode = (tsmMovePoint, tsmCurveModeAuto, tsmCurveModeAngle, tsmCurveModeSpline);
- function ToolSplineModeFromShape(AShape: TVectorShape): TToolSplineMode;
- type
- TFitMode = (fmNever, fmIfChange, fmAlways);
- type
- { TVectorialTool }
- TVectorialTool = class(TGenericTool)
- private
- function GetEditor: TBGRAOriginalEditor;
- function GetIsHandDrawing: boolean;
- function GetIsIdle: boolean;
- protected
- class var SquareHintShown: boolean;
- FLayerWasEmpty: boolean;
- FShape: TVectorShape;
- FTemporaryStorage: TBGRACustomOriginalStorage;
- FLastDraftUpdate: Boolean;
- FSwapColor: boolean;
- FQuickDefine: Boolean;
- FQuickDefineStartPoint, FQuickDefineUserEndPoint, FQuickDefineEndPoint: TPointF;
- FPreviousUpdateBounds, FPreviousEditorBounds: TRect;
- FEditor: TBGRAOriginalEditor;
- FRightDown, FLeftDown: boolean;
- FLastPos: TPointF;
- FLastShapeTransform: TAffineMatrix;
- FUseOriginal: boolean;
- function AlwaysRasterizeShape: boolean; virtual;
- function CreateShape: TVectorShape; virtual;
- procedure ClearShape; virtual;
- function ShapeClass: TVectorShapeAny; virtual; abstract;
- function UseOriginal: boolean; virtual;
- function HasBrush: boolean; virtual;
- function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; {%H-}ADraft: boolean): TRect; virtual;
- procedure DrawCustomShape(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); virtual;
- procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); virtual;
- function GetManagerShapeOptions: TShapeOptions; virtual;
- procedure QuickDefineShape(AStart,AEnd: TPointF); virtual;
- function RoundCoordinate(constref ptF: TPointF): TPointF; virtual;
- function GetIsSelectingTool: boolean; override;
- function UpdateShape(toolDest: TBGRABitmap): TRect; virtual;
- function PreferDraftUpdate: boolean;
- function VectorTransform(APixelCentered: boolean): TAffineMatrix;
- procedure UpdateCursor(ACursor: TOriginalEditorCursor);
- function FixLayerOffset: boolean; override;
- function UpdateQuickDefine: TRect;
- function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF; rightBtn: boolean): TRect; override;
- function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF): TRect; override;
- function DoToolUpdate({%H-}toolDest: TBGRABitmap): TRect; override;
- function DoToolKeyDown(var key: Word): TRect; override;
- function DoToolKeyUp(var key: Word): TRect; override;
- procedure ShapeChange({%H-}ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff); virtual;
- procedure ShapeEditingChange({%H-}ASender: TObject); virtual;
- procedure ShapeRemoveQuery({%H-}ASender: TObject; var AHandled: boolean);
- function GetStatusText: string; override;
- function SlowShape: boolean; virtual;
- procedure QuickDefineEnd; virtual;
- procedure OnTryStop({%H-}sender: TCustomLayerAction); override;
- procedure UpdateUseOriginal;
- function ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference; virtual;
- procedure ShapeValidated; virtual;
- function ForeGradTexMode: TVectorShapeUsermode; virtual;
- function BackGradTexMode: TVectorShapeUsermode; virtual;
- function OutlineGradTexMode: TVectorShapeUsermode; virtual;
- function ForeFitMode: TFitMode;
- function BackFitMode: TFitMode;
- function OutlineFitMode: TFitMode;
- function ManagerForeFill: TVectorialFill;
- function ManagerBackFill: TVectorialFill;
- function ManagerOutlineFill: TVectorialFill;
- function GetIsForeEditGradTexPoints: boolean; override;
- function GetIsBackEditGradTexPoints: boolean; override;
- function GetIsOutlineEditGradTexPoints: boolean; override;
- function GetGridMatrix: TAffineMatrix; virtual;
- function GetIsEditingText: boolean; override;
- property Editor: TBGRAOriginalEditor read GetEditor;
- public
- class procedure ForgetHintShown;
- function ValidateShape: TRect;
- function CancelShape: TRect;
- constructor Create(AManager: TToolManager); override;
- function ToolUp: TRect; override;
- function ToolKeyPress(var key: TUTF8Char): TRect; override;
- function ToolCommand(ACommand: TToolCommand): boolean; override;
- function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
- function SuggestGradientBox: TAffineBox; override;
- function GetContextualToolbars: TContextualToolbars; override;
- function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
- property IsIdle: boolean read GetIsIdle;
- property IsHandDrawing: boolean read GetIsHandDrawing;
- destructor Destroy; override;
- end;
- { TEditShapeTool }
- TEditShapeMode = (esmNone, esmSelection, esmGradient, esmOtherOriginal, esmShape, esmNoShape);
- TEditShapeTool = class(TGenericTool)
- private
- function GetNothingSelected: boolean;
- function GetPointSize: integer;
- protected
- FDownHandled,FRectEditorCapture,FLayerOriginalCapture,
- FLeftButton,FRightButton: boolean;
- FLastPos: TPointF;
- FOriginalLayerId: integer;
- FOriginalRect: TRectShape;
- FOriginalRectUntransformed: TRectF;
- FRectEditor: TBGRAOriginalEditor;
- FSelectionRect: TRectShape;
- FSelectionRectUntransformed: TRectF;
- FIsEditingGradient: boolean;
- procedure RetrieveLightPosition;
- procedure UpdateToolManagerFromShape(AShape: TVectorShape);
- procedure UpdateDraftMode;
- procedure BindOriginalEvent(ABind: boolean);
- procedure SelectShape({%H-}ASender: TObject; AShape: TVectorShape; {%H-}APreviousShape: TVectorShape);
- function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF; rightBtn: boolean): TRect; override;
- function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF): TRect; override;
- function DoToolUpdate({%H-}toolDest: TBGRABitmap): TRect; override;
- function DoToolKeyDown(var key: Word): TRect; override;
- function DoToolKeyUp(var key: Word): TRect; override;
- procedure UpdateSnap(AEditor: TBGRAOriginalEditor);
- function GetAction: TLayerAction; override;
- function DoGetToolDrawingLayer: TBGRABitmap; override;
- procedure OnTryStop({%H-}sender: TCustomLayerAction); override;
- procedure StopEdit(AUpdateInterface, ARaiseToolUp: boolean);
- function IsEditing: boolean;
- procedure MakeImageOriginal;
- procedure MakeVectorOriginal;
- procedure UpdateMatrixFromRect;
- procedure DoEditSelection;
- function GetMatrixFromRect(ARect: TRectShape; AUntransformedRect: TRectF): TAffineMatrix;
- function CreateRect(AUntransformedRect: TRectF; AMatrix: TAffineMatrix): TRectShape;
- function GetIsSelectingTool: boolean; override;
- function GetVectorOriginal: TVectorOriginal;
- function GetGradientOriginal: TBGRALayerGradientOriginal;
- function GetImageOriginal: TBGRALayerImageOriginal;
- function GetOriginalTransform: TAffineMatrix;
- function FixLayerOffset: boolean; override;
- function GetCurrentSplineMode: TToolSplineMode;
- procedure SetCurrentSplineMode(AMode: TToolSplineMode);
- function ConvertToSpline: boolean;
- function GetEditMode: TEditShapeMode;
- function InvalidEditMode: boolean;
- function ForeGradTexMode: TVectorShapeUsermode; virtual;
- function BackGradTexMode: TVectorShapeUsermode; virtual;
- function OutlineGradTexMode: TVectorShapeUsermode; virtual;
- function ForeFitMode: TFitMode;
- function BackFitMode: TFitMode;
- function OutlineFitMode: TFitMode;
- function GetIsForeEditGradTexPoints: boolean; override;
- function GetIsBackEditGradTexPoints: boolean; override;
- function GetIsOutlineEditGradTexPoints: boolean; override;
- function GetAllowedBackFillTypes: TVectorialFillTypes; override;
- function GetStatusText: string; override;
- public
- constructor Create(AManager: TToolManager); override;
- destructor Destroy; override;
- function GetContextualToolbars: TContextualToolbars; override;
- function Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth, VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect; override;
- function ToolKeyPress(var key: TUTF8Char): TRect; override;
- function ToolUp: TRect; override;
- function ToolCommand(ACommand: TToolCommand): boolean; override;
- function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
- function SuggestGradientBox: TAffineBox; override;
- property CurrentSplineMode: TToolSplineMode read GetCurrentSplineMode write SetCurrentSplineMode;
- property NothingSelected: boolean read GetNothingSelected;
- end;
- procedure AssignFill(ATarget, ASource: TVectorialFill; const ABox: TAffineBox; AFitMode: TFitMode);
- function GetShapeStatusText(AShape: TVectorShape; const AMatrix: TAffineMatrix): string;
- function GetGradientStatusText(AGradient: TBGRALayerGradientOriginal; const AMatrix: TAffineMatrix): string;
- implementation
- uses LazPaintType, LCVectorPolyShapes, LCVectorTextShapes, BGRASVGOriginal,
- ULoading, BGRATransform, math, UImageDiff, Controls, BGRAPen, UResourceStrings, ugraph,
- LCScaleDPI, LCVectorClipboard, BGRAGradientScanner, UClipboard, BGRAUTF8;
- const PointSize = 6;
- function OriginalCursorToCursor(ACursor: TOriginalEditorCursor): TCursor;
- begin
- case ACursor of
- oecMove: result := crSizeAll;
- oecMoveN: result := crSizeN;
- oecMoveS: result := crSizeS;
- oecMoveE: result := crSizeE;
- oecMoveW: result := crSizeW;
- oecMoveNE: result := crSizeNE;
- oecMoveSW: result := crSizeSW;
- oecMoveNW: result := crSizeNW;
- oecMoveSE: result := crSizeSE;
- oecHandPoint: result := crHandPoint;
- oecText: result := crIBeam;
- else result := crDefault;
- end;
- end;
- function ToolSplineModeFromShape(AShape: TVectorShape): TToolSplineMode;
- var
- c: TCurveShape;
- begin
- result := tsmMovePoint;
- if not (AShape is TCurveShape) then exit;
- c := TCurveShape(AShape);
- case c.Usermode of
- vsuEdit: result := tsmMovePoint;
- vsuCreate: if c.PointCount > 1 then
- begin
- case c.CurveMode[c.PointCount-2] of
- cmAuto: result := tsmCurveModeAuto;
- cmAngle: result := tsmCurveModeAngle;
- cmCurve: result := tsmCurveModeSpline;
- end;
- end else
- result := tsmCurveModeAuto;
- vsuCurveSetAuto: result := tsmCurveModeAuto;
- vsuCurveSetAngle: result := tsmCurveModeAngle;
- vsuCurveSetCurve: result := tsmCurveModeSpline;
- end;
- end;
- function ContextualToolbarsFromShape(AShapeClass: TVectorShapeAny; AShape: TVectorShape): TContextualToolbars;
- var
- f: TVectorShapeFields;
- begin
- result:= [ctPenFill, ctBackFill];
- if Assigned(AShape) then
- f := AShape.MultiFields
- else f := AShapeClass.Fields;
- if vsfPenWidth in f then result += [ctPenWidth];
- if vsfPenStyle in f then result += [ctPenStyle];
- if vsfJoinStyle in f then result += [ctJoinStyle];
- if [vsfPenStyle,vsfPenFill,vsfBackFill] <= f then result += [ctShape];
- if vsfOutlineFill in f then
- begin
- result += [ctOutlineFill];
- if not (vsfBackFill in f) then result -= [ctBackFill];
- end;
- if vsfOutlineWidth in f then result += [ctOutlineWidth];
- if AShapeClass = TCurveShape then result := result + [ctShape,ctCloseShape,ctLineCap,ctSplineStyle]
- else if AShapeClass = TPolylineShape then result := result + [ctShape,ctCloseShape,ctLineCap]
- else if AShapeClass = TPhongShape then result := result + [ctPhong,ctAltitude]
- else if AShapeClass = TTextShape then
- begin
- result := result + [ctText,ctAliasing];
- if TTextShape(AShape).PenPhong then include(result, ctAltitude);
- end;
- if vsfAliased in f then
- result += [ctAliasing];
- end;
- procedure AlignShape(AShape: TVectorShape; ACommand: TToolCommand; const AMatrix: TAffineMatrix; const ARect: TRect);
- begin
- case ACommand of
- tcAlignLeft: AShape.AlignHorizontally(taLeftJustify,AMatrix,ARect);
- tcCenterHorizontally: AShape.AlignHorizontally(taCenter,AMatrix,ARect);
- tcAlignRight: AShape.AlignHorizontally(taRightJustify,AMatrix,ARect);
- tcAlignTop..tcAlignBottom:
- AShape.AlignVertically(TTextLayout(ord(ACommand)-ord(tcAlignTop)+ord(tlTop)),AMatrix,ARect);
- end;
- end;
- procedure AssignFill(ATarget, ASource: TVectorialFill; const ABox: TAffineBox; AFitMode: TFitMode);
- var
- temp: TVectorialFill;
- change: Boolean;
- begin
- if ASource.IsFullyTransparent then ATarget.Clear else
- begin
- change := ((ATarget.FillType = vftGradient) and (ASource.FillType = vftGradient) and
- (ATarget.Gradient.GradientType <> ASource.Gradient.GradientType) and
- not ([ATarget.Gradient.GradientType,ASource.Gradient.GradientType] <= [gtRadial,gtDiamond,gtAngular])) or
- ((ATarget.FillType = vftTexture) and (ASource.FillType = vftTexture) and
- (ATarget.TextureRepetition <> ASource.TextureRepetition));
- if ((AFitMode = fmIfChange) and change) or (AFitMode = fmAlways)
- or (ATarget.FillType <> ASource.FillType) then
- begin
- temp := ATarget.Duplicate;
- temp.AssignExceptGeometry(ASource);
- temp.FitGeometry(ABox);
- ATarget.Assign(temp);
- temp.Free;
- end else
- ATarget.AssignExceptGeometry(ASource);
- end;
- end;
- function GetShapeStatusText(AShape: TVectorShape; const AMatrix: TAffineMatrix): string;
- var
- orig, xa, ya, corner1, corner2: TPointF;
- overline: string4;
- i, nb: Integer;
- rF: TRectF;
- begin
- if AShape is TEllipseShape then
- with TEllipseShape(AShape) do
- begin
- orig := AMatrix*Origin;
- xa := AMatrix*XAxis;
- ya := AMatrix*YAxis;
- result := 'x = '+FloatToStrF(orig.x,ffFixed,6,1)+'|y = '+FloatToStrF(orig.y,ffFixed,6,1)+'|'+
- 'rx = '+FloatToStrF(VectLen(xa-orig),ffFixed,6,1)+'|ry = '+FloatToStrF(VectLen(ya-orig),ffFixed,6,1)
- end
- else if AShape is TCustomRectShape then
- with TCustomRectShape(AShape) do
- begin
- orig := AMatrix*Origin;
- xa := AMatrix*XAxis;
- ya := AMatrix*YAxis;
- corner1 := orig-(xa-orig)-(ya-orig);
- corner2 := xa + (ya-orig);
- result := 'x1 = '+FloatToStrF(corner1.x,ffFixed,6,1)+'|y1 = '+FloatToStrF(corner1.y,ffFixed,6,1)+'|'+
- 'x2 = '+FloatToStrF(corner2.x,ffFixed,6,1)+'|y2 = '+FloatToStrF(corner2.y,ffFixed,6,1)+'|'+
- 'Δx = '+FloatToStrF(VectLen(xa-orig)*2,ffFixed,6,1)+'|Δy = '+FloatToStrF(VectLen(ya-orig)*2,ffFixed,6,1);
- end
- else if AShape is TCustomPolypointShape then
- with TCustomPolypointShape(AShape) do
- begin
- result := 'count = ';
- nb := 0;
- for i := 0 to PointCount-1 do
- if Points[i].IsEmpty then
- begin
- if nb > 0 then result += inttostr(nb)+', ';
- nb := 0;
- end else inc(nb);
- result += inttostr(nb);
- if not Center.IsEmpty then
- begin
- orig := AMatrix*Center;
- overline := UnicodeCharToUTF8($0305);
- result += '|x'+overline+' = '+FloatToStrF(orig.x,ffFixed,6,1);
- result += '|y'+overline+' = '+FloatToStrF(orig.y,ffFixed,6,1);
- end;
- if (Usermode = vsuCreate) and (PointCount > 0) then
- begin
- xa := AMatrix*Points[PointCount-1];
- result += '|x = '+FloatToStrF(xa.x,ffFixed,6,1);
- result += '|y = '+FloatToStrF(xa.y,ffFixed,6,1);
- end else
- if HoverPoint <> -1 then
- begin
- xa := AMatrix*Points[HoverPoint];
- result += '|x = '+FloatToStrF(xa.x,ffFixed,6,1);
- result += '|y = '+FloatToStrF(xa.y,ffFixed,6,1);
- end else
- begin
- rF := GetPointBounds(AMatrix);
- result += '|Δx = '+FloatToStrF(rF.Width,ffFixed,6,1);
- result += '|Δy = '+FloatToStrF(rF.Height,ffFixed,6,1);
- end;
- end else
- result := '';
- end;
- function GetGradientStatusText(AGradient: TBGRALayerGradientOriginal; const AMatrix: TAffineMatrix): string;
- var
- orig, xa: TPointF;
- begin
- with AGradient do
- begin
- orig := AMatrix*Origin;
- xa := AMatrix*XAxis;
- result := 'x1 = '+FloatToStrF(orig.x,ffFixed,6,1)+'|y1 = '+FloatToStrF(orig.y,ffFixed,6,1)+'|'+
- 'x2 = '+FloatToStrF(xa.x,ffFixed,6,1)+'|y2 = '+FloatToStrF(xa.y,ffFixed,6,1)+'|'+
- 'Δx = '+FloatToStrF(abs(xa.x-orig.x),ffFixed,6,1)+'|Δy = '+FloatToStrF(abs(xa.y-orig.y),ffFixed,6,1);
- end;
- end;
- { TEditShapeTool }
- procedure TEditShapeTool.SelectShape(ASender: TObject; AShape: TVectorShape;
- APreviousShape: TVectorShape);
- begin
- if Assigned(AShape) and (GetCurrentLayerKind = lkVectorial) then
- begin
- UpdateToolManagerFromShape(AShape);
- Manager.UpdateContextualToolbars;
- end else
- if Assigned(APreviousShape) then
- Manager.UpdateContextualToolbars;
- end;
- function TEditShapeTool.GetNothingSelected: boolean;
- begin
- result := GetEditMode in [esmNone, esmNoShape];
- end;
- function TEditShapeTool.GetPointSize: integer;
- begin
- result := DoScaleX(PointSize*Manager.CanvasScale,OriginalDPI);
- end;
- procedure TEditShapeTool.RetrieveLightPosition;
- var
- shape: TVectorShape;
- m: TAffineMatrix;
- begin
- if GetCurrentLayerKind = lkVectorial then
- begin
- shape := GetVectorOriginal.SelectedShape;
- if shape=nil then exit;
- m := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
- if (shape is TTextShape) and TTextShape(shape).PenPhong then
- Manager.LightPosition := m*TTextShape(shape).LightPosition
- else if shape is TPhongShape then
- Manager.LightPosition := m*TPhongShape(shape).LightPosition;
- end;
- end;
- procedure TEditShapeTool.UpdateToolManagerFromShape(AShape: TVectorShape);
- var
- opt: TShapeOptions;
- zoom: single;
- m: TAffineMatrix;
- doFill, doDraw: Boolean;
- f: TVectorShapeFields;
- begin
- m := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
- zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
- if AShape.Usermode in [vsuEditBackFill, vsuEditPenFill] then
- AShape.Usermode := vsuEdit;
- opt := Manager.ShapeOptions;
- f := AShape.MultiFields;
- if vsfAliased in f then
- begin
- if AShape.Aliased then
- include(opt,toAliasing)
- else exclude(opt,toAliasing);
- end;
- doDraw := vsfPenFill in f;
- doFill := vsfBackFill in f;
- if vsfPenStyle in f then
- begin
- doDraw := AShape.PenVisible;
- if doDraw then doFill := AShape.BackVisible;
- if not doFill then
- exclude(opt,toFillShape)
- else include(opt,toFillShape);
- if not doDraw then
- exclude(opt,toDrawShape)
- else
- begin
- include(opt,toDrawShape);
- Manager.PenStyle := BGRAToPenStyle(AShape.PenStyle);
- end;
- end;
- if doDraw then
- begin
- if not AShape.PenVisible then
- Manager.ForeColor := BGRA(Manager.ForeColor.red,
- Manager.ForeColor.green,Manager.ForeColor.blue,0)
- else
- Manager.ForeFill.Assign(AShape.PenFill);
- end;
- if doFill then
- begin
- if not AShape.BackVisible then
- Manager.BackColor := BGRA(Manager.BackColor.red,
- Manager.BackColor.green,Manager.BackColor.blue,0)
- else
- Manager.BackFill.Assign(AShape.BackFill);
- end;
- if not AShape.OutlineVisible then
- Manager.SetTextOutline(false, Manager.TextOutlineWidth) else
- begin
- Manager.SetTextOutline(true, AShape.OutlineWidth*zoom);
- Manager.OutlineFill.Assign(AShape.OutlineFill);
- end;
- if toDrawShape in opt then
- begin
- if vsfPenWidth in f then Manager.PenWidth := AShape.PenWidth*zoom;
- if vsfJoinStyle in f then Manager.JoinStyle:= AShape.JoinStyle;
- if AShape is TCustomPolypointShape then
- begin
- if TCustomPolypointShape(AShape).Closed then
- include(opt, toCloseShape)
- else
- exclude(opt, toCloseShape);
- Manager.LineCap := TCustomPolypointShape(AShape).LineCap;
- Manager.ArrowSize := TCustomPolypointShape(AShape).ArrowSize;
- Manager.ArrowStart := TCustomPolypointShape(AShape).ArrowStartKind;
- Manager.ArrowEnd := TCustomPolypointShape(AShape).ArrowEndKind;
- end;
- if AShape is TCurveShape then
- Manager.SplineStyle := TCurveShape(AShape).SplineStyle;
- end;
- if AShape is TTextShape then
- with TTextShape(AShape) do
- begin
- Manager.TextPhong := PenPhong;
- Manager.LightPosition := m*LightPosition;
- Manager.PhongShapeAltitude := round(AltitudePercent);
- Manager.TextAlign:= ParagraphAlignment;
- Manager.TextVerticalAlign:= VerticalAlignment;
- Manager.SetTextFont(FontName, FontEmHeight*zoom*72/Manager.Image.DPI, FontStyle);
- Manager.TextShadow:= false;
- end;
- Manager.ShapeOptions := opt;
- if AShape is TPhongShape then
- with TPhongShape(AShape) do
- begin
- Manager.PhongShapeKind:= ShapeKind;
- Manager.LightPosition:= LightPosition;
- Manager.PhongShapeAltitude:= round(ShapeAltitudePercent);
- Manager.PhongShapeBorderSize:= round(BorderSizePercent);
- end;
- end;
- procedure TEditShapeTool.UpdateDraftMode;
- begin
- case GetEditMode of
- esmShape: Manager.Image.DraftOriginal:= GetVectorOriginal.PreferDraftMode(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor, GetOriginalTransform);
- esmNoShape: Manager.Image.DraftOriginal:= false;
- else Manager.Image.DraftOriginal:= FLeftButton or FRightButton;
- end;
- end;
- procedure TEditShapeTool.BindOriginalEvent(ABind: boolean);
- begin
- case GetCurrentLayerKind of
- lkVectorial:
- begin
- if ABind then
- begin
- GetVectorOriginal.OnSelectShape:= @SelectShape;
- Manager.Image.CurrentState.DiscardOriginalDiff := false;
- end else
- begin
- GetVectorOriginal.OnSelectShape := nil;
- Manager.Image.CurrentState.DiscardOriginalDiff := true;
- end;
- end;
- lkGradient:
- begin
- if ABind then
- begin
- Manager.Image.CurrentState.DiscardOriginalDiff := false;
- end else
- begin
- Manager.Image.CurrentState.DiscardOriginalDiff := true;
- end;
- end;
- end;
- end;
- function TEditShapeTool.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
- ptF: TPointF; rightBtn: boolean): TRect;
- var
- cur: TOriginalEditorCursor;
- handled: boolean;
- ptView: TPointF;
- begin
- Result:= EmptyRect;
- FRightButton:= rightBtn;
- FLeftButton:= not rightBtn;
- FRectEditorCapture:= false;
- FLayerOriginalCapture:= false;
- FLastPos := ptF;
- handled := false;
- if not handled and (GetEditMode in [esmSelection,esmOtherOriginal]) and Assigned(FRectEditor) then
- begin
- ptView := FRectEditor.Matrix*ptF;
- UpdateSnap(FRectEditor);
- FRectEditor.MouseDown(rightBtn, ShiftState, ptView.X,ptView.Y, cur, handled);
- Cursor := OriginalCursorToCursor(cur);
- if handled then
- begin
- FRectEditorCapture:= true;
- result := OnlyRenderChange;
- UpdateMatrixFromRect;
- end;
- end;
- if not handled and (GetEditMode in [esmShape,esmGradient,esmNoShape]) then
- begin
- BindOriginalEvent(true);
- try
- UpdateSnap(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor);
- Manager.Image.CurrentState.LayeredBitmap.MouseDown(rightBtn, ShiftState, ptF.X,ptF.Y, cur, handled);
- finally
- BindOriginalEvent(false);
- end;
- if handled then
- begin
- Cursor := OriginalCursorToCursor(cur);
- FLayerOriginalCapture:= true;
- end;
- end;
- FDownHandled:= handled;
- end;
- function TEditShapeTool.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
- ptF: TPointF): TRect;
- var
- cur: TOriginalEditorCursor;
- handled: boolean;
- ptView: TPointF;
- begin
- FLastPos := ptF;
- Result:= EmptyRect;
- UpdateDraftMode;
- case GetEditMode of
- esmGradient, esmShape, esmNoShape:
- begin
- BindOriginalEvent(true);
- try
- UpdateSnap(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor);
- Manager.Image.CurrentState.LayeredBitmap.MouseMove(ShiftState, ptF.X,ptF.Y, cur, handled);
- finally
- BindOriginalEvent(false);
- end;
- Cursor := OriginalCursorToCursor(cur);
- end;
- esmSelection, esmOtherOriginal:
- if Assigned(FRectEditor) then
- begin
- ptView := FRectEditor.Matrix*ptF;
- UpdateSnap(FRectEditor);
- FRectEditor.MouseMove(ShiftState, ptView.X,ptView.Y, cur, handled);
- Cursor := OriginalCursorToCursor(cur);
- if handled then
- begin
- result := OnlyRenderChange;
- UpdateMatrixFromRect;
- end;
- end;
- end;
- end;
- function TEditShapeTool.DoToolUpdate(toolDest: TBGRABitmap): TRect;
- var
- doDraw, doFill: Boolean;
- m: TAffineMatrix;
- zoom: Single;
- gradBox: TAffineBox;
- f: TVectorShapeFields;
- shape: TVectorShape;
- begin
- shape := nil;
- case GetEditMode of
- esmShape:
- try
- BindOriginalEvent(true);
- shape := GetVectorOriginal.SelectedShape;
- shape.BeginUpdate;
- gradBox := shape.SuggestGradientBox(AffineMatrixIdentity);
- m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
- zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
- f := shape.MultiFields;
- if vsfAliased in f then
- shape.Aliased := Manager.ShapeOptionAliasing;
- if f*[vsfPenFill,vsfBackFill,vsfPenStyle] = [vsfPenFill,vsfBackFill,vsfPenStyle] then
- begin
- doDraw := toDrawShape in Manager.ShapeOptions;
- doFill := toFillShape in Manager.ShapeOptions;
- if doDraw then
- shape.PenStyle := PenStyleToBGRA(Manager.PenStyle)
- else
- shape.PenStyle := ClearPenStyle;
- if doDraw and (vsfPenWidth in f) then shape.PenWidth := Manager.PenWidth*zoom;
- if doDraw and (vsfJoinStyle in f) then shape.JoinStyle := Manager.JoinStyle;
- if shape is TCustomPolypointShape then
- begin
- TCustomPolypointShape(shape).Closed := toCloseShape in Manager.ShapeOptions;
- if not TCustomPolypointShape(shape).Closed then
- begin
- TCustomPolypointShape(shape).LineCap:= Manager.LineCap;
- TCustomPolypointShape(shape).ArrowSize:= Manager.ArrowSize;
- TCustomPolypointShape(shape).ArrowStartKind:= Manager.ArrowStart;
- TCustomPolypointShape(shape).ArrowEndKind:= Manager.ArrowEnd;
- end;
- end;
- if shape is TCurveShape then
- TCurveShape(shape).SplineStyle:= Manager.SplineStyle;
- end else
- begin
- doDraw := vsfPenFill in f;
- doFill := vsfBackFill in f;
- end;
- if doFill then AssignFill(shape.BackFill, Manager.BackFill, gradBox, BackFitMode)
- else if vsfBackFill in f then
- shape.BackFill.Clear;
- if doDraw then AssignFill(shape.PenFill, Manager.ForeFill, gradBox, ForeFitMode);
- if (vsfOutlineWidth in f) and Manager.TextOutline then shape.OutlineWidth := Manager.TextOutlineWidth*zoom;
- if vsfOutlineFill in f then
- begin
- if Manager.TextOutline then
- AssignFill(shape.OutLineFill, Manager.OutLineFill, gradBox, OutlineFitMode)
- else shape.OutlineFill.Clear;
- end;
- if shape is TTextShape then
- with TTextShape(shape) do
- begin
- PenPhong := Manager.TextPhong;
- LightPosition := m*Manager.LightPosition;
- AltitudePercent := Manager.PhongShapeAltitude;
- if FontBidiMode <> Manager.TextBidiMode then
- begin
- FontBidiMode:= Manager.TextBidiMode;
- Manager.TextAlign:= ParagraphAlignment;
- end else
- ParagraphAlignment := Manager.TextAlign;
- VerticalAlignment:= Manager.TextVerticalAlign;
- FontName:= Manager.TextFontName;
- FontEmHeight:= Manager.TextFontSize*zoom*Manager.Image.DPI/72;
- FontStyle := Manager.TextFontStyle;
- end;
- if shape is TPhongShape then
- with TPhongShape(shape) do
- begin
- ShapeKind := Manager.PhongShapeKind;
- LightPosition := Manager.LightPosition;
- ShapeAltitudePercent := Manager.PhongShapeAltitude;
- BorderSizePercent := Manager.PhongShapeBorderSize;
- end;
- finally
- if Assigned(shape) then shape.EndUpdate;
- BindOriginalEvent(false);
- end;
- esmGradient:
- try
- BindOriginalEvent(true);
- case Manager.BackFill.FillType of
- vftGradient: GetGradientOriginal.AssignExceptGeometry(Manager.BackFill.Gradient);
- vftSolid: GetGradientOriginal.SetColors(Manager.BackFill.SolidColor, Manager.BackFill.SolidColor);
- end;
- finally
- BindOriginalEvent(false);
- end;
- end;
- Result := EmptyRect;
- end;
- procedure TEditShapeTool.UpdateSnap(AEditor: TBGRAOriginalEditor);
- begin
- if Assigned(AEditor) then
- AEditor.GridActive := ssSnap in ShiftState;
- end;
- function TEditShapeTool.GetAction: TLayerAction;
- begin
- result := nil;
- end;
- function TEditShapeTool.DoGetToolDrawingLayer: TBGRABitmap;
- begin
- Result:= Manager.Image.LayerBitmap[Manager.Image.CurrentLayerIndex];
- end;
- procedure TEditShapeTool.OnTryStop(sender: TCustomLayerAction);
- begin
- StopEdit(True, True);
- inherited OnTryStop(sender);
- end;
- procedure TEditShapeTool.StopEdit(AUpdateInterface, ARaiseToolUp: boolean);
- var
- r: TRect;
- begin
- if ARaiseToolUp and (FLeftButton or FRightButton) then
- begin
- r := ToolUp;
- Manager.Image.LayerMayChange(GetToolDrawingLayer,r);
- end;
- case GetEditMode of
- esmShape: GetVectorOriginal.DeselectShapes;
- esmGradient: FIsEditingGradient:= false;
- esmOtherOriginal: FreeAndNil(FOriginalRect);
- esmSelection: FreeAndNil(FSelectionRect);
- end;
- Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
- FLayerOriginalCapture:= false;
- FreeAndNil(FRectEditor);
- FRectEditorCapture := false;
- Cursor := crDefault;
- if AUpdateInterface then
- begin
- Manager.Image.OnImageChanged.NotifyObservers;
- Manager.UpdateContextualToolbars;
- end;
- end;
- function TEditShapeTool.IsEditing: boolean;
- begin
- result := not (GetEditMode in[esmNone, esmNoShape]);
- end;
- procedure TEditShapeTool.MakeImageOriginal;
- var
- diff: TReplaceLayerByImageOriginalDifference;
- begin
- if GetCurrentLayerKind = lkBitmap then
- begin
- diff := TReplaceLayerByImageOriginalDifference.Create(Manager.Image.CurrentState,
- Manager.Image.CurrentLayerIndex, false);
- Manager.Image.AddUndo(diff);
- if Assigned(Manager.Image.OnStackChanged) then
- Manager.Image.OnStackChanged(Manager.Image, False);
- end;
- end;
- procedure TEditShapeTool.MakeVectorOriginal;
- var
- diff: TReplaceLayerByVectorOriginalDifference;
- begin
- if GetCurrentLayerKind in [lkEmpty,lkBitmap,lkTransformedBitmap] then
- begin
- StopEdit(True, True);
- diff := TReplaceLayerByVectorOriginalDifference.Create(Manager.Image.CurrentState,
- Manager.Image.CurrentLayerIndex, false);
- Manager.Image.AddUndo(diff);
- if Assigned(Manager.Image.OnStackChanged) then
- Manager.Image.OnStackChanged(Manager.Image, False);
- end;
- end;
- procedure TEditShapeTool.UpdateMatrixFromRect;
- begin
- if Assigned(FOriginalRect) then
- Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] :=
- GetMatrixFromRect(FOriginalRect,FOriginalRectUntransformed);
- if Assigned(FSelectionRect) then
- begin
- Manager.Image.SelectionTransform :=
- GetMatrixFromRect(FSelectionRect,FSelectionRectUntransformed);
- Manager.Image.OnImageChanged.NotifyObservers;
- end;
- end;
- procedure TEditShapeTool.DoEditSelection;
- begin
- if not IsEditing then
- begin
- with Manager.Image.SelectionMaskBounds do
- FSelectionRectUntransformed := rectF(Left-0.5, Top-0.5, Right-0.5, Bottom-0.5);
- FSelectionRect := CreateRect(FSelectionRectUntransformed, Manager.Image.SelectionTransform);
- end;
- end;
- function TEditShapeTool.GetMatrixFromRect(ARect: TRectShape; AUntransformedRect: TRectF): TAffineMatrix;
- var
- u, v: TPointF;
- mAfter, mBefore: TAffineMatrix;
- begin
- u := (ARect.XAxis-ARect.Origin)*2;
- v := (ARect.YAxis-ARect.Origin)*2;
- mAfter := AffineMatrix(u,v,ARect.Origin-(u+v)*0.5);
- mBefore := AffineMatrixTranslation(AUntransformedRect.Left,
- AUntransformedRect.Top)
- *AffineMatrixScale(AUntransformedRect.Width,AUntransformedRect.Height);
- if IsAffineMatrixInversible(mBefore) then
- result := mAfter*AffineMatrixInverse(mBefore)
- else
- result := AffineMatrixIdentity;
- end;
- function TEditShapeTool.CreateRect(AUntransformedRect: TRectF; AMatrix: TAffineMatrix): TRectShape;
- var
- box: TAffineBox;
- begin
- if (AUntransformedRect.Width > 0) and (AUntransformedRect.Height > 0) then
- begin
- result := TRectShape.Create(nil);
- result.PenStyle := ClearPenStyle;
- result.BackFill.SetSolid(BGRAWhite);
- box := AMatrix*TAffineBox.AffineBox(AUntransformedRect);
- result.Origin := (box.TopLeft+box.BottomRight)*0.5;
- result.XAxis := result.Origin+(box.TopRight-box.TopLeft)*0.5;
- result.YAxis := result.Origin+(box.BottomLeft-box.TopLeft)*0.5;
- Manager.UpdateContextualToolbars;
- end else
- result := nil;
- end;
- function TEditShapeTool.GetIsSelectingTool: boolean;
- begin
- result := false;
- end;
- function TEditShapeTool.GetVectorOriginal: TVectorOriginal;
- begin
- result := Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TVectorOriginal;
- end;
- function TEditShapeTool.GetGradientOriginal: TBGRALayerGradientOriginal;
- begin
- result := Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TBGRALayerGradientOriginal;
- end;
- function TEditShapeTool.GetImageOriginal: TBGRALayerImageOriginal;
- begin
- result := Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TBGRALayerImageOriginal;
- end;
- function TEditShapeTool.GetOriginalTransform: TAffineMatrix;
- begin
- result := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
- end;
- function TEditShapeTool.FixLayerOffset: boolean;
- begin
- Result:= false;
- end;
- destructor TEditShapeTool.Destroy;
- begin
- FreeAndNil(FOriginalRect);
- FreeAndNil(FSelectionRect);
- Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
- FreeAndNil(FRectEditor);
- inherited Destroy;
- end;
- function TEditShapeTool.GetContextualToolbars: TContextualToolbars;
- var
- shape: TVectorShape;
- begin
- case GetEditMode of
- esmShape:
- begin
- shape := GetVectorOriginal.SelectedShape;
- result := ContextualToolbarsFromShape(TVectorShapeAny(shape.ClassType), shape);
- end;
- esmGradient: result := [ctBackFill];
- else
- Result:= [ctPenFill, ctBackFill];
- end;
- end;
- function TEditShapeTool.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
- VirtualScreenHeight: integer;
- BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
- var
- orig, xAxis, yAxis: TPointF;
- viewMatrix, editMatrix: TAffineMatrix;
- begin
- if InvalidEditMode then StopEdit(false,false);
- with LayerOffset do
- begin
- orig := BitmapToVirtualScreen(PointF(-X,-Y));
- xAxis := BitmapToVirtualScreen(PointF(-X+1,-Y));
- yAxis := BitmapToVirtualScreen(PointF(-X,-Y+1));
- end;
- viewMatrix := AffineMatrixTranslation(0.5,0.5)
- *AffineMatrix(xAxis-orig,yAxis-orig,orig)
- *AffineMatrixTranslation(-0.5,-0.5);
- case GetEditMode of
- esmGradient, esmShape:
- begin
- FreeAndNil(FRectEditor);
- FRectEditorCapture := false;
- if Assigned(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor) then
- Manager.Image.CurrentState.LayeredBitmap.OriginalEditor.GridMatrix := AffineMatrixScale(0.5,0.5);
- if Assigned(VirtualScreen) then
- result := Manager.Image.CurrentState.LayeredBitmap.DrawEditor(VirtualScreen,
- Manager.Image.CurrentLayerIndex, viewMatrix, GetPointSize)
- else
- result := Manager.Image.CurrentState.LayeredBitmap.GetEditorBounds(
- rect(0,0,VirtualScreenWidth,VirtualScreenHeight),
- Manager.Image.CurrentLayerIndex, viewMatrix, GetPointSize);
- RetrieveLightPosition;
- end;
- esmSelection, esmOtherOriginal:
- begin
- result := EmptyRect;
- Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
- FLayerOriginalCapture:= false;
- if not Assigned(FRectEditor) then
- begin
- FRectEditor := TVectorOriginalEditor.Create(nil);
- FRectEditor.GridMatrix := AffineMatrixScale(0.5,0.5);
- FRectEditor.Focused := true;
- FRectEditor.PointSize := GetPointSize;
- end;
- FRectEditor.Clear;
- editMatrix := AffineMatrixTranslation(-0.5,-0.5)*viewMatrix*AffineMatrixTranslation(0.5,0.5);
- if IsAffineMatrixInversible(editMatrix) then
- begin
- FRectEditor.Matrix := editMatrix;
- if Assigned(FOriginalRect) then FOriginalRect.ConfigureEditor(FRectEditor);
- if Assigned(FSelectionRect) then FSelectionRect.ConfigureEditor(FRectEditor);
- if Assigned(VirtualScreen) then
- result := FRectEditor.Render(VirtualScreen,
- rect(0,0,VirtualScreenWidth,VirtualScreenHeight))
- else
- result := FRectEditor.GetRenderBounds(
- rect(0,0,VirtualScreenWidth,VirtualScreenHeight));
- end
- else
- result := EmptyRect;
- end;
- else
- begin
- result := EmptyRect;
- Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
- FLayerOriginalCapture := false;
- FreeAndNil(FRectEditor);
- FRectEditorCapture := false;
- end;
- end;
- end;
- function TEditShapeTool.GetCurrentSplineMode: TToolSplineMode;
- var
- orig: TVectorOriginal;
- begin
- if GetEditMode = esmShape then
- begin
- orig := GetVectorOriginal;
- if Assigned(orig.SelectedShape) and
- (orig.SelectedShape is TCurveShape) then
- exit(ToolSplineModeFromShape(orig.SelectedShape));
- end;
- result := tsmMovePoint;
- end;
- procedure TEditShapeTool.SetCurrentSplineMode(AMode: TToolSplineMode);
- var
- c: TCurveShape;
- begin
- if (GetEditMode = esmShape) and
- (GetVectorOriginal.SelectedShape is TCurveShape) then
- begin
- c := TCurveShape(GetVectorOriginal.SelectedShape);
- case AMode of
- tsmMovePoint: if not (c.Usermode in [vsuEdit,vsuCreate]) then c.Usermode := vsuEdit;
- tsmCurveModeAuto: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetAuto else
- if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmAuto;
- tsmCurveModeAngle: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetAngle else
- if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmAngle;
- tsmCurveModeSpline: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetCurve else
- if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmCurve;
- end;
- end;
- end;
- function TEditShapeTool.ConvertToSpline: boolean;
- var
- shapeBefore: TVectorShape;
- orig: TVectorOriginal;
- shapeAfter: TCurveShape;
- begin
- if (GetEditMode = esmShape) and
- TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape) then
- begin
- orig := GetVectorOriginal;
- shapeBefore:= orig.SelectedShape;
- shapeAfter := TCurveShape.CreateFrom(orig, shapeBefore);
- shapeAfter.JoinStyle := pjsRound;
- orig.ReplaceShape(orig.IndexOfShape(shapeBefore), shapeAfter);
- orig.SelectShape(shapeAfter, False);
- result := true;
- end else
- result := false;
- end;
- function TEditShapeTool.GetEditMode: TEditShapeMode;
- begin
- if InvalidEditMode then exit(esmNone);
- if Assigned(FSelectionRect) then exit(esmSelection)
- else if Assigned(FOriginalRect) then exit(esmOtherOriginal)
- else
- case GetCurrentLayerKind of
- lkGradient: if FIsEditingGradient then exit(esmGradient) else exit(esmNone);
- lkVectorial: if Assigned(GetVectorOriginal.SelectedShape) then exit(esmShape) else exit(esmNoShape);
- else exit(esmNone);
- end;
- end;
- function TEditShapeTool.InvalidEditMode: boolean;
- begin
- if Assigned(FOriginalRect) and
- ((FOriginalLayerId <> Manager.Image.LayerId[Manager.Image.CurrentLayerIndex])
- or not (GetCurrentLayerKind in[lkTransformedBitmap,lkSVG,lkOther])) then
- result := true
- else if Assigned(FSelectionRect) and
- Manager.Image.SelectionMaskEmpty then result := true
- else if FIsEditingGradient and (GetCurrentLayerKind <> lkGradient) then
- result := true
- else
- result := false;
- end;
- function TEditShapeTool.ForeGradTexMode: TVectorShapeUsermode;
- begin
- result := vsuEditPenFill;
- end;
- function TEditShapeTool.BackGradTexMode: TVectorShapeUsermode;
- begin
- result := vsuEditBackFill;
- end;
- function TEditShapeTool.OutlineGradTexMode: TVectorShapeUsermode;
- begin
- result := vsuEditOutlineFill;
- end;
- function TEditShapeTool.ForeFitMode: TFitMode;
- begin
- if IsForeEditGradTexPoints then result := fmNever
- else result := fmIfChange;
- end;
- function TEditShapeTool.BackFitMode: TFitMode;
- begin
- if IsBackEditGradTexPoints then result := fmNever
- else result := fmIfChange;
- end;
- function TEditShapeTool.OutlineFitMode: TFitMode;
- begin
- if IsOutlineEditGradTexPoints then result := fmNever
- else result := fmIfChange;
- end;
- function TEditShapeTool.GetIsForeEditGradTexPoints: boolean;
- begin
- result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = ForeGradTexMode);
- end;
- function TEditShapeTool.GetIsBackEditGradTexPoints: boolean;
- begin
- result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode);
- end;
- function TEditShapeTool.GetIsOutlineEditGradTexPoints: boolean;
- begin
- result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = OutlineGradTexMode);
- end;
- function TEditShapeTool.GetAllowedBackFillTypes: TVectorialFillTypes;
- begin
- if GetEditMode = esmGradient then
- result := [vftGradient] else
- Result:=inherited GetAllowedBackFillTypes;
- end;
- function TEditShapeTool.GetStatusText: string;
- var
- m: TAffineMatrix;
- begin
- m := AffineMatrixTranslation(-0.5, -0.5) *
- Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] *
- AffineMatrixTranslation(0.5, 0.5);
- if (GetEditMode = esmShape) and Assigned(GetVectorOriginal.SelectedShape) then
- result := GetShapeStatusText(GetVectorOriginal.SelectedShape, m) else
- if (GetEditMode = esmSelection) and Assigned(FSelectionRect) then
- result := GetShapeStatusText(FSelectionRect, AffineMatrixIdentity) else
- if (GetEditMode = esmOtherOriginal) and Assigned(FOriginalRect) then
- result := GetShapeStatusText(FOriginalRect, AffineMatrixIdentity) else
- if (GetEditMode = esmGradient) then
- result := GetGradientStatusText(GetGradientOriginal, m) else
- Result:=inherited GetStatusText;
- end;
- constructor TEditShapeTool.Create(AManager: TToolManager);
- var
- orig: TVectorOriginal;
- begin
- inherited Create(AManager);
- FRectEditor := nil;
- FSelectionRect := nil;
- FOriginalRect := nil;
- FIsEditingGradient:= false;
- FLeftButton:= false;
- FRightButton:= false;
- if GetCurrentLayerKind = lkVectorial then
- orig := GetVectorOriginal
- else orig := nil;
- if not Manager.Image.SelectionMaskEmpty then
- begin
- if Assigned(orig) and Assigned(orig.SelectedShape) then
- orig.DeselectShapes;
- DoEditSelection;
- end else
- if Assigned(orig) and Assigned(orig.SelectedShape) then
- UpdateToolManagerFromShape(orig.SelectedShape);
- end;
- function TEditShapeTool.DoToolKeyDown(var key: Word): TRect;
- var
- handled: boolean;
- keyUtf8: TUTF8Char;
- diff: TComposedImageDifference;
- begin
- Result:= EmptyRect;
- if (Key = VK_SPACE) and (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape is TTextShape) then
- begin
- keyUtf8:= ' ';
- result := ToolKeyPress(keyUtf8);
- Key := 0;
- end else
- begin
- if GetEditMode in [esmShape,esmNoShape] then
- begin
- BindOriginalEvent(true);
- try
- Manager.Image.CurrentState.LayeredBitmap.KeyDown(ShiftState, LCLKeyToSpecialKey(key, ShiftState), handled);
- if handled then key := 0 else
- begin
- if (key = VK_DELETE) and Assigned(GetVectorOriginal.SelectedShape) then
- begin
- diff := Manager.Image.DoBegin;
- try
- GetVectorOriginal.RemoveShape(GetVectorOriginal.SelectedShape);
- finally
- Manager.Image.DoEnd(diff);
- end;
- key := 0;
- end else
- if (key = VK_ESCAPE) and Assigned(GetVectorOriginal.SelectedShape) then
- begin
- if GetVectorOriginal.SelectedShape.Usermode = vsuEditText then
- GetVectorOriginal.SelectedShape.Usermode := vsuEdit
- else
- GetVectorOriginal.DeselectShapes;
- key := 0;
- end;
- end;
- finally
- BindOriginalEvent(false);
- end;
- end else
- begin
- if (Key = VK_DELETE) and (GetEditMode in [esmGradient,esmOtherOriginal]) then
- begin
- StopEdit(true, true);
- Manager.Image.ClearLayer;
- Key := 0;
- end else
- if key = VK_RETURN then
- begin
- if IsEditing then
- begin
- StopEdit(true, true);
- key := 0;
- end;
- end;
- end;
- end;
- end;
- function TEditShapeTool.ToolKeyPress(var key: TUTF8Char): TRect;
- var
- handled: boolean;
- keyCode: word;
- begin
- Result:= EmptyRect;
- if GetEditMode in [esmShape,esmNoShape] then
- begin
- if Assigned(GetVectorOriginal.SelectedShape) and
- (GetVectorOriginal.SelectedShape is TCustomPolypointShape) and
- ((Key='i') or (Key='I')) then
- begin
- keyCode := VK_INSERT;
- ToolKeyDown(keyCode);
- if keyCode = 0 then key := #0;
- keyCode := VK_INSERT;
- ToolKeyUp(keyCode);
- result := EmptyRect;
- end else
- begin
- BindOriginalEvent(true);
- try
- Manager.Image.CurrentState.LayeredBitmap.KeyPress(key, handled);
- if handled then key := #0;
- finally
- BindOriginalEvent(false);
- end;
- end;
- end;
- end;
- function TEditShapeTool.DoToolKeyUp(var key: Word): TRect;
- var
- handled: boolean;
- begin
- Result:= EmptyRect;
- if GetEditMode in [esmShape,esmNoShape] then
- begin
- BindOriginalEvent(true);
- try
- Manager.Image.CurrentState.LayeredBitmap.KeyUp(ShiftState, LCLKeyToSpecialKey(key, ShiftState), handled);
- if handled then key := 0;
- finally
- BindOriginalEvent(false);
- end;
- end;
- end;
- function TEditShapeTool.ToolUp: TRect;
- var
- cur: TOriginalEditorCursor;
- handled: boolean;
- m: TAffineMatrix;
- ptView, ptSel: TPointF;
- zoom: Single;
- begin
- Result:= EmptyRect;
- if FLeftButton or FRightButton then
- begin
- handled := false;
- if not handled and FRectEditorCapture and Assigned(FRectEditor) then
- begin
- ptView := FRectEditor.Matrix*FLastPos;
- UpdateSnap(FRectEditor);
- FRectEditor.MouseUp(FRightButton, ShiftState, ptView.X,ptView.Y, cur, handled);
- Cursor := OriginalCursorToCursor(cur);
- if handled then
- begin
- result := OnlyRenderChange;
- UpdateMatrixFromRect;
- end else
- begin
- StopEdit(False, False);
- result := OnlyRenderChange;
- end;
- end;
- if not handled and FLayerOriginalCapture and (GetEditMode in [esmGradient, esmShape, esmNoShape]) then
- begin
- BindOriginalEvent(true);
- try
- Manager.Image.CurrentState.LayeredBitmap.MouseUp(FRightButton, ShiftState, FLastPos.X,FLastPos.Y, cur, handled);
- if handled then
- begin
- Cursor := OriginalCursorToCursor(cur);
- result := OnlyRenderChange;
- end;
- finally
- BindOriginalEvent(false);
- end;
- end;
- if not handled and not Manager.Image.SelectionMaskEmpty then
- begin
- ptSel := AffineMatrixInverse(Manager.Image.SelectionTransform)*FLastPos;
- if (Manager.Image.SelectionMaskReadonly.GetPixel(ptSel.x,ptSel.y).green > 0) then
- begin
- if GetEditMode <> esmSelection then
- begin
- StopEdit(false, false);
- DoEditSelection;
- result := OnlyRenderChange;
- end;
- handled := true;
- end else
- if GetEditMode = esmSelection then
- begin
- StopEdit(false, false);
- result := OnlyRenderChange;
- end;
- end;
- if not handled then
- begin
- case GetEditMode of
- esmShape, esmNoShape:
- if not FDownHandled then
- begin
- m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
- zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2/Manager.Image.ZoomFactor;
- BindOriginalEvent(true);
- try
- if GetVectorOriginal.MouseClick(m*FLastPos, DoScaleX(PointSize*Manager.CanvasScale, OriginalDPI)*zoom, ssSnap in ShiftState) then
- begin
- handled := true;
- result := OnlyRenderChange;
- end;
- finally
- BindOriginalEvent(false);
- end;
- end;
- esmGradient:
- begin
- FIsEditingGradient:= false;
- result := OnlyRenderChange;
- end;
- end;
- end;
- if not handled and (GetCurrentLayerKind in [lkBitmap, lkTransformedBitmap, lkSVG, lkOther]) and
- (Manager.Image.CurrentLayerReadOnly.GetPixel(FLastPos.X-LayerOffset.X, FLastPos.Y-LayerOffset.Y).alpha <> 0) then
- begin
- if GetEditMode <> esmOtherOriginal then
- begin
- StopEdit(false, false);
- MakeImageOriginal;
- if GetCurrentLayerKind in [lkTransformedBitmap, lkSVG, lkOther] then
- begin
- with Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex].
- GetRenderBounds(InfiniteRect, AffineMatrixIdentity) do
- FOriginalRectUntransformed := rectF(Left-0.5, Top-0.5, Right-0.5, Bottom-0.5);
- FOriginalRect := CreateRect(FOriginalRectUntransformed,
- Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
- FOriginalLayerId:= Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
- result := OnlyRenderChange;
- end;
- end;
- handled := true;
- end;
- if not handled and (GetCurrentLayerKind = lkGradient) then
- begin
- if not FIsEditingGradient then
- begin
- FIsEditingGradient:= true;
- Manager.BackFill.SetGradient(GetGradientOriginal, false);
- Manager.UpdateContextualToolbars;
- handled := true;
- result := OnlyRenderChange;
- end;
- end;
- FLeftButton:= false;
- FRightButton:= false;
- if Manager.Image.DraftOriginal then
- UpdateDraftMode;
- end;
- end;
- function TEditShapeTool.ToolCommand(ACommand: TToolCommand): boolean;
- var
- key: Word;
- b: TRect;
- bmp: TBGRABitmap;
- s: TRectShape;
- diff: TComposedImageDifference;
- begin
- if not ToolProvideCommand(ACommand) then exit(false);
- if ACommand = tcDelete then
- begin
- key := VK_DELETE;
- ToolKeyDown(key);
- if key = 0 then
- begin
- key := VK_DELETE;
- ToolKeyUp(key);
- result := true;
- end else
- result := false;
- end else
- if ACommand = tcPaste then
- begin
- result := false;
- MakeVectorOriginal;
- if GetCurrentLayerKind = lkVectorial then
- begin
- BindOriginalEvent(true);
- try
- PasteShapesFromClipboard(GetVectorOriginal, GetOriginalTransform, Manager.Image.VisibleArea);
- finally
- BindOriginalEvent(false);
- end;
- result := true;
- end;
- end else
- begin
- result := true;
- case GetEditMode of
- esmShape:
- try
- BindOriginalEvent(true);
- case ACommand of
- tcMoveUp: GetVectorOriginal.SelectedShape.MoveUp(true);
- tcMoveToFront: GetVectorOriginal.SelectedShape.BringToFront;
- tcMoveDown: GetVectorOriginal.SelectedShape.MoveDown(true);
- tcMoveToBack: GetVectorOriginal.SelectedShape.SendToBack;
- tcCopy: Result:= CopyShapesToClipboard([GetVectorOriginal.SelectedShape], GetOriginalTransform);
- tcCut: begin
- result := CopyShapesToClipboard([GetVectorOriginal.SelectedShape], GetOriginalTransform);
- if result then
- begin
- diff := Manager.Image.DoBegin;
- try
- GetVectorOriginal.RemoveShape(GetVectorOriginal.SelectedShape);
- finally
- Manager.Image.DoEnd(diff);
- end;
- end;
- end;
- tcAlignLeft..tcAlignBottom: AlignShape(GetVectorOriginal.SelectedShape, ACommand,
- Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex],
- rect(0,0,Manager.Image.Width,Manager.Image.Height));
- tcForeEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = ForeGradTexMode then
- GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
- GetVectorOriginal.SelectedShape.Usermode := ForeGradTexMode;
- tcBackEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode then
- GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
- GetVectorOriginal.SelectedShape.Usermode := BackGradTexMode;
- tcOutlineEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = OutlineGradTexMode then
- GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
- GetVectorOriginal.SelectedShape.Usermode := OutlineGradTexMode;
- tcForeAdjustToShape: GetVectorOriginal.SelectedShape.PenFill.FitGeometry(SuggestGradientBox);
- tcBackAdjustToShape: GetVectorOriginal.SelectedShape.BackFill.FitGeometry(SuggestGradientBox);
- tcOutlineAdjustToShape: GetVectorOriginal.SelectedShape.OutlineFill.FitGeometry(SuggestGradientBox);
- tcShapeToSpline: result := ConvertToSpline;
- else result := false;
- end;
- finally
- BindOriginalEvent(false);
- end;
- esmGradient:
- begin
- case ACommand of
- tcBackAdjustToShape: GetGradientOriginal.FitGeometry(SuggestGradientBox);
- tcCut,tcCopy: begin
- s := TRectShape.Create(nil);
- try
- s.PenStyle := ClearPenStyle;
- s.QuickDefine(PointF(-0.5,-0.5),PointF(Manager.Image.Width-0.5,Manager.Image.Height-0.5));
- s.BackFill.SetGradient(GetGradientOriginal, false);
- s.BackFill.Transform(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
- CopyShapesToClipboard([s],AffineMatrixIdentity);
- finally
- s.free;
- end;
- if ACommand = tcCut then ToolCommand(tcDelete);
- end;
- else result := false;
- end;
- end;
- esmOtherOriginal:
- begin
- case ACommand of
- tcCut,tcCopy: begin
- b := Manager.Image.CurrentLayerReadOnly.GetImageBounds;
- if not b.IsEmpty then
- begin
- if GetCurrentLayerKind = lkTransformedBitmap then
- begin
- bmp := GetImageOriginal.GetImageCopy;
- s:= TRectShape.Create(nil);
- s.QuickDefine(PointF(-0.5,-0.5),PointF(bmp.Width-0.5,bmp.Height-0.5));
- s.PenStyle := ClearPenStyle;
- s.BackFill.SetTexture(bmp,AffineMatrixIdentity,255,trNone);
- s.Transform(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
- bmp.FreeReference;
- end else
- begin
- bmp := Manager.Image.CurrentLayerReadOnly.GetPart(b) as TBGRABitmap;
- s:= TRectShape.Create(nil);
- s.QuickDefine(PointF(b.Left-0.5,b.Top-0.5),PointF(b.Right-0.5,b.Bottom-0.5));
- s.PenStyle := ClearPenStyle;
- s.BackFill.SetTexture(bmp,AffineMatrixTranslation(b.Left,b.Top),255,trNone);
- with Manager.Image.LayerOffset[Manager.Image.CurrentLayerIndex] do
- s.Transform(AffineMatrixTranslation(x,y));
- bmp.FreeReference;
- end;
- try
- CopyShapesToClipboard([s],AffineMatrixIdentity);
- finally
- s.Free;
- end;
- if ACommand = tcCut then ToolCommand(tcDelete);
- end;
- end;
- tcAlignLeft..tcAlignBottom:
- begin
- AlignShape(FOriginalRect, ACommand,
- AffineMatrixIdentity,rect(0,0,Manager.Image.Width,Manager.Image.Height));
- UpdateMatrixFromRect;
- end
- else result := false;
- end;
- end;
- esmSelection:
- begin
- if ACommand in [tcAlignLeft..tcAlignBottom] then
- begin
- AlignShape(FSelectionRect, ACommand,
- AffineMatrixIdentity,rect(0,0,Manager.Image.Width,Manager.Image.Height));
- UpdateMatrixFromRect;
- end;
- end;
- end;
- end;
- end;
- function TEditShapeTool.ToolProvideCommand(ACommand: TToolCommand): boolean;
- begin
- case ACommand of
- tcCut,tcCopy,tcDelete: result:= GetEditMode in [esmShape,esmOtherOriginal,esmGradient];
- tcForeAdjustToShape,tcOutlineAdjustToShape: result := GetEditMode = esmShape;
- tcBackAdjustToShape: result := GetEditMode in [esmShape,esmGradient];
- tcForeEditGradTexPoints: result := (GetEditMode = esmShape) and
- (ForeGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
- tcBackEditGradTexPoints: result := (GetEditMode = esmShape) and
- (BackGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
- tcOutlineEditGradTexPoints: result := (GetEditMode = esmShape) and
- (OutlineGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
- tcShapeToSpline: result:= (GetEditMode = esmShape)
- and TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape);
- tcAlignLeft..tcAlignBottom: result:= GetEditMode in [esmShape, esmOtherOriginal, esmSelection];
- tcPaste: result := ClipboardHasShapes and (GetCurrentLayerKind in [lkEmpty,lkBitmap,lkTransformedBitmap,lkVectorial]);
- tcMoveUp,tcMoveToFront: result := (GetEditMode = esmShape)
- and not GetVectorOriginal.SelectedShape.IsFront;
- tcMoveDown,tcMoveToBack: result := (GetEditMode = esmShape)
- and not GetVectorOriginal.SelectedShape.IsBack;
- else
- result := false;
- end;
- end;
- function TEditShapeTool.SuggestGradientBox: TAffineBox;
- begin
- if GetEditMode = esmShape then
- result := GetVectorOriginal.SelectedShape.SuggestGradientBox(AffineMatrixIdentity)
- else
- result:= inherited SuggestGradientBox;
- end;
- { TVectorialTool }
- procedure TVectorialTool.ShapeChange(ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff);
- var
- toolDest: TBGRABitmap;
- r: TRect;
- matrix: TAffineMatrix;
- begin
- if isEmptyPointF(ABounds.TopLeft) or isEmptyPointF(ABounds.BottomRight) then
- raise exception.Create('Unexpected empty point');
- toolDest := GetToolDrawingLayer;
- matrix := VectorTransform(false);
- r := (matrix*TAffineBox.AffineBox(ABounds)).RectBounds;
- UpdateShape(toolDest);
- Action.NotifyChange(toolDest, r);
- with FShape.GetRenderBounds(rect(0,0,toolDest.Width,toolDest.Height),matrix,[]) do
- FPreviousUpdateBounds := rect(floor(Left),floor(Top),ceil(Right),ceil(Bottom));
- if r.IsEmpty then ShapeEditingChange(ASender);
- ADiff.Free;
- end;
- procedure TVectorialTool.ShapeEditingChange(ASender: TObject);
- var
- toolDest: TBGRABitmap;
- newEditorBounds, r: TRect;
- begin
- toolDest := GetToolDrawingLayer;
- with (Editor.Matrix*PointF(toolDest.Width,toolDest.Height)) do
- newEditorBounds := Editor.GetRenderBounds(rect(0,0,ceil(x),ceil(y)));
- r := RectUnion(FPreviousEditorBounds,newEditorBounds);
- if not r.IsEmpty then
- Manager.Image.RenderMayChange(r,false);
- FPreviousEditorBounds := newEditorBounds;
- end;
- procedure TVectorialTool.ShapeRemoveQuery(ASender: TObject;
- var AHandled: boolean);
- var
- r: TRect;
- toolDest: TBGRABitmap;
- begin
- if ASender <> FShape then exit;
- AHandled := true;
- toolDest := GetToolDrawingLayer;
- r := CancelShape;
- Action.NotifyChange(toolDest, r);
- end;
- function TVectorialTool.GetStatusText: string;
- begin
- if Assigned(FShape) then
- result := GetShapeStatusText(FShape, VectorTransform(True))
- else Result:=inherited GetStatusText;
- end;
- function TVectorialTool.SlowShape: boolean;
- begin
- if Assigned(FShape) then
- result := FShape.GetIsSlow(VectorTransform(false))
- else
- result := false;
- end;
- procedure TVectorialTool.QuickDefineEnd;
- begin
- //nothing
- end;
- procedure TVectorialTool.OnTryStop(sender: TCustomLayerAction);
- begin
- ValidateShape;
- end;
- procedure TVectorialTool.UpdateUseOriginal;
- begin
- if not IsSelectingTool and Manager.Image.SelectionMaskEmpty and
- (GetCurrentLayerKind = lkVectorial) then
- FUseOriginal:= true
- else
- FUseOriginal:= false;
- end;
- function TVectorialTool.ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference;
- var
- transf: TAffineMatrix;
- diff: TComposedImageDifference;
- replaceDiff: TReplaceLayerByVectorOriginalDifference;
- layerId: integer;
- addDiff: TAddShapeToVectorOriginalDifference;
- begin
- layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
- transf := VectorTransform(false);
- diff := TComposedImageDifference.Create;
- replaceDiff := TReplaceLayerByVectorOriginalDifference.Create(Manager.Image.CurrentState,Manager.Image.CurrentLayerIndex,
- GetCurrentLayerKind = lkVectorial);
- diff.Add(replaceDiff);
- transf := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex])*transf;
- FShape.Transform(transf);
- addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
- diff.Add(addDiff);
- result := diff;
- ARect := addDiff.ChangingBounds;
- FShape := nil;
- end;
- procedure TVectorialTool.ShapeValidated;
- begin
- //nothing
- end;
- function TVectorialTool.ForeGradTexMode: TVectorShapeUsermode;
- begin
- if Assigned(FShape) and FSwapColor then
- begin
- if vsfBackFill in FShape.Fields then
- result := vsuEditBackFill
- else if vsfOutlineFill in FShape.Fields then
- result := vsuEditOutlineFill
- else
- result := vsuEditPenFill;
- end else
- result := vsuEditPenFill;
- end;
- function TVectorialTool.BackGradTexMode: TVectorShapeUsermode;
- begin
- if Assigned(FShape) and FSwapColor and (vsfPenFill in FShape.Fields) then
- result := vsuEditPenFill
- else
- result := vsuEditBackFill;
- end;
- function TVectorialTool.OutlineGradTexMode: TVectorShapeUsermode;
- begin
- if Assigned(FShape) and FSwapColor and ([vsfPenFill,vsfBackFill]*FShape.Fields = [vsfPenFill]) then
- result := vsuEditPenFill
- else
- result := vsuEditOutlineFill;
- end;
- function TVectorialTool.ForeFitMode: TFitMode;
- begin
- if IsForeEditGradTexPoints then result := fmNever
- else result := fmIfChange;
- end;
- function TVectorialTool.BackFitMode: TFitMode;
- begin
- if IsBackEditGradTexPoints then result := fmNever
- else result := fmIfChange;
- end;
- function TVectorialTool.OutlineFitMode: TFitMode;
- begin
- if IsOutlineEditGradTexPoints then result := fmNever
- else result := fmIfChange;
- end;
- function TVectorialTool.ManagerForeFill: TVectorialFill;
- begin
- if Assigned(FShape) and FSwapColor then
- begin
- if vsfBackFill in FShape.Fields then
- result := Manager.BackFill
- else if vsfOutlineFill in FShape.Fields then
- result := Manager.OutlineFill
- else
- result := Manager.ForeFill;
- end else
- result := Manager.ForeFill;
- end;
- function TVectorialTool.ManagerBackFill: TVectorialFill;
- begin
- if Assigned(FShape) and FSwapColor and (vsfPenFill in FShape.Fields) then
- result := Manager.ForeFill
- else
- result := Manager.BackFill;
- end;
- function TVectorialTool.ManagerOutlineFill: TVectorialFill;
- begin
- if Assigned(FShape) and FSwapColor and ([vsfPenFill,vsfBackFill]*FShape.Fields = [vsfPenFill]) then
- result := Manager.ForeFill
- else
- result := Manager.OutlineFill;
- end;
-
- function TVectorialTool.GetIsForeEditGradTexPoints: boolean;
- begin
- result := Assigned(FShape) and (FShape.Usermode = ForeGradTexMode);
- end;
- function TVectorialTool.GetIsBackEditGradTexPoints: boolean;
- begin
- result := Assigned(FShape) and (FShape.Usermode = BackGradTexMode);
- end;
- function TVectorialTool.GetIsOutlineEditGradTexPoints: boolean;
- begin
- result := Assigned(FShape) and (FShape.Usermode = OutlineGradTexMode);
- end;
- function TVectorialTool.GetGridMatrix: TAffineMatrix;
- begin
- if Manager.Image.ZoomFactor > DoScaleX(35, OriginalDPI)/10 then
- result := AffineMatrixScale(0.5,0.5)
- else
- begin
- if Assigned(FShape) and
- (not (vsfPenFill in FShape.MultiFields) or
- (FShape.PenFill.IsFullyTransparent)) then
- result := AffineMatrixTranslation(0.5, 0.5)
- else
- result := AffineMatrixIdentity;
- end;
- end;
- function TVectorialTool.GetIsEditingText: boolean;
- begin
- Result:= assigned(FShape) and (FShape.Usermode = vsuEditText);
- end;
- class procedure TVectorialTool.ForgetHintShown;
- begin
- SquareHintShown:= false;
- end;
- function TVectorialTool.ValidateShape: TRect;
- var
- layerId: LongInt;
- rF: TRectF;
- changeBounds: TRect;
- addDiff: TAddShapeToVectorOriginalDifference;
- begin
- if Assigned(FShape) then
- begin
- FShape.OnChange:= nil;
- FShape.OnEditingChange:= nil;
- FShape.OnRemoveQuery:= nil;
- if not AlwaysRasterizeShape and Manager.Image.SelectionMaskEmpty then
- begin
- CancelAction;
- if FShape.Usermode = vsuCreate then FShape.Usermode:= vsuEdit;
- rF := FShape.GetRenderBounds(rect(0,0,Manager.Image.Width,Manager.Image.Height), VectorTransform(false));
- if rF.IntersectsWith(rectF(0,0,Manager.Image.Width,Manager.Image.Height)) then
- begin
- if UseOriginal then
- begin
- layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
- addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
- changeBounds := addDiff.ChangingBounds;
- Manager.Image.AddUndo(addDiff);
- FShape := nil;
- end
- else
- Manager.Image.AddUndo(ReplaceLayerAndAddShape(changeBounds));
- Manager.Image.ImageMayChange(changeBounds);
- end;
- ClearShape;
- end else
- begin
- ValidateActionPartially;
- ClearShape;
- end;
- Cursor := crDefault;
- result := OnlyRenderChange;
- UpdateUseOriginal;
- ShapeValidated;
- end else
- result := EmptyRect;
- end;
- function TVectorialTool.CancelShape: TRect;
- begin
- CancelActionPartially;
- ClearShape;
- Cursor := crDefault;
- result := OnlyRenderChange;
- end;
- function TVectorialTool.GetEditor: TBGRAOriginalEditor;
- begin
- FEditor.GridActive := ssSnap in ShiftState;
- result := FEditor;
- end;
- function TVectorialTool.GetIsHandDrawing: boolean;
- begin
- result := Assigned(FShape) and (FQuickDefine or (FShape.Usermode = vsuCreate));
- end;
- function TVectorialTool.GetIsIdle: boolean;
- begin
- result := FShape = nil;
- end;
- function TVectorialTool.AlwaysRasterizeShape: boolean;
- begin
- result := false;
- end;
- function TVectorialTool.CreateShape: TVectorShape;
- begin
- result := ShapeClass.Create(nil);
- end;
- procedure TVectorialTool.ClearShape;
- begin
- FreeAndNil(FShape);
- FreeAndNil(FTemporaryStorage);
- Editor.Clear;
- end;
- function TVectorialTool.UseOriginal: boolean;
- begin
- result := FUseOriginal;
- end;
- function TVectorialTool.HasBrush: boolean;
- begin
- result := (toFillShape in GetManagerShapeOptions) or not (ctShape in GetContextualToolbars);
- end;
- function TVectorialTool.GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; ADraft: boolean): TRect;
- begin
- with FShape.GetRenderBounds(ADestBounds,AMatrix,[]) do
- result := rect(floor(Left),floor(Top),ceil(Right),ceil(Bottom));
- end;
- procedure TVectorialTool.DrawCustomShape(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean);
- begin
- FShape.Render(ADest,AMatrix,ADraft);
- end;
- procedure TVectorialTool.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
- var
- f: TVectorShapeFields;
- zoom: Single;
- gradBox: TAffineBox;
- fitMode: TFitMode;
- begin
- zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
- f := FShape.MultiFields;
- gradBox := FShape.SuggestGradientBox(AffineMatrixIdentity);
- if vsfAliased in f then
- FShape.Aliased:= Manager.ShapeOptionAliasing;
- if vsfPenFill in f then
- begin
- if HasPen then
- begin
- if AAlwaysFit then fitMode := fmAlways else fitMode := ForeFitMode;
- AssignFill(FShape.PenFill, ManagerForeFill, gradBox, fitMode)
- end else
- FShape.PenFill.Clear;
- end;
- if vsfPenWidth in f then FShape.PenWidth := zoom*Manager.PenWidth;
- if vsfPenStyle in f Then FShape.PenStyle := PenStyleToBGRA(Manager.PenStyle);
- if vsfJoinStyle in f then FShape.JoinStyle:= Manager.JoinStyle;
- if vsfBackFill in f then
- begin
- if HasBrush then
- begin
- if AAlwaysFit then fitMode := fmAlways else fitMode := BackFitMode;
- AssignFill(FShape.BackFill, ManagerBackFill, gradBox, fitMode)
- end else
- FShape.BackFill.Clear;
- end;
- if vsfOutlineFill in f then
- begin
- if Manager.TextOutline then
- begin
- if AAlwaysFit then fitMode := fmAlways else fitMode := OutlineFitMode;
- AssignFill(FShape.OutlineFill, ManagerOutlineFill, gradBox, fitMode);
- end else
- FShape.OutlineFill.Clear;
- end;
- if (vsfOutlineWidth in f) and Manager.TextOutline then
- FShape.OutlineWidth := zoom*Manager.TextOutlineWidth;
- end;
- function TVectorialTool.GetManagerShapeOptions: TShapeOptions;
- begin
- result := Manager.ShapeOptions;
- end;
- procedure TVectorialTool.QuickDefineShape(AStart, AEnd: TPointF);
- begin
- FShape.QuickDefine(AStart, AEnd);
- end;
- function TVectorialTool.RoundCoordinate(constref ptF: TPointF): TPointF;
- begin
- if not (toDrawShape in GetManagerShapeOptions) or
- (Assigned(FShape) and not (vsfPenFill in FShape.MultiFields)) then
- result := PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5)
- else
- result := PointF(round(ptF.x),round(ptF.y));
- end;
- function TVectorialTool.GetIsSelectingTool: boolean;
- begin
- result := false;
- end;
- function TVectorialTool.UpdateShape(toolDest: TBGRABitmap): TRect;
- var
- newBounds: TRect;
- oldClip: TRect;
- matrix: TAffineMatrix;
- begin
- result := FPreviousUpdateBounds;
- RestoreBackupDrawingLayer;
- matrix := VectorTransform(false);
- FLastDraftUpdate := PreferDraftUpdate;
- newBounds := GetCustomShapeBounds(toolDest.ClipRect,matrix,FLastDraftUpdate);
- result := RectUnion(result, newBounds);
- oldClip := toolDest.IntersectClip(newBounds);
- DrawCustomShape(toolDest,matrix,FLastDraftUpdate);
- toolDest.ClipRect := oldClip;
- FPreviousUpdateBounds := newBounds;
- end;
- function TVectorialTool.PreferDraftUpdate: boolean;
- begin
- if Assigned(FShape) then
- result := (FEditor.IsMovingPoint or FShape.IsFollowingMouse or FQuickDefine) and SlowShape
- else
- result := false;
- end;
- function TVectorialTool.VectorTransform(APixelCentered: boolean): TAffineMatrix;
- begin
- if not UseOriginal then
- result := AffineMatrixIdentity
- else
- result := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
- if APixelCentered then
- result := MatrixForPixelCentered(result);
- end;
- procedure TVectorialTool.UpdateCursor(ACursor: TOriginalEditorCursor);
- begin
- Cursor := OriginalCursorToCursor(ACursor);
- end;
- function TVectorialTool.FixLayerOffset: boolean;
- begin
- Result:= false;
- end;
- function TVectorialTool.UpdateQuickDefine: TRect;
- var
- s: TPointF;
- avg: single;
- begin
- if not Assigned(FShape) then exit(EmptyRect);
- if ssShift in ShiftState then
- begin
- s := FQuickDefineUserEndPoint-FQuickDefineStartPoint;
- avg := sqrt(abs(s.x*s.y));
- if s.x > 0 then FQuickDefineEndPoint.x := FQuickDefineStartPoint.x + avg else FQuickDefineEndPoint.x := FQuickDefineStartPoint.x - avg;
- if s.y > 0 then FQuickDefineEndPoint.y := FQuickDefineStartPoint.y + avg else FQuickDefineEndPoint.y := FQuickDefineStartPoint.y - avg;
- end else
- FQuickDefineEndPoint := FQuickDefineUserEndPoint;
- FShape.BeginUpdate;
- QuickDefineShape(FQuickDefineStartPoint, FQuickDefineEndPoint);
- FLastShapeTransform := AffineMatrixInverse(VectorTransform(false));
- FShape.Transform(FLastShapeTransform);
- AssignShapeStyle(FLastShapeTransform, true);
- FShape.EndUpdate;
- result := OnlyRenderChange;
- end;
- function TVectorialTool.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
- ptF: TPointF; rightBtn: boolean): TRect;
- var
- viewPt, shapePt: TPointF;
- cur: TOriginalEditorCursor;
- handled: boolean;
- begin
- result := EmptyRect;
- FRightDown := rightBtn;
- FLeftDown := not rightBtn;
- with LayerOffset do
- FLastPos := AffineMatrixTranslation(X,Y)*ptF;
- if Assigned(FShape) then
- begin
- viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
- Editor.MouseDown(rightBtn, ShiftState, viewPt.X,viewPt.Y, cur, handled);
- if not handled and Assigned(FShape) then
- begin
- shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
- If Editor.GridActive then shapePt := Editor.SnapToGrid(shapePt, false);
- FShape.MouseDown(rightBtn, Editor.ConsecutiveClickCount, ShiftState, shapePt.X,shapePt.Y, cur, handled);
- end;
- UpdateCursor(cur);
- if handled then exit
- else result := RectUnion(result, ValidateShape);
- end;
- if FShape=nil then
- begin
- UpdateUseOriginal;
- if UseOriginal and
- ((Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TVectorOriginal).GetShapesCost >= MediumShapeCost) then
- begin
- MessagePopup(rsTooManyShapesInLayer, 3000);
- end
- else
- if (GetCurrentLayerKind = lkSVG) and not IsSelectingTool then
- begin
- MessagePopup(rsCannotDrawShapeOnSVGLayer, 3000);
- end
- else
- begin
- toolDest := GetToolDrawingLayer;
- FSwapColor:= rightBtn;
- if IsSelectingTool then
- FLayerWasEmpty := Manager.Image.SelectionMaskEmpty
- else if Manager.Image.SelectionMaskEmpty then
- FLayerWasEmpty := Manager.Image.CurrentLayerEmpty
- else
- FLayerWasEmpty := Manager.Image.SelectionLayerIsEmpty;
- FShape := CreateShape;
- if FTemporaryStorage = nil then FTemporaryStorage := TBGRAMemOriginalStorage.Create;
- FShape.TemporaryStorage := FTemporaryStorage;
- FQuickDefine := true;
- FQuickDefineStartPoint := RoundCoordinate(FLastPos);
- FQuickDefineUserEndPoint := FQuickDefineStartPoint;
- FQuickDefineEndPoint := FQuickDefineStartPoint;
- FShape.BeginUpdate;
- QuickDefineShape(FQuickDefineStartPoint,FQuickDefineEndPoint);
- FLastShapeTransform := AffineMatrixInverse(VectorTransform(false));
- FShape.Transform(FLastShapeTransform);
- shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
- handled := false;
- FShape.MouseMove(ShiftState, shapePt.X,shapePt.Y, cur, handled);
- AssignShapeStyle(FLastShapeTransform, true);
- FShape.EndUpdate;
- FShape.OnChange:= @ShapeChange;
- FShape.OnEditingChange:=@ShapeEditingChange;
- FShape.OnRemoveQuery:= @ShapeRemoveQuery;
- result := RectUnion(result, UpdateShape(toolDest));
- if not SquareHintShown and (FShape is TCustomRectShape) then
- begin
- SquareHintShown := true;
- Manager.ToolPopup(tpmHoldKeyForSquare, VK_SHIFT);
- end;
- end;
- end;
- end;
- function TVectorialTool.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
- ptF: TPointF): TRect;
- var
- viewPt, shapePt: TPointF;
- handled: boolean;
- cur: TOriginalEditorCursor;
- begin
- Editor.GridMatrix := GetGridMatrix;
- with LayerOffset do
- FLastPos := AffineMatrixTranslation(X,Y)*ptF;
- if FQuickDefine then
- begin
- FQuickDefineUserEndPoint := RoundCoordinate(ptF);
- result := UpdateQuickDefine;
- end else
- begin
- viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
- Editor.MouseMove(ShiftState, viewPt.X,viewPt.Y, cur, handled);
- if not handled and Assigned(FShape) then
- begin
- shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
- If Editor.GridActive then shapePt := Editor.SnapToGrid(shapePt, false);
- FShape.MouseMove(ShiftState, shapePt.X,shapePt.Y, cur, handled);
- end;
- UpdateCursor(cur);
- if handled then result := OnlyRenderChange
- else result := EmptyRect;
- end;
- end;
- function TVectorialTool.DoToolUpdate(toolDest: TBGRABitmap): TRect;
- begin
- if Assigned(FShape) then
- begin
- FShape.BeginUpdate;
- AssignShapeStyle(FLastShapeTransform, false);
- FShape.EndUpdate;
- end;
- result := EmptyRect;
- end;
- constructor TVectorialTool.Create(AManager: TToolManager);
- begin
- inherited Create(AManager);
- UpdateUseOriginal;
- FPreviousUpdateBounds := EmptyRect;
- FEditor := TVectorOriginalEditor.Create(nil);
- FEditor.GridMatrix := GetGridMatrix;
- FEditor.Focused := true;
- FPreviousEditorBounds := EmptyRect;
- FLastShapeTransform := AffineMatrixIdentity;
- FTemporaryStorage := TBGRAMemOriginalStorage.Create;
- end;
- function TVectorialTool.ToolUp: TRect;
- var
- viewPt, shapePt: TPointF;
- cur: TOriginalEditorCursor;
- handled, wasRight: boolean;
- begin
- wasRight := FRightDown;
- FRightDown := false;
- FLeftDown := false;
- if FQuickDefine then
- begin
- FQuickDefine := false;
- result := EmptyRect;
- QuickDefineEnd;
- end else
- begin
- viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
- Editor.MouseUp(wasRight, ShiftState, viewPt.X,viewPt.Y, cur, handled);
- if not handled and Assigned(FShape) then
- begin
- shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
- FShape.MouseUp(wasRight, ShiftState, shapePt.X,shapePt.Y, cur, handled);
- end;
- UpdateCursor(cur);
- result := EmptyRect;
- end;
- if (FLastDraftUpdate and not PreferDraftUpdate) and Assigned(FShape) then
- result := UpdateShape(GetToolDrawingLayer);
- end;
- function TVectorialTool.DoToolKeyDown(var key: Word): TRect;
- var
- handled: boolean;
- begin
- result := EmptyRect;
- if (Key = VK_RETURN) and not FQuickDefine and
- Assigned(FShape) then
- begin
- result := ValidateShape;
- Key := 0;
- end else
- if (Key = VK_ESCAPE) and not FQuickDefine and
- Assigned(FShape) then
- begin
- result := CancelShape;
- Key := 0;
- end else
- if (Key = VK_SHIFT) and FQuickDefine and Assigned(FShape) then
- begin
- result := UpdateQuickDefine;
- Key := 0;
- end else
- begin
- Editor.KeyDown(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
- if not handled and Assigned(FShape) then FShape.KeyDown(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
- if handled then Key := 0;
- end;
- end;
- function TVectorialTool.ToolKeyPress(var key: TUTF8Char): TRect;
- var
- handled: boolean;
- begin
- result := EmptyRect;
- Editor.KeyPress(key, handled);
- if not handled and Assigned(FShape) then FShape.KeyPress(key, handled);
- if handled then Key := #0;
- end;
- function TVectorialTool.DoToolKeyUp(var key: Word): TRect;
- var
- handled: boolean;
- begin
- result := EmptyRect;
- if (Key = VK_SHIFT) and FQuickDefine and Assigned(FShape) then
- begin
- result := UpdateQuickDefine;
- Key := 0;
- end else
- begin
- Editor.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
- if not handled and Assigned(FShape) then FShape.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
- if handled then Key := 0;
- end;
- end;
- function TVectorialTool.ToolCommand(ACommand: TToolCommand): boolean;
- var
- r: TRect;
- toolDest: TBGRABitmap;
- begin
- result := false;
- case ACommand of
- tcCopy:
- if ToolProvideCommand(tcCopy) then
- result := CopyShapesToClipboard([FShape], VectorTransform(false));
- tcCut:
- if ToolCommand(tcCopy) then
- begin
- toolDest := GetToolDrawingLayer;
- r := CancelShape;
- Action.NotifyChange(toolDest, r);
- result := true;
- end;
- tcForeAdjustToShape: if Assigned(FShape) then FShape.PenFill.FitGeometry(SuggestGradientBox);
- tcBackAdjustToShape: if Assigned(FShape) then FShape.BackFill.FitGeometry(SuggestGradientBox);
- tcOutlineAdjustToShape: if Assigned(FShape) then FShape.OutlineFill.FitGeometry(SuggestGradientBox);
- tcForeEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
- begin
- if FShape.Usermode = ForeGradTexMode then
- FShape.Usermode := vsuEdit else
- FShape.Usermode := ForeGradTexMode;
- end;
- tcBackEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
- begin
- if FShape.Usermode = BackGradTexMode then
- FShape.Usermode := vsuEdit else
- FShape.Usermode := BackGradTexMode;
- end;
- tcOutlineEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
- begin
- if FShape.Usermode = OutlineGradTexMode then
- FShape.Usermode := vsuEdit else
- FShape.Usermode := OutlineGradTexMode;
- end;
- tcFinish: begin
- toolDest := GetToolDrawingLayer;
- r := ValidateShape;
- Action.NotifyChange(toolDest, r);
- result := true;
- end;
- tcAlignLeft..tcAlignBottom:
- if ToolProvideCommand(ACommand) then
- begin
- AlignShape(FShape, ACommand,
- Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex],
- rect(0,0,Manager.Image.Width,Manager.Image.Height));
- result := true;
- end;
- else
- result := false;
- end;
- end;
- function TVectorialTool.ToolProvideCommand(ACommand: TToolCommand): boolean;
- begin
- case ACommand of
- tcCopy,tcCut: Result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape);
- tcFinish: result := not IsIdle;
- tcForeAdjustToShape, tcBackAdjustToShape, tcOutlineAdjustToShape:
- result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine;
- tcForeEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
- (ForeGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
- tcBackEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
- (BackGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
- tcOutlineEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
- (OutlineGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
- tcShapeToSpline: result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape)
- and TCurveShape.CanCreateFrom(FShape);
- tcAlignLeft..tcAlignBottom: Result:= not FQuickDefine and Assigned(FShape);
- tcMoveDown,tcMoveToBack: result := not IsSelectingTool and not FQuickDefine and Assigned(FShape)
- and not AlwaysRasterizeShape and Manager.Image.SelectionMaskEmpty and not FLayerWasEmpty;
- else result := false;
- end;
- end;
- function TVectorialTool.SuggestGradientBox: TAffineBox;
- begin
- if Assigned(FShape) then
- result := FShape.SuggestGradientBox(AffineMatrixIdentity)
- else
- result:= inherited SuggestGradientBox;
- end;
- function TVectorialTool.GetContextualToolbars: TContextualToolbars;
- begin
- result := ContextualToolbarsFromShape(ShapeClass, FShape);
- end;
- function TVectorialTool.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
- VirtualScreenHeight: integer;
- BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
- var
- orig, xAxis, yAxis: TPointF;
- editMatrix: TAffineMatrix;
- begin
- if Assigned(FShape) then
- begin
- with LayerOffset do
- begin
- orig := BitmapToVirtualScreen(PointF(0,0));
- xAxis := BitmapToVirtualScreen(PointF(1,0));
- yAxis := BitmapToVirtualScreen(PointF(0,1));
- end;
- Editor.Clear;
- editMatrix := AffineMatrix(xAxis-orig,yAxis-orig,orig)*VectorTransform(true);
- if IsAffineMatrixInversible(editMatrix) then
- begin
- Editor.Matrix := editMatrix;
- Editor.PointSize := DoScaleX(PointSize*Manager.CanvasScale, OriginalDPI);
- if Assigned(FShape) then FShape.ConfigureEditor(Editor);
- if Assigned(VirtualScreen) then
- Result:= Editor.Render(VirtualScreen, rect(0,0,VirtualScreen.Width,VirtualScreen.Height))
- else
- Result:= Editor.GetRenderBounds(rect(0,0,VirtualScreenWidth,VirtualScreenHeight));
- end else
- result := EmptyRect;
- end else
- begin
- result := EmptyRect;
- Editor.Clear;
- end;
- FPreviousEditorBounds := result;
- end;
- destructor TVectorialTool.Destroy;
- begin
- if Assigned(FShape) then ValidateShape;
- FEditor.Free;
- FTemporaryStorage.Free;
- inherited Destroy;
- end;
- initialization
- RegisterTool(ptEditShape, TEditShapeTool);
- end.
|