sdltruetypefont.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. unit sdltruetypefont;
  2. {
  3. $Id: sdltruetypefont.pas,v 1.1 2004/09/30 22:39:50 savage Exp $
  4. }
  5. {******************************************************************************}
  6. { }
  7. { JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer }
  8. { Wrapper class for SDL_ttf }
  9. { }
  10. { The initial developer of this Pascal code was : }
  11. { Dominqiue Louis <[email protected]> }
  12. { }
  13. { Portions created by Dominqiue Louis are }
  14. { Copyright (C) 2000 - 2001 Dominqiue Louis. }
  15. { }
  16. { }
  17. { Contributor(s) }
  18. { -------------- }
  19. { }
  20. { }
  21. { Obtained through: }
  22. { Joint Endeavour of Delphi Innovators ( Project JEDI ) }
  23. { }
  24. { You may retrieve the latest version of this file at the Project }
  25. { JEDI home page, located at http://delphi-jedi.org }
  26. { }
  27. { The contents of this file are used with permission, subject to }
  28. { the Mozilla Public License Version 1.1 (the "License"); you may }
  29. { not use this file except in compliance with the License. You may }
  30. { obtain a copy of the License at }
  31. { http://www.mozilla.org/MPL/MPL-1.1.html }
  32. { }
  33. { Software distributed under the License is distributed on an }
  34. { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
  35. { implied. See the License for the specific language governing }
  36. { rights and limitations under the License. }
  37. { }
  38. { Description }
  39. { ----------- }
  40. { }
  41. { }
  42. { }
  43. { }
  44. { }
  45. { }
  46. { }
  47. { Requires }
  48. { -------- }
  49. { The SDL Runtime libraris on Win32 : SDL.dll on Linux : libSDL.so }
  50. { They are available from... }
  51. { http://www.libsdl.org . }
  52. { }
  53. { Programming Notes }
  54. { ----------------- }
  55. { }
  56. { }
  57. { }
  58. { }
  59. { Revision History }
  60. { ---------------- }
  61. { September 23 2004 - DL : Initial Creation }
  62. {
  63. $Log: sdltruetypefont.pas,v $
  64. Revision 1.1 2004/09/30 22:39:50 savage
  65. Added a true type font class which contains a wrap text function.
  66. Changed the sdl_ttf.pas header to reflect the future of jedi-sdl.
  67. }
  68. {******************************************************************************}
  69. interface
  70. uses
  71. sdl,
  72. sdl_ttf;
  73. type
  74. TRenderType = ( rtLatin1, rtUTF8, rtUnicode );
  75. TSDLFontStyle = ( fsBold, fsItalic, fsUnderline, fsStrikeOut );
  76. TSDLFontStyles = set of TSDLFontStyle;
  77. TTrueTypeFont = class( TObject )
  78. private
  79. FFont : PTTF_Font;
  80. FSolid : Boolean;
  81. FBackGroundColour : TSDL_Color;
  82. FForeGroundColour : TSDL_Color;
  83. FRenderType : TRenderType;
  84. FStyle : TSDLFontStyles;
  85. FFontFile : string;
  86. FFontSize : integer;
  87. procedure PrepareFont;
  88. protected
  89. public
  90. constructor Create( aFontFile : string; aRenderStyle : TSDLFontStyles = [ ]; aFontSize : integer = 14 );
  91. destructor Destroy; override;
  92. function DrawText( aText : WideString ) : PSDL_Surface; overload;
  93. function DrawText( aText : WideString; aWidth, aHeight : Integer ) : PSDL_Surface; overload;
  94. property BackGroundColour : TSDL_Color read FBackGroundColour write FBackGroundColour;
  95. property ForeGroundColour : TSDL_Color read FForeGroundColour write FForeGroundColour;
  96. property FontFile : string read FFontFile write FFontFile;
  97. property RenderType : TRenderType read FRenderType write FRenderType;
  98. property Solid : Boolean read FSolid write FSolid;
  99. property Style : TSDLFontStyles read FStyle write FStyle;
  100. property FontSize : integer read FFontSize write FFontSize;
  101. end;
  102. implementation
  103. uses
  104. SysUtils;
  105. { TTrueTypeFont }
  106. constructor TTrueTypeFont.Create( aFontFile : string; aRenderStyle : TSDLFontStyles; aFontSize : integer );
  107. begin
  108. inherited Create;
  109. if FileExists( aFontFile ) then
  110. begin
  111. FStyle := aRenderStyle;
  112. FFontSize := aFontSize;
  113. FSolid := false;
  114. FBackGroundColour.r := 255;
  115. FBackGroundColour.g := 255;
  116. FBackGroundColour.b := 255;
  117. FForeGroundColour.r := 0;
  118. FForeGroundColour.g := 0;
  119. FForeGroundColour.b := 0;
  120. FRenderType := rtUTF8;
  121. if ( TTF_Init >= 0 ) then
  122. begin
  123. FFontFile := aFontFile;
  124. end
  125. else
  126. raise Exception.Create( 'Failed to Initialiase SDL_TTF' );
  127. end
  128. else
  129. raise Exception.Create( 'Font File does not exist' );
  130. end;
  131. destructor TTrueTypeFont.Destroy;
  132. begin
  133. if FFont <> nil then
  134. TTF_CloseFont( FFont );
  135. TTF_Quit;
  136. inherited;
  137. end;
  138. function TTrueTypeFont.DrawText( aText : WideString ) : PSDL_Surface;
  139. begin
  140. PrepareFont;
  141. result := nil;
  142. case FRenderType of
  143. rtLatin1 :
  144. begin
  145. if ( FSolid ) then
  146. begin
  147. result := TTF_RenderText_Solid( FFont, PChar( string( aText ) ), FForeGroundColour );
  148. end
  149. else
  150. begin
  151. result := TTF_RenderText_Shaded( FFont, PChar( string( aText ) ), FForeGroundColour, FBackGroundColour );
  152. end;
  153. end;
  154. rtUTF8 :
  155. begin
  156. if ( FSolid ) then
  157. begin
  158. result := TTF_RenderUTF8_Solid( FFont, PChar( string( aText ) ), FForeGroundColour );
  159. end
  160. else
  161. begin
  162. result := TTF_RenderUTF8_Shaded( FFont, PChar( string( aText ) ), FForeGroundColour, FBackGroundColour );
  163. end;
  164. end;
  165. rtUnicode :
  166. begin
  167. if ( FSolid ) then
  168. begin
  169. result := TTF_RenderUNICODE_Solid( FFont, PUInt16( aText ), FForeGroundColour );
  170. end
  171. else
  172. begin
  173. result := TTF_RenderUNICODE_Shaded( FFont, PUInt16( aText ), FForeGroundColour, FBackGroundColour );
  174. end;
  175. end;
  176. end;
  177. end;
  178. function TTrueTypeFont.DrawText( aText : WideString; aWidth, aHeight : Integer ) : PSDL_Surface;
  179. var
  180. textw, texth, i, yPos : integer;
  181. strChopped : WideString;
  182. SurfaceList : array of PSDL_Surface;
  183. strlist : array of WideString;
  184. ReturnedSurface : PSDL_Surface;
  185. BltRect : TSDL_Rect;
  186. begin
  187. PrepareFont;
  188. // Do an initial check to see if it already fits
  189. case FRenderType of
  190. rtLatin1 :
  191. begin
  192. if TTF_SizeText( FFont, PChar( string( aText ) ), textw, texth ) = 0 then
  193. begin
  194. if ( textw < aWidth )
  195. and ( texth < aHeight ) then
  196. begin
  197. result := DrawText( aText );
  198. exit;
  199. end
  200. end;
  201. end;
  202. rtUTF8 :
  203. begin
  204. if TTF_SizeUTF8( FFont, PChar( string( aText ) ), textw, texth ) = 0 then
  205. begin
  206. if ( textw < aWidth )
  207. and ( texth < aHeight ) then
  208. begin
  209. result := DrawText( aText );
  210. exit;
  211. end
  212. end;
  213. end;
  214. rtUnicode :
  215. begin
  216. if TTF_SizeUNICODE( FFont, PUInt16( aText ), textw, texth ) = 0 then
  217. begin
  218. if ( textw < aWidth )
  219. and ( texth < aHeight ) then
  220. begin
  221. result := DrawText( aText );
  222. exit;
  223. end
  224. end;
  225. end;
  226. end;
  227. // Create the Surface we will be returning
  228. ReturnedSurface := SDL_DisplayFormat( SDL_CreateRGBSurface( SDL_SRCCOLORKEY or SDL_RLEACCEL or SDL_HWACCEL, aWidth, aHeight, 16, 0, 0, 0, 0 ) );
  229. // If we are still here there is some serious parsing to do
  230. case FRenderType of
  231. rtLatin1 :
  232. begin
  233. strChopped := aText;
  234. i := Length( strChopped );
  235. while ( i <> 0 ) do
  236. begin
  237. if ( string( strChopped[ i ] ) <> ' ' ) and ( Integer( string( strChopped[ i ] ) ) <> 13 ) then
  238. dec( i )
  239. else
  240. begin
  241. dec( i );
  242. strChopped := Copy( strChopped, 0, i );
  243. if TTF_SizeText( FFont, PChar( string( strChopped ) ), textw, texth ) = 0 then
  244. begin
  245. if ( textw < aWidth )
  246. and ( texth < aHeight ) then
  247. begin
  248. SetLength( strlist, Length( strlist ) + 1 );
  249. strlist[ Length( strlist ) - 1 ] := strChopped;
  250. strChopped := Copy( aText, i + 2, Length( aText ) - ( i - 1 ) );
  251. i := Length( strChopped );
  252. if TTF_SizeText( FFont, PChar( string( strChopped ) ), textw, texth ) = 0 then
  253. begin
  254. SetLength( strlist, Length( strlist ) + 1 );
  255. strlist[ Length( strlist ) - 1 ] := strChopped;
  256. break;
  257. end;
  258. end;
  259. end;
  260. end;
  261. end;
  262. SetLength( SurfaceList, Length( strlist ) );
  263. for i := Low( strlist ) to High( strlist ) do
  264. begin
  265. if ( FSolid ) then
  266. begin
  267. SurfaceList[ i ] := TTF_RenderText_Solid( FFont, PChar( string( strlist[ i ] ) ), FForeGroundColour );
  268. end
  269. else
  270. begin
  271. SurfaceList[ i ] := TTF_RenderText_Shaded( FFont, PChar( string( strlist[ i ] ) ), FForeGroundColour, FBackGroundColour );
  272. end;
  273. end;
  274. end;
  275. rtUTF8 :
  276. begin
  277. strChopped := aText;
  278. i := Length( strChopped );
  279. while ( i <> 0 ) do
  280. begin
  281. if ( string( strChopped[ i ] ) <> ' ' ) and ( Integer( string( strChopped[ i ] ) ) <> 13 ) then
  282. dec( i )
  283. else
  284. begin
  285. dec( i );
  286. strChopped := Copy( strChopped, 0, i );
  287. if TTF_SizeUTF8( FFont, PChar( string( strChopped ) ), textw, texth ) = 0 then
  288. begin
  289. if ( textw < aWidth )
  290. and ( texth < aHeight ) then
  291. begin
  292. SetLength( strlist, Length( strlist ) + 1 );
  293. strlist[ Length( strlist ) - 1 ] := strChopped;
  294. strChopped := Copy( aText, i + 2, Length( aText ) - ( i - 1 ) );
  295. i := Length( strChopped );
  296. if TTF_SizeUTF8( FFont, PChar( string( strChopped ) ), textw, texth ) = 0 then
  297. begin
  298. SetLength( strlist, Length( strlist ) + 1 );
  299. strlist[ Length( strlist ) - 1 ] := strChopped;
  300. break;
  301. end;
  302. end;
  303. end;
  304. end;
  305. end;
  306. SetLength( SurfaceList, Length( strlist ) );
  307. for i := Low( strlist ) to High( strlist ) do
  308. begin
  309. if ( FSolid ) then
  310. begin
  311. SurfaceList[ i ] := TTF_RenderUTF8_Solid( FFont, PChar( string( strlist[ i ] ) ), FForeGroundColour );
  312. end
  313. else
  314. begin
  315. SurfaceList[ i ] := TTF_RenderUTF8_Shaded( FFont, PChar( string( strlist[ i ] ) ), FForeGroundColour, FBackGroundColour );
  316. end;
  317. end;
  318. end;
  319. rtUnicode :
  320. begin
  321. strChopped := aText;
  322. i := Length( strChopped );
  323. while ( i <> 0 ) do
  324. begin
  325. if ( string( strChopped[ i ] ) <> ' ' ) and ( Integer( string( strChopped[ i ] ) ) <> 13 ) then
  326. dec( i )
  327. else
  328. begin
  329. dec( i );
  330. strChopped := Copy( strChopped, 0, i );
  331. if TTF_SizeUNICODE( FFont, PUInt16( strChopped ), textw, texth ) = 0 then
  332. begin
  333. if ( textw < aWidth )
  334. and ( texth < aHeight ) then
  335. begin
  336. SetLength( strlist, Length( strlist ) + 1 );
  337. strlist[ Length( strlist ) - 1 ] := strChopped;
  338. strChopped := Copy( aText, i + 2, Length( aText ) - ( i - 1 ) );
  339. i := Length( strChopped );
  340. if TTF_SizeUNICODE( FFont, PUInt16( strChopped ), textw, texth ) = 0 then
  341. begin
  342. SetLength( strlist, Length( strlist ) + 1 );
  343. strlist[ Length( strlist ) - 1 ] := strChopped;
  344. break;
  345. end;
  346. end;
  347. end;
  348. end;
  349. end;
  350. SetLength( SurfaceList, Length( strlist ) );
  351. for i := Low( strlist ) to High( strlist ) do
  352. begin
  353. if ( FSolid ) then
  354. begin
  355. SurfaceList[ i ] := TTF_RenderUNICODE_Solid( FFont, PUInt16( strlist[ i ] ), FForeGroundColour );
  356. end
  357. else
  358. begin
  359. SurfaceList[ i ] := TTF_RenderUNICODE_Shaded( FFont, PUInt16( strlist[ i ] ), FForeGroundColour, FBackGroundColour );
  360. end;
  361. end;
  362. end;
  363. end;
  364. // Now Draw the SurfaceList onto the resulting Surface
  365. yPos := 6;
  366. for i := Low( SurfaceList ) to High( SurfaceList ) do
  367. begin
  368. BltRect.x := 6;
  369. BltRect.y := yPos;
  370. BltRect.w := SurfaceList[ i ].w;
  371. BltRect.h := SurfaceList[ i ].h;
  372. SDL_BlitSurface( SurfaceList[ i ], nil, ReturnedSurface, @BltRect );
  373. yPos := yPos + TTF_FontHeight( FFont );
  374. end;
  375. result := ReturnedSurface;
  376. for i := Low( SurfaceList ) to High( SurfaceList ) do
  377. begin
  378. SDL_FreeSurface( SurfaceList[ i ] );
  379. end;
  380. SetLength( SurfaceList, 0 );
  381. SetLength( strlist, 0 );
  382. end;
  383. procedure TTrueTypeFont.PrepareFont;
  384. var
  385. renderstyle : integer;
  386. begin
  387. if FFont <> nil then
  388. TTF_CloseFont( FFont );
  389. FFont := TTF_OpenFont( PChar( FFontFile ), FFontSize );
  390. renderstyle := TTF_STYLE_NORMAL;
  391. if ( fsBold in FStyle ) then
  392. renderstyle := renderstyle or TTF_STYLE_BOLD;
  393. if ( fsItalic in FStyle ) then
  394. renderstyle := renderstyle or TTF_STYLE_ITALIC;
  395. if ( fsUnderline in FStyle ) then
  396. renderstyle := renderstyle or TTF_STYLE_UNDERLINE;
  397. TTF_SetFontStyle( FFont, renderstyle );
  398. end;
  399. end.