utoolvectorial.pas 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit UToolVectorial;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, LCLType, BGRABitmap, BGRABitmapTypes,
  7. BGRALayerOriginal, BGRAGraphics, LCVectorOriginal, LCVectorialFill,
  8. UTool, UImageType, ULayerAction, LCVectorRectShapes, LCVectorMultishape,
  9. BGRAGradientOriginal, UStateType;
  10. type
  11. TToolSplineMode = (tsmMovePoint, tsmCurveModeAuto, tsmCurveModeAngle, tsmCurveModeSpline);
  12. function ToolSplineModeFromShape(AShape: TVectorShape): TToolSplineMode;
  13. type
  14. TFitMode = (fmNever, fmIfChange, fmAlways);
  15. type
  16. { TVectorialTool }
  17. TVectorialTool = class(TGenericTool)
  18. private
  19. function GetEditor: TBGRAOriginalEditor;
  20. function GetIsHandDrawing: boolean;
  21. function GetIsIdle: boolean;
  22. protected
  23. class var SquareHintShown: boolean;
  24. FLayerWasEmpty: boolean;
  25. FShape: TVectorShape;
  26. FTemporaryStorage: TBGRACustomOriginalStorage;
  27. FLastDraftUpdate: Boolean;
  28. FSwapColor: boolean;
  29. FQuickDefine: Boolean;
  30. FQuickDefineStartPoint, FQuickDefineUserEndPoint, FQuickDefineEndPoint: TPointF;
  31. FPreviousUpdateBounds, FPreviousEditorBounds: TRect;
  32. FEditor: TBGRAOriginalEditor;
  33. FRightDown, FLeftDown: boolean;
  34. FLastPos: TPointF;
  35. FLastShapeTransform: TAffineMatrix;
  36. FUseOriginal: boolean;
  37. function AlwaysRasterizeShape: boolean; virtual;
  38. function CreateShape: TVectorShape; virtual;
  39. procedure ClearShape; virtual;
  40. function ShapeClass: TVectorShapeAny; virtual; abstract;
  41. function UseOriginal: boolean; virtual;
  42. function HasBrush: boolean; virtual;
  43. function GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; {%H-}ADraft: boolean): TRect; virtual;
  44. procedure DrawCustomShape(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); virtual;
  45. procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); virtual;
  46. function GetManagerShapeOptions: TShapeOptions; virtual;
  47. procedure QuickDefineShape(AStart,AEnd: TPointF); virtual;
  48. function RoundCoordinate(constref ptF: TPointF): TPointF; virtual;
  49. function GetIsSelectingTool: boolean; override;
  50. function UpdateShape(toolDest: TBGRABitmap): TRect; virtual;
  51. function PreferDraftUpdate: boolean;
  52. function VectorTransform(APixelCentered: boolean): TAffineMatrix;
  53. procedure UpdateCursor(ACursor: TOriginalEditorCursor);
  54. function FixLayerOffset: boolean; override;
  55. function UpdateQuickDefine: TRect;
  56. function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF; rightBtn: boolean): TRect; override;
  57. function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF): TRect; override;
  58. function DoToolUpdate({%H-}toolDest: TBGRABitmap): TRect; override;
  59. function DoToolKeyDown(var key: Word): TRect; override;
  60. function DoToolKeyUp(var key: Word): TRect; override;
  61. procedure ShapeChange({%H-}ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff); virtual;
  62. procedure ShapeEditingChange({%H-}ASender: TObject); virtual;
  63. procedure ShapeRemoveQuery({%H-}ASender: TObject; var AHandled: boolean);
  64. function GetStatusText: string; override;
  65. function SlowShape: boolean; virtual;
  66. procedure QuickDefineEnd; virtual;
  67. procedure OnTryStop({%H-}sender: TCustomLayerAction); override;
  68. procedure UpdateUseOriginal;
  69. function ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference; virtual;
  70. procedure ShapeValidated; virtual;
  71. function ForeGradTexMode: TVectorShapeUsermode; virtual;
  72. function BackGradTexMode: TVectorShapeUsermode; virtual;
  73. function OutlineGradTexMode: TVectorShapeUsermode; virtual;
  74. function ForeFitMode: TFitMode;
  75. function BackFitMode: TFitMode;
  76. function OutlineFitMode: TFitMode;
  77. function ManagerForeFill: TVectorialFill;
  78. function ManagerBackFill: TVectorialFill;
  79. function ManagerOutlineFill: TVectorialFill;
  80. function GetIsForeEditGradTexPoints: boolean; override;
  81. function GetIsBackEditGradTexPoints: boolean; override;
  82. function GetIsOutlineEditGradTexPoints: boolean; override;
  83. function GetGridMatrix: TAffineMatrix; virtual;
  84. function GetIsEditingText: boolean; override;
  85. property Editor: TBGRAOriginalEditor read GetEditor;
  86. public
  87. class procedure ForgetHintShown;
  88. function ValidateShape: TRect;
  89. function CancelShape: TRect;
  90. constructor Create(AManager: TToolManager); override;
  91. function ToolUp: TRect; override;
  92. function ToolKeyPress(var key: TUTF8Char): TRect; override;
  93. function ToolCommand(ACommand: TToolCommand): boolean; override;
  94. function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
  95. function SuggestGradientBox: TAffineBox; override;
  96. function GetContextualToolbars: TContextualToolbars; override;
  97. function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
  98. property IsIdle: boolean read GetIsIdle;
  99. property IsHandDrawing: boolean read GetIsHandDrawing;
  100. destructor Destroy; override;
  101. end;
  102. { TEditShapeTool }
  103. TEditShapeMode = (esmNone, esmSelection, esmGradient, esmOtherOriginal, esmShape, esmNoShape);
  104. TEditShapeTool = class(TGenericTool)
  105. private
  106. function GetNothingSelected: boolean;
  107. function GetPointSize: integer;
  108. protected
  109. FDownHandled,FRectEditorCapture,FLayerOriginalCapture,
  110. FLeftButton,FRightButton: boolean;
  111. FLastPos: TPointF;
  112. FOriginalLayerId: integer;
  113. FOriginalRect: TRectShape;
  114. FOriginalRectUntransformed: TRectF;
  115. FRectEditor: TBGRAOriginalEditor;
  116. FSelectionRect: TRectShape;
  117. FSelectionRectUntransformed: TRectF;
  118. FIsEditingGradient: boolean;
  119. procedure RetrieveLightPosition;
  120. procedure UpdateToolManagerFromShape(AShape: TVectorShape);
  121. procedure UpdateDraftMode;
  122. procedure BindOriginalEvent(ABind: boolean);
  123. procedure SelectShape({%H-}ASender: TObject; AShape: TVectorShape; {%H-}APreviousShape: TVectorShape);
  124. function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF; rightBtn: boolean): TRect; override;
  125. function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; {%H-}ptF: TPointF): TRect; override;
  126. function DoToolUpdate({%H-}toolDest: TBGRABitmap): TRect; override;
  127. function DoToolKeyDown(var key: Word): TRect; override;
  128. function DoToolKeyUp(var key: Word): TRect; override;
  129. procedure UpdateSnap(AEditor: TBGRAOriginalEditor);
  130. function GetAction: TLayerAction; override;
  131. function DoGetToolDrawingLayer: TBGRABitmap; override;
  132. procedure OnTryStop({%H-}sender: TCustomLayerAction); override;
  133. procedure StopEdit(AUpdateInterface, ARaiseToolUp: boolean);
  134. function IsEditing: boolean;
  135. procedure MakeImageOriginal;
  136. procedure MakeVectorOriginal;
  137. procedure UpdateMatrixFromRect;
  138. procedure DoEditSelection;
  139. function GetMatrixFromRect(ARect: TRectShape; AUntransformedRect: TRectF): TAffineMatrix;
  140. function CreateRect(AUntransformedRect: TRectF; AMatrix: TAffineMatrix): TRectShape;
  141. function GetIsSelectingTool: boolean; override;
  142. function GetVectorOriginal: TVectorOriginal;
  143. function GetGradientOriginal: TBGRALayerGradientOriginal;
  144. function GetImageOriginal: TBGRALayerImageOriginal;
  145. function GetOriginalTransform: TAffineMatrix;
  146. function FixLayerOffset: boolean; override;
  147. function GetCurrentSplineMode: TToolSplineMode;
  148. procedure SetCurrentSplineMode(AMode: TToolSplineMode);
  149. function ConvertToSpline: boolean;
  150. function GetEditMode: TEditShapeMode;
  151. function InvalidEditMode: boolean;
  152. function ForeGradTexMode: TVectorShapeUsermode; virtual;
  153. function BackGradTexMode: TVectorShapeUsermode; virtual;
  154. function OutlineGradTexMode: TVectorShapeUsermode; virtual;
  155. function ForeFitMode: TFitMode;
  156. function BackFitMode: TFitMode;
  157. function OutlineFitMode: TFitMode;
  158. function GetIsForeEditGradTexPoints: boolean; override;
  159. function GetIsBackEditGradTexPoints: boolean; override;
  160. function GetIsOutlineEditGradTexPoints: boolean; override;
  161. function GetAllowedBackFillTypes: TVectorialFillTypes; override;
  162. function GetStatusText: string; override;
  163. public
  164. constructor Create(AManager: TToolManager); override;
  165. destructor Destroy; override;
  166. function GetContextualToolbars: TContextualToolbars; override;
  167. function Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth, VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect; override;
  168. function ToolKeyPress(var key: TUTF8Char): TRect; override;
  169. function ToolUp: TRect; override;
  170. function ToolCommand(ACommand: TToolCommand): boolean; override;
  171. function ToolProvideCommand(ACommand: TToolCommand): boolean; override;
  172. function SuggestGradientBox: TAffineBox; override;
  173. property CurrentSplineMode: TToolSplineMode read GetCurrentSplineMode write SetCurrentSplineMode;
  174. property NothingSelected: boolean read GetNothingSelected;
  175. end;
  176. procedure AssignFill(ATarget, ASource: TVectorialFill; const ABox: TAffineBox; AFitMode: TFitMode);
  177. function GetShapeStatusText(AShape: TVectorShape; const AMatrix: TAffineMatrix): string;
  178. function GetGradientStatusText(AGradient: TBGRALayerGradientOriginal; const AMatrix: TAffineMatrix): string;
  179. implementation
  180. uses LazPaintType, LCVectorPolyShapes, LCVectorTextShapes, BGRASVGOriginal,
  181. ULoading, BGRATransform, math, UImageDiff, Controls, BGRAPen, UResourceStrings, ugraph,
  182. LCScaleDPI, LCVectorClipboard, BGRAGradientScanner, UClipboard, BGRAUTF8;
  183. const PointSize = 6;
  184. function OriginalCursorToCursor(ACursor: TOriginalEditorCursor): TCursor;
  185. begin
  186. case ACursor of
  187. oecMove: result := crSizeAll;
  188. oecMoveN: result := crSizeN;
  189. oecMoveS: result := crSizeS;
  190. oecMoveE: result := crSizeE;
  191. oecMoveW: result := crSizeW;
  192. oecMoveNE: result := crSizeNE;
  193. oecMoveSW: result := crSizeSW;
  194. oecMoveNW: result := crSizeNW;
  195. oecMoveSE: result := crSizeSE;
  196. oecHandPoint: result := crHandPoint;
  197. oecText: result := crIBeam;
  198. else result := crDefault;
  199. end;
  200. end;
  201. function ToolSplineModeFromShape(AShape: TVectorShape): TToolSplineMode;
  202. var
  203. c: TCurveShape;
  204. begin
  205. result := tsmMovePoint;
  206. if not (AShape is TCurveShape) then exit;
  207. c := TCurveShape(AShape);
  208. case c.Usermode of
  209. vsuEdit: result := tsmMovePoint;
  210. vsuCreate: if c.PointCount > 1 then
  211. begin
  212. case c.CurveMode[c.PointCount-2] of
  213. cmAuto: result := tsmCurveModeAuto;
  214. cmAngle: result := tsmCurveModeAngle;
  215. cmCurve: result := tsmCurveModeSpline;
  216. end;
  217. end else
  218. result := tsmCurveModeAuto;
  219. vsuCurveSetAuto: result := tsmCurveModeAuto;
  220. vsuCurveSetAngle: result := tsmCurveModeAngle;
  221. vsuCurveSetCurve: result := tsmCurveModeSpline;
  222. end;
  223. end;
  224. function ContextualToolbarsFromShape(AShapeClass: TVectorShapeAny; AShape: TVectorShape): TContextualToolbars;
  225. var
  226. f: TVectorShapeFields;
  227. begin
  228. result:= [ctPenFill, ctBackFill];
  229. if Assigned(AShape) then
  230. f := AShape.MultiFields
  231. else f := AShapeClass.Fields;
  232. if vsfPenWidth in f then result += [ctPenWidth];
  233. if vsfPenStyle in f then result += [ctPenStyle];
  234. if vsfJoinStyle in f then result += [ctJoinStyle];
  235. if [vsfPenStyle,vsfPenFill,vsfBackFill] <= f then result += [ctShape];
  236. if vsfOutlineFill in f then
  237. begin
  238. result += [ctOutlineFill];
  239. if not (vsfBackFill in f) then result -= [ctBackFill];
  240. end;
  241. if vsfOutlineWidth in f then result += [ctOutlineWidth];
  242. if AShapeClass = TCurveShape then result := result + [ctShape,ctCloseShape,ctLineCap,ctSplineStyle]
  243. else if AShapeClass = TPolylineShape then result := result + [ctShape,ctCloseShape,ctLineCap]
  244. else if AShapeClass = TPhongShape then result := result + [ctPhong,ctAltitude]
  245. else if AShapeClass = TTextShape then
  246. begin
  247. result := result + [ctText,ctAliasing];
  248. if TTextShape(AShape).PenPhong then include(result, ctAltitude);
  249. end;
  250. if vsfAliased in f then
  251. result += [ctAliasing];
  252. end;
  253. procedure AlignShape(AShape: TVectorShape; ACommand: TToolCommand; const AMatrix: TAffineMatrix; const ARect: TRect);
  254. begin
  255. case ACommand of
  256. tcAlignLeft: AShape.AlignHorizontally(taLeftJustify,AMatrix,ARect);
  257. tcCenterHorizontally: AShape.AlignHorizontally(taCenter,AMatrix,ARect);
  258. tcAlignRight: AShape.AlignHorizontally(taRightJustify,AMatrix,ARect);
  259. tcAlignTop..tcAlignBottom:
  260. AShape.AlignVertically(TTextLayout(ord(ACommand)-ord(tcAlignTop)+ord(tlTop)),AMatrix,ARect);
  261. end;
  262. end;
  263. procedure AssignFill(ATarget, ASource: TVectorialFill; const ABox: TAffineBox; AFitMode: TFitMode);
  264. var
  265. temp: TVectorialFill;
  266. change: Boolean;
  267. begin
  268. if ASource.IsFullyTransparent then ATarget.Clear else
  269. begin
  270. change := ((ATarget.FillType = vftGradient) and (ASource.FillType = vftGradient) and
  271. (ATarget.Gradient.GradientType <> ASource.Gradient.GradientType) and
  272. not ([ATarget.Gradient.GradientType,ASource.Gradient.GradientType] <= [gtRadial,gtDiamond,gtAngular])) or
  273. ((ATarget.FillType = vftTexture) and (ASource.FillType = vftTexture) and
  274. (ATarget.TextureRepetition <> ASource.TextureRepetition));
  275. if ((AFitMode = fmIfChange) and change) or (AFitMode = fmAlways)
  276. or (ATarget.FillType <> ASource.FillType) then
  277. begin
  278. temp := ATarget.Duplicate;
  279. temp.AssignExceptGeometry(ASource);
  280. temp.FitGeometry(ABox);
  281. ATarget.Assign(temp);
  282. temp.Free;
  283. end else
  284. ATarget.AssignExceptGeometry(ASource);
  285. end;
  286. end;
  287. function GetShapeStatusText(AShape: TVectorShape; const AMatrix: TAffineMatrix): string;
  288. var
  289. orig, xa, ya, corner1, corner2: TPointF;
  290. overline: string4;
  291. i, nb: Integer;
  292. rF: TRectF;
  293. begin
  294. if AShape is TEllipseShape then
  295. with TEllipseShape(AShape) do
  296. begin
  297. orig := AMatrix*Origin;
  298. xa := AMatrix*XAxis;
  299. ya := AMatrix*YAxis;
  300. result := 'x = '+FloatToStrF(orig.x,ffFixed,6,1)+'|y = '+FloatToStrF(orig.y,ffFixed,6,1)+'|'+
  301. 'rx = '+FloatToStrF(VectLen(xa-orig),ffFixed,6,1)+'|ry = '+FloatToStrF(VectLen(ya-orig),ffFixed,6,1)
  302. end
  303. else if AShape is TCustomRectShape then
  304. with TCustomRectShape(AShape) do
  305. begin
  306. orig := AMatrix*Origin;
  307. xa := AMatrix*XAxis;
  308. ya := AMatrix*YAxis;
  309. corner1 := orig-(xa-orig)-(ya-orig);
  310. corner2 := xa + (ya-orig);
  311. result := 'x1 = '+FloatToStrF(corner1.x,ffFixed,6,1)+'|y1 = '+FloatToStrF(corner1.y,ffFixed,6,1)+'|'+
  312. 'x2 = '+FloatToStrF(corner2.x,ffFixed,6,1)+'|y2 = '+FloatToStrF(corner2.y,ffFixed,6,1)+'|'+
  313. 'Δx = '+FloatToStrF(VectLen(xa-orig)*2,ffFixed,6,1)+'|Δy = '+FloatToStrF(VectLen(ya-orig)*2,ffFixed,6,1);
  314. end
  315. else if AShape is TCustomPolypointShape then
  316. with TCustomPolypointShape(AShape) do
  317. begin
  318. result := 'count = ';
  319. nb := 0;
  320. for i := 0 to PointCount-1 do
  321. if Points[i].IsEmpty then
  322. begin
  323. if nb > 0 then result += inttostr(nb)+', ';
  324. nb := 0;
  325. end else inc(nb);
  326. result += inttostr(nb);
  327. if not Center.IsEmpty then
  328. begin
  329. orig := AMatrix*Center;
  330. overline := UnicodeCharToUTF8($0305);
  331. result += '|x'+overline+' = '+FloatToStrF(orig.x,ffFixed,6,1);
  332. result += '|y'+overline+' = '+FloatToStrF(orig.y,ffFixed,6,1);
  333. end;
  334. if (Usermode = vsuCreate) and (PointCount > 0) then
  335. begin
  336. xa := AMatrix*Points[PointCount-1];
  337. result += '|x = '+FloatToStrF(xa.x,ffFixed,6,1);
  338. result += '|y = '+FloatToStrF(xa.y,ffFixed,6,1);
  339. end else
  340. if HoverPoint <> -1 then
  341. begin
  342. xa := AMatrix*Points[HoverPoint];
  343. result += '|x = '+FloatToStrF(xa.x,ffFixed,6,1);
  344. result += '|y = '+FloatToStrF(xa.y,ffFixed,6,1);
  345. end else
  346. begin
  347. rF := GetPointBounds(AMatrix);
  348. result += '|Δx = '+FloatToStrF(rF.Width,ffFixed,6,1);
  349. result += '|Δy = '+FloatToStrF(rF.Height,ffFixed,6,1);
  350. end;
  351. end else
  352. result := '';
  353. end;
  354. function GetGradientStatusText(AGradient: TBGRALayerGradientOriginal; const AMatrix: TAffineMatrix): string;
  355. var
  356. orig, xa: TPointF;
  357. begin
  358. with AGradient do
  359. begin
  360. orig := AMatrix*Origin;
  361. xa := AMatrix*XAxis;
  362. result := 'x1 = '+FloatToStrF(orig.x,ffFixed,6,1)+'|y1 = '+FloatToStrF(orig.y,ffFixed,6,1)+'|'+
  363. 'x2 = '+FloatToStrF(xa.x,ffFixed,6,1)+'|y2 = '+FloatToStrF(xa.y,ffFixed,6,1)+'|'+
  364. 'Δx = '+FloatToStrF(abs(xa.x-orig.x),ffFixed,6,1)+'|Δy = '+FloatToStrF(abs(xa.y-orig.y),ffFixed,6,1);
  365. end;
  366. end;
  367. { TEditShapeTool }
  368. procedure TEditShapeTool.SelectShape(ASender: TObject; AShape: TVectorShape;
  369. APreviousShape: TVectorShape);
  370. begin
  371. if Assigned(AShape) and (GetCurrentLayerKind = lkVectorial) then
  372. begin
  373. UpdateToolManagerFromShape(AShape);
  374. Manager.UpdateContextualToolbars;
  375. end else
  376. if Assigned(APreviousShape) then
  377. Manager.UpdateContextualToolbars;
  378. end;
  379. function TEditShapeTool.GetNothingSelected: boolean;
  380. begin
  381. result := GetEditMode in [esmNone, esmNoShape];
  382. end;
  383. function TEditShapeTool.GetPointSize: integer;
  384. begin
  385. result := DoScaleX(PointSize*Manager.CanvasScale,OriginalDPI);
  386. end;
  387. procedure TEditShapeTool.RetrieveLightPosition;
  388. var
  389. shape: TVectorShape;
  390. m: TAffineMatrix;
  391. begin
  392. if GetCurrentLayerKind = lkVectorial then
  393. begin
  394. shape := GetVectorOriginal.SelectedShape;
  395. if shape=nil then exit;
  396. m := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
  397. if (shape is TTextShape) and TTextShape(shape).PenPhong then
  398. Manager.LightPosition := m*TTextShape(shape).LightPosition
  399. else if shape is TPhongShape then
  400. Manager.LightPosition := m*TPhongShape(shape).LightPosition;
  401. end;
  402. end;
  403. procedure TEditShapeTool.UpdateToolManagerFromShape(AShape: TVectorShape);
  404. var
  405. opt: TShapeOptions;
  406. zoom: single;
  407. m: TAffineMatrix;
  408. doFill, doDraw: Boolean;
  409. f: TVectorShapeFields;
  410. begin
  411. m := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
  412. zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
  413. if AShape.Usermode in [vsuEditBackFill, vsuEditPenFill] then
  414. AShape.Usermode := vsuEdit;
  415. opt := Manager.ShapeOptions;
  416. f := AShape.MultiFields;
  417. if vsfAliased in f then
  418. begin
  419. if AShape.Aliased then
  420. include(opt,toAliasing)
  421. else exclude(opt,toAliasing);
  422. end;
  423. doDraw := vsfPenFill in f;
  424. doFill := vsfBackFill in f;
  425. if vsfPenStyle in f then
  426. begin
  427. doDraw := AShape.PenVisible;
  428. if doDraw then doFill := AShape.BackVisible;
  429. if not doFill then
  430. exclude(opt,toFillShape)
  431. else include(opt,toFillShape);
  432. if not doDraw then
  433. exclude(opt,toDrawShape)
  434. else
  435. begin
  436. include(opt,toDrawShape);
  437. Manager.PenStyle := BGRAToPenStyle(AShape.PenStyle);
  438. end;
  439. end;
  440. if doDraw then
  441. begin
  442. if not AShape.PenVisible then
  443. Manager.ForeColor := BGRA(Manager.ForeColor.red,
  444. Manager.ForeColor.green,Manager.ForeColor.blue,0)
  445. else
  446. Manager.ForeFill.Assign(AShape.PenFill);
  447. end;
  448. if doFill then
  449. begin
  450. if not AShape.BackVisible then
  451. Manager.BackColor := BGRA(Manager.BackColor.red,
  452. Manager.BackColor.green,Manager.BackColor.blue,0)
  453. else
  454. Manager.BackFill.Assign(AShape.BackFill);
  455. end;
  456. if not AShape.OutlineVisible then
  457. Manager.SetTextOutline(false, Manager.TextOutlineWidth) else
  458. begin
  459. Manager.SetTextOutline(true, AShape.OutlineWidth*zoom);
  460. Manager.OutlineFill.Assign(AShape.OutlineFill);
  461. end;
  462. if toDrawShape in opt then
  463. begin
  464. if vsfPenWidth in f then Manager.PenWidth := AShape.PenWidth*zoom;
  465. if vsfJoinStyle in f then Manager.JoinStyle:= AShape.JoinStyle;
  466. if AShape is TCustomPolypointShape then
  467. begin
  468. if TCustomPolypointShape(AShape).Closed then
  469. include(opt, toCloseShape)
  470. else
  471. exclude(opt, toCloseShape);
  472. Manager.LineCap := TCustomPolypointShape(AShape).LineCap;
  473. Manager.ArrowSize := TCustomPolypointShape(AShape).ArrowSize;
  474. Manager.ArrowStart := TCustomPolypointShape(AShape).ArrowStartKind;
  475. Manager.ArrowEnd := TCustomPolypointShape(AShape).ArrowEndKind;
  476. end;
  477. if AShape is TCurveShape then
  478. Manager.SplineStyle := TCurveShape(AShape).SplineStyle;
  479. end;
  480. if AShape is TTextShape then
  481. with TTextShape(AShape) do
  482. begin
  483. Manager.TextPhong := PenPhong;
  484. Manager.LightPosition := m*LightPosition;
  485. Manager.PhongShapeAltitude := round(AltitudePercent);
  486. Manager.TextAlign:= ParagraphAlignment;
  487. Manager.TextVerticalAlign:= VerticalAlignment;
  488. Manager.SetTextFont(FontName, FontEmHeight*zoom*72/Manager.Image.DPI, FontStyle);
  489. Manager.TextShadow:= false;
  490. end;
  491. Manager.ShapeOptions := opt;
  492. if AShape is TPhongShape then
  493. with TPhongShape(AShape) do
  494. begin
  495. Manager.PhongShapeKind:= ShapeKind;
  496. Manager.LightPosition:= LightPosition;
  497. Manager.PhongShapeAltitude:= round(ShapeAltitudePercent);
  498. Manager.PhongShapeBorderSize:= round(BorderSizePercent);
  499. end;
  500. end;
  501. procedure TEditShapeTool.UpdateDraftMode;
  502. begin
  503. case GetEditMode of
  504. esmShape: Manager.Image.DraftOriginal:= GetVectorOriginal.PreferDraftMode(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor, GetOriginalTransform);
  505. esmNoShape: Manager.Image.DraftOriginal:= false;
  506. else Manager.Image.DraftOriginal:= FLeftButton or FRightButton;
  507. end;
  508. end;
  509. procedure TEditShapeTool.BindOriginalEvent(ABind: boolean);
  510. begin
  511. case GetCurrentLayerKind of
  512. lkVectorial:
  513. begin
  514. if ABind then
  515. begin
  516. GetVectorOriginal.OnSelectShape:= @SelectShape;
  517. Manager.Image.CurrentState.DiscardOriginalDiff := false;
  518. end else
  519. begin
  520. GetVectorOriginal.OnSelectShape := nil;
  521. Manager.Image.CurrentState.DiscardOriginalDiff := true;
  522. end;
  523. end;
  524. lkGradient:
  525. begin
  526. if ABind then
  527. begin
  528. Manager.Image.CurrentState.DiscardOriginalDiff := false;
  529. end else
  530. begin
  531. Manager.Image.CurrentState.DiscardOriginalDiff := true;
  532. end;
  533. end;
  534. end;
  535. end;
  536. function TEditShapeTool.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
  537. ptF: TPointF; rightBtn: boolean): TRect;
  538. var
  539. cur: TOriginalEditorCursor;
  540. handled: boolean;
  541. ptView: TPointF;
  542. begin
  543. Result:= EmptyRect;
  544. FRightButton:= rightBtn;
  545. FLeftButton:= not rightBtn;
  546. FRectEditorCapture:= false;
  547. FLayerOriginalCapture:= false;
  548. FLastPos := ptF;
  549. handled := false;
  550. if not handled and (GetEditMode in [esmSelection,esmOtherOriginal]) and Assigned(FRectEditor) then
  551. begin
  552. ptView := FRectEditor.Matrix*ptF;
  553. UpdateSnap(FRectEditor);
  554. FRectEditor.MouseDown(rightBtn, ShiftState, ptView.X,ptView.Y, cur, handled);
  555. Cursor := OriginalCursorToCursor(cur);
  556. if handled then
  557. begin
  558. FRectEditorCapture:= true;
  559. result := OnlyRenderChange;
  560. UpdateMatrixFromRect;
  561. end;
  562. end;
  563. if not handled and (GetEditMode in [esmShape,esmGradient,esmNoShape]) then
  564. begin
  565. BindOriginalEvent(true);
  566. try
  567. UpdateSnap(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor);
  568. Manager.Image.CurrentState.LayeredBitmap.MouseDown(rightBtn, ShiftState, ptF.X,ptF.Y, cur, handled);
  569. finally
  570. BindOriginalEvent(false);
  571. end;
  572. if handled then
  573. begin
  574. Cursor := OriginalCursorToCursor(cur);
  575. FLayerOriginalCapture:= true;
  576. end;
  577. end;
  578. FDownHandled:= handled;
  579. end;
  580. function TEditShapeTool.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
  581. ptF: TPointF): TRect;
  582. var
  583. cur: TOriginalEditorCursor;
  584. handled: boolean;
  585. ptView: TPointF;
  586. begin
  587. FLastPos := ptF;
  588. Result:= EmptyRect;
  589. UpdateDraftMode;
  590. case GetEditMode of
  591. esmGradient, esmShape, esmNoShape:
  592. begin
  593. BindOriginalEvent(true);
  594. try
  595. UpdateSnap(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor);
  596. Manager.Image.CurrentState.LayeredBitmap.MouseMove(ShiftState, ptF.X,ptF.Y, cur, handled);
  597. finally
  598. BindOriginalEvent(false);
  599. end;
  600. Cursor := OriginalCursorToCursor(cur);
  601. end;
  602. esmSelection, esmOtherOriginal:
  603. if Assigned(FRectEditor) then
  604. begin
  605. ptView := FRectEditor.Matrix*ptF;
  606. UpdateSnap(FRectEditor);
  607. FRectEditor.MouseMove(ShiftState, ptView.X,ptView.Y, cur, handled);
  608. Cursor := OriginalCursorToCursor(cur);
  609. if handled then
  610. begin
  611. result := OnlyRenderChange;
  612. UpdateMatrixFromRect;
  613. end;
  614. end;
  615. end;
  616. end;
  617. function TEditShapeTool.DoToolUpdate(toolDest: TBGRABitmap): TRect;
  618. var
  619. doDraw, doFill: Boolean;
  620. m: TAffineMatrix;
  621. zoom: Single;
  622. gradBox: TAffineBox;
  623. f: TVectorShapeFields;
  624. shape: TVectorShape;
  625. begin
  626. shape := nil;
  627. case GetEditMode of
  628. esmShape:
  629. try
  630. BindOriginalEvent(true);
  631. shape := GetVectorOriginal.SelectedShape;
  632. shape.BeginUpdate;
  633. gradBox := shape.SuggestGradientBox(AffineMatrixIdentity);
  634. m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
  635. zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
  636. f := shape.MultiFields;
  637. if vsfAliased in f then
  638. shape.Aliased := Manager.ShapeOptionAliasing;
  639. if f*[vsfPenFill,vsfBackFill,vsfPenStyle] = [vsfPenFill,vsfBackFill,vsfPenStyle] then
  640. begin
  641. doDraw := toDrawShape in Manager.ShapeOptions;
  642. doFill := toFillShape in Manager.ShapeOptions;
  643. if doDraw then
  644. shape.PenStyle := PenStyleToBGRA(Manager.PenStyle)
  645. else
  646. shape.PenStyle := ClearPenStyle;
  647. if doDraw and (vsfPenWidth in f) then shape.PenWidth := Manager.PenWidth*zoom;
  648. if doDraw and (vsfJoinStyle in f) then shape.JoinStyle := Manager.JoinStyle;
  649. if shape is TCustomPolypointShape then
  650. begin
  651. TCustomPolypointShape(shape).Closed := toCloseShape in Manager.ShapeOptions;
  652. if not TCustomPolypointShape(shape).Closed then
  653. begin
  654. TCustomPolypointShape(shape).LineCap:= Manager.LineCap;
  655. TCustomPolypointShape(shape).ArrowSize:= Manager.ArrowSize;
  656. TCustomPolypointShape(shape).ArrowStartKind:= Manager.ArrowStart;
  657. TCustomPolypointShape(shape).ArrowEndKind:= Manager.ArrowEnd;
  658. end;
  659. end;
  660. if shape is TCurveShape then
  661. TCurveShape(shape).SplineStyle:= Manager.SplineStyle;
  662. end else
  663. begin
  664. doDraw := vsfPenFill in f;
  665. doFill := vsfBackFill in f;
  666. end;
  667. if doFill then AssignFill(shape.BackFill, Manager.BackFill, gradBox, BackFitMode)
  668. else if vsfBackFill in f then
  669. shape.BackFill.Clear;
  670. if doDraw then AssignFill(shape.PenFill, Manager.ForeFill, gradBox, ForeFitMode);
  671. if (vsfOutlineWidth in f) and Manager.TextOutline then shape.OutlineWidth := Manager.TextOutlineWidth*zoom;
  672. if vsfOutlineFill in f then
  673. begin
  674. if Manager.TextOutline then
  675. AssignFill(shape.OutLineFill, Manager.OutLineFill, gradBox, OutlineFitMode)
  676. else shape.OutlineFill.Clear;
  677. end;
  678. if shape is TTextShape then
  679. with TTextShape(shape) do
  680. begin
  681. PenPhong := Manager.TextPhong;
  682. LightPosition := m*Manager.LightPosition;
  683. AltitudePercent := Manager.PhongShapeAltitude;
  684. if FontBidiMode <> Manager.TextBidiMode then
  685. begin
  686. FontBidiMode:= Manager.TextBidiMode;
  687. Manager.TextAlign:= ParagraphAlignment;
  688. end else
  689. ParagraphAlignment := Manager.TextAlign;
  690. VerticalAlignment:= Manager.TextVerticalAlign;
  691. FontName:= Manager.TextFontName;
  692. FontEmHeight:= Manager.TextFontSize*zoom*Manager.Image.DPI/72;
  693. FontStyle := Manager.TextFontStyle;
  694. end;
  695. if shape is TPhongShape then
  696. with TPhongShape(shape) do
  697. begin
  698. ShapeKind := Manager.PhongShapeKind;
  699. LightPosition := Manager.LightPosition;
  700. ShapeAltitudePercent := Manager.PhongShapeAltitude;
  701. BorderSizePercent := Manager.PhongShapeBorderSize;
  702. end;
  703. finally
  704. if Assigned(shape) then shape.EndUpdate;
  705. BindOriginalEvent(false);
  706. end;
  707. esmGradient:
  708. try
  709. BindOriginalEvent(true);
  710. case Manager.BackFill.FillType of
  711. vftGradient: GetGradientOriginal.AssignExceptGeometry(Manager.BackFill.Gradient);
  712. vftSolid: GetGradientOriginal.SetColors(Manager.BackFill.SolidColor, Manager.BackFill.SolidColor);
  713. end;
  714. finally
  715. BindOriginalEvent(false);
  716. end;
  717. end;
  718. Result := EmptyRect;
  719. end;
  720. procedure TEditShapeTool.UpdateSnap(AEditor: TBGRAOriginalEditor);
  721. begin
  722. if Assigned(AEditor) then
  723. AEditor.GridActive := ssSnap in ShiftState;
  724. end;
  725. function TEditShapeTool.GetAction: TLayerAction;
  726. begin
  727. result := nil;
  728. end;
  729. function TEditShapeTool.DoGetToolDrawingLayer: TBGRABitmap;
  730. begin
  731. Result:= Manager.Image.LayerBitmap[Manager.Image.CurrentLayerIndex];
  732. end;
  733. procedure TEditShapeTool.OnTryStop(sender: TCustomLayerAction);
  734. begin
  735. StopEdit(True, True);
  736. inherited OnTryStop(sender);
  737. end;
  738. procedure TEditShapeTool.StopEdit(AUpdateInterface, ARaiseToolUp: boolean);
  739. var
  740. r: TRect;
  741. begin
  742. if ARaiseToolUp and (FLeftButton or FRightButton) then
  743. begin
  744. r := ToolUp;
  745. Manager.Image.LayerMayChange(GetToolDrawingLayer,r);
  746. end;
  747. case GetEditMode of
  748. esmShape: GetVectorOriginal.DeselectShapes;
  749. esmGradient: FIsEditingGradient:= false;
  750. esmOtherOriginal: FreeAndNil(FOriginalRect);
  751. esmSelection: FreeAndNil(FSelectionRect);
  752. end;
  753. Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
  754. FLayerOriginalCapture:= false;
  755. FreeAndNil(FRectEditor);
  756. FRectEditorCapture := false;
  757. Cursor := crDefault;
  758. if AUpdateInterface then
  759. begin
  760. Manager.Image.OnImageChanged.NotifyObservers;
  761. Manager.UpdateContextualToolbars;
  762. end;
  763. end;
  764. function TEditShapeTool.IsEditing: boolean;
  765. begin
  766. result := not (GetEditMode in[esmNone, esmNoShape]);
  767. end;
  768. procedure TEditShapeTool.MakeImageOriginal;
  769. var
  770. diff: TReplaceLayerByImageOriginalDifference;
  771. begin
  772. if GetCurrentLayerKind = lkBitmap then
  773. begin
  774. diff := TReplaceLayerByImageOriginalDifference.Create(Manager.Image.CurrentState,
  775. Manager.Image.CurrentLayerIndex, false);
  776. Manager.Image.AddUndo(diff);
  777. if Assigned(Manager.Image.OnStackChanged) then
  778. Manager.Image.OnStackChanged(Manager.Image, False);
  779. end;
  780. end;
  781. procedure TEditShapeTool.MakeVectorOriginal;
  782. var
  783. diff: TReplaceLayerByVectorOriginalDifference;
  784. begin
  785. if GetCurrentLayerKind in [lkEmpty,lkBitmap,lkTransformedBitmap] then
  786. begin
  787. StopEdit(True, True);
  788. diff := TReplaceLayerByVectorOriginalDifference.Create(Manager.Image.CurrentState,
  789. Manager.Image.CurrentLayerIndex, false);
  790. Manager.Image.AddUndo(diff);
  791. if Assigned(Manager.Image.OnStackChanged) then
  792. Manager.Image.OnStackChanged(Manager.Image, False);
  793. end;
  794. end;
  795. procedure TEditShapeTool.UpdateMatrixFromRect;
  796. begin
  797. if Assigned(FOriginalRect) then
  798. Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] :=
  799. GetMatrixFromRect(FOriginalRect,FOriginalRectUntransformed);
  800. if Assigned(FSelectionRect) then
  801. begin
  802. Manager.Image.SelectionTransform :=
  803. GetMatrixFromRect(FSelectionRect,FSelectionRectUntransformed);
  804. Manager.Image.OnImageChanged.NotifyObservers;
  805. end;
  806. end;
  807. procedure TEditShapeTool.DoEditSelection;
  808. begin
  809. if not IsEditing then
  810. begin
  811. with Manager.Image.SelectionMaskBounds do
  812. FSelectionRectUntransformed := rectF(Left-0.5, Top-0.5, Right-0.5, Bottom-0.5);
  813. FSelectionRect := CreateRect(FSelectionRectUntransformed, Manager.Image.SelectionTransform);
  814. end;
  815. end;
  816. function TEditShapeTool.GetMatrixFromRect(ARect: TRectShape; AUntransformedRect: TRectF): TAffineMatrix;
  817. var
  818. u, v: TPointF;
  819. mAfter, mBefore: TAffineMatrix;
  820. begin
  821. u := (ARect.XAxis-ARect.Origin)*2;
  822. v := (ARect.YAxis-ARect.Origin)*2;
  823. mAfter := AffineMatrix(u,v,ARect.Origin-(u+v)*0.5);
  824. mBefore := AffineMatrixTranslation(AUntransformedRect.Left,
  825. AUntransformedRect.Top)
  826. *AffineMatrixScale(AUntransformedRect.Width,AUntransformedRect.Height);
  827. if IsAffineMatrixInversible(mBefore) then
  828. result := mAfter*AffineMatrixInverse(mBefore)
  829. else
  830. result := AffineMatrixIdentity;
  831. end;
  832. function TEditShapeTool.CreateRect(AUntransformedRect: TRectF; AMatrix: TAffineMatrix): TRectShape;
  833. var
  834. box: TAffineBox;
  835. begin
  836. if (AUntransformedRect.Width > 0) and (AUntransformedRect.Height > 0) then
  837. begin
  838. result := TRectShape.Create(nil);
  839. result.PenStyle := ClearPenStyle;
  840. result.BackFill.SetSolid(BGRAWhite);
  841. box := AMatrix*TAffineBox.AffineBox(AUntransformedRect);
  842. result.Origin := (box.TopLeft+box.BottomRight)*0.5;
  843. result.XAxis := result.Origin+(box.TopRight-box.TopLeft)*0.5;
  844. result.YAxis := result.Origin+(box.BottomLeft-box.TopLeft)*0.5;
  845. Manager.UpdateContextualToolbars;
  846. end else
  847. result := nil;
  848. end;
  849. function TEditShapeTool.GetIsSelectingTool: boolean;
  850. begin
  851. result := false;
  852. end;
  853. function TEditShapeTool.GetVectorOriginal: TVectorOriginal;
  854. begin
  855. result := Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TVectorOriginal;
  856. end;
  857. function TEditShapeTool.GetGradientOriginal: TBGRALayerGradientOriginal;
  858. begin
  859. result := Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TBGRALayerGradientOriginal;
  860. end;
  861. function TEditShapeTool.GetImageOriginal: TBGRALayerImageOriginal;
  862. begin
  863. result := Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TBGRALayerImageOriginal;
  864. end;
  865. function TEditShapeTool.GetOriginalTransform: TAffineMatrix;
  866. begin
  867. result := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
  868. end;
  869. function TEditShapeTool.FixLayerOffset: boolean;
  870. begin
  871. Result:= false;
  872. end;
  873. destructor TEditShapeTool.Destroy;
  874. begin
  875. FreeAndNil(FOriginalRect);
  876. FreeAndNil(FSelectionRect);
  877. Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
  878. FreeAndNil(FRectEditor);
  879. inherited Destroy;
  880. end;
  881. function TEditShapeTool.GetContextualToolbars: TContextualToolbars;
  882. var
  883. shape: TVectorShape;
  884. begin
  885. case GetEditMode of
  886. esmShape:
  887. begin
  888. shape := GetVectorOriginal.SelectedShape;
  889. result := ContextualToolbarsFromShape(TVectorShapeAny(shape.ClassType), shape);
  890. end;
  891. esmGradient: result := [ctBackFill];
  892. else
  893. Result:= [ctPenFill, ctBackFill];
  894. end;
  895. end;
  896. function TEditShapeTool.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
  897. VirtualScreenHeight: integer;
  898. BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
  899. var
  900. orig, xAxis, yAxis: TPointF;
  901. viewMatrix, editMatrix: TAffineMatrix;
  902. begin
  903. if InvalidEditMode then StopEdit(false,false);
  904. with LayerOffset do
  905. begin
  906. orig := BitmapToVirtualScreen(PointF(-X,-Y));
  907. xAxis := BitmapToVirtualScreen(PointF(-X+1,-Y));
  908. yAxis := BitmapToVirtualScreen(PointF(-X,-Y+1));
  909. end;
  910. viewMatrix := AffineMatrixTranslation(0.5,0.5)
  911. *AffineMatrix(xAxis-orig,yAxis-orig,orig)
  912. *AffineMatrixTranslation(-0.5,-0.5);
  913. case GetEditMode of
  914. esmGradient, esmShape:
  915. begin
  916. FreeAndNil(FRectEditor);
  917. FRectEditorCapture := false;
  918. if Assigned(Manager.Image.CurrentState.LayeredBitmap.OriginalEditor) then
  919. Manager.Image.CurrentState.LayeredBitmap.OriginalEditor.GridMatrix := AffineMatrixScale(0.5,0.5);
  920. if Assigned(VirtualScreen) then
  921. result := Manager.Image.CurrentState.LayeredBitmap.DrawEditor(VirtualScreen,
  922. Manager.Image.CurrentLayerIndex, viewMatrix, GetPointSize)
  923. else
  924. result := Manager.Image.CurrentState.LayeredBitmap.GetEditorBounds(
  925. rect(0,0,VirtualScreenWidth,VirtualScreenHeight),
  926. Manager.Image.CurrentLayerIndex, viewMatrix, GetPointSize);
  927. RetrieveLightPosition;
  928. end;
  929. esmSelection, esmOtherOriginal:
  930. begin
  931. result := EmptyRect;
  932. Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
  933. FLayerOriginalCapture:= false;
  934. if not Assigned(FRectEditor) then
  935. begin
  936. FRectEditor := TVectorOriginalEditor.Create(nil);
  937. FRectEditor.GridMatrix := AffineMatrixScale(0.5,0.5);
  938. FRectEditor.Focused := true;
  939. FRectEditor.PointSize := GetPointSize;
  940. end;
  941. FRectEditor.Clear;
  942. editMatrix := AffineMatrixTranslation(-0.5,-0.5)*viewMatrix*AffineMatrixTranslation(0.5,0.5);
  943. if IsAffineMatrixInversible(editMatrix) then
  944. begin
  945. FRectEditor.Matrix := editMatrix;
  946. if Assigned(FOriginalRect) then FOriginalRect.ConfigureEditor(FRectEditor);
  947. if Assigned(FSelectionRect) then FSelectionRect.ConfigureEditor(FRectEditor);
  948. if Assigned(VirtualScreen) then
  949. result := FRectEditor.Render(VirtualScreen,
  950. rect(0,0,VirtualScreenWidth,VirtualScreenHeight))
  951. else
  952. result := FRectEditor.GetRenderBounds(
  953. rect(0,0,VirtualScreenWidth,VirtualScreenHeight));
  954. end
  955. else
  956. result := EmptyRect;
  957. end;
  958. else
  959. begin
  960. result := EmptyRect;
  961. Manager.Image.CurrentState.LayeredBitmap.ClearEditor;
  962. FLayerOriginalCapture := false;
  963. FreeAndNil(FRectEditor);
  964. FRectEditorCapture := false;
  965. end;
  966. end;
  967. end;
  968. function TEditShapeTool.GetCurrentSplineMode: TToolSplineMode;
  969. var
  970. orig: TVectorOriginal;
  971. begin
  972. if GetEditMode = esmShape then
  973. begin
  974. orig := GetVectorOriginal;
  975. if Assigned(orig.SelectedShape) and
  976. (orig.SelectedShape is TCurveShape) then
  977. exit(ToolSplineModeFromShape(orig.SelectedShape));
  978. end;
  979. result := tsmMovePoint;
  980. end;
  981. procedure TEditShapeTool.SetCurrentSplineMode(AMode: TToolSplineMode);
  982. var
  983. c: TCurveShape;
  984. begin
  985. if (GetEditMode = esmShape) and
  986. (GetVectorOriginal.SelectedShape is TCurveShape) then
  987. begin
  988. c := TCurveShape(GetVectorOriginal.SelectedShape);
  989. case AMode of
  990. tsmMovePoint: if not (c.Usermode in [vsuEdit,vsuCreate]) then c.Usermode := vsuEdit;
  991. tsmCurveModeAuto: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetAuto else
  992. if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmAuto;
  993. tsmCurveModeAngle: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetAngle else
  994. if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmAngle;
  995. tsmCurveModeSpline: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetCurve else
  996. if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmCurve;
  997. end;
  998. end;
  999. end;
  1000. function TEditShapeTool.ConvertToSpline: boolean;
  1001. var
  1002. shapeBefore: TVectorShape;
  1003. orig: TVectorOriginal;
  1004. shapeAfter: TCurveShape;
  1005. begin
  1006. if (GetEditMode = esmShape) and
  1007. TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape) then
  1008. begin
  1009. orig := GetVectorOriginal;
  1010. shapeBefore:= orig.SelectedShape;
  1011. shapeAfter := TCurveShape.CreateFrom(orig, shapeBefore);
  1012. shapeAfter.JoinStyle := pjsRound;
  1013. orig.ReplaceShape(orig.IndexOfShape(shapeBefore), shapeAfter);
  1014. orig.SelectShape(shapeAfter, False);
  1015. result := true;
  1016. end else
  1017. result := false;
  1018. end;
  1019. function TEditShapeTool.GetEditMode: TEditShapeMode;
  1020. begin
  1021. if InvalidEditMode then exit(esmNone);
  1022. if Assigned(FSelectionRect) then exit(esmSelection)
  1023. else if Assigned(FOriginalRect) then exit(esmOtherOriginal)
  1024. else
  1025. case GetCurrentLayerKind of
  1026. lkGradient: if FIsEditingGradient then exit(esmGradient) else exit(esmNone);
  1027. lkVectorial: if Assigned(GetVectorOriginal.SelectedShape) then exit(esmShape) else exit(esmNoShape);
  1028. else exit(esmNone);
  1029. end;
  1030. end;
  1031. function TEditShapeTool.InvalidEditMode: boolean;
  1032. begin
  1033. if Assigned(FOriginalRect) and
  1034. ((FOriginalLayerId <> Manager.Image.LayerId[Manager.Image.CurrentLayerIndex])
  1035. or not (GetCurrentLayerKind in[lkTransformedBitmap,lkSVG,lkOther])) then
  1036. result := true
  1037. else if Assigned(FSelectionRect) and
  1038. Manager.Image.SelectionMaskEmpty then result := true
  1039. else if FIsEditingGradient and (GetCurrentLayerKind <> lkGradient) then
  1040. result := true
  1041. else
  1042. result := false;
  1043. end;
  1044. function TEditShapeTool.ForeGradTexMode: TVectorShapeUsermode;
  1045. begin
  1046. result := vsuEditPenFill;
  1047. end;
  1048. function TEditShapeTool.BackGradTexMode: TVectorShapeUsermode;
  1049. begin
  1050. result := vsuEditBackFill;
  1051. end;
  1052. function TEditShapeTool.OutlineGradTexMode: TVectorShapeUsermode;
  1053. begin
  1054. result := vsuEditOutlineFill;
  1055. end;
  1056. function TEditShapeTool.ForeFitMode: TFitMode;
  1057. begin
  1058. if IsForeEditGradTexPoints then result := fmNever
  1059. else result := fmIfChange;
  1060. end;
  1061. function TEditShapeTool.BackFitMode: TFitMode;
  1062. begin
  1063. if IsBackEditGradTexPoints then result := fmNever
  1064. else result := fmIfChange;
  1065. end;
  1066. function TEditShapeTool.OutlineFitMode: TFitMode;
  1067. begin
  1068. if IsOutlineEditGradTexPoints then result := fmNever
  1069. else result := fmIfChange;
  1070. end;
  1071. function TEditShapeTool.GetIsForeEditGradTexPoints: boolean;
  1072. begin
  1073. result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = ForeGradTexMode);
  1074. end;
  1075. function TEditShapeTool.GetIsBackEditGradTexPoints: boolean;
  1076. begin
  1077. result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode);
  1078. end;
  1079. function TEditShapeTool.GetIsOutlineEditGradTexPoints: boolean;
  1080. begin
  1081. result := (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape.Usermode = OutlineGradTexMode);
  1082. end;
  1083. function TEditShapeTool.GetAllowedBackFillTypes: TVectorialFillTypes;
  1084. begin
  1085. if GetEditMode = esmGradient then
  1086. result := [vftGradient] else
  1087. Result:=inherited GetAllowedBackFillTypes;
  1088. end;
  1089. function TEditShapeTool.GetStatusText: string;
  1090. var
  1091. m: TAffineMatrix;
  1092. begin
  1093. m := AffineMatrixTranslation(-0.5, -0.5) *
  1094. Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex] *
  1095. AffineMatrixTranslation(0.5, 0.5);
  1096. if (GetEditMode = esmShape) and Assigned(GetVectorOriginal.SelectedShape) then
  1097. result := GetShapeStatusText(GetVectorOriginal.SelectedShape, m) else
  1098. if (GetEditMode = esmSelection) and Assigned(FSelectionRect) then
  1099. result := GetShapeStatusText(FSelectionRect, AffineMatrixIdentity) else
  1100. if (GetEditMode = esmOtherOriginal) and Assigned(FOriginalRect) then
  1101. result := GetShapeStatusText(FOriginalRect, AffineMatrixIdentity) else
  1102. if (GetEditMode = esmGradient) then
  1103. result := GetGradientStatusText(GetGradientOriginal, m) else
  1104. Result:=inherited GetStatusText;
  1105. end;
  1106. constructor TEditShapeTool.Create(AManager: TToolManager);
  1107. var
  1108. orig: TVectorOriginal;
  1109. begin
  1110. inherited Create(AManager);
  1111. FRectEditor := nil;
  1112. FSelectionRect := nil;
  1113. FOriginalRect := nil;
  1114. FIsEditingGradient:= false;
  1115. FLeftButton:= false;
  1116. FRightButton:= false;
  1117. if GetCurrentLayerKind = lkVectorial then
  1118. orig := GetVectorOriginal
  1119. else orig := nil;
  1120. if not Manager.Image.SelectionMaskEmpty then
  1121. begin
  1122. if Assigned(orig) and Assigned(orig.SelectedShape) then
  1123. orig.DeselectShapes;
  1124. DoEditSelection;
  1125. end else
  1126. if Assigned(orig) and Assigned(orig.SelectedShape) then
  1127. UpdateToolManagerFromShape(orig.SelectedShape);
  1128. end;
  1129. function TEditShapeTool.DoToolKeyDown(var key: Word): TRect;
  1130. var
  1131. handled: boolean;
  1132. keyUtf8: TUTF8Char;
  1133. diff: TComposedImageDifference;
  1134. begin
  1135. Result:= EmptyRect;
  1136. if (Key = VK_SPACE) and (GetEditMode = esmShape) and (GetVectorOriginal.SelectedShape is TTextShape) then
  1137. begin
  1138. keyUtf8:= ' ';
  1139. result := ToolKeyPress(keyUtf8);
  1140. Key := 0;
  1141. end else
  1142. begin
  1143. if GetEditMode in [esmShape,esmNoShape] then
  1144. begin
  1145. BindOriginalEvent(true);
  1146. try
  1147. Manager.Image.CurrentState.LayeredBitmap.KeyDown(ShiftState, LCLKeyToSpecialKey(key, ShiftState), handled);
  1148. if handled then key := 0 else
  1149. begin
  1150. if (key = VK_DELETE) and Assigned(GetVectorOriginal.SelectedShape) then
  1151. begin
  1152. diff := Manager.Image.DoBegin;
  1153. try
  1154. GetVectorOriginal.RemoveShape(GetVectorOriginal.SelectedShape);
  1155. finally
  1156. Manager.Image.DoEnd(diff);
  1157. end;
  1158. key := 0;
  1159. end else
  1160. if (key = VK_ESCAPE) and Assigned(GetVectorOriginal.SelectedShape) then
  1161. begin
  1162. if GetVectorOriginal.SelectedShape.Usermode = vsuEditText then
  1163. GetVectorOriginal.SelectedShape.Usermode := vsuEdit
  1164. else
  1165. GetVectorOriginal.DeselectShapes;
  1166. key := 0;
  1167. end;
  1168. end;
  1169. finally
  1170. BindOriginalEvent(false);
  1171. end;
  1172. end else
  1173. begin
  1174. if (Key = VK_DELETE) and (GetEditMode in [esmGradient,esmOtherOriginal]) then
  1175. begin
  1176. StopEdit(true, true);
  1177. Manager.Image.ClearLayer;
  1178. Key := 0;
  1179. end else
  1180. if key = VK_RETURN then
  1181. begin
  1182. if IsEditing then
  1183. begin
  1184. StopEdit(true, true);
  1185. key := 0;
  1186. end;
  1187. end;
  1188. end;
  1189. end;
  1190. end;
  1191. function TEditShapeTool.ToolKeyPress(var key: TUTF8Char): TRect;
  1192. var
  1193. handled: boolean;
  1194. keyCode: word;
  1195. begin
  1196. Result:= EmptyRect;
  1197. if GetEditMode in [esmShape,esmNoShape] then
  1198. begin
  1199. if Assigned(GetVectorOriginal.SelectedShape) and
  1200. (GetVectorOriginal.SelectedShape is TCustomPolypointShape) and
  1201. ((Key='i') or (Key='I')) then
  1202. begin
  1203. keyCode := VK_INSERT;
  1204. ToolKeyDown(keyCode);
  1205. if keyCode = 0 then key := #0;
  1206. keyCode := VK_INSERT;
  1207. ToolKeyUp(keyCode);
  1208. result := EmptyRect;
  1209. end else
  1210. begin
  1211. BindOriginalEvent(true);
  1212. try
  1213. Manager.Image.CurrentState.LayeredBitmap.KeyPress(key, handled);
  1214. if handled then key := #0;
  1215. finally
  1216. BindOriginalEvent(false);
  1217. end;
  1218. end;
  1219. end;
  1220. end;
  1221. function TEditShapeTool.DoToolKeyUp(var key: Word): TRect;
  1222. var
  1223. handled: boolean;
  1224. begin
  1225. Result:= EmptyRect;
  1226. if GetEditMode in [esmShape,esmNoShape] then
  1227. begin
  1228. BindOriginalEvent(true);
  1229. try
  1230. Manager.Image.CurrentState.LayeredBitmap.KeyUp(ShiftState, LCLKeyToSpecialKey(key, ShiftState), handled);
  1231. if handled then key := 0;
  1232. finally
  1233. BindOriginalEvent(false);
  1234. end;
  1235. end;
  1236. end;
  1237. function TEditShapeTool.ToolUp: TRect;
  1238. var
  1239. cur: TOriginalEditorCursor;
  1240. handled: boolean;
  1241. m: TAffineMatrix;
  1242. ptView, ptSel: TPointF;
  1243. zoom: Single;
  1244. begin
  1245. Result:= EmptyRect;
  1246. if FLeftButton or FRightButton then
  1247. begin
  1248. handled := false;
  1249. if not handled and FRectEditorCapture and Assigned(FRectEditor) then
  1250. begin
  1251. ptView := FRectEditor.Matrix*FLastPos;
  1252. UpdateSnap(FRectEditor);
  1253. FRectEditor.MouseUp(FRightButton, ShiftState, ptView.X,ptView.Y, cur, handled);
  1254. Cursor := OriginalCursorToCursor(cur);
  1255. if handled then
  1256. begin
  1257. result := OnlyRenderChange;
  1258. UpdateMatrixFromRect;
  1259. end else
  1260. begin
  1261. StopEdit(False, False);
  1262. result := OnlyRenderChange;
  1263. end;
  1264. end;
  1265. if not handled and FLayerOriginalCapture and (GetEditMode in [esmGradient, esmShape, esmNoShape]) then
  1266. begin
  1267. BindOriginalEvent(true);
  1268. try
  1269. Manager.Image.CurrentState.LayeredBitmap.MouseUp(FRightButton, ShiftState, FLastPos.X,FLastPos.Y, cur, handled);
  1270. if handled then
  1271. begin
  1272. Cursor := OriginalCursorToCursor(cur);
  1273. result := OnlyRenderChange;
  1274. end;
  1275. finally
  1276. BindOriginalEvent(false);
  1277. end;
  1278. end;
  1279. if not handled and not Manager.Image.SelectionMaskEmpty then
  1280. begin
  1281. ptSel := AffineMatrixInverse(Manager.Image.SelectionTransform)*FLastPos;
  1282. if (Manager.Image.SelectionMaskReadonly.GetPixel(ptSel.x,ptSel.y).green > 0) then
  1283. begin
  1284. if GetEditMode <> esmSelection then
  1285. begin
  1286. StopEdit(false, false);
  1287. DoEditSelection;
  1288. result := OnlyRenderChange;
  1289. end;
  1290. handled := true;
  1291. end else
  1292. if GetEditMode = esmSelection then
  1293. begin
  1294. StopEdit(false, false);
  1295. result := OnlyRenderChange;
  1296. end;
  1297. end;
  1298. if not handled then
  1299. begin
  1300. case GetEditMode of
  1301. esmShape, esmNoShape:
  1302. if not FDownHandled then
  1303. begin
  1304. m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
  1305. zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2/Manager.Image.ZoomFactor;
  1306. BindOriginalEvent(true);
  1307. try
  1308. if GetVectorOriginal.MouseClick(m*FLastPos, DoScaleX(PointSize*Manager.CanvasScale, OriginalDPI)*zoom, ssSnap in ShiftState) then
  1309. begin
  1310. handled := true;
  1311. result := OnlyRenderChange;
  1312. end;
  1313. finally
  1314. BindOriginalEvent(false);
  1315. end;
  1316. end;
  1317. esmGradient:
  1318. begin
  1319. FIsEditingGradient:= false;
  1320. result := OnlyRenderChange;
  1321. end;
  1322. end;
  1323. end;
  1324. if not handled and (GetCurrentLayerKind in [lkBitmap, lkTransformedBitmap, lkSVG, lkOther]) and
  1325. (Manager.Image.CurrentLayerReadOnly.GetPixel(FLastPos.X-LayerOffset.X, FLastPos.Y-LayerOffset.Y).alpha <> 0) then
  1326. begin
  1327. if GetEditMode <> esmOtherOriginal then
  1328. begin
  1329. StopEdit(false, false);
  1330. MakeImageOriginal;
  1331. if GetCurrentLayerKind in [lkTransformedBitmap, lkSVG, lkOther] then
  1332. begin
  1333. with Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex].
  1334. GetRenderBounds(InfiniteRect, AffineMatrixIdentity) do
  1335. FOriginalRectUntransformed := rectF(Left-0.5, Top-0.5, Right-0.5, Bottom-0.5);
  1336. FOriginalRect := CreateRect(FOriginalRectUntransformed,
  1337. Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
  1338. FOriginalLayerId:= Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
  1339. result := OnlyRenderChange;
  1340. end;
  1341. end;
  1342. handled := true;
  1343. end;
  1344. if not handled and (GetCurrentLayerKind = lkGradient) then
  1345. begin
  1346. if not FIsEditingGradient then
  1347. begin
  1348. FIsEditingGradient:= true;
  1349. Manager.BackFill.SetGradient(GetGradientOriginal, false);
  1350. Manager.UpdateContextualToolbars;
  1351. handled := true;
  1352. result := OnlyRenderChange;
  1353. end;
  1354. end;
  1355. FLeftButton:= false;
  1356. FRightButton:= false;
  1357. if Manager.Image.DraftOriginal then
  1358. UpdateDraftMode;
  1359. end;
  1360. end;
  1361. function TEditShapeTool.ToolCommand(ACommand: TToolCommand): boolean;
  1362. var
  1363. key: Word;
  1364. b: TRect;
  1365. bmp: TBGRABitmap;
  1366. s: TRectShape;
  1367. diff: TComposedImageDifference;
  1368. begin
  1369. if not ToolProvideCommand(ACommand) then exit(false);
  1370. if ACommand = tcDelete then
  1371. begin
  1372. key := VK_DELETE;
  1373. ToolKeyDown(key);
  1374. if key = 0 then
  1375. begin
  1376. key := VK_DELETE;
  1377. ToolKeyUp(key);
  1378. result := true;
  1379. end else
  1380. result := false;
  1381. end else
  1382. if ACommand = tcPaste then
  1383. begin
  1384. result := false;
  1385. MakeVectorOriginal;
  1386. if GetCurrentLayerKind = lkVectorial then
  1387. begin
  1388. BindOriginalEvent(true);
  1389. try
  1390. PasteShapesFromClipboard(GetVectorOriginal, GetOriginalTransform, Manager.Image.VisibleArea);
  1391. finally
  1392. BindOriginalEvent(false);
  1393. end;
  1394. result := true;
  1395. end;
  1396. end else
  1397. begin
  1398. result := true;
  1399. case GetEditMode of
  1400. esmShape:
  1401. try
  1402. BindOriginalEvent(true);
  1403. case ACommand of
  1404. tcMoveUp: GetVectorOriginal.SelectedShape.MoveUp(true);
  1405. tcMoveToFront: GetVectorOriginal.SelectedShape.BringToFront;
  1406. tcMoveDown: GetVectorOriginal.SelectedShape.MoveDown(true);
  1407. tcMoveToBack: GetVectorOriginal.SelectedShape.SendToBack;
  1408. tcCopy: Result:= CopyShapesToClipboard([GetVectorOriginal.SelectedShape], GetOriginalTransform);
  1409. tcCut: begin
  1410. result := CopyShapesToClipboard([GetVectorOriginal.SelectedShape], GetOriginalTransform);
  1411. if result then
  1412. begin
  1413. diff := Manager.Image.DoBegin;
  1414. try
  1415. GetVectorOriginal.RemoveShape(GetVectorOriginal.SelectedShape);
  1416. finally
  1417. Manager.Image.DoEnd(diff);
  1418. end;
  1419. end;
  1420. end;
  1421. tcAlignLeft..tcAlignBottom: AlignShape(GetVectorOriginal.SelectedShape, ACommand,
  1422. Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex],
  1423. rect(0,0,Manager.Image.Width,Manager.Image.Height));
  1424. tcForeEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = ForeGradTexMode then
  1425. GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
  1426. GetVectorOriginal.SelectedShape.Usermode := ForeGradTexMode;
  1427. tcBackEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = BackGradTexMode then
  1428. GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
  1429. GetVectorOriginal.SelectedShape.Usermode := BackGradTexMode;
  1430. tcOutlineEditGradTexPoints: if GetVectorOriginal.SelectedShape.Usermode = OutlineGradTexMode then
  1431. GetVectorOriginal.SelectedShape.Usermode := vsuEdit else
  1432. GetVectorOriginal.SelectedShape.Usermode := OutlineGradTexMode;
  1433. tcForeAdjustToShape: GetVectorOriginal.SelectedShape.PenFill.FitGeometry(SuggestGradientBox);
  1434. tcBackAdjustToShape: GetVectorOriginal.SelectedShape.BackFill.FitGeometry(SuggestGradientBox);
  1435. tcOutlineAdjustToShape: GetVectorOriginal.SelectedShape.OutlineFill.FitGeometry(SuggestGradientBox);
  1436. tcShapeToSpline: result := ConvertToSpline;
  1437. else result := false;
  1438. end;
  1439. finally
  1440. BindOriginalEvent(false);
  1441. end;
  1442. esmGradient:
  1443. begin
  1444. case ACommand of
  1445. tcBackAdjustToShape: GetGradientOriginal.FitGeometry(SuggestGradientBox);
  1446. tcCut,tcCopy: begin
  1447. s := TRectShape.Create(nil);
  1448. try
  1449. s.PenStyle := ClearPenStyle;
  1450. s.QuickDefine(PointF(-0.5,-0.5),PointF(Manager.Image.Width-0.5,Manager.Image.Height-0.5));
  1451. s.BackFill.SetGradient(GetGradientOriginal, false);
  1452. s.BackFill.Transform(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
  1453. CopyShapesToClipboard([s],AffineMatrixIdentity);
  1454. finally
  1455. s.free;
  1456. end;
  1457. if ACommand = tcCut then ToolCommand(tcDelete);
  1458. end;
  1459. else result := false;
  1460. end;
  1461. end;
  1462. esmOtherOriginal:
  1463. begin
  1464. case ACommand of
  1465. tcCut,tcCopy: begin
  1466. b := Manager.Image.CurrentLayerReadOnly.GetImageBounds;
  1467. if not b.IsEmpty then
  1468. begin
  1469. if GetCurrentLayerKind = lkTransformedBitmap then
  1470. begin
  1471. bmp := GetImageOriginal.GetImageCopy;
  1472. s:= TRectShape.Create(nil);
  1473. s.QuickDefine(PointF(-0.5,-0.5),PointF(bmp.Width-0.5,bmp.Height-0.5));
  1474. s.PenStyle := ClearPenStyle;
  1475. s.BackFill.SetTexture(bmp,AffineMatrixIdentity,255,trNone);
  1476. s.Transform(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
  1477. bmp.FreeReference;
  1478. end else
  1479. begin
  1480. bmp := Manager.Image.CurrentLayerReadOnly.GetPart(b) as TBGRABitmap;
  1481. s:= TRectShape.Create(nil);
  1482. s.QuickDefine(PointF(b.Left-0.5,b.Top-0.5),PointF(b.Right-0.5,b.Bottom-0.5));
  1483. s.PenStyle := ClearPenStyle;
  1484. s.BackFill.SetTexture(bmp,AffineMatrixTranslation(b.Left,b.Top),255,trNone);
  1485. with Manager.Image.LayerOffset[Manager.Image.CurrentLayerIndex] do
  1486. s.Transform(AffineMatrixTranslation(x,y));
  1487. bmp.FreeReference;
  1488. end;
  1489. try
  1490. CopyShapesToClipboard([s],AffineMatrixIdentity);
  1491. finally
  1492. s.Free;
  1493. end;
  1494. if ACommand = tcCut then ToolCommand(tcDelete);
  1495. end;
  1496. end;
  1497. tcAlignLeft..tcAlignBottom:
  1498. begin
  1499. AlignShape(FOriginalRect, ACommand,
  1500. AffineMatrixIdentity,rect(0,0,Manager.Image.Width,Manager.Image.Height));
  1501. UpdateMatrixFromRect;
  1502. end
  1503. else result := false;
  1504. end;
  1505. end;
  1506. esmSelection:
  1507. begin
  1508. if ACommand in [tcAlignLeft..tcAlignBottom] then
  1509. begin
  1510. AlignShape(FSelectionRect, ACommand,
  1511. AffineMatrixIdentity,rect(0,0,Manager.Image.Width,Manager.Image.Height));
  1512. UpdateMatrixFromRect;
  1513. end;
  1514. end;
  1515. end;
  1516. end;
  1517. end;
  1518. function TEditShapeTool.ToolProvideCommand(ACommand: TToolCommand): boolean;
  1519. begin
  1520. case ACommand of
  1521. tcCut,tcCopy,tcDelete: result:= GetEditMode in [esmShape,esmOtherOriginal,esmGradient];
  1522. tcForeAdjustToShape,tcOutlineAdjustToShape: result := GetEditMode = esmShape;
  1523. tcBackAdjustToShape: result := GetEditMode in [esmShape,esmGradient];
  1524. tcForeEditGradTexPoints: result := (GetEditMode = esmShape) and
  1525. (ForeGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
  1526. tcBackEditGradTexPoints: result := (GetEditMode = esmShape) and
  1527. (BackGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
  1528. tcOutlineEditGradTexPoints: result := (GetEditMode = esmShape) and
  1529. (OutlineGradTexMode in GetVectorOriginal.SelectedShape.MultiUsermodes);
  1530. tcShapeToSpline: result:= (GetEditMode = esmShape)
  1531. and TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape);
  1532. tcAlignLeft..tcAlignBottom: result:= GetEditMode in [esmShape, esmOtherOriginal, esmSelection];
  1533. tcPaste: result := ClipboardHasShapes and (GetCurrentLayerKind in [lkEmpty,lkBitmap,lkTransformedBitmap,lkVectorial]);
  1534. tcMoveUp,tcMoveToFront: result := (GetEditMode = esmShape)
  1535. and not GetVectorOriginal.SelectedShape.IsFront;
  1536. tcMoveDown,tcMoveToBack: result := (GetEditMode = esmShape)
  1537. and not GetVectorOriginal.SelectedShape.IsBack;
  1538. else
  1539. result := false;
  1540. end;
  1541. end;
  1542. function TEditShapeTool.SuggestGradientBox: TAffineBox;
  1543. begin
  1544. if GetEditMode = esmShape then
  1545. result := GetVectorOriginal.SelectedShape.SuggestGradientBox(AffineMatrixIdentity)
  1546. else
  1547. result:= inherited SuggestGradientBox;
  1548. end;
  1549. { TVectorialTool }
  1550. procedure TVectorialTool.ShapeChange(ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff);
  1551. var
  1552. toolDest: TBGRABitmap;
  1553. r: TRect;
  1554. matrix: TAffineMatrix;
  1555. begin
  1556. if isEmptyPointF(ABounds.TopLeft) or isEmptyPointF(ABounds.BottomRight) then
  1557. raise exception.Create('Unexpected empty point');
  1558. toolDest := GetToolDrawingLayer;
  1559. matrix := VectorTransform(false);
  1560. r := (matrix*TAffineBox.AffineBox(ABounds)).RectBounds;
  1561. UpdateShape(toolDest);
  1562. Action.NotifyChange(toolDest, r);
  1563. with FShape.GetRenderBounds(rect(0,0,toolDest.Width,toolDest.Height),matrix,[]) do
  1564. FPreviousUpdateBounds := rect(floor(Left),floor(Top),ceil(Right),ceil(Bottom));
  1565. if r.IsEmpty then ShapeEditingChange(ASender);
  1566. ADiff.Free;
  1567. end;
  1568. procedure TVectorialTool.ShapeEditingChange(ASender: TObject);
  1569. var
  1570. toolDest: TBGRABitmap;
  1571. newEditorBounds, r: TRect;
  1572. begin
  1573. toolDest := GetToolDrawingLayer;
  1574. with (Editor.Matrix*PointF(toolDest.Width,toolDest.Height)) do
  1575. newEditorBounds := Editor.GetRenderBounds(rect(0,0,ceil(x),ceil(y)));
  1576. r := RectUnion(FPreviousEditorBounds,newEditorBounds);
  1577. if not r.IsEmpty then
  1578. Manager.Image.RenderMayChange(r,false);
  1579. FPreviousEditorBounds := newEditorBounds;
  1580. end;
  1581. procedure TVectorialTool.ShapeRemoveQuery(ASender: TObject;
  1582. var AHandled: boolean);
  1583. var
  1584. r: TRect;
  1585. toolDest: TBGRABitmap;
  1586. begin
  1587. if ASender <> FShape then exit;
  1588. AHandled := true;
  1589. toolDest := GetToolDrawingLayer;
  1590. r := CancelShape;
  1591. Action.NotifyChange(toolDest, r);
  1592. end;
  1593. function TVectorialTool.GetStatusText: string;
  1594. begin
  1595. if Assigned(FShape) then
  1596. result := GetShapeStatusText(FShape, VectorTransform(True))
  1597. else Result:=inherited GetStatusText;
  1598. end;
  1599. function TVectorialTool.SlowShape: boolean;
  1600. begin
  1601. if Assigned(FShape) then
  1602. result := FShape.GetIsSlow(VectorTransform(false))
  1603. else
  1604. result := false;
  1605. end;
  1606. procedure TVectorialTool.QuickDefineEnd;
  1607. begin
  1608. //nothing
  1609. end;
  1610. procedure TVectorialTool.OnTryStop(sender: TCustomLayerAction);
  1611. begin
  1612. ValidateShape;
  1613. end;
  1614. procedure TVectorialTool.UpdateUseOriginal;
  1615. begin
  1616. if not IsSelectingTool and Manager.Image.SelectionMaskEmpty and
  1617. (GetCurrentLayerKind = lkVectorial) then
  1618. FUseOriginal:= true
  1619. else
  1620. FUseOriginal:= false;
  1621. end;
  1622. function TVectorialTool.ReplaceLayerAndAddShape(out ARect: TRect): TCustomImageDifference;
  1623. var
  1624. transf: TAffineMatrix;
  1625. diff: TComposedImageDifference;
  1626. replaceDiff: TReplaceLayerByVectorOriginalDifference;
  1627. layerId: integer;
  1628. addDiff: TAddShapeToVectorOriginalDifference;
  1629. begin
  1630. layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
  1631. transf := VectorTransform(false);
  1632. diff := TComposedImageDifference.Create;
  1633. replaceDiff := TReplaceLayerByVectorOriginalDifference.Create(Manager.Image.CurrentState,Manager.Image.CurrentLayerIndex,
  1634. GetCurrentLayerKind = lkVectorial);
  1635. diff.Add(replaceDiff);
  1636. transf := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex])*transf;
  1637. FShape.Transform(transf);
  1638. addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
  1639. diff.Add(addDiff);
  1640. result := diff;
  1641. ARect := addDiff.ChangingBounds;
  1642. FShape := nil;
  1643. end;
  1644. procedure TVectorialTool.ShapeValidated;
  1645. begin
  1646. //nothing
  1647. end;
  1648. function TVectorialTool.ForeGradTexMode: TVectorShapeUsermode;
  1649. begin
  1650. if Assigned(FShape) and FSwapColor then
  1651. begin
  1652. if vsfBackFill in FShape.Fields then
  1653. result := vsuEditBackFill
  1654. else if vsfOutlineFill in FShape.Fields then
  1655. result := vsuEditOutlineFill
  1656. else
  1657. result := vsuEditPenFill;
  1658. end else
  1659. result := vsuEditPenFill;
  1660. end;
  1661. function TVectorialTool.BackGradTexMode: TVectorShapeUsermode;
  1662. begin
  1663. if Assigned(FShape) and FSwapColor and (vsfPenFill in FShape.Fields) then
  1664. result := vsuEditPenFill
  1665. else
  1666. result := vsuEditBackFill;
  1667. end;
  1668. function TVectorialTool.OutlineGradTexMode: TVectorShapeUsermode;
  1669. begin
  1670. if Assigned(FShape) and FSwapColor and ([vsfPenFill,vsfBackFill]*FShape.Fields = [vsfPenFill]) then
  1671. result := vsuEditPenFill
  1672. else
  1673. result := vsuEditOutlineFill;
  1674. end;
  1675. function TVectorialTool.ForeFitMode: TFitMode;
  1676. begin
  1677. if IsForeEditGradTexPoints then result := fmNever
  1678. else result := fmIfChange;
  1679. end;
  1680. function TVectorialTool.BackFitMode: TFitMode;
  1681. begin
  1682. if IsBackEditGradTexPoints then result := fmNever
  1683. else result := fmIfChange;
  1684. end;
  1685. function TVectorialTool.OutlineFitMode: TFitMode;
  1686. begin
  1687. if IsOutlineEditGradTexPoints then result := fmNever
  1688. else result := fmIfChange;
  1689. end;
  1690. function TVectorialTool.ManagerForeFill: TVectorialFill;
  1691. begin
  1692. if Assigned(FShape) and FSwapColor then
  1693. begin
  1694. if vsfBackFill in FShape.Fields then
  1695. result := Manager.BackFill
  1696. else if vsfOutlineFill in FShape.Fields then
  1697. result := Manager.OutlineFill
  1698. else
  1699. result := Manager.ForeFill;
  1700. end else
  1701. result := Manager.ForeFill;
  1702. end;
  1703. function TVectorialTool.ManagerBackFill: TVectorialFill;
  1704. begin
  1705. if Assigned(FShape) and FSwapColor and (vsfPenFill in FShape.Fields) then
  1706. result := Manager.ForeFill
  1707. else
  1708. result := Manager.BackFill;
  1709. end;
  1710. function TVectorialTool.ManagerOutlineFill: TVectorialFill;
  1711. begin
  1712. if Assigned(FShape) and FSwapColor and ([vsfPenFill,vsfBackFill]*FShape.Fields = [vsfPenFill]) then
  1713. result := Manager.ForeFill
  1714. else
  1715. result := Manager.OutlineFill;
  1716. end;
  1717. function TVectorialTool.GetIsForeEditGradTexPoints: boolean;
  1718. begin
  1719. result := Assigned(FShape) and (FShape.Usermode = ForeGradTexMode);
  1720. end;
  1721. function TVectorialTool.GetIsBackEditGradTexPoints: boolean;
  1722. begin
  1723. result := Assigned(FShape) and (FShape.Usermode = BackGradTexMode);
  1724. end;
  1725. function TVectorialTool.GetIsOutlineEditGradTexPoints: boolean;
  1726. begin
  1727. result := Assigned(FShape) and (FShape.Usermode = OutlineGradTexMode);
  1728. end;
  1729. function TVectorialTool.GetGridMatrix: TAffineMatrix;
  1730. begin
  1731. if Manager.Image.ZoomFactor > DoScaleX(35, OriginalDPI)/10 then
  1732. result := AffineMatrixScale(0.5,0.5)
  1733. else
  1734. begin
  1735. if Assigned(FShape) and
  1736. (not (vsfPenFill in FShape.MultiFields) or
  1737. (FShape.PenFill.IsFullyTransparent)) then
  1738. result := AffineMatrixTranslation(0.5, 0.5)
  1739. else
  1740. result := AffineMatrixIdentity;
  1741. end;
  1742. end;
  1743. function TVectorialTool.GetIsEditingText: boolean;
  1744. begin
  1745. Result:= assigned(FShape) and (FShape.Usermode = vsuEditText);
  1746. end;
  1747. class procedure TVectorialTool.ForgetHintShown;
  1748. begin
  1749. SquareHintShown:= false;
  1750. end;
  1751. function TVectorialTool.ValidateShape: TRect;
  1752. var
  1753. layerId: LongInt;
  1754. rF: TRectF;
  1755. changeBounds: TRect;
  1756. addDiff: TAddShapeToVectorOriginalDifference;
  1757. begin
  1758. if Assigned(FShape) then
  1759. begin
  1760. FShape.OnChange:= nil;
  1761. FShape.OnEditingChange:= nil;
  1762. FShape.OnRemoveQuery:= nil;
  1763. if not AlwaysRasterizeShape and Manager.Image.SelectionMaskEmpty then
  1764. begin
  1765. CancelAction;
  1766. if FShape.Usermode = vsuCreate then FShape.Usermode:= vsuEdit;
  1767. rF := FShape.GetRenderBounds(rect(0,0,Manager.Image.Width,Manager.Image.Height), VectorTransform(false));
  1768. if rF.IntersectsWith(rectF(0,0,Manager.Image.Width,Manager.Image.Height)) then
  1769. begin
  1770. if UseOriginal then
  1771. begin
  1772. layerId := Manager.Image.LayerId[Manager.Image.CurrentLayerIndex];
  1773. addDiff := TAddShapeToVectorOriginalDifference.Create(Manager.Image.CurrentState,layerId,FShape);
  1774. changeBounds := addDiff.ChangingBounds;
  1775. Manager.Image.AddUndo(addDiff);
  1776. FShape := nil;
  1777. end
  1778. else
  1779. Manager.Image.AddUndo(ReplaceLayerAndAddShape(changeBounds));
  1780. Manager.Image.ImageMayChange(changeBounds);
  1781. end;
  1782. ClearShape;
  1783. end else
  1784. begin
  1785. ValidateActionPartially;
  1786. ClearShape;
  1787. end;
  1788. Cursor := crDefault;
  1789. result := OnlyRenderChange;
  1790. UpdateUseOriginal;
  1791. ShapeValidated;
  1792. end else
  1793. result := EmptyRect;
  1794. end;
  1795. function TVectorialTool.CancelShape: TRect;
  1796. begin
  1797. CancelActionPartially;
  1798. ClearShape;
  1799. Cursor := crDefault;
  1800. result := OnlyRenderChange;
  1801. end;
  1802. function TVectorialTool.GetEditor: TBGRAOriginalEditor;
  1803. begin
  1804. FEditor.GridActive := ssSnap in ShiftState;
  1805. result := FEditor;
  1806. end;
  1807. function TVectorialTool.GetIsHandDrawing: boolean;
  1808. begin
  1809. result := Assigned(FShape) and (FQuickDefine or (FShape.Usermode = vsuCreate));
  1810. end;
  1811. function TVectorialTool.GetIsIdle: boolean;
  1812. begin
  1813. result := FShape = nil;
  1814. end;
  1815. function TVectorialTool.AlwaysRasterizeShape: boolean;
  1816. begin
  1817. result := false;
  1818. end;
  1819. function TVectorialTool.CreateShape: TVectorShape;
  1820. begin
  1821. result := ShapeClass.Create(nil);
  1822. end;
  1823. procedure TVectorialTool.ClearShape;
  1824. begin
  1825. FreeAndNil(FShape);
  1826. FreeAndNil(FTemporaryStorage);
  1827. Editor.Clear;
  1828. end;
  1829. function TVectorialTool.UseOriginal: boolean;
  1830. begin
  1831. result := FUseOriginal;
  1832. end;
  1833. function TVectorialTool.HasBrush: boolean;
  1834. begin
  1835. result := (toFillShape in GetManagerShapeOptions) or not (ctShape in GetContextualToolbars);
  1836. end;
  1837. function TVectorialTool.GetCustomShapeBounds(ADestBounds: TRect; AMatrix: TAffineMatrix; ADraft: boolean): TRect;
  1838. begin
  1839. with FShape.GetRenderBounds(ADestBounds,AMatrix,[]) do
  1840. result := rect(floor(Left),floor(Top),ceil(Right),ceil(Bottom));
  1841. end;
  1842. procedure TVectorialTool.DrawCustomShape(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean);
  1843. begin
  1844. FShape.Render(ADest,AMatrix,ADraft);
  1845. end;
  1846. procedure TVectorialTool.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
  1847. var
  1848. f: TVectorShapeFields;
  1849. zoom: Single;
  1850. gradBox: TAffineBox;
  1851. fitMode: TFitMode;
  1852. begin
  1853. zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
  1854. f := FShape.MultiFields;
  1855. gradBox := FShape.SuggestGradientBox(AffineMatrixIdentity);
  1856. if vsfAliased in f then
  1857. FShape.Aliased:= Manager.ShapeOptionAliasing;
  1858. if vsfPenFill in f then
  1859. begin
  1860. if HasPen then
  1861. begin
  1862. if AAlwaysFit then fitMode := fmAlways else fitMode := ForeFitMode;
  1863. AssignFill(FShape.PenFill, ManagerForeFill, gradBox, fitMode)
  1864. end else
  1865. FShape.PenFill.Clear;
  1866. end;
  1867. if vsfPenWidth in f then FShape.PenWidth := zoom*Manager.PenWidth;
  1868. if vsfPenStyle in f Then FShape.PenStyle := PenStyleToBGRA(Manager.PenStyle);
  1869. if vsfJoinStyle in f then FShape.JoinStyle:= Manager.JoinStyle;
  1870. if vsfBackFill in f then
  1871. begin
  1872. if HasBrush then
  1873. begin
  1874. if AAlwaysFit then fitMode := fmAlways else fitMode := BackFitMode;
  1875. AssignFill(FShape.BackFill, ManagerBackFill, gradBox, fitMode)
  1876. end else
  1877. FShape.BackFill.Clear;
  1878. end;
  1879. if vsfOutlineFill in f then
  1880. begin
  1881. if Manager.TextOutline then
  1882. begin
  1883. if AAlwaysFit then fitMode := fmAlways else fitMode := OutlineFitMode;
  1884. AssignFill(FShape.OutlineFill, ManagerOutlineFill, gradBox, fitMode);
  1885. end else
  1886. FShape.OutlineFill.Clear;
  1887. end;
  1888. if (vsfOutlineWidth in f) and Manager.TextOutline then
  1889. FShape.OutlineWidth := zoom*Manager.TextOutlineWidth;
  1890. end;
  1891. function TVectorialTool.GetManagerShapeOptions: TShapeOptions;
  1892. begin
  1893. result := Manager.ShapeOptions;
  1894. end;
  1895. procedure TVectorialTool.QuickDefineShape(AStart, AEnd: TPointF);
  1896. begin
  1897. FShape.QuickDefine(AStart, AEnd);
  1898. end;
  1899. function TVectorialTool.RoundCoordinate(constref ptF: TPointF): TPointF;
  1900. begin
  1901. if not (toDrawShape in GetManagerShapeOptions) or
  1902. (Assigned(FShape) and not (vsfPenFill in FShape.MultiFields)) then
  1903. result := PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5)
  1904. else
  1905. result := PointF(round(ptF.x),round(ptF.y));
  1906. end;
  1907. function TVectorialTool.GetIsSelectingTool: boolean;
  1908. begin
  1909. result := false;
  1910. end;
  1911. function TVectorialTool.UpdateShape(toolDest: TBGRABitmap): TRect;
  1912. var
  1913. newBounds: TRect;
  1914. oldClip: TRect;
  1915. matrix: TAffineMatrix;
  1916. begin
  1917. result := FPreviousUpdateBounds;
  1918. RestoreBackupDrawingLayer;
  1919. matrix := VectorTransform(false);
  1920. FLastDraftUpdate := PreferDraftUpdate;
  1921. newBounds := GetCustomShapeBounds(toolDest.ClipRect,matrix,FLastDraftUpdate);
  1922. result := RectUnion(result, newBounds);
  1923. oldClip := toolDest.IntersectClip(newBounds);
  1924. DrawCustomShape(toolDest,matrix,FLastDraftUpdate);
  1925. toolDest.ClipRect := oldClip;
  1926. FPreviousUpdateBounds := newBounds;
  1927. end;
  1928. function TVectorialTool.PreferDraftUpdate: boolean;
  1929. begin
  1930. if Assigned(FShape) then
  1931. result := (FEditor.IsMovingPoint or FShape.IsFollowingMouse or FQuickDefine) and SlowShape
  1932. else
  1933. result := false;
  1934. end;
  1935. function TVectorialTool.VectorTransform(APixelCentered: boolean): TAffineMatrix;
  1936. begin
  1937. if not UseOriginal then
  1938. result := AffineMatrixIdentity
  1939. else
  1940. result := Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex];
  1941. if APixelCentered then
  1942. result := MatrixForPixelCentered(result);
  1943. end;
  1944. procedure TVectorialTool.UpdateCursor(ACursor: TOriginalEditorCursor);
  1945. begin
  1946. Cursor := OriginalCursorToCursor(ACursor);
  1947. end;
  1948. function TVectorialTool.FixLayerOffset: boolean;
  1949. begin
  1950. Result:= false;
  1951. end;
  1952. function TVectorialTool.UpdateQuickDefine: TRect;
  1953. var
  1954. s: TPointF;
  1955. avg: single;
  1956. begin
  1957. if not Assigned(FShape) then exit(EmptyRect);
  1958. if ssShift in ShiftState then
  1959. begin
  1960. s := FQuickDefineUserEndPoint-FQuickDefineStartPoint;
  1961. avg := sqrt(abs(s.x*s.y));
  1962. if s.x > 0 then FQuickDefineEndPoint.x := FQuickDefineStartPoint.x + avg else FQuickDefineEndPoint.x := FQuickDefineStartPoint.x - avg;
  1963. if s.y > 0 then FQuickDefineEndPoint.y := FQuickDefineStartPoint.y + avg else FQuickDefineEndPoint.y := FQuickDefineStartPoint.y - avg;
  1964. end else
  1965. FQuickDefineEndPoint := FQuickDefineUserEndPoint;
  1966. FShape.BeginUpdate;
  1967. QuickDefineShape(FQuickDefineStartPoint, FQuickDefineEndPoint);
  1968. FLastShapeTransform := AffineMatrixInverse(VectorTransform(false));
  1969. FShape.Transform(FLastShapeTransform);
  1970. AssignShapeStyle(FLastShapeTransform, true);
  1971. FShape.EndUpdate;
  1972. result := OnlyRenderChange;
  1973. end;
  1974. function TVectorialTool.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
  1975. ptF: TPointF; rightBtn: boolean): TRect;
  1976. var
  1977. viewPt, shapePt: TPointF;
  1978. cur: TOriginalEditorCursor;
  1979. handled: boolean;
  1980. begin
  1981. result := EmptyRect;
  1982. FRightDown := rightBtn;
  1983. FLeftDown := not rightBtn;
  1984. with LayerOffset do
  1985. FLastPos := AffineMatrixTranslation(X,Y)*ptF;
  1986. if Assigned(FShape) then
  1987. begin
  1988. viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
  1989. Editor.MouseDown(rightBtn, ShiftState, viewPt.X,viewPt.Y, cur, handled);
  1990. if not handled and Assigned(FShape) then
  1991. begin
  1992. shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
  1993. If Editor.GridActive then shapePt := Editor.SnapToGrid(shapePt, false);
  1994. FShape.MouseDown(rightBtn, Editor.ConsecutiveClickCount, ShiftState, shapePt.X,shapePt.Y, cur, handled);
  1995. end;
  1996. UpdateCursor(cur);
  1997. if handled then exit
  1998. else result := RectUnion(result, ValidateShape);
  1999. end;
  2000. if FShape=nil then
  2001. begin
  2002. UpdateUseOriginal;
  2003. if UseOriginal and
  2004. ((Manager.Image.LayerOriginal[Manager.Image.CurrentLayerIndex] as TVectorOriginal).GetShapesCost >= MediumShapeCost) then
  2005. begin
  2006. MessagePopup(rsTooManyShapesInLayer, 3000);
  2007. end
  2008. else
  2009. if (GetCurrentLayerKind = lkSVG) and not IsSelectingTool then
  2010. begin
  2011. MessagePopup(rsCannotDrawShapeOnSVGLayer, 3000);
  2012. end
  2013. else
  2014. begin
  2015. toolDest := GetToolDrawingLayer;
  2016. FSwapColor:= rightBtn;
  2017. if IsSelectingTool then
  2018. FLayerWasEmpty := Manager.Image.SelectionMaskEmpty
  2019. else if Manager.Image.SelectionMaskEmpty then
  2020. FLayerWasEmpty := Manager.Image.CurrentLayerEmpty
  2021. else
  2022. FLayerWasEmpty := Manager.Image.SelectionLayerIsEmpty;
  2023. FShape := CreateShape;
  2024. if FTemporaryStorage = nil then FTemporaryStorage := TBGRAMemOriginalStorage.Create;
  2025. FShape.TemporaryStorage := FTemporaryStorage;
  2026. FQuickDefine := true;
  2027. FQuickDefineStartPoint := RoundCoordinate(FLastPos);
  2028. FQuickDefineUserEndPoint := FQuickDefineStartPoint;
  2029. FQuickDefineEndPoint := FQuickDefineStartPoint;
  2030. FShape.BeginUpdate;
  2031. QuickDefineShape(FQuickDefineStartPoint,FQuickDefineEndPoint);
  2032. FLastShapeTransform := AffineMatrixInverse(VectorTransform(false));
  2033. FShape.Transform(FLastShapeTransform);
  2034. shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
  2035. handled := false;
  2036. FShape.MouseMove(ShiftState, shapePt.X,shapePt.Y, cur, handled);
  2037. AssignShapeStyle(FLastShapeTransform, true);
  2038. FShape.EndUpdate;
  2039. FShape.OnChange:= @ShapeChange;
  2040. FShape.OnEditingChange:=@ShapeEditingChange;
  2041. FShape.OnRemoveQuery:= @ShapeRemoveQuery;
  2042. result := RectUnion(result, UpdateShape(toolDest));
  2043. if not SquareHintShown and (FShape is TCustomRectShape) then
  2044. begin
  2045. SquareHintShown := true;
  2046. Manager.ToolPopup(tpmHoldKeyForSquare, VK_SHIFT);
  2047. end;
  2048. end;
  2049. end;
  2050. end;
  2051. function TVectorialTool.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
  2052. ptF: TPointF): TRect;
  2053. var
  2054. viewPt, shapePt: TPointF;
  2055. handled: boolean;
  2056. cur: TOriginalEditorCursor;
  2057. begin
  2058. Editor.GridMatrix := GetGridMatrix;
  2059. with LayerOffset do
  2060. FLastPos := AffineMatrixTranslation(X,Y)*ptF;
  2061. if FQuickDefine then
  2062. begin
  2063. FQuickDefineUserEndPoint := RoundCoordinate(ptF);
  2064. result := UpdateQuickDefine;
  2065. end else
  2066. begin
  2067. viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
  2068. Editor.MouseMove(ShiftState, viewPt.X,viewPt.Y, cur, handled);
  2069. if not handled and Assigned(FShape) then
  2070. begin
  2071. shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
  2072. If Editor.GridActive then shapePt := Editor.SnapToGrid(shapePt, false);
  2073. FShape.MouseMove(ShiftState, shapePt.X,shapePt.Y, cur, handled);
  2074. end;
  2075. UpdateCursor(cur);
  2076. if handled then result := OnlyRenderChange
  2077. else result := EmptyRect;
  2078. end;
  2079. end;
  2080. function TVectorialTool.DoToolUpdate(toolDest: TBGRABitmap): TRect;
  2081. begin
  2082. if Assigned(FShape) then
  2083. begin
  2084. FShape.BeginUpdate;
  2085. AssignShapeStyle(FLastShapeTransform, false);
  2086. FShape.EndUpdate;
  2087. end;
  2088. result := EmptyRect;
  2089. end;
  2090. constructor TVectorialTool.Create(AManager: TToolManager);
  2091. begin
  2092. inherited Create(AManager);
  2093. UpdateUseOriginal;
  2094. FPreviousUpdateBounds := EmptyRect;
  2095. FEditor := TVectorOriginalEditor.Create(nil);
  2096. FEditor.GridMatrix := GetGridMatrix;
  2097. FEditor.Focused := true;
  2098. FPreviousEditorBounds := EmptyRect;
  2099. FLastShapeTransform := AffineMatrixIdentity;
  2100. FTemporaryStorage := TBGRAMemOriginalStorage.Create;
  2101. end;
  2102. function TVectorialTool.ToolUp: TRect;
  2103. var
  2104. viewPt, shapePt: TPointF;
  2105. cur: TOriginalEditorCursor;
  2106. handled, wasRight: boolean;
  2107. begin
  2108. wasRight := FRightDown;
  2109. FRightDown := false;
  2110. FLeftDown := false;
  2111. if FQuickDefine then
  2112. begin
  2113. FQuickDefine := false;
  2114. result := EmptyRect;
  2115. QuickDefineEnd;
  2116. end else
  2117. begin
  2118. viewPt := Editor.Matrix*AffineMatrixInverse(VectorTransform(true))*FLastPos;
  2119. Editor.MouseUp(wasRight, ShiftState, viewPt.X,viewPt.Y, cur, handled);
  2120. if not handled and Assigned(FShape) then
  2121. begin
  2122. shapePt := AffineMatrixInverse(VectorTransform(true))*FLastPos;
  2123. FShape.MouseUp(wasRight, ShiftState, shapePt.X,shapePt.Y, cur, handled);
  2124. end;
  2125. UpdateCursor(cur);
  2126. result := EmptyRect;
  2127. end;
  2128. if (FLastDraftUpdate and not PreferDraftUpdate) and Assigned(FShape) then
  2129. result := UpdateShape(GetToolDrawingLayer);
  2130. end;
  2131. function TVectorialTool.DoToolKeyDown(var key: Word): TRect;
  2132. var
  2133. handled: boolean;
  2134. begin
  2135. result := EmptyRect;
  2136. if (Key = VK_RETURN) and not FQuickDefine and
  2137. Assigned(FShape) then
  2138. begin
  2139. result := ValidateShape;
  2140. Key := 0;
  2141. end else
  2142. if (Key = VK_ESCAPE) and not FQuickDefine and
  2143. Assigned(FShape) then
  2144. begin
  2145. result := CancelShape;
  2146. Key := 0;
  2147. end else
  2148. if (Key = VK_SHIFT) and FQuickDefine and Assigned(FShape) then
  2149. begin
  2150. result := UpdateQuickDefine;
  2151. Key := 0;
  2152. end else
  2153. begin
  2154. Editor.KeyDown(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
  2155. if not handled and Assigned(FShape) then FShape.KeyDown(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
  2156. if handled then Key := 0;
  2157. end;
  2158. end;
  2159. function TVectorialTool.ToolKeyPress(var key: TUTF8Char): TRect;
  2160. var
  2161. handled: boolean;
  2162. begin
  2163. result := EmptyRect;
  2164. Editor.KeyPress(key, handled);
  2165. if not handled and Assigned(FShape) then FShape.KeyPress(key, handled);
  2166. if handled then Key := #0;
  2167. end;
  2168. function TVectorialTool.DoToolKeyUp(var key: Word): TRect;
  2169. var
  2170. handled: boolean;
  2171. begin
  2172. result := EmptyRect;
  2173. if (Key = VK_SHIFT) and FQuickDefine and Assigned(FShape) then
  2174. begin
  2175. result := UpdateQuickDefine;
  2176. Key := 0;
  2177. end else
  2178. begin
  2179. Editor.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
  2180. if not handled and Assigned(FShape) then FShape.KeyUp(ShiftState, LCLKeyToSpecialKey(Key, ShiftState), handled);
  2181. if handled then Key := 0;
  2182. end;
  2183. end;
  2184. function TVectorialTool.ToolCommand(ACommand: TToolCommand): boolean;
  2185. var
  2186. r: TRect;
  2187. toolDest: TBGRABitmap;
  2188. begin
  2189. result := false;
  2190. case ACommand of
  2191. tcCopy:
  2192. if ToolProvideCommand(tcCopy) then
  2193. result := CopyShapesToClipboard([FShape], VectorTransform(false));
  2194. tcCut:
  2195. if ToolCommand(tcCopy) then
  2196. begin
  2197. toolDest := GetToolDrawingLayer;
  2198. r := CancelShape;
  2199. Action.NotifyChange(toolDest, r);
  2200. result := true;
  2201. end;
  2202. tcForeAdjustToShape: if Assigned(FShape) then FShape.PenFill.FitGeometry(SuggestGradientBox);
  2203. tcBackAdjustToShape: if Assigned(FShape) then FShape.BackFill.FitGeometry(SuggestGradientBox);
  2204. tcOutlineAdjustToShape: if Assigned(FShape) then FShape.OutlineFill.FitGeometry(SuggestGradientBox);
  2205. tcForeEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
  2206. begin
  2207. if FShape.Usermode = ForeGradTexMode then
  2208. FShape.Usermode := vsuEdit else
  2209. FShape.Usermode := ForeGradTexMode;
  2210. end;
  2211. tcBackEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
  2212. begin
  2213. if FShape.Usermode = BackGradTexMode then
  2214. FShape.Usermode := vsuEdit else
  2215. FShape.Usermode := BackGradTexMode;
  2216. end;
  2217. tcOutlineEditGradTexPoints: if Assigned(FShape) and not FQuickDefine then
  2218. begin
  2219. if FShape.Usermode = OutlineGradTexMode then
  2220. FShape.Usermode := vsuEdit else
  2221. FShape.Usermode := OutlineGradTexMode;
  2222. end;
  2223. tcFinish: begin
  2224. toolDest := GetToolDrawingLayer;
  2225. r := ValidateShape;
  2226. Action.NotifyChange(toolDest, r);
  2227. result := true;
  2228. end;
  2229. tcAlignLeft..tcAlignBottom:
  2230. if ToolProvideCommand(ACommand) then
  2231. begin
  2232. AlignShape(FShape, ACommand,
  2233. Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex],
  2234. rect(0,0,Manager.Image.Width,Manager.Image.Height));
  2235. result := true;
  2236. end;
  2237. else
  2238. result := false;
  2239. end;
  2240. end;
  2241. function TVectorialTool.ToolProvideCommand(ACommand: TToolCommand): boolean;
  2242. begin
  2243. case ACommand of
  2244. tcCopy,tcCut: Result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape);
  2245. tcFinish: result := not IsIdle;
  2246. tcForeAdjustToShape, tcBackAdjustToShape, tcOutlineAdjustToShape:
  2247. result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine;
  2248. tcForeEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
  2249. (ForeGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
  2250. tcBackEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
  2251. (BackGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
  2252. tcOutlineEditGradTexPoints: result := not IsSelectingTool and Assigned(FShape) and not FQuickDefine and
  2253. (OutlineGradTexMode in FShape.Usermodes) and not (FShape.Usermode = vsuCreate);
  2254. tcShapeToSpline: result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape)
  2255. and TCurveShape.CanCreateFrom(FShape);
  2256. tcAlignLeft..tcAlignBottom: Result:= not FQuickDefine and Assigned(FShape);
  2257. tcMoveDown,tcMoveToBack: result := not IsSelectingTool and not FQuickDefine and Assigned(FShape)
  2258. and not AlwaysRasterizeShape and Manager.Image.SelectionMaskEmpty and not FLayerWasEmpty;
  2259. else result := false;
  2260. end;
  2261. end;
  2262. function TVectorialTool.SuggestGradientBox: TAffineBox;
  2263. begin
  2264. if Assigned(FShape) then
  2265. result := FShape.SuggestGradientBox(AffineMatrixIdentity)
  2266. else
  2267. result:= inherited SuggestGradientBox;
  2268. end;
  2269. function TVectorialTool.GetContextualToolbars: TContextualToolbars;
  2270. begin
  2271. result := ContextualToolbarsFromShape(ShapeClass, FShape);
  2272. end;
  2273. function TVectorialTool.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
  2274. VirtualScreenHeight: integer;
  2275. BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
  2276. var
  2277. orig, xAxis, yAxis: TPointF;
  2278. editMatrix: TAffineMatrix;
  2279. begin
  2280. if Assigned(FShape) then
  2281. begin
  2282. with LayerOffset do
  2283. begin
  2284. orig := BitmapToVirtualScreen(PointF(0,0));
  2285. xAxis := BitmapToVirtualScreen(PointF(1,0));
  2286. yAxis := BitmapToVirtualScreen(PointF(0,1));
  2287. end;
  2288. Editor.Clear;
  2289. editMatrix := AffineMatrix(xAxis-orig,yAxis-orig,orig)*VectorTransform(true);
  2290. if IsAffineMatrixInversible(editMatrix) then
  2291. begin
  2292. Editor.Matrix := editMatrix;
  2293. Editor.PointSize := DoScaleX(PointSize*Manager.CanvasScale, OriginalDPI);
  2294. if Assigned(FShape) then FShape.ConfigureEditor(Editor);
  2295. if Assigned(VirtualScreen) then
  2296. Result:= Editor.Render(VirtualScreen, rect(0,0,VirtualScreen.Width,VirtualScreen.Height))
  2297. else
  2298. Result:= Editor.GetRenderBounds(rect(0,0,VirtualScreenWidth,VirtualScreenHeight));
  2299. end else
  2300. result := EmptyRect;
  2301. end else
  2302. begin
  2303. result := EmptyRect;
  2304. Editor.Clear;
  2305. end;
  2306. FPreviousEditorBounds := result;
  2307. end;
  2308. destructor TVectorialTool.Destroy;
  2309. begin
  2310. if Assigned(FShape) then ValidateShape;
  2311. FEditor.Free;
  2312. FTemporaryStorage.Free;
  2313. inherited Destroy;
  2314. end;
  2315. initialization
  2316. RegisterTool(ptEditShape, TEditShapeTool);
  2317. end.