Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

278 строки
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. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. //TtsPostProcessFillColor///////////////////////////////////////////////////////////////////////////////////////////////
  64. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  65. procedure TtsPostProcessFillColor.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  66. begin
  67. if Assigned(aCharImage) then
  68. aCharImage.FillColor(fColor, fChannels, fModes);
  69. end;
  70. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  71. constructor TtsPostProcessFillColor.Create(const aColor: TtsColor4f; const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  72. begin
  73. inherited Create;
  74. fColor := aColor;
  75. fModes := aModes;
  76. fChannels := aChannels;
  77. end;
  78. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  79. //TtsPostProcessFillPattern/////////////////////////////////////////////////////////////////////////////////////////////
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. procedure TtsPostProcessFillPattern.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  82. begin
  83. if Assigned(aCharImage) then
  84. aCharImage.FillPattern(fPattern, fX, fY, fChannels, fModes);
  85. end;
  86. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. constructor TtsPostProcessFillPattern.Create(const aPattern: TtsImage; const aOwnsPattern: Boolean; const X,
  88. Y: Integer; const aModes: TtsImageModes; const aChannels: TtsColorChannels);
  89. begin
  90. inherited Create;
  91. fPattern := aPattern;
  92. fOwnsPattern := aOwnsPattern;
  93. fX := X;
  94. fY := Y;
  95. fModes := aModes;
  96. fChannels := aChannels;
  97. end;
  98. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  99. destructor TtsPostProcessFillPattern.Destroy;
  100. begin
  101. if fOwnsPattern then
  102. FreeAndNil(fPattern);
  103. inherited Destroy;
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. //TtsPostProcessBorder//////////////////////////////////////////////////////////////////////////////////////////////////
  107. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. procedure TtsPostProcessBorder.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  109. var
  110. orig: TtsImage;
  111. x, y: Integer;
  112. dst: PByte;
  113. function BorderLookup: TtsColor4f;
  114. var
  115. i: Integer;
  116. c: TtsColor4f;
  117. s: Single;
  118. chan: TtsColorChannel;
  119. mask: TtsColorChannels;
  120. tmpX, tmpY: Integer;
  121. begin
  122. mask := TS_CHANNELS_RGBA;
  123. result := tsColor4f(0, 0, 0, 0);
  124. for i := 0 to fKernel.ItemCount-1 do begin
  125. tmpX := x + fKernel.Items[i].OffsetX;
  126. tmpY := y + fKernel.Items[i].OffsetY;
  127. if (tmpX >= 0) and (tmpX < orig.Width) and
  128. (tmpY >= 0) and (tmpY < orig.Height) and
  129. orig.GetPixelAt(tmpX, tmpY, c) then
  130. begin
  131. {$IFDEF FPC}
  132. for chan in mask do begin
  133. {$ELSE}
  134. for chan := low(TtsColorChannel) to high(TtsColorChannel) do if (chan in mask) then begin
  135. {$ENDIF}
  136. s := c.arr[Integer(chan)] * fColor.arr[Integer(chan)] * fKernel.Items[i].Value;
  137. if (s > result.arr[Integer(chan)]) then begin
  138. result.arr[Integer(chan)] := s;
  139. if (s >= 1.0) then begin
  140. Exclude(mask, chan);
  141. if (mask = []) then
  142. exit;
  143. end;
  144. end;
  145. end;
  146. end;
  147. end;
  148. end;
  149. begin
  150. if not Assigned(aCharImage) then
  151. exit;
  152. aCharImage.Resize(
  153. aCharImage.Width + 2 * fKernel.SizeX,
  154. aCharImage.Height + 2 * fKernel.SizeY,
  155. fKernel.SizeX, fKernel.SizeY);
  156. orig := TtsImage.Create;
  157. try
  158. orig.Assign(aCharImage);
  159. aCharImage.FillColor(fColor, TS_CHANNELS_RGBA, TS_MODES_REPLACE_ALL);
  160. for y := 0 to orig.Height-1 do begin
  161. dst := aCharImage.Scanline[y];
  162. for x := 0 to orig.Width-1 do
  163. tsFormatMap(aCharImage.Format, dst, BorderLookup);
  164. end;
  165. aCharImage.Blend(orig, 0, 0, @tsBlendFundAdditiveAlpha);
  166. finally
  167. FreeAndNil(orig);
  168. end;
  169. aChar.GlyphRect := tsRect(
  170. aChar.GlyphRect.Left,
  171. aChar.GlyphRect.Top,
  172. aChar.GlyphRect.Right + 2 * fKernel.SizeX,
  173. aChar.GlyphRect.Bottom + 2 * fKernel.SizeY);
  174. if fKeepCharSize then begin
  175. aChar.GlyphOrigin := tsPosition(
  176. aChar.GlyphOrigin.x - fKernel.SizeX,
  177. aChar.GlyphOrigin.y + fKernel.SizeY);
  178. end else begin
  179. aChar.Advance := aChar.Advance + 2 * fKernel.SizeX;
  180. aChar.GlyphOrigin := tsPosition(
  181. aChar.GlyphOrigin.x,
  182. aChar.GlyphOrigin.y + fKernel.SizeY);
  183. end;
  184. end;
  185. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  186. constructor TtsPostProcessBorder.Create(const aWidth, aStrength: Single; const aColor: TtsColor4f; const aKeepCharSize: Boolean);
  187. begin
  188. inherited Create;
  189. fKernel := TtsKernel2D.Create(aWidth, aStrength);
  190. fColor := aColor;
  191. fKeepCharSize := aKeepCharSize;
  192. end;
  193. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. destructor TtsPostProcessBorder.Destroy;
  195. begin
  196. FreeAndNil(fKernel);
  197. inherited Destroy;
  198. end;
  199. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  200. //TtsPostProcessShadow//////////////////////////////////////////////////////////////////////////////////////////////////
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  202. procedure TtsPostProcessShadow.Execute(const aChar: TtsChar; const aCharImage: TtsImage);
  203. var
  204. orig: TtsImage;
  205. tmpX, tmpY: Integer;
  206. begin
  207. orig := TtsImage.Create;
  208. try
  209. orig.Assign(aCharImage);
  210. aCharImage.Resize(
  211. aCharImage.Width + 2 * fKernel.Size,
  212. aCharImage.Height + 2 * fKernel.Size,
  213. fKernel.Size, fKernel.Size);
  214. aCharImage.FillColor(fColor, TS_CHANNELS_RGBA, TS_MODES_MODULATE_ALPHA);
  215. aCharImage.Blur(fKernel, fKernel, [tsChannelAlpha]);
  216. tmpX := fKernel.Size - fX;
  217. tmpY := fKernel.Size - fY;
  218. aCharImage.Blend(orig, tmpX, tmpY, @tsBlendFundAlpha);
  219. aChar.GlyphRect := tsRect(
  220. aChar.GlyphRect.Left,
  221. aChar.GlyphRect.Top,
  222. aChar.GlyphRect.Right + 2 * fKernel.Size,
  223. aChar.GlyphRect.Bottom + 2 * fKernel.Size);
  224. aChar.GlyphOrigin := tsPosition(
  225. aChar.GlyphOrigin.x - tmpX,
  226. aChar.GlyphOrigin.y + tmpX);
  227. finally
  228. FreeAndNil(orig);
  229. end;
  230. end;
  231. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  232. constructor TtsPostProcessShadow.Create(const aRadius, aStrength: Single; const X, Y: Integer; const aColor: TtsColor4f);
  233. begin
  234. inherited Create;
  235. fKernel := TtsKernel1D.Create(aRadius, aStrength);
  236. fX := X;
  237. fY := Y;
  238. fColor := aColor;
  239. end;
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. destructor TtsPostProcessShadow.Destroy;
  242. begin
  243. FreeAndNil(fKernel);
  244. inherited Destroy;
  245. end;
  246. end.