ftfont.pp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2003 by the Free Pascal development team
  4. Basic canvas definitions.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}{$h+}
  12. unit ftfont;
  13. interface
  14. uses SysUtils, Classes, FPCanvas, fpimgcmn, freetype, freetypeh;
  15. type
  16. FreeTypeFontException = class (TFPFontException);
  17. TFreeTypeFont = class (TFPCustomDrawFont)
  18. private
  19. FResolution : longword;
  20. FAntiAliased : boolean;
  21. FLastText : TStringBitmaps;
  22. FIndex, FFontID : integer;
  23. FFace : PFT_Face;
  24. FAngle : real;
  25. procedure DrawChar (x,y:integer; data:PByteArray; pitch, width, height:integer);
  26. procedure DrawCharBW (x,y:integer; data:PByteArray; pitch, width, height:integer);
  27. procedure ClearLastText;
  28. protected
  29. procedure SetName (AValue:string); override;
  30. procedure SetIndex (AValue : integer);
  31. procedure SetSize (AValue : integer); override;
  32. function GetFlags (index:integer) : boolean; override;
  33. procedure SetFlags (index:integer; AValue:boolean); override;
  34. procedure DoAllocateResources; override;
  35. procedure DoDeAllocateResources; override;
  36. procedure DoCopyProps (From:TFPCanvasHelper); override;
  37. procedure DoDrawText (atx,aty:integer; atext:string); override;
  38. procedure DoGetTextSize (text:string; var w,h:integer); override;
  39. function DoGetTextHeight (text:string) : integer; override;
  40. function DoGetTextWidth (text:string) : integer; override;
  41. procedure GetText (aText:string);
  42. procedure GetFace;
  43. public
  44. constructor create; override;
  45. destructor Destroy; override;
  46. property FontIndex : integer read FIndex write SetIndex;
  47. property Resolution : longword read FResolution write FResolution;
  48. property AntiAliased : boolean read FAntiAliased write FAntiAliased;
  49. property Angle : real read FAngle write FAngle;
  50. end;
  51. var
  52. FontMgr : TFontManager;
  53. procedure InitEngine;
  54. procedure DoneEngine;
  55. implementation
  56. uses fpimage;
  57. procedure InitEngine;
  58. begin
  59. if not assigned (FontMgr) then
  60. FontMgr := TFontManager.create;
  61. end;
  62. procedure DoneEngine;
  63. begin
  64. if assigned (FontMgr) then
  65. FontMgr.Free;
  66. end;
  67. constructor TFreeTypeFont.Create;
  68. begin
  69. inherited;
  70. FFontID := -1;
  71. FAntiAliased := True;
  72. FResolution := DefaultResolution;
  73. end;
  74. destructor TFreeTypeFont.Destroy;
  75. begin
  76. ClearLastText;
  77. inherited Destroy;
  78. end;
  79. procedure TFreeTypeFont.DoCopyProps (From:TFPCanvasHelper);
  80. var f : TFreeTypeFont;
  81. begin
  82. inherited;
  83. if from is TFreeTypeFont then
  84. begin
  85. f := TFreeTypeFont(from);
  86. FIndex := F.Findex;
  87. FAntiAliased := f.FAntiAliased;
  88. FResolution := f.FResolution;
  89. FAngle := f.FAngle;
  90. end;
  91. end;
  92. procedure TFreeTypeFont.SetName (AValue:string);
  93. begin
  94. inherited;
  95. ClearLastText;
  96. if allocated then
  97. FFontID := FontMgr.RequestFont(Name, FIndex);
  98. end;
  99. procedure TFreeTypeFont.SetIndex (AValue : integer);
  100. begin
  101. FIndex := AValue;
  102. ClearLastText;
  103. if allocated then
  104. FFontID := FontMgr.RequestFont(Name, FIndex);
  105. end;
  106. procedure TFreeTypeFont.SetSize (AValue : integer);
  107. begin
  108. ClearLastText;
  109. inherited;
  110. end;
  111. procedure TFreeTypeFont.ClearLastText;
  112. begin
  113. if assigned(FLastText) then
  114. begin
  115. FLastText.Free;
  116. FlastText := nil;
  117. end;
  118. end;
  119. procedure TFreeTypeFont.DoAllocateResources;
  120. begin
  121. InitEngine;
  122. FFontID := FontMgr.RequestFont(Name, FIndex);
  123. end;
  124. procedure TFreeTypeFont.DoDeAllocateResources;
  125. begin
  126. end;
  127. procedure TFreeTypeFont.DoGetTextSize (text:string; var w,h:integer);
  128. var r : TRect;
  129. begin
  130. GetText (text);
  131. FLastText.GetBoundRect (r);
  132. with r do
  133. begin
  134. w := right - left;
  135. h := top - bottom;
  136. end;
  137. end;
  138. function TFreeTypeFont.DoGetTextHeight (text:string) : integer;
  139. var r : TRect;
  140. begin
  141. GetText (text);
  142. FLastText.GetBoundRect (r);
  143. with r do
  144. result := top - bottom;
  145. end;
  146. function TFreeTypeFont.DoGetTextWidth (text:string) : integer;
  147. var r : TRect;
  148. begin
  149. GetText (text);
  150. FLastText.GetBoundRect (r);
  151. with r do
  152. result := right - left;
  153. end;
  154. procedure TFreeTypeFont.SetFlags (index:integer; AValue:boolean);
  155. begin
  156. if not (index in [5,6]) then // bold,italic
  157. inherited SetFlags (index, AValue);
  158. end;
  159. procedure TFreeTypeFont.GetFace;
  160. begin
  161. if not assigned(FFace) then
  162. FFace := FontMgr.GetFreeTypeFont (FFontID);
  163. end;
  164. function TFreeTypeFont.GetFlags (index:integer) : boolean;
  165. begin
  166. if index = 5 then //bold
  167. begin
  168. GetFace;
  169. result := (FFace^.style_flags and FT_STYLE_FLAG_BOLD) <> 0;
  170. end
  171. else if index = 6 then //italic
  172. begin
  173. GetFace;
  174. result := (FFace^.style_flags and FT_STYLE_FLAG_ITALIC) <> 0;
  175. end
  176. else
  177. result := inherited GetFlags (index);
  178. end;
  179. procedure TFreeTypeFont.GetText (aText:string);
  180. var b : boolean;
  181. begin
  182. if assigned (FLastText) then
  183. begin
  184. if CompareStr(FLastText.Text,aText) <> 0 then
  185. begin
  186. FLastText.Free;
  187. b := true;
  188. end
  189. else
  190. begin
  191. if FAntiAliased then
  192. b := (FLastText.mode <> bt256Gray)
  193. else
  194. b := (FLastText.mode <> btBlackWhite);
  195. if b then
  196. FLastText.Free;
  197. end;
  198. end
  199. else
  200. b := true;
  201. if b then
  202. begin
  203. FontMgr.Resolution := FResolution;
  204. if FAntiAliased then
  205. FLastText := FontMgr.GetStringGray (FFontId, aText, Size, Angle)
  206. else
  207. FLastText := FontMgr.GetString (FFontId, aText, Size, Angle);
  208. end;
  209. end;
  210. procedure TFreeTypeFont.DoDrawText (atX,atY:integer; atext:string);
  211. var r,i : integer;
  212. f : longint;
  213. begin
  214. GetText (atext);
  215. with FLastText do
  216. for r := 0 to count-1 do
  217. with Bitmaps[r]^ do
  218. begin
  219. if mode = btBlackWhite then
  220. DrawCharBW (atX+x, atY+y, data, pitch, width, height)
  221. else
  222. DrawChar (atX+x, atY+y, data, pitch, width, height);
  223. end;
  224. end;
  225. const
  226. //bits : array[0..7] of byte = (1,2,4,8,16,32,64,128);
  227. bits : array[0..7] of byte = (128,64,32,16,8,4,2,1);
  228. procedure TFreeTypeFont.DrawChar (x,y:integer; data:PByteArray; pitch, width, height:integer);
  229. procedure Combine (canv:TFPCustomCanvas; x,y:integer; c : TFPColor; t:longword);
  230. var a,r,g,b:longword;
  231. begin
  232. if t = 255 then
  233. canv.colors[x,y] := c
  234. else if t <> 0 then
  235. begin
  236. with canv.colors[x,y] do
  237. begin
  238. a := 255-t;
  239. r := ((red * a) + (c.red * t)) div 255;
  240. g := ((green * a) + (c.green * t)) div 255;
  241. b := ((blue * a) + (c.blue * t)) div 255;
  242. end;
  243. canv.colors[x,y] := FPImage.FPColor(r,g,b,alphaOpaque);
  244. end;
  245. end;
  246. var b,rx,ry : integer;
  247. begin
  248. b := 0;
  249. for ry := 0 to height-1 do
  250. begin
  251. for rx := 0 to width-1 do
  252. combine (canvas, x+rx, y+ry, FPColor, data^[b+rx]);
  253. inc (b, pitch);
  254. end;
  255. end;
  256. procedure TFreeTypeFont.DrawCharBW (x,y:integer; data:PByteArray; pitch, width, height:integer);
  257. var rb : byte;
  258. rx,ry,b,l : integer;
  259. begin
  260. b := 0;
  261. for ry := 0 to height-1 do
  262. begin
  263. l := 0;
  264. for rx := 0 to width-1 do
  265. begin
  266. rb := rx mod 8;
  267. if (data^[b+l] and bits[rb]) <> 0 then
  268. canvas.colors[x+rx,y+ry] := FPColor;
  269. if rb = 7 then
  270. inc (l);
  271. end;
  272. inc (b, pitch);
  273. end;
  274. end;
  275. finalization
  276. DoneEngine;
  277. end.