Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

281 Zeilen
9.6 KiB

  1. unit utsPostProcess;
  2. {$IFDEF FPC}
  3. {$mode delphi}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. Classes, SysUtils, utsTextSuite, utsTypes;
  8. type
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TtsPostProcessFillColor = class(TtsPostProcessStep)
  11. private
  12. fColor: TtsColor4f;
  13. fModes: TtsImageModes;
  14. fChannels: TtsColorChannels;
  15. protected
  16. procedure Execute(const aChar: TtsChar; const aCharImage: TtsImage); override;
  17. public
  18. constructor Create(const aColor: TtsColor4f;
  19. const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  20. end;
  21. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. TtsPostProcessFillPattern = class(TtsPostProcessStep)
  23. private
  24. fPattern: TtsImage;
  25. fOwnsPattern: Boolean;
  26. fX, fY: Integer;
  27. fModes: TtsImageModes;
  28. fChannels: TtsColorChannels;
  29. protected
  30. procedure Execute(const aChar: TtsChar; const aCharImage: TtsImage); override;
  31. public
  32. constructor Create(const aPattern: TtsImage; const aOwnsPattern: Boolean; const X, Y: Integer;
  33. const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  34. destructor Destroy; override;
  35. end;
  36. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. TtsPostProcessBorder = class(TtsPostProcessStep)
  38. private
  39. fKernel: TtsKernel2D;
  40. fColor: TtsColor4f;
  41. fKeepCharSize: Boolean;
  42. public
  43. procedure Execute(const aChar: TtsChar; const aCharImage: TtsImage); override;
  44. public
  45. constructor Create(const aWidth, aStrength: Single; const aColor: TtsColor4f;
  46. const aKeepCharSize: Boolean = false);
  47. destructor Destroy; override;
  48. end;
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. TtsPostProcessShadow = class(TtsPostProcessStep)
  51. private
  52. fKernel: TtsKernel1D;
  53. fColor: TtsColor4f;
  54. fX, fY: Integer;
  55. protected
  56. procedure Execute(const aChar: TtsChar; const aCharImage: TtsImage); override;
  57. public
  58. constructor Create(const aRadius, aStrength: Single; const X, Y: Integer; const aColor: TtsColor4f);
  59. destructor Destroy; override;
  60. end;
  61. implementation
  62. uses
  63. Math;
  64. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  65. //TtsPostProcessFillColor///////////////////////////////////////////////////////////////////////////////////////////////
  66. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  67. procedure TtsPostProcessFillColor.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  68. begin
  69. if Assigned(aCharImage) then
  70. aCharImage.FillColor(fColor, fChannels, fModes);
  71. end;
  72. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. constructor TtsPostProcessFillColor.Create(const aColor: TtsColor4f; const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  74. begin
  75. inherited Create;
  76. fColor := aColor;
  77. fModes := aModes;
  78. fChannels := aChannels;
  79. end;
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. //TtsPostProcessFillPattern/////////////////////////////////////////////////////////////////////////////////////////////
  82. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  83. procedure TtsPostProcessFillPattern.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  84. begin
  85. if Assigned(aCharImage) then
  86. aCharImage.FillPattern(fPattern, fX, fY, fChannels, fModes);
  87. end;
  88. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. constructor TtsPostProcessFillPattern.Create(const aPattern: TtsImage; const aOwnsPattern: Boolean; const X,
  90. Y: Integer; const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  91. begin
  92. inherited Create;
  93. fPattern := aPattern;
  94. fOwnsPattern := aOwnsPattern;
  95. fX := X;
  96. fY := Y;
  97. fModes := aModes;
  98. fChannels := aChannels;
  99. end;
  100. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  101. destructor TtsPostProcessFillPattern.Destroy;
  102. begin
  103. if fOwnsPattern then
  104. FreeAndNil(fPattern);
  105. inherited Destroy;
  106. end;
  107. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. //TtsPostProcessBorder//////////////////////////////////////////////////////////////////////////////////////////////////
  109. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  110. procedure TtsPostProcessBorder.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  111. var
  112. orig: TtsImage;
  113. x, y: Integer;
  114. dst: PByte;
  115. function BorderLookup: TtsColor4f;
  116. var
  117. i: Integer;
  118. c: TtsColor4f;
  119. s: Single;
  120. chan: TtsColorChannel;
  121. mask: TtsColorChannels;
  122. tmpX, tmpY: Integer;
  123. begin
  124. mask := TS_CHANNELS_RGBA;
  125. result := tsColor4f(0, 0, 0, 0);
  126. for i := 0 to fKernel.ItemCount-1 do begin
  127. tmpX := x + fKernel.Items[i].OffsetX;
  128. tmpY := y + fKernel.Items[i].OffsetY;
  129. if (tmpX >= 0) and (tmpX < orig.Width) and
  130. (tmpY >= 0) and (tmpY < orig.Height) and
  131. orig.GetPixelAt(tmpX, tmpY, c) then
  132. begin
  133. {$IFDEF FPC}
  134. for chan in mask do begin
  135. {$ELSE}
  136. for chan := low(TtsColorChannel) to high(TtsColorChannel) do if (chan in mask) then begin
  137. {$ENDIF}
  138. s := c.arr[Integer(chan)] * fColor.arr[Integer(chan)] * fKernel.Items[i].Value;
  139. if (s > result.arr[Integer(chan)]) then begin
  140. result.arr[Integer(chan)] := s;
  141. if (s >= 1.0) then begin
  142. Exclude(mask, chan);
  143. if (mask = []) then
  144. exit;
  145. end;
  146. end;
  147. end;
  148. end;
  149. end;
  150. end;
  151. begin
  152. if not Assigned(aCharImage) then
  153. exit;
  154. aCharImage.Resize(
  155. aCharImage.Width + 2 * fKernel.SizeX,
  156. aCharImage.Height + 2 * fKernel.SizeY,
  157. fKernel.SizeX, fKernel.SizeY);
  158. orig := TtsImage.Create;
  159. try
  160. orig.Assign(aCharImage);
  161. aCharImage.FillColor(fColor, TS_CHANNELS_RGBA, TS_MODES_REPLACE_ALL);
  162. for y := 0 to orig.Height-1 do begin
  163. dst := aCharImage.Scanline[y];
  164. for x := 0 to orig.Width-1 do
  165. tsFormatMap(aCharImage.Format, dst, BorderLookup);
  166. end;
  167. aCharImage.Blend(orig, 0, 0, @tsBlendFundAdditiveAlpha);
  168. finally
  169. FreeAndNil(orig);
  170. end;
  171. aChar.GlyphRect := tsRect(
  172. aChar.GlyphRect.Left,
  173. aChar.GlyphRect.Top,
  174. aChar.GlyphRect.Right + 2 * fKernel.SizeX,
  175. aChar.GlyphRect.Bottom + 2 * fKernel.SizeY);
  176. if fKeepCharSize then begin
  177. aChar.GlyphOrigin := tsPosition(
  178. aChar.GlyphOrigin.x - fKernel.SizeX,
  179. aChar.GlyphOrigin.y + fKernel.SizeY);
  180. end else begin
  181. aChar.Advance := aChar.Advance + 2 * fKernel.SizeX;
  182. aChar.GlyphOrigin := tsPosition(
  183. aChar.GlyphOrigin.x,
  184. aChar.GlyphOrigin.y + fKernel.SizeY);
  185. end;
  186. end;
  187. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. constructor TtsPostProcessBorder.Create(const aWidth, aStrength: Single; const aColor: TtsColor4f; const aKeepCharSize: Boolean);
  189. begin
  190. inherited Create;
  191. fKernel := TtsKernel2D.Create(aWidth, aStrength);
  192. fColor := aColor;
  193. fKeepCharSize := aKeepCharSize;
  194. end;
  195. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  196. destructor TtsPostProcessBorder.Destroy;
  197. begin
  198. FreeAndNil(fKernel);
  199. inherited Destroy;
  200. end;
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  202. //TtsPostProcessShadow//////////////////////////////////////////////////////////////////////////////////////////////////
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. procedure TtsPostProcessShadow.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  205. var
  206. orig: TtsImage;
  207. tmpX, tmpY: Integer;
  208. begin
  209. orig := TtsImage.Create;
  210. try
  211. orig.Assign(aCharImage);
  212. aCharImage.Resize(
  213. aCharImage.Width + 2 * fKernel.Size,
  214. aCharImage.Height + 2 * fKernel.Size,
  215. fKernel.Size, fKernel.Size);
  216. aCharImage.FillColor(fColor, TS_CHANNELS_RGBA, TS_MODES_MODULATE_ALPHA);
  217. aCharImage.Blur(fKernel, fKernel, [tsChannelAlpha]);
  218. tmpX := fKernel.Size - fX;
  219. tmpY := fKernel.Size - fY;
  220. aCharImage.Blend(orig, tmpX, tmpY, @tsBlendFundAlpha);
  221. aChar.GlyphRect := tsRect(
  222. aChar.GlyphRect.Left,
  223. aChar.GlyphRect.Top,
  224. aChar.GlyphRect.Right + 2 * fKernel.Size,
  225. aChar.GlyphRect.Bottom + 2 * fKernel.Size);
  226. aChar.GlyphOrigin := tsPosition(
  227. aChar.GlyphOrigin.x - tmpX,
  228. aChar.GlyphOrigin.y + tmpX);
  229. finally
  230. FreeAndNil(orig);
  231. end;
  232. end;
  233. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. constructor TtsPostProcessShadow.Create(const aRadius, aStrength: Single; const X, Y: Integer; const aColor: TtsColor4f);
  235. begin
  236. inherited Create;
  237. fKernel := TtsKernel1D.Create(aRadius, aStrength);
  238. fX := X;
  239. fY := Y;
  240. fColor := aColor;
  241. end;
  242. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  243. destructor TtsPostProcessShadow.Destroy;
  244. begin
  245. FreeAndNil(fKernel);
  246. inherited Destroy;
  247. end;
  248. end.