utoolselect.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit UToolSelect;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, Graphics, BGRABitmapTypes, BGRABitmap,
  7. UTool, UToolBasic, UToolVectorial, UToolPolygon,
  8. ULayerAction, LCVectorOriginal;
  9. type
  10. { TVectorialSelectTool }
  11. TVectorialSelectTool = class(TVectorialTool)
  12. protected
  13. function GetIsSelectingTool: boolean; override;
  14. procedure AssignShapeStyle({%H-}AMatrix: TAffineMatrix; {%H-}AAlwaysFit: boolean); override;
  15. function RoundCoordinate(constref ptF: TPointF): TPointF; override;
  16. function UpdateShape(toolDest: TBGRABitmap): TRect; override;
  17. procedure ShapeChange({%H-}ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff); override;
  18. procedure QuickDefineEnd; override;
  19. function BigImage: boolean;
  20. public
  21. function GetContextualToolbars: TContextualToolbars; override;
  22. end;
  23. { TToolSelectRect }
  24. TToolSelectRect = class(TVectorialSelectTool)
  25. protected
  26. function ShapeClass: TVectorShapeAny; override;
  27. public
  28. function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
  29. function GetContextualToolbars: TContextualToolbars; override;
  30. end;
  31. { TToolSelectEllipse }
  32. TToolSelectEllipse = class(TVectorialSelectTool)
  33. protected
  34. function ShapeClass: TVectorShapeAny; override;
  35. function GetGridMatrix: TAffineMatrix; override;
  36. public
  37. function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
  38. function GetContextualToolbars: TContextualToolbars; override;
  39. end;
  40. { TToolSelectPoly }
  41. TToolSelectPoly = class(TToolPolygon)
  42. protected
  43. procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
  44. function GetIsSelectingTool: boolean; override;
  45. public
  46. function GetContextualToolbars: TContextualToolbars; override;
  47. end;
  48. { TToolSelectSpline }
  49. TToolSelectSpline = class(TToolSpline)
  50. protected
  51. procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
  52. function GetIsSelectingTool: boolean; override;
  53. public
  54. function GetContextualToolbars: TContextualToolbars; override;
  55. end;
  56. { TToolMagicWand }
  57. TToolMagicWand = class(TGenericTool)
  58. protected
  59. function GetIsSelectingTool: boolean; override;
  60. function DoToolDown(toolDest: TBGRABitmap; pt: TPoint; {%H-}ptF: TPointF;
  61. rightBtn: boolean): TRect; override;
  62. public
  63. function GetContextualToolbars: TContextualToolbars; override;
  64. end;
  65. { TToolSelectionPen }
  66. TToolSelectionPen = class(TToolPen)
  67. protected
  68. function GetIsSelectingTool: boolean; override;
  69. function GetUniversalBrush(ARightButton: boolean): TUniversalBrush; override;
  70. public
  71. function GetContextualToolbars: TContextualToolbars; override;
  72. end;
  73. { TTransformSelectionTool }
  74. TTransformSelectionTool = class(TGenericTool)
  75. protected
  76. function GetIsSelectingTool: boolean; override;
  77. function GetAction: TLayerAction; override;
  78. function FixSelectionTransform: boolean; override;
  79. function DoGetToolDrawingLayer: TBGRABitmap; override;
  80. end;
  81. { TToolMoveSelection }
  82. TToolMoveSelection = class(TTransformSelectionTool)
  83. protected
  84. handMoving: boolean;
  85. handOriginF: TPointF;
  86. selectionTransformBefore: TAffineMatrix;
  87. function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF;
  88. {%H-}rightBtn: boolean): TRect; override;
  89. function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF): TRect; override;
  90. public
  91. constructor Create(AManager: TToolManager); override;
  92. function ToolUp: TRect; override;
  93. destructor Destroy; override;
  94. end;
  95. { TToolRotateSelection }
  96. TToolRotateSelection = class(TTransformSelectionTool)
  97. protected
  98. class var HintShowed: boolean;
  99. FHandRotating, FHandTranslating: boolean;
  100. FHandOrigin: TPointF;
  101. FSnapMode: boolean;
  102. FUnsnappedAngle: single;
  103. FOriginalTransform: TAffineMatrix;
  104. FCurrentAngle: single;
  105. FCurrentCenter: TPointF;
  106. FOffsetBeforeMove, FFinalOffset: TPointF;
  107. function DoToolDown({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF;
  108. rightBtn: boolean): TRect; override;
  109. function DoToolMove({%H-}toolDest: TBGRABitmap; {%H-}pt: TPoint; ptF: TPointF): TRect; override;
  110. function DoToolKeyDown(var key: Word): TRect; override;
  111. function DoToolKeyUp(var key: Word): TRect; override;
  112. function GetStatusText: string; override;
  113. procedure UpdateTransform;
  114. public
  115. constructor Create(AManager: TToolManager); override;
  116. function ToolUp: TRect; override;
  117. function Render(VirtualScreen: TBGRABitmap; {%H-}VirtualScreenWidth, {%H-}VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction):TRect; override;
  118. destructor Destroy; override;
  119. end;
  120. implementation
  121. uses types, ugraph, LCLType, LazPaintType, Math, BGRATransform, BGRAPath,
  122. BGRAPen, LCVectorRectShapes, Controls;
  123. procedure AssignSelectShapeStyle(AShape: TVectorShape; ASwapColor: boolean);
  124. var
  125. f: TVectorShapeFields;
  126. begin
  127. f:= AShape.MultiFields;
  128. if vsfPenFill in f then AShape.PenFill.Clear;
  129. if vsfPenStyle in f Then AShape.PenStyle := ClearPenStyle;
  130. if vsfBackFill in f then
  131. begin
  132. if ASwapColor then
  133. AShape.BackFill.SetSolid(BGRABlack)
  134. else
  135. AShape.BackFill.SetSolid(BGRAWhite);
  136. end;
  137. end;
  138. { TToolSelectSpline }
  139. procedure TToolSelectSpline.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
  140. begin
  141. FShape.BeginUpdate;
  142. inherited AssignShapeStyle(AMatrix, AAlwaysFit);
  143. AssignSelectShapeStyle(FShape, FSwapColor);
  144. FShape.EndUpdate;
  145. end;
  146. function TToolSelectSpline.GetIsSelectingTool: boolean;
  147. begin
  148. Result:= true;
  149. end;
  150. function TToolSelectSpline.GetContextualToolbars: TContextualToolbars;
  151. begin
  152. Result:= [ctSplineStyle, ctCloseShape];
  153. end;
  154. { TToolSelectPoly }
  155. procedure TToolSelectPoly.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
  156. begin
  157. FShape.BeginUpdate;
  158. inherited AssignShapeStyle(AMatrix, AAlwaysFit);
  159. AssignSelectShapeStyle(FShape, FSwapColor);
  160. FShape.EndUpdate;
  161. end;
  162. function TToolSelectPoly.GetIsSelectingTool: boolean;
  163. begin
  164. Result:= true;
  165. end;
  166. function TToolSelectPoly.GetContextualToolbars: TContextualToolbars;
  167. begin
  168. Result:= [];
  169. end;
  170. { TVectorialSelectTool }
  171. function TVectorialSelectTool.GetIsSelectingTool: boolean;
  172. begin
  173. Result:= true;
  174. end;
  175. procedure TVectorialSelectTool.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
  176. begin
  177. AssignSelectShapeStyle(FShape, FSwapColor);
  178. if FShape is TCustomRectShape then
  179. begin
  180. if Manager.ShapeRatio = 0 then
  181. TCustomRectShape(FShape).FixedRatio:= EmptySingle
  182. else
  183. TCustomRectShape(FShape).FixedRatio:= Manager.ShapeRatio;
  184. end;
  185. end;
  186. function TVectorialSelectTool.RoundCoordinate(constref ptF: TPointF): TPointF;
  187. begin
  188. Result:= PointF(floor(ptF.x)+0.5,floor(ptF.y)+0.5);
  189. end;
  190. function TVectorialSelectTool.UpdateShape(toolDest: TBGRABitmap): TRect;
  191. begin
  192. if BigImage and FQuickDefine then
  193. result := OnlyRenderChange
  194. else
  195. Result:= inherited UpdateShape(toolDest);
  196. end;
  197. procedure TVectorialSelectTool.ShapeChange(ASender: TObject; ABounds: TRectF;
  198. ADiff: TVectorShapeDiff);
  199. begin
  200. if BigImage and FQuickDefine then
  201. begin
  202. ADiff.Free;
  203. exit;
  204. end;
  205. inherited ShapeChange(ASender, ABounds, ADiff);
  206. end;
  207. procedure TVectorialSelectTool.QuickDefineEnd;
  208. var
  209. toolDest: TBGRABitmap;
  210. r: TRect;
  211. begin
  212. toolDest := GetToolDrawingLayer;
  213. r := UpdateShape(toolDest);
  214. Action.NotifyChange(toolDest, r);
  215. end;
  216. function TVectorialSelectTool.BigImage: boolean;
  217. begin
  218. result := Manager.Image.Width*Manager.Image.Height > 480000;
  219. end;
  220. function TVectorialSelectTool.GetContextualToolbars: TContextualToolbars;
  221. begin
  222. Result:= [];
  223. end;
  224. { TToolSelectRect }
  225. function TToolSelectRect.ShapeClass: TVectorShapeAny;
  226. begin
  227. result := TRectShape;
  228. end;
  229. function TToolSelectRect.Render(VirtualScreen: TBGRABitmap; VirtualScreenWidth,
  230. VirtualScreenHeight: integer;
  231. BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
  232. var
  233. ab: TAffineBox;
  234. ptsF: ArrayOfTPointF;
  235. pts: array of TPoint;
  236. i: Integer;
  237. abBounds: TRect;
  238. begin
  239. Result:= inherited Render(VirtualScreen, VirtualScreenWidth,
  240. VirtualScreenHeight, BitmapToVirtualScreen);
  241. if BigImage and FQuickDefine then
  242. begin
  243. ab := TCustomRectShape(FShape).GetAffineBox(
  244. AffineMatrixTranslation(0.5,0.5)*FEditor.Matrix*AffineMatrixTranslation(-0.5,-0.5), false);
  245. abBounds := ab.RectBounds;
  246. abBounds.Inflate(1,1);
  247. result := RectUnion(result, abBounds);
  248. if Assigned(VirtualScreen) then
  249. begin
  250. ptsF := ab.AsPolygon;
  251. setlength(pts, length(ptsF));
  252. for i := 0 to high(ptsF) do
  253. pts[i] := (ptsF[i]+PointF(0.5,0.5)).Round;
  254. VirtualScreen.DrawPolygonAntialias(pts,BGRAWhite,BGRABlack,FrameDashLength);
  255. end;
  256. end;
  257. end;
  258. function TToolSelectRect.GetContextualToolbars: TContextualToolbars;
  259. begin
  260. Result:= [ctRatio];
  261. end;
  262. { TToolSelectEllipse }
  263. function TToolSelectEllipse.ShapeClass: TVectorShapeAny;
  264. begin
  265. result := TEllipseShape;
  266. end;
  267. function TToolSelectEllipse.GetGridMatrix: TAffineMatrix;
  268. begin
  269. result := AffineMatrixScale(0.5,0.5);
  270. end;
  271. function TToolSelectEllipse.Render(VirtualScreen: TBGRABitmap;
  272. VirtualScreenWidth, VirtualScreenHeight: integer;
  273. BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
  274. var
  275. ab: TAffineBox;
  276. ptsF: ArrayOfTPointF;
  277. pts: array of TPoint;
  278. i: Integer;
  279. abBounds: TRect;
  280. begin
  281. Result:= inherited Render(VirtualScreen, VirtualScreenWidth,
  282. VirtualScreenHeight, BitmapToVirtualScreen);
  283. if BigImage and FQuickDefine then
  284. begin
  285. ab := TCustomRectShape(FShape).GetAffineBox(
  286. AffineMatrixTranslation(0.5,0.5)*FEditor.Matrix*AffineMatrixTranslation(-0.5,-0.5), false);
  287. abBounds := ab.RectBounds;
  288. abBounds.Inflate(1,1);
  289. result := RectUnion(result, abBounds);
  290. if Assigned(VirtualScreen) then
  291. begin
  292. with TCustomRectShape(FShape) do
  293. ptsF := BGRAPath.ComputeEllipse(FEditor.Matrix*Origin,
  294. FEditor.Matrix*XAxis,FEditor.Matrix*YAxis);
  295. setlength(pts, length(ptsF));
  296. for i := 0 to high(ptsF) do
  297. pts[i] := ptsF[i].Round;
  298. VirtualScreen.DrawPolygonAntialias(pts,BGRAWhite,BGRABlack,FrameDashLength);
  299. end;
  300. end;
  301. end;
  302. function TToolSelectEllipse.GetContextualToolbars: TContextualToolbars;
  303. begin
  304. Result:= [ctRatio];
  305. end;
  306. { TTransformSelectionTool }
  307. function TTransformSelectionTool.GetIsSelectingTool: boolean;
  308. begin
  309. result := true;
  310. end;
  311. function TTransformSelectionTool.GetAction: TLayerAction;
  312. begin
  313. Result:= nil;
  314. end;
  315. function TTransformSelectionTool.FixSelectionTransform: boolean;
  316. begin
  317. Result:= false;
  318. end;
  319. function TTransformSelectionTool.DoGetToolDrawingLayer: TBGRABitmap;
  320. begin
  321. result := Manager.Image.SelectionMaskReadonly;
  322. end;
  323. { TToolRotateSelection }
  324. function TToolRotateSelection.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
  325. ptF: TPointF; rightBtn: boolean): TRect;
  326. begin
  327. result := EmptyRect;
  328. if not FHandRotating and not FHandTranslating and not Manager.Image.SelectionMaskEmpty then
  329. begin
  330. if rightBtn then
  331. begin
  332. if FSnapMode then
  333. begin
  334. ptF.x := round(ptF.x*2)/2;
  335. ptF.y := round(ptF.y*2)/2;
  336. end;
  337. FCurrentAngle := 0;
  338. FFinalOffset := PointF(0, 0);
  339. FCurrentCenter := ptF;
  340. UpdateTransform;
  341. result := OnlyRenderChange;
  342. end else
  343. begin
  344. if VectLen(ptF - (FCurrentCenter + FFinalOffset)) < SelectionMaxPointDistance then
  345. FHandTranslating:= true
  346. else
  347. FHandRotating := true;
  348. FHandOrigin := ptF;
  349. FOffsetBeforeMove := FFinalOffset;
  350. end;
  351. end;
  352. end;
  353. function TToolRotateSelection.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
  354. ptF: TPointF): TRect;
  355. var angleDiff: single;
  356. finalCenter, newOfs: TPointF;
  357. begin
  358. if not HintShowed then
  359. begin
  360. Manager.ToolPopup(tpmHoldKeyRestrictRotation, VK_CONTROL);
  361. HintShowed:= true;
  362. end;
  363. if FHandRotating and ((FHandOrigin.X <> ptF.X) or (FHandOrigin.Y <> ptF.Y)) then
  364. begin
  365. finalCenter := FCurrentCenter + FFinalOffset;
  366. angleDiff := ComputeAngle(ptF.X - finalCenter.X, ptF.Y - finalCenter.Y)-
  367. ComputeAngle(FHandOrigin.X - finalCenter.X, FHandOrigin.Y - finalCenter.Y);
  368. if FSnapMode then
  369. begin
  370. FUnsnappedAngle += angleDiff;
  371. FCurrentAngle := round(FUnsnappedAngle/15)*15;
  372. end else
  373. FCurrentAngle := FCurrentAngle + angleDiff;
  374. UpdateTransform;
  375. FHandOrigin := ptF;
  376. result := OnlyRenderChange;
  377. end else
  378. if FHandTranslating and ((FHandOrigin.X <> ptF.X) or (FHandOrigin.Y <> ptF.Y)) then
  379. begin
  380. newOfs := FOffsetBeforeMove + ptF - FHandOrigin;
  381. if FSnapMode then
  382. begin
  383. newOfs.X := round(newOfs.x*2)/2;
  384. newOfs.Y := round(newOfs.y*2)/2;
  385. end;
  386. if newOfs <> FFinalOffset then
  387. begin
  388. FFinalOffset := newOfs;
  389. UpdateTransform;
  390. result := OnlyRenderChange;
  391. end else
  392. result := EmptyRect;
  393. end else
  394. begin
  395. if VectLen(ptF - (FCurrentCenter + FFinalOffset)) < SelectionMaxPointDistance then
  396. Cursor := crSizeAll else Cursor := crDefault;
  397. result := EmptyRect;
  398. end;
  399. end;
  400. function TToolRotateSelection.GetStatusText: string;
  401. begin
  402. Result:= 'α = '+FloatToStrF(FCurrentAngle,ffFixed,5,1) + '|' +
  403. 'Δx = '+FloatToStrF(FFinalOffset.X,ffFixed,6,1) + '|' +
  404. 'Δy = '+FloatToStrF(FFinalOffset.Y,ffFixed,6,1);
  405. end;
  406. procedure TToolRotateSelection.UpdateTransform;
  407. begin
  408. Manager.Image.SelectionTransform := AffineMatrixTranslation(FFinalOffset.X, FFinalOffset.Y) *
  409. AffineMatrixTranslation(FCurrentCenter.X,FCurrentCenter.Y) *
  410. AffineMatrixRotationDeg(FCurrentAngle) *
  411. AffineMatrixTranslation(-FCurrentCenter.X,-FCurrentCenter.Y) *
  412. FOriginalTransform;
  413. end;
  414. constructor TToolRotateSelection.Create(AManager: TToolManager);
  415. begin
  416. inherited Create(AManager);
  417. FCurrentCenter := Manager.Image.SelectionTransform * Manager.Image.GetSelectionMaskCenter;
  418. FOriginalTransform := Manager.Image.SelectionTransform;
  419. FCurrentAngle := 0;
  420. FFinalOffset := PointF(0, 0);
  421. end;
  422. function TToolRotateSelection.DoToolKeyDown(var key: Word): TRect;
  423. begin
  424. result := EmptyRect;
  425. if key = VK_CONTROL then
  426. begin
  427. if not FSnapMode then
  428. begin
  429. FSnapMode := true;
  430. FUnsnappedAngle := FCurrentAngle;
  431. if FHandRotating then
  432. begin
  433. FCurrentAngle := round(FUnsnappedAngle/15)*15;
  434. UpdateTransform;
  435. result := OnlyRenderChange;
  436. end else
  437. if FHandTranslating then
  438. begin
  439. FFinalOffset.x := round(FFinalOffset.x*2)/2;
  440. FFinalOffset.y := round(FFinalOffset.y*2)/2;
  441. UpdateTransform;
  442. result := OnlyRenderChange;
  443. end;
  444. end;
  445. Key := 0;
  446. end else
  447. if key = VK_ESCAPE then
  448. begin
  449. if FCurrentAngle <> 0 then
  450. begin
  451. FCurrentAngle := 0;
  452. FFinalOffset := PointF(0, 0);
  453. UpdateTransform;
  454. result := OnlyRenderChange;
  455. end;
  456. Key := 0;
  457. end;
  458. end;
  459. function TToolRotateSelection.DoToolKeyUp(var key: Word): TRect;
  460. begin
  461. if key = VK_CONTROL then
  462. begin
  463. FSnapMode := false;
  464. Key := 0;
  465. end;
  466. result := EmptyRect;
  467. end;
  468. function TToolRotateSelection.ToolUp: TRect;
  469. begin
  470. FHandRotating:= false;
  471. FHandTranslating:= false;
  472. Result:= EmptyRect;
  473. end;
  474. function TToolRotateSelection.Render(VirtualScreen: TBGRABitmap;
  475. VirtualScreenWidth, VirtualScreenHeight: integer; BitmapToVirtualScreen: TBitmapToVirtualScreenFunction): TRect;
  476. var pictureRotateCenter: TPointF;
  477. begin
  478. pictureRotateCenter := BitmapToVirtualScreen(FCurrentCenter + FFinalOffset);
  479. result := NicePoint(VirtualScreen, pictureRotateCenter.X,pictureRotateCenter.Y);
  480. end;
  481. destructor TToolRotateSelection.Destroy;
  482. begin
  483. if FHandRotating then FHandRotating := false;
  484. if FHandTranslating then FHandTranslating := false;
  485. inherited Destroy;
  486. end;
  487. { TToolMoveSelection }
  488. function TToolMoveSelection.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
  489. ptF: TPointF; rightBtn: boolean): TRect;
  490. begin
  491. if not handMoving and not Manager.Image.SelectionMaskEmpty then
  492. begin
  493. handMoving := true;
  494. handOriginF := ptF;
  495. selectionTransformBefore := Manager.Image.SelectionTransform;
  496. end;
  497. result := EmptyRect;
  498. end;
  499. function TToolMoveSelection.DoToolMove(toolDest: TBGRABitmap; pt: TPoint;
  500. ptF: TPointF): TRect;
  501. var dx,dy: single;
  502. newSelTransform: TAffineMatrix;
  503. begin
  504. result := EmptyRect;
  505. if handMoving then
  506. begin
  507. dx := ptF.X-HandOriginF.X;
  508. dy := ptF.Y-HandOriginF.Y;
  509. if ssSnap in ShiftState then
  510. begin
  511. dx := round(dx);
  512. dy := round(dy);
  513. end;
  514. newSelTransform := AffineMatrixTranslation(dx,dy) * selectionTransformBefore;
  515. if Manager.Image.SelectionTransform <> newSelTransform then
  516. begin
  517. Manager.Image.SelectionTransform := newSelTransform;
  518. result := OnlyRenderChange;
  519. end;
  520. end;
  521. end;
  522. constructor TToolMoveSelection.Create(AManager: TToolManager);
  523. begin
  524. inherited Create(AManager);
  525. handMoving := false;
  526. end;
  527. function TToolMoveSelection.ToolUp: TRect;
  528. begin
  529. handMoving := false;
  530. result := EmptyRect;
  531. end;
  532. destructor TToolMoveSelection.Destroy;
  533. begin
  534. if handMoving then handMoving := false;
  535. inherited Destroy;
  536. end;
  537. { TToolSelectionPen }
  538. function TToolSelectionPen.GetIsSelectingTool: boolean;
  539. begin
  540. Result:= true;
  541. end;
  542. function TToolSelectionPen.GetUniversalBrush(ARightButton: boolean): TUniversalBrush;
  543. begin
  544. if ARightButton then
  545. TBGRABitmap.SolidBrush(result, BGRABlack, dmLinearBlend)
  546. else
  547. TBGRABitmap.SolidBrush(result, BGRAWhite, dmLinearBlend);
  548. end;
  549. function TToolSelectionPen.GetContextualToolbars: TContextualToolbars;
  550. begin
  551. Result:= [ctPenWidth, ctAliasing];
  552. end;
  553. { TToolMagicWand }
  554. function TToolMagicWand.GetIsSelectingTool: boolean;
  555. begin
  556. Result:= true;
  557. end;
  558. function TToolMagicWand.DoToolDown(toolDest: TBGRABitmap; pt: TPoint;
  559. ptF: TPointF; rightBtn: boolean): TRect;
  560. var penColor: TBGRAPixel;
  561. ofs: TPoint;
  562. begin
  563. if not Manager.Image.CurrentLayerVisible then
  564. begin
  565. result := EmptyRect;
  566. exit;
  567. end;
  568. if rightBtn then penColor := BGRABlack else penColor := BGRAWhite;
  569. ofs := Manager.Image.LayerOffset[Manager.Image.CurrentLayerIndex];
  570. Manager.Image.CurrentLayerReadOnly.ParallelFloodFill(pt.X-ofs.X, pt.Y-ofs.Y,
  571. toolDest, penColor, fmDrawWithTransparency, Manager.Tolerance, ofs.X, ofs.Y);
  572. result := rect(0,0,toolDest.Width,toolDest.Height);
  573. Action.NotifyChange(toolDest, result);
  574. ValidateAction;
  575. end;
  576. function TToolMagicWand.GetContextualToolbars: TContextualToolbars;
  577. begin
  578. Result:= [ctTolerance];
  579. end;
  580. initialization
  581. RegisterTool(ptMagicWand,TToolMagicWand);
  582. RegisterTool(ptSelectPen,TToolSelectionPen);
  583. RegisterTool(ptSelectRect,TToolSelectRect);
  584. RegisterTool(ptSelectEllipse,TToolSelectEllipse);
  585. RegisterTool(ptSelectPoly,TToolSelectPoly);
  586. RegisterTool(ptSelectSpline,TToolSelectSpline);
  587. RegisterTool(ptMoveSelection,TToolMoveSelection);
  588. RegisterTool(ptRotateSelection,TToolRotateSelection);
  589. end.