Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

603 wiersze
21 KiB

  1. unit utsPostProcessor;
  2. {$IFDEF FPC}
  3. {$mode objfpc}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. Classes, SysUtils, contnrs,
  8. utsUtils, utsChar, utsImage, utsContext, utsTypes;
  9. type
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  11. TtsCharRange = record
  12. Start: WideChar;
  13. Stop: WideChar;
  14. end;
  15. PtsCharRange = ^TtsCharRange;
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. TtsCharRangeUsage = (
  18. tsUsageInclude,
  19. tsUsageExclude);
  20. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. TtsPostProcessor = class(TtsRefManager)
  22. private
  23. fContext: TtsContext;
  24. fIncludeCharRanges: TList;
  25. fExcludeCharRanges: TList;
  26. procedure ClearList(const aList: TList);
  27. public
  28. property Context: TtsContext read fContext;
  29. function IsInRange(const aCharCode: WideChar): Boolean;
  30. procedure AddRange(const aUsage: TtsCharRangeUsage; const aStart, aStop: WideChar);
  31. procedure AddChars(const aUsage: TtsCharRangeUsage; aChars: PWideChar);
  32. procedure ClearRanges;
  33. function Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean; virtual;
  34. constructor Create(const aContext: TtsContext);
  35. destructor Destroy; override;
  36. end;
  37. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  38. TtsPostProcessorList = class(TtsPostProcessor)
  39. private
  40. fItems: TObjectList;
  41. function GetCount: Integer;
  42. function GetOwnsObjects: Boolean;
  43. procedure SetOwnsObjects(const aValue: Boolean);
  44. public
  45. property Count: Integer read GetCount;
  46. property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects;
  47. procedure Add(const aPostProcessor: TtsPostProcessor);
  48. procedure Delete(const aIndex: Integer);
  49. procedure Clear;
  50. function Remove(const aPostProcessor: TtsPostProcessor): Integer;
  51. function IndexOf(const aPostProcessor: TtsPostProcessor): Integer;
  52. function Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean; override;
  53. constructor Create(const aContext: TtsContext; const aOwnsObjects: Boolean);
  54. destructor Destroy; override;
  55. end;
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. TtsPostProcessorFillColor = class(TtsPostProcessor)
  58. private
  59. fColor: TtsColor4f;
  60. fModes: TtsImageModes;
  61. fChannels: TtsColorChannels;
  62. public
  63. property Color: TtsColor4f read fColor write fColor;
  64. property Modes: TtsImageModes read fModes write fModes;
  65. property Channels: TtsColorChannels read fChannels write fChannels;
  66. function Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean; override;
  67. constructor Create(
  68. const aContext: TtsContext;
  69. const aColor: TtsColor4f;
  70. const aModes: TtsImageModes;
  71. const aChannels: TtsColorChannels);
  72. end;
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. TtsPostProcessorFillPattern = class(TtsPostProcessor)
  75. private
  76. fPattern: TtsImage;
  77. fOwnsPattern: Boolean;
  78. fPosition: TtsPosition;
  79. fModes: TtsImageModes;
  80. fChannels: TtsColorChannels;
  81. procedure SetPattern(aValue: TtsImage);
  82. public
  83. property Pattern: TtsImage read fPattern write SetPattern;
  84. property OwnsPattern: Boolean read fOwnsPattern write fOwnsPattern;
  85. property Position: TtsPosition read fPosition write fPosition;
  86. property Modes: TtsImageModes read fModes write fModes;
  87. property Channels: TtsColorChannels read fChannels write fChannels;
  88. function Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean; override;
  89. constructor Create(
  90. const aContext: TtsContext;
  91. const aPattern: TtsImage;
  92. const aOwnsPattern: Boolean;
  93. const aPosition: TtsPosition;
  94. const aModes: TtsImageModes;
  95. const aChannels: TtsColorChannels);
  96. destructor Destroy; override;
  97. end;
  98. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  99. TtsPostProcessorBorder = class(TtsPostProcessor)
  100. private
  101. fKernel: TtsKernel2D;
  102. fKeepSize: Boolean;
  103. fColor: TtsColor4f;
  104. fStrength: Single;
  105. fWidth: Single;
  106. procedure SetStrength(const aValue: Single);
  107. procedure SetWidth(const aValue: Single);
  108. public
  109. property Width: Single read fWidth write SetWidth;
  110. property Strength: Single read fStrength write SetStrength;
  111. property Color: TtsColor4f read fColor write fColor;
  112. property KeepSize: Boolean read fKeepSize write fKeepSize;
  113. function Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean; override;
  114. constructor Create(
  115. const aContext: TtsContext;
  116. const aWidth, aStrength: Single;
  117. const aColor: TtsColor4f;
  118. const aKeepSize: Boolean);
  119. destructor Destroy; override;
  120. end;
  121. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. TtsPostProcessorShadow = class(TtsPostProcessor)
  123. private
  124. fKernel: TtsKernel1D;
  125. fColor: TtsColor4f;
  126. fOffset: TtsPosition;
  127. fRadius: Single;
  128. fStrength: Single;
  129. procedure SetRadius(const aValue: Single);
  130. procedure SetStrength(const aValue: Single);
  131. public
  132. property Radius: Single read fRadius write SetRadius;
  133. property Strength: Single read fStrength write SetStrength;
  134. property Offset: TtsPosition read fOffset write fOffset;
  135. property Color: TtsColor4f read fColor write fColor;
  136. function Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean; override;
  137. constructor Create(
  138. const aContext: TtsContext;
  139. const aRadius, aStrength: Single;
  140. const aOffset: TtsPosition;
  141. const aColor: TtsColor4f);
  142. destructor Destroy; override;
  143. end;
  144. implementation
  145. uses
  146. utsConstants;
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. //TtsPostProcessor//////////////////////////////////////////////////////////////////////////////////////////////////////
  149. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  150. procedure TtsPostProcessor.ClearList(const aList: TList);
  151. var
  152. i: Integer;
  153. p: PtsCharRange;
  154. begin
  155. for i := 0 to aList.Count-1 do begin
  156. p := aList[i];
  157. Dispose(p);
  158. end;
  159. aList.Clear;
  160. end;
  161. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. function TtsPostProcessor.IsInRange(const aCharCode: WideChar): Boolean;
  163. var
  164. i: Integer;
  165. p: PtsCharRange;
  166. begin
  167. result := (fIncludeCharRanges.Count = 0);
  168. if not result then for i := 0 to fIncludeCharRanges.Count-1 do begin
  169. p := fIncludeCharRanges[i];
  170. if (aCharCode >= p^.Start) and (aCharCode <= p^.Stop) then begin
  171. result := true;
  172. break;
  173. end;
  174. end;
  175. if result then for i := 0 to fExcludeCharRanges.Count-1 do begin
  176. p := fExcludeCharRanges[i];
  177. if (aCharCode >= p^.Start) and (aCharCode <= p^.Stop) then begin
  178. result := false;
  179. break;
  180. end;
  181. end;
  182. end;
  183. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  184. procedure TtsPostProcessor.AddRange(const aUsage: TtsCharRangeUsage; const aStart, aStop: WideChar);
  185. var
  186. p: PtsCharRange;
  187. begin
  188. new(p);
  189. p^.Start := aStart;
  190. p^.Stop := aStop;
  191. case aUsage of
  192. tsUsageInclude: fIncludeCharRanges.Add(p);
  193. tsUsageExclude: fExcludeCharRanges.Add(p);
  194. end;
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. procedure TtsPostProcessor.AddChars(const aUsage: TtsCharRangeUsage; aChars: PWideChar);
  198. begin
  199. if not Assigned(aChars) then
  200. exit;
  201. while (aChars^ <> #0) do begin
  202. AddRange(aUsage, aChars^, aChars^);
  203. inc(aChars);
  204. end;
  205. end;
  206. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  207. procedure TtsPostProcessor.ClearRanges;
  208. begin
  209. ClearList(fIncludeCharRanges);
  210. ClearList(fExcludeCharRanges);
  211. end;
  212. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213. function TtsPostProcessor.Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean;
  214. begin
  215. result := IsInRange(aChar.CharCode);
  216. end;
  217. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. constructor TtsPostProcessor.Create(const aContext: TtsContext);
  219. begin
  220. inherited Create(aContext);
  221. fIncludeCharRanges := TList.Create;
  222. fExcludeCharRanges := TList.Create;
  223. end;
  224. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  225. destructor TtsPostProcessor.Destroy;
  226. begin
  227. ClearRanges;
  228. FreeAndNil(fIncludeCharRanges);
  229. FreeAndNil(fExcludeCharRanges);
  230. inherited Destroy;
  231. end;
  232. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  233. //TtsPostProcessorList//////////////////////////////////////////////////////////////////////////////////////////////////
  234. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  235. function TtsPostProcessorList.GetCount: Integer;
  236. begin
  237. result := fItems.Count;
  238. end;
  239. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  240. function TtsPostProcessorList.GetOwnsObjects: Boolean;
  241. begin
  242. result := fItems.OwnsObjects;
  243. end;
  244. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. procedure TtsPostProcessorList.SetOwnsObjects(const aValue: Boolean);
  246. begin
  247. fItems.OwnsObjects := aValue;
  248. end;
  249. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  250. procedure TtsPostProcessorList.Add(const aPostProcessor: TtsPostProcessor);
  251. begin
  252. fItems.Add(aPostProcessor);
  253. end;
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. procedure TtsPostProcessorList.Delete(const aIndex: Integer);
  256. begin
  257. fItems.Delete(aIndex);
  258. end;
  259. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. procedure TtsPostProcessorList.Clear;
  261. begin
  262. fItems.Clear;
  263. end;
  264. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  265. function TtsPostProcessorList.Remove(const aPostProcessor: TtsPostProcessor): Integer;
  266. begin
  267. result := fItems.IndexOf(aPostProcessor);
  268. if (result >= 0) then
  269. fItems.Delete(result);
  270. end;
  271. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  272. function TtsPostProcessorList.IndexOf(const aPostProcessor: TtsPostProcessor): Integer;
  273. begin
  274. result := fItems.IndexOf(aPostProcessor);
  275. end;
  276. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  277. function TtsPostProcessorList.Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean;
  278. var
  279. i: Integer;
  280. begin
  281. result := inherited Execute(aChar, aImage);
  282. if result then
  283. for i := 0 to fItems.Count-1 do
  284. (fItems[i] as TtsPostProcessor).Execute(aChar, aImage);
  285. end;
  286. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  287. constructor TtsPostProcessorList.Create(const aContext: TtsContext; const aOwnsObjects: Boolean);
  288. begin
  289. inherited Create(aContext);
  290. fItems := TObjectList.Create(aOwnsObjects);
  291. end;
  292. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  293. destructor TtsPostProcessorList.Destroy;
  294. begin
  295. FreeAndNil(fItems);
  296. inherited Destroy;
  297. end;
  298. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  299. //TtsPostProcessorFillColor/////////////////////////////////////////////////////////////////////////////////////////////
  300. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  301. function TtsPostProcessorFillColor.Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean;
  302. begin
  303. result := inherited Execute(aChar, aImage);
  304. if result and Assigned(aImage) then
  305. aImage.FillColor(fColor, fChannels, fModes);
  306. end;
  307. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  308. constructor TtsPostProcessorFillColor.Create(const aContext: TtsContext; const aColor: TtsColor4f;
  309. const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  310. begin
  311. inherited Create(aContext);
  312. fColor := aColor;
  313. fModes := aModes;
  314. fChannels := aChannels;
  315. end;
  316. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  317. //TtsPostProcessorFillPattern///////////////////////////////////////////////////////////////////////////////////////////
  318. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  319. procedure TtsPostProcessorFillPattern.SetPattern(aValue: TtsImage);
  320. begin
  321. if (fPattern = aValue) then
  322. exit;
  323. if fOwnsPattern then
  324. FreeAndNil(fPattern);
  325. fPattern := aValue;
  326. end;
  327. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  328. function TtsPostProcessorFillPattern.Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean;
  329. begin
  330. result := inherited Execute(aChar, aImage);
  331. if result and Assigned(aImage) then
  332. aImage.FillPattern(fPattern, fPosition.x, fPosition.y, fChannels, fModes);
  333. end;
  334. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  335. constructor TtsPostProcessorFillPattern.Create(const aContext: TtsContext; const aPattern: TtsImage;
  336. const aOwnsPattern: Boolean; const aPosition: TtsPosition; const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  337. begin
  338. inherited Create(aContext);
  339. fPattern := aPattern;
  340. fOwnsPattern := aOwnsPattern;
  341. fPosition := aPosition;
  342. fModes := aModes;
  343. fChannels := aChannels;
  344. end;
  345. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  346. destructor TtsPostProcessorFillPattern.Destroy;
  347. begin
  348. if fOwnsPattern then
  349. FreeAndNil(fPattern);
  350. inherited Destroy;
  351. end;
  352. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  353. //TtsPostProcessorBorder////////////////////////////////////////////////////////////////////////////////////////////////
  354. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  355. procedure TtsPostProcessorBorder.SetStrength(const aValue: Single);
  356. begin
  357. fStrength := aValue;
  358. FreeAndNil(fKernel);
  359. fKernel := TtsKernel2D.Create(fWidth, fStrength);
  360. end;
  361. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  362. procedure TtsPostProcessorBorder.SetWidth(const aValue: Single);
  363. begin
  364. fWidth := aValue;
  365. FreeAndNil(fKernel);
  366. fKernel := TtsKernel2D.Create(fWidth, fStrength);
  367. end;
  368. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  369. function TtsPostProcessorBorder.Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean;
  370. var
  371. orig: TtsImage;
  372. x, y: Integer;
  373. dst: PByte;
  374. m: TtsGlyphMetric;
  375. function BorderLookup: TtsColor4f;
  376. var
  377. i: Integer;
  378. c: TtsColor4f;
  379. s: Single;
  380. chan: TtsColorChannel;
  381. mask: TtsColorChannels;
  382. tmpX, tmpY: Integer;
  383. begin
  384. mask := TS_COLOR_CHANNELS_RGBA;
  385. result := tsColor4f(0, 0, 0, 0);
  386. for i := 0 to fKernel.ItemCount-1 do begin
  387. tmpX := x + fKernel.Items[i].OffsetX;
  388. tmpY := y + fKernel.Items[i].OffsetY;
  389. if (tmpX >= 0) and (tmpX < orig.Width) and
  390. (tmpY >= 0) and (tmpY < orig.Height) and
  391. orig.GetPixelAt(tmpX, tmpY, c) then
  392. begin
  393. {$IFDEF FPC}
  394. for chan in mask do begin
  395. {$ELSE}
  396. for chan := low(TtsColorChannel) to high(TtsColorChannel) do if (chan in mask) then begin
  397. {$ENDIF}
  398. s := c.arr[Integer(chan)] * fColor.arr[Integer(chan)] * fKernel.Items[i].Value;
  399. if (s > result.arr[Integer(chan)]) then begin
  400. result.arr[Integer(chan)] := s;
  401. if (s >= 1.0) then begin
  402. Exclude(mask, chan);
  403. if (mask = []) then
  404. exit;
  405. end;
  406. end;
  407. end;
  408. end;
  409. end;
  410. end;
  411. begin
  412. result := inherited Execute(aChar, aImage);
  413. if not result or not Assigned(aImage) then
  414. exit;
  415. aImage.Resize(
  416. aImage.Width + 2 * fKernel.SizeX,
  417. aImage.Height + 2 * fKernel.SizeY,
  418. fKernel.SizeX, fKernel.SizeY);
  419. orig := TtsImage.Create;
  420. try
  421. orig.Assign(aImage);
  422. aImage.FillColor(fColor, TS_COLOR_CHANNELS_RGBA, TS_IMAGE_MODES_REPLACE_ALL);
  423. for y := 0 to orig.Height-1 do begin
  424. dst := aImage.Scanline[y];
  425. for x := 0 to orig.Width-1 do
  426. tsFormatMap(aImage.Format, dst, BorderLookup);
  427. end;
  428. aImage.Blend(orig, 0, 0, @tsBlendColorAdditiveAlpha);
  429. finally
  430. FreeAndNil(orig);
  431. end;
  432. m := aChar.GlyphMetric;
  433. m.GlyphRect.Right := m.GlyphRect.Right + 2 * fKernel.SizeX;
  434. m.GlyphRect.Bottom := m.GlyphRect.Bottom + 2 * fKernel.SizeY;
  435. if fKeepSize then begin
  436. m.GlyphOrigin.x := m.GlyphOrigin.x - fKernel.SizeX;
  437. m.GlyphOrigin.y := m.GlyphOrigin.y + fKernel.SizeY;
  438. end else begin
  439. m.Advance := m.Advance + 2 * fKernel.SizeX;
  440. m.GlyphOrigin.y := m.GlyphOrigin.y + fKernel.SizeY;
  441. end;
  442. aChar.GlyphMetric := m;
  443. end;
  444. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  445. constructor TtsPostProcessorBorder.Create(const aContext: TtsContext;
  446. const aWidth, aStrength: Single; const aColor: TtsColor4f; const aKeepSize: Boolean);
  447. begin
  448. inherited Create(aContext);
  449. fWidth := aWidth;
  450. fStrength := aStrength;
  451. fColor := aColor;
  452. fKeepSize := aKeepSize;
  453. fKernel := TtsKernel2D.Create(fWidth, fStrength);
  454. end;
  455. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  456. destructor TtsPostProcessorBorder.Destroy;
  457. begin
  458. FreeAndNil(fKernel);
  459. inherited Destroy;
  460. end;
  461. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  462. //TtsPostProcessorShadow////////////////////////////////////////////////////////////////////////////////////////////////
  463. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  464. procedure TtsPostProcessorShadow.SetRadius(const aValue: Single);
  465. begin
  466. fRadius := aValue;
  467. FreeAndNil(fKernel);
  468. fKernel := TtsKernel1D.Create(fRadius, fStrength);
  469. end;
  470. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  471. procedure TtsPostProcessorShadow.SetStrength(const aValue: Single);
  472. begin
  473. fStrength := aValue;
  474. FreeAndNil(fKernel);
  475. fKernel := TtsKernel1D.Create(fRadius, fStrength);
  476. end;
  477. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  478. function TtsPostProcessorShadow.Execute(const aChar: TtsChar; const aImage: TtsImage): Boolean;
  479. var
  480. orig: TtsImage;
  481. tmpX, tmpY: Integer;
  482. m: TtsGlyphMetric;
  483. begin
  484. result := inherited Execute(aChar, aImage);
  485. if not result or not Assigned(aImage) then
  486. exit;
  487. orig := TtsImage.Create;
  488. try
  489. orig.Assign(aImage);
  490. aImage.Resize(
  491. aImage.Width + 2 * fKernel.Size,
  492. aImage.Height + 2 * fKernel.Size,
  493. fKernel.Size, fKernel.Size);
  494. aImage.FillColor(fColor, TS_COLOR_CHANNELS_RGBA, TS_IMAGE_MODES_MODULATE_ALPHA);
  495. aImage.Blur(fKernel, fKernel, [tsChannelAlpha]);
  496. tmpX := fKernel.Size - fOffset.x;
  497. tmpY := fKernel.Size - fOffset.y;
  498. aImage.Blend(orig, tmpX, tmpY, @tsBlendColorAlpha);
  499. m := aChar.GlyphMetric;
  500. m.GlyphRect.Right := m.GlyphRect.Right + 2 * fKernel.Size;
  501. m.GlyphRect.Bottom := m.GlyphRect.Bottom + 2 * fKernel.Size;
  502. m.GlyphOrigin.x := m.GlyphOrigin.x - tmpX;
  503. m.GlyphOrigin.y := m.GlyphOrigin.y + tmpX;
  504. aChar.GlyphMetric := m;
  505. finally
  506. FreeAndNil(orig);
  507. end;
  508. end;
  509. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  510. constructor TtsPostProcessorShadow.Create(const aContext: TtsContext; const aRadius, aStrength: Single;
  511. const aOffset: TtsPosition; const aColor: TtsColor4f);
  512. begin
  513. inherited Create(aContext);
  514. fRadius := aRadius;
  515. fStrength := aStrength;
  516. fOffset := aOffset;
  517. fColor := aColor;
  518. fKernel := TtsKernel1D.Create(fRadius, fStrength);
  519. end;
  520. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  521. destructor TtsPostProcessorShadow.Destroy;
  522. begin
  523. FreeAndNil(fKernel);
  524. inherited Destroy;
  525. end;
  526. end.