MainUnit.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. unit MainUnit;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Gradient Sampler Example
  23. *
  24. * The Initial Developer(s) of the Original Code is:
  25. * Christian-W. Budde <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2012
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. *
  31. * ***** END LICENSE BLOCK ***** *)
  32. interface
  33. uses
  34. {$IFDEF FPC} LCLIntf, LResources, Buttons, {$ENDIF} SysUtils, Classes,
  35. Graphics, Controls, Forms, Dialogs, Menus, ExtCtrls,
  36. GR32, GR32_Image, GR32_ColorGradients;
  37. type
  38. TMesh = record
  39. Point: TFloatPoint;
  40. Velocity: TFloatPoint;
  41. Color: TColor32;
  42. HueChange: Single;
  43. end;
  44. TFrmGradientSampler = class(TForm)
  45. PaintBox32: TPaintBox32;
  46. MainMenu: TMainMenu;
  47. MnuFile: TMenuItem;
  48. MnuClose: TMenuItem;
  49. MnuGradient: TMenuItem;
  50. MnuGradientRadial: TMenuItem;
  51. MnuGradientConic: TMenuItem;
  52. MnuGradientDiamond: TMenuItem;
  53. MnuGradientXY: TMenuItem;
  54. MnuGradientXYSqrt: TMenuItem;
  55. MnuGradientLinear: TMenuItem;
  56. MnuGradientCustom: TMenuItem;
  57. MnuWrapMode: TMenuItem;
  58. MnuWrapModeClamp: TMenuItem;
  59. MnuWrapModeRepeat: TMenuItem;
  60. MnuWrapModeMirror: TMenuItem;
  61. Animation: TTimer;
  62. MnuBackground: TMenuItem;
  63. MnuBackgroundGradientTriangular: TMenuItem;
  64. MnuBackgroundGradientVoronoi: TMenuItem;
  65. MnuBackgroundGradientShepards: TMenuItem;
  66. MnuBackgroundGradientCustomIDW: TMenuItem;
  67. procedure FormCreate(Sender: TObject);
  68. procedure FormDestroy(Sender: TObject);
  69. procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  70. procedure MnuCloseClick(Sender: TObject);
  71. procedure MnuGradientConicClick(Sender: TObject);
  72. procedure MnuGradientDiamondClick(Sender: TObject);
  73. procedure MnuGradientLinearClick(Sender: TObject);
  74. procedure MnuGradientRadialClick(Sender: TObject);
  75. procedure MnuGradientXYClick(Sender: TObject);
  76. procedure MnuGradientXYSqrtClick(Sender: TObject);
  77. procedure MnuGradientCustomClick(Sender: TObject);
  78. procedure MnuWrapModeClampClick(Sender: TObject);
  79. procedure MnuWrapModeRepeatClick(Sender: TObject);
  80. procedure MnuWrapModeMirrorClick(Sender: TObject);
  81. procedure PaintBox32PaintBuffer(Sender: TObject);
  82. procedure PaintBox32MouseDown(Sender: TObject; Button: TMouseButton;
  83. Shift: TShiftState; X, Y: Integer);
  84. procedure PaintBox32MouseMove(Sender: TObject; Shift: TShiftState; X,
  85. Y: Integer);
  86. procedure PaintBox32MouseUp(Sender: TObject; Button: TMouseButton;
  87. Shift: TShiftState; X, Y: Integer);
  88. procedure AnimationTimer(Sender: TObject);
  89. procedure PaintBox32DblClick(Sender: TObject);
  90. procedure MnuBackgroundGradientVoronoiClick(Sender: TObject);
  91. procedure MnuBackgroundGradientTriangularClick(Sender: TObject);
  92. procedure MnuBackgroundGradientShepardsClick(Sender: TObject);
  93. procedure MnuBackgroundGradientCustomIDWClick(Sender: TObject);
  94. private
  95. FCenter: TFloatPoint;
  96. FWrapMode: TWrapMode;
  97. FGradCenter: TFloatPoint;
  98. FAngle, FRadius: TFloat;
  99. FStarAngle: TFloat;
  100. FStarVertices: Integer;
  101. FLastPos: TFloatPoint;
  102. FOutline: TArrayOfFloatPoint;
  103. FStartColor: TColor32;
  104. FEndColor: TColor32;
  105. FGradientSampler: TCustomGradientSampler;
  106. FBackgroundGradientSampler: TCustomSparsePointGradientSampler;
  107. FMesh: array of TMesh;
  108. public
  109. procedure UpdateBackgroundGradientSampler;
  110. end;
  111. TMyGradient = class(TCustomGradientLookUpTableSampler)
  112. private
  113. FPolygon: PArrayOfFloatPoint;
  114. FRadius: TFloat;
  115. FScale: TFloat;
  116. procedure SetRadius(const Value: TFloat);
  117. protected
  118. procedure AssignTo(Dest: TPersistent); override;
  119. procedure UpdateInternals; override;
  120. public
  121. constructor Create(WrapMode: TWrapMode = wmMirror); override;
  122. function GetSampleFloat(X: Single; Y: Single): TColor32; override;
  123. property Polygon: PArrayOfFloatPoint read FPolygon write FPolygon;
  124. property Radius: TFloat read FRadius write SetRadius;
  125. end;
  126. var
  127. FrmGradientSampler: TFrmGradientSampler;
  128. implementation
  129. {$IFDEF FPC}
  130. {$R *.lfm}
  131. {$ELSE}
  132. {$R *.dfm}
  133. {$ENDIF}
  134. uses
  135. Math, GR32_Math, GR32_LowLevel, GR32_Polygons, GR32_Geometry,
  136. GR32_VectorUtils;
  137. { TMyGradient }
  138. constructor TMyGradient.Create(WrapMode: TWrapMode = wmMirror);
  139. begin
  140. inherited;
  141. FRadius := 10;
  142. end;
  143. function TMyGradient.GetSampleFloat(X, Y: Single): TColor32;
  144. var
  145. Pt: TFloatPoint;
  146. Index: Integer;
  147. Dist, MinDist, MaxDist: TFloat;
  148. begin
  149. Pt := FloatPoint(X, Y);
  150. Dist := Distance(Pt, FPolygon^[0]) ;
  151. MinDist := Dist;
  152. MaxDist := Dist;
  153. for Index := 1 to High(FPolygon^) do
  154. begin
  155. Dist := Distance(Pt, FPolygon^[Index]);
  156. if Dist < MinDist then
  157. MinDist := Dist
  158. else
  159. if Dist > MaxDist then
  160. MaxDist := Dist;
  161. end;
  162. Result := LutPtr^[WrapProc(Round((MaxDist + MinDist) * FScale),
  163. LutMask)];
  164. end;
  165. procedure TMyGradient.SetRadius(const Value: TFloat);
  166. begin
  167. if FRadius <> Value then
  168. begin
  169. FRadius := Value;
  170. FInitialized := False;
  171. end;
  172. end;
  173. procedure TMyGradient.UpdateInternals;
  174. begin
  175. inherited;
  176. FScale := LutMask / FRadius;
  177. end;
  178. procedure TMyGradient.AssignTo(Dest: TPersistent);
  179. begin
  180. inherited;
  181. end;
  182. { TFrmGradientSampler }
  183. procedure TFrmGradientSampler.FormCreate(Sender: TObject);
  184. var
  185. Index: Integer;
  186. begin
  187. FGradientSampler := TDiamondGradientSampler.Create;
  188. FCenter := FloatPoint(0.5 * PaintBox32.Width, 0.5 * PaintBox32.Height);
  189. FGradCenter := FCenter;
  190. FAngle := 0.4;
  191. FRadius := 50;
  192. FWrapMode := wmMirror;
  193. FStarVertices := 5;
  194. FStarAngle := 0;
  195. FOutline := Star(FCenter, 180, FStarVertices, FStarAngle);
  196. FBackgroundGradientSampler := TBarycentricGradientSampler.Create;
  197. SetLength(FMesh, FBackgroundGradientSampler.Count);
  198. for Index := 0 to High(FMesh) do
  199. begin
  200. FMesh[Index].Point := FloatPoint(PaintBox32.Width * Random,
  201. PaintBox32.Height * Random);
  202. FMesh[Index].Velocity := FloatPoint(2 * Random - 1, 2 * Random - 1);
  203. FMesh[Index].Color := SetAlpha(Random($FFFFFF), $FF);
  204. FMesh[Index].HueChange := 0.001 * (2 * Random - 1);
  205. end;
  206. FStartColor := SetAlpha(Random($FFFFFF), $FF);
  207. FEndColor := SetAlpha(Random($FFFFFF), $FF);
  208. UpdateBackgroundGradientSampler;
  209. PaintBox32.Invalidate;
  210. end;
  211. procedure TFrmGradientSampler.UpdateBackgroundGradientSampler;
  212. var
  213. Index: Integer;
  214. begin
  215. for Index := 0 to FBackgroundGradientSampler.Count - 1 do
  216. begin
  217. FBackgroundGradientSampler.Point[Index] := FMesh[Index].Point;
  218. FBackgroundGradientSampler.Color[Index] := FMesh[Index].Color;
  219. end;
  220. end;
  221. procedure TFrmGradientSampler.FormDestroy(Sender: TObject);
  222. begin
  223. FBackgroundGradientSampler.Free;
  224. FGradientSampler.Free;
  225. end;
  226. procedure TFrmGradientSampler.FormKeyDown(Sender: TObject; var Key: Word;
  227. Shift: TShiftState);
  228. begin
  229. case Key of
  230. 27: Close;
  231. 52..57:
  232. begin
  233. FStarVertices := Key - 48;
  234. FOutline := Star(FCenter, 180, FStarVertices);
  235. PaintBox32.Invalidate;
  236. end;
  237. end;
  238. end;
  239. procedure TFrmGradientSampler.MnuCloseClick(Sender: TObject);
  240. begin
  241. Close;
  242. end;
  243. procedure TFrmGradientSampler.MnuGradientRadialClick(Sender: TObject);
  244. var
  245. OldGradientSampler: TCustomGradientSampler;
  246. begin
  247. OldGradientSampler := FGradientSampler;
  248. FGradientSampler := TRadialGradientSampler.Create;
  249. FGradientSampler.Assign(OldGradientSampler);
  250. OldGradientSampler.Free;
  251. MnuGradientRadial.Checked := True;
  252. PaintBox32.Invalidate;
  253. end;
  254. procedure TFrmGradientSampler.MnuGradientConicClick(Sender: TObject);
  255. var
  256. OldGradientSampler: TCustomGradientSampler;
  257. begin
  258. OldGradientSampler := FGradientSampler;
  259. FGradientSampler := TConicGradientSampler.Create;
  260. FGradientSampler.Assign(OldGradientSampler);
  261. OldGradientSampler.Free;
  262. MnuGradientConic.Checked := True;
  263. PaintBox32.Invalidate;
  264. end;
  265. procedure TFrmGradientSampler.MnuGradientCustomClick(Sender: TObject);
  266. var
  267. OldGradientSampler: TCustomGradientSampler;
  268. begin
  269. OldGradientSampler := FGradientSampler;
  270. FGradientSampler := TMyGradient.Create;
  271. FGradientSampler.Assign(OldGradientSampler);
  272. OldGradientSampler.Free;
  273. MnuGradientCustom.Checked := True;
  274. PaintBox32.Invalidate;
  275. end;
  276. procedure TFrmGradientSampler.MnuGradientDiamondClick(Sender: TObject);
  277. var
  278. OldGradientSampler: TCustomGradientSampler;
  279. begin
  280. OldGradientSampler := FGradientSampler;
  281. FGradientSampler := TDiamondGradientSampler.Create;
  282. FGradientSampler.Assign(OldGradientSampler);
  283. OldGradientSampler.Free;
  284. MnuGradientDiamond.Checked := True;
  285. PaintBox32.Invalidate;
  286. end;
  287. procedure TFrmGradientSampler.MnuGradientXYClick(Sender: TObject);
  288. var
  289. OldGradientSampler: TCustomGradientSampler;
  290. begin
  291. OldGradientSampler := FGradientSampler;
  292. FGradientSampler := TXYGradientSampler.Create;
  293. FGradientSampler.Assign(OldGradientSampler);
  294. OldGradientSampler.Free;
  295. MnuGradientXY.Checked := True;
  296. PaintBox32.Invalidate;
  297. end;
  298. procedure TFrmGradientSampler.MnuGradientXYSqrtClick(Sender: TObject);
  299. var
  300. OldGradientSampler: TCustomGradientSampler;
  301. begin
  302. OldGradientSampler := FGradientSampler;
  303. FGradientSampler := TXYSqrtGradientSampler.Create;
  304. FGradientSampler.Assign(OldGradientSampler);
  305. OldGradientSampler.Free;
  306. MnuGradientXYSqrt.Checked := True;
  307. PaintBox32.Invalidate;
  308. end;
  309. procedure TFrmGradientSampler.MnuBackgroundGradientCustomIDWClick(
  310. Sender: TObject);
  311. var
  312. Index: Integer;
  313. begin
  314. if not MnuBackgroundGradientCustomIDW.Checked then
  315. begin
  316. MnuBackgroundGradientCustomIDW.Checked := True;
  317. FBackgroundGradientSampler.Free;
  318. FBackgroundGradientSampler := TInvertedDistanceWeightingSampler.Create;
  319. TInvertedDistanceWeightingSampler(FBackgroundGradientSampler).Power := 8;
  320. with TCustomArbitrarySparsePointGradientSampler(FBackgroundGradientSampler) do
  321. for Index := 0 to High(FMesh) do
  322. Add(FMesh[Index].Point, FMesh[Index].Color);
  323. PaintBox32.Invalidate;
  324. end;
  325. end;
  326. procedure TFrmGradientSampler.MnuBackgroundGradientShepardsClick(Sender: TObject);
  327. var
  328. Index: Integer;
  329. begin
  330. if not MnuBackgroundGradientShepards.Checked then
  331. begin
  332. MnuBackgroundGradientShepards.Checked := True;
  333. FBackgroundGradientSampler.Free;
  334. FBackgroundGradientSampler := TInvertedDistanceWeightingSampler.Create;
  335. with TCustomArbitrarySparsePointGradientSampler(FBackgroundGradientSampler) do
  336. for Index := 0 to High(FMesh) do
  337. Add(FMesh[Index].Point, FMesh[Index].Color);
  338. PaintBox32.Invalidate;
  339. end;
  340. end;
  341. procedure TFrmGradientSampler.MnuBackgroundGradientTriangularClick(Sender: TObject);
  342. begin
  343. if not MnuBackgroundGradientTriangular.Checked then
  344. begin
  345. MnuBackgroundGradientTriangular.Checked := True;
  346. FBackgroundGradientSampler.Free;
  347. FBackgroundGradientSampler := TBarycentricGradientSampler.Create;
  348. UpdateBackgroundGradientSampler;
  349. PaintBox32.Invalidate;
  350. end;
  351. end;
  352. procedure TFrmGradientSampler.MnuBackgroundGradientVoronoiClick(Sender: TObject);
  353. var
  354. Index: Integer;
  355. begin
  356. if not MnuBackgroundGradientVoronoi.Checked then
  357. begin
  358. MnuBackgroundGradientVoronoi.Checked := True;
  359. FBackgroundGradientSampler.Free;
  360. FBackgroundGradientSampler := TVoronoiSampler.Create;
  361. with TCustomArbitrarySparsePointGradientSampler(FBackgroundGradientSampler) do
  362. for Index := 0 to High(FMesh) do
  363. Add(FMesh[Index].Point, FMesh[Index].Color);
  364. PaintBox32.Invalidate;
  365. end;
  366. end;
  367. procedure TFrmGradientSampler.MnuWrapModeClampClick(Sender: TObject);
  368. begin
  369. FWrapMode := wmClamp;
  370. MnuWrapModeClamp.Checked := True;
  371. PaintBox32.Invalidate;
  372. end;
  373. procedure TFrmGradientSampler.MnuWrapModeMirrorClick(Sender: TObject);
  374. begin
  375. FWrapMode := wmMirror;
  376. MnuWrapModeMirror.Checked := True;
  377. PaintBox32.Invalidate;
  378. end;
  379. procedure TFrmGradientSampler.MnuWrapModeRepeatClick(Sender: TObject);
  380. begin
  381. FWrapMode := wmRepeat;
  382. MnuWrapModeRepeat.Checked := True;
  383. PaintBox32.Invalidate;
  384. end;
  385. procedure TFrmGradientSampler.MnuGradientLinearClick(Sender: TObject);
  386. var
  387. OldGradientSampler: TCustomGradientSampler;
  388. begin
  389. OldGradientSampler := FGradientSampler;
  390. FGradientSampler := TXGradientSampler.Create;
  391. FGradientSampler.Assign(OldGradientSampler);
  392. OldGradientSampler.Free;
  393. MnuGradientLinear.Checked := True;
  394. PaintBox32.Invalidate;
  395. end;
  396. procedure TFrmGradientSampler.PaintBox32DblClick(Sender: TObject);
  397. begin
  398. Animation.Enabled := not Animation.Enabled;
  399. end;
  400. procedure TFrmGradientSampler.PaintBox32MouseDown(Sender: TObject;
  401. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  402. var
  403. Index: Integer;
  404. begin
  405. if (ssCtrl in Shift) then
  406. begin
  407. Animation.Enabled := not Animation.Enabled;
  408. Exit;
  409. end;
  410. if (ssShift in Shift) then
  411. begin
  412. for Index := 0 to 2 do
  413. begin
  414. FMesh[Index].Point := FloatPoint(PaintBox32.Width * Random,
  415. PaintBox32.Height * Random);
  416. FMesh[Index].Velocity := FloatPoint(2 * Random - 1, 2 * Random - 1);
  417. FMesh[Index].Color := SetAlpha(Random($FFFFFF), $FF);
  418. FMesh[Index].HueChange := 0.001 * (2 * Random - 1);
  419. end;
  420. UpdateBackgroundGradientSampler;
  421. FStartColor := SetAlpha(Random($FFFFFF), $FF);
  422. FEndColor := SetAlpha(Random($FFFFFF), $FF);
  423. PaintBox32.Invalidate;
  424. Exit;
  425. end;
  426. PaintBox32.OnMouseMove := PaintBox32MouseMove;
  427. if ssRight in Shift then
  428. begin
  429. if ssShift in Shift then
  430. FCenter := FloatPoint(X, Y)
  431. else
  432. FGradCenter := FloatPoint(X, Y);
  433. PaintBox32.Invalidate;
  434. end;
  435. FLastPos := FloatPoint(X, Y);
  436. end;
  437. procedure TFrmGradientSampler.PaintBox32MouseMove(Sender: TObject;
  438. Shift: TShiftState; X, Y: Integer);
  439. begin
  440. if ssRight in Shift then
  441. begin
  442. if ssShift in Shift then
  443. FCenter := FloatPoint(X, Y)
  444. else
  445. FGradCenter := FloatPoint(X, Y);
  446. PaintBox32.Invalidate;
  447. end else
  448. if ssLeft in Shift then
  449. begin
  450. if (Y = FGradCenter.Y) and (X = FGradCenter.X) then
  451. begin
  452. FRadius := 0;
  453. end
  454. else
  455. begin
  456. FAngle := FAngle - ArcTan2(Y - FGradCenter.Y, X - FGradCenter.X) +
  457. ArcTan2(FLastPos.Y - FGradCenter.Y, FLastPos.X - FGradCenter.X);
  458. FRadius := FRadius * (Hypot(Y - FGradCenter.Y, X - FGradCenter.X) /
  459. Distance(FLastPos, FGradCenter));
  460. end;
  461. PaintBox32.Invalidate;
  462. end;
  463. FLastPos := FloatPoint(X, Y);
  464. end;
  465. procedure TFrmGradientSampler.PaintBox32MouseUp(Sender: TObject;
  466. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  467. begin
  468. PaintBox32.OnMouseMove := nil;
  469. end;
  470. procedure TFrmGradientSampler.PaintBox32PaintBuffer(Sender: TObject);
  471. var
  472. Renderer: TPolygonRenderer32;
  473. SamplerFiller: TSamplerFiller;
  474. X, Y: Integer;
  475. begin
  476. PaintBox32.Buffer.Clear(clWhite32);
  477. FBackgroundGradientSampler.PrepareSampling;
  478. with PaintBox32.Buffer do
  479. for Y := 0 to Height - 1 do
  480. for X := 0 to Width - 1 do
  481. Pixel[X, Y] := FBackgroundGradientSampler.GetSampleInt(X, Y);
  482. Renderer := TPolygonRenderer32VPR.Create(PaintBox32.Buffer);
  483. try
  484. Renderer.Color := clWhite32;
  485. if FGradientSampler is TCustomCenterRadiusLutGradientSampler then
  486. TCustomCenterRadiusLutGradientSampler(FGradientSampler).Radius := FRadius;
  487. if FGradientSampler is TCustomCenterRadiusAngleLutGradientSampler then
  488. with TCustomCenterRadiusAngleLutGradientSampler(FGradientSampler) do
  489. Angle := FAngle;
  490. if FGradientSampler is TConicGradientSampler then
  491. TConicGradientSampler(FGradientSampler).Angle := FAngle;
  492. if FGradientSampler is TCustomCenterLutGradientSampler then
  493. TCustomCenterLutGradientSampler(FGradientSampler).Center := FGradCenter;
  494. FGradientSampler.Gradient.StartColor := FStartColor;
  495. FGradientSampler.Gradient.EndColor := FEndColor;
  496. FGradientSampler.WrapMode := FWrapMode;
  497. SamplerFiller := TSamplerFiller.Create(FGradientSampler);
  498. try
  499. Renderer.Filler := SamplerFiller;
  500. if FGradientSampler is TMyGradient then
  501. with TMyGradient(FGradientSampler) do
  502. begin
  503. Polygon := @FOutline;
  504. Radius := Self.FRadius;
  505. end;
  506. Renderer.PolygonFS(FOutline);
  507. finally
  508. SamplerFiller.Free;
  509. end;
  510. Renderer.Filler := nil;
  511. Renderer.Color := clBlack32;
  512. Renderer.PolyPolygonFS(BuildPolyPolyline(PolyPolygon(FOutline), True, 5,
  513. jsRound, esRound));
  514. finally
  515. Renderer.Free;
  516. end;
  517. end;
  518. procedure TFrmGradientSampler.AnimationTimer(Sender: TObject);
  519. var
  520. Index: Integer;
  521. H, S, L: Single;
  522. begin
  523. FAngle := FAngle + 0.01;
  524. FStarAngle := FStarAngle + 0.01;
  525. FOutline := Star(FCenter, 180, FStarVertices, FStarAngle);
  526. for Index := 0 to FBackgroundGradientSampler.Count - 1 do
  527. begin
  528. FMesh[Index].Point.X := FMesh[Index].Point.X + FMesh[Index].Velocity.X;
  529. if FMesh[Index].Point.X < 0 then
  530. begin
  531. FMesh[Index].Point.X := -FMesh[Index].Point.X;
  532. FMesh[Index].Velocity.X := -FMesh[Index].Velocity.X;
  533. end;
  534. if FMesh[Index].Point.X >= PaintBox32.Width then
  535. begin
  536. FMesh[Index].Point.X := 2 * PaintBox32.Width - FMesh[Index].Point.X;
  537. FMesh[Index].Velocity.X := -FMesh[Index].Velocity.X;
  538. end;
  539. FMesh[Index].Point.Y := FMesh[Index].Point.Y + FMesh[Index].Velocity.Y;
  540. if FMesh[Index].Point.Y < 0 then
  541. begin
  542. FMesh[Index].Point.Y := -FMesh[Index].Point.Y;
  543. FMesh[Index].Velocity.Y := -FMesh[Index].Velocity.Y;
  544. end;
  545. FMesh[Index].Point.Y := FMesh[Index].Point.Y + FMesh[Index].Velocity.Y;
  546. if FMesh[Index].Point.Y >= PaintBox32.Height then
  547. begin
  548. FMesh[Index].Point.Y := 2 * PaintBox32.Height - FMesh[Index].Point.Y;
  549. FMesh[Index].Velocity.Y := -FMesh[Index].Velocity.Y;
  550. end;
  551. RGBtoHSL(FMesh[Index].Color, H, S, L);
  552. FMesh[Index].Color := HSLtoRGB(H + FMesh[Index].HueChange, S, L);
  553. end;
  554. UpdateBackgroundGradientSampler;
  555. PaintBox32.Invalidate;
  556. end;
  557. end.