MainUnit.pas 19 KB

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