sfont.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. unit sfont;
  2. {******************************************************************}
  3. {
  4. $Id: sfont.pas,v 1.2 2004/03/31 09:04:31 savage Exp $
  5. }
  6. { }
  7. { Borland Delphi SFont }
  8. { Conversion of the Linux Games- SFont Library for SDL }
  9. { }
  10. { Original work created by Karl Bartel <[email protected]> }
  11. { Copyright (C) 2003 Karl Bartel. }
  12. { All Rights Reserved. }
  13. { }
  14. { The original files are : sfont.c }
  15. { }
  16. { The original Pascal code is : SFont.pas }
  17. { The initial developer of the Pascal code is : }
  18. { Jason Farmer <[email protected]> }
  19. { }
  20. { }
  21. { Contributor(s) }
  22. { -------------- }
  23. { Dominique Louis <[email protected]> }
  24. { }
  25. { Obtained through: }
  26. { Joint Endeavour of Delphi Innovators ( Project JEDI ) }
  27. { }
  28. { You may retrieve the latest version of this file at the Project }
  29. { JEDI home page, located at http://delphi-jedi.org }
  30. { }
  31. { The contents of this file are used with permission, subject to }
  32. { the Mozilla Public License Version 1.1 (the "License"); you may }
  33. { not use this file except in compliance with the License. You may }
  34. { obtain a copy of the License at }
  35. { http://www.mozilla.org/NPL/NPL-1_1Final.html }
  36. { }
  37. { Software distributed under the License is distributed on an }
  38. { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
  39. { implied. See the License for the specific language governing }
  40. { rights and limitations under the License. }
  41. { }
  42. { Description }
  43. { ----------- }
  44. { }
  45. { SFONT - SDL Font Library by Karl Bartel <[email protected]> }
  46. { }
  47. { All functions are explained below. }
  48. { There are two versions of each }
  49. { funtction. The first is the normal one, }
  50. { the function with the 2 at the end can be used when you }
  51. { want to handle more than one font }
  52. { in your program. }
  53. { }
  54. { }
  55. { }
  56. { }
  57. { Requires }
  58. { -------- }
  59. { SDL runtime libary somewhere in your path }
  60. { The Latest SDL runtime can be found on http://www.libsdl.org }
  61. { }
  62. { Programming Notes }
  63. { ----------------- }
  64. { }
  65. { }
  66. { }
  67. { }
  68. { }
  69. { Revision History }
  70. { ---------------- }
  71. { July 04 2001 - JF : Initial translation. }
  72. { Sept 29 2001 - JF : Added Róbert Surface Adding and }
  73. { Subtraction functions }
  74. { }
  75. {
  76. $Log: sfont.pas,v $
  77. Revision 1.2 2004/03/31 09:04:31 savage
  78. Added jedi-sdl.inc files for better FreePascal/multi compiler support.
  79. Revision 1.1 2004/03/28 10:45:16 savage
  80. Standardised SFont Functions so that they are prefixed with SFont_ and more in line with Karl's v2.02 release. Demos have been updated appropriately.
  81. }
  82. {******************************************************************}
  83. {$I jedi-sdl.inc}
  84. interface
  85. uses
  86. SysUtils,
  87. sdl,
  88. sdlutils;
  89. // Delcare one variable of this type for each font you are using.
  90. // To load the fonts, load the font image into YourFont->Surface
  91. // and call InitFont( YourFont );
  92. type
  93. TSfont_FontInfo = record
  94. Surface : PSDL_Surface; //SDL_Surface *Surface;
  95. CharPos : array[ 0..511 ] of integer; //int CharPos[512];
  96. MaxPos : integer; //int h;
  97. end;
  98. PSFont_FontInfo = ^TSfont_FontInfo;
  99. // Initializes the font
  100. // Font: this contains the suface with the font.
  101. // The font must be loaded before using this function.
  102. procedure SFont_InitFont( Font : PSDL_Surface );
  103. procedure SFont_InitFont2( Font : PSFont_FontInfo );
  104. // Blits a string to a surface
  105. // Destination: the suface you want to blit to
  106. // text: a string containing the text you want to blit.
  107. procedure SFont_Write( Surface_ : PSDL_Surface; x : Integer; y : Integer; text :
  108. pchar );
  109. procedure SFont_WriteAdd( Surface_ : PSDL_Surface; x : Integer; y : Integer; text :
  110. pchar );
  111. procedure SFont_WriteSub( Surface_ : PSDL_Surface; x : Integer; y : Integer; text :
  112. pchar );
  113. procedure SFont_Write2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; x : integer;
  114. y : integer; text : pchar );
  115. procedure SFont_WriteAdd2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; x : integer;
  116. y : integer; text : pchar );
  117. procedure SFont_WriteSub2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; x : integer;
  118. y : integer; text : pchar );
  119. // Returns the width of "text" in pixels
  120. function SFont_TextWidth( Text : pchar ) : integer;
  121. function SFont_TextWidth2( Font : PSFont_FontInfo; Text : pchar ) : integer;
  122. // Blits a string to with centered x position
  123. procedure SFont_WriteCentered( Surface_ : PSDL_Surface; y : Integer; text : pchar );
  124. procedure SFont_WriteCentered2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; y :
  125. integer; text : pchar );
  126. // Allows the user to enter text
  127. // Width: What is the maximum width of the text (in pixels)
  128. // text: This string contains the text which was entered by the user
  129. procedure SFont_Input( Destination : PSDL_Surface; x : Integer; y : integer; Width :
  130. integer; text : pchar );
  131. procedure SFont_Input2( Destination : PSDL_Surface; Font : PSFont_FontInfo; x :
  132. integer; y : integer; Width : integer; text : pchar );
  133. // Not part of the original implementation, but We really shouldn't be falling for the C Scanf problem...
  134. // This version requires a maximum length for the amount of text to input.
  135. procedure SFont_Input3( Destination : PSDL_Surface; Font : PSFont_FontInfo; x :
  136. integer; y : integer; Width : integer; text : pchar; MaxChars : Cardinal );
  137. { We'll use SDL for reporting errors }
  138. procedure SFont_SetError( fmt : PChar );
  139. function SFont_GetError : PChar;
  140. var
  141. InternalFont : TSFont_FontInfo;
  142. implementation
  143. procedure SFont_SetError( fmt : PChar );
  144. begin
  145. SDL_SetError( fmt );
  146. end;
  147. function SFont_GetError : PChar;
  148. begin
  149. result := SDL_GetError;
  150. end;
  151. procedure SFont_InitFont2( Font : PSFont_FontInfo );
  152. var
  153. X : Integer;
  154. I : Integer;
  155. begin
  156. x := 0;
  157. i := 0;
  158. if Font.Surface = nil then
  159. begin
  160. //Font_SetError ("The font has not been loaded!");
  161. //printf("The font has not been loaded!\n");
  162. //exit(1);
  163. exit;
  164. end;
  165. while x < Font.Surface.w do
  166. begin
  167. if SDL_GetPixel( Font.Surface, x, 0 ) = SDL_MapRGB( Font.Surface.format, 255, 0,
  168. 255 ) then
  169. begin
  170. Font.CharPos[ i ] := x;
  171. inc( i );
  172. while ( ( x < Font.Surface.w - 1 ) and ( SDL_GetPixel( Font.Surface, x, 0 ) =
  173. SDL_MapRGB( Font.Surface.format, 255, 0, 255 ) ) ) do
  174. begin
  175. inc( x );
  176. end;
  177. Font.CharPos[ i ] := x;
  178. inc( i );
  179. end;
  180. inc( x );
  181. end;
  182. Font.MaxPos := Font.Surface.h;
  183. SDL_SetColorKey( Font.Surface, SDL_SRCCOLORKEY, SDL_GetPixel( Font.Surface, 0,
  184. Font.Surface.h - 1 ) );
  185. end;
  186. procedure SFont_InitFont( Font : PSDL_Surface );
  187. begin
  188. InternalFont.Surface := Font;
  189. SFont_InitFont2( @InternalFont );
  190. end;
  191. procedure SFont_WriteAdd2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; x : integer;
  192. y : integer; text : pchar );
  193. var
  194. ofs : Integer;
  195. i : Integer;
  196. srcrect, dstrect : SDL_Rect;
  197. begin
  198. i := 0;
  199. while text[ i ] <> chr( 0 ) do
  200. begin
  201. if text[ i ] = ' ' then
  202. begin
  203. x := x + Font.CharPos[ 2 ] - Font.CharPos[ 1 ];
  204. inc( i );
  205. end
  206. else
  207. begin
  208. ofs := ( ( integer( text[ i ] ) - 33 ) * 2 ) + 1;
  209. srcrect.w := ( Font.CharPos[ ofs + 2 ] + Font.CharPos[ ofs + 1 ] ) div 2 -
  210. ( Font.CharPos[ ofs ] + Font.CharPos[ ofs - 1 ] ) div 2;
  211. dstrect.w := srcrect.w;
  212. srcrect.h := Font.Surface.h - 1;
  213. dstrect.h := srcrect.h;
  214. srcrect.x := ( Font.CharPos[ ofs ] + Font.CharPos[ ofs - 1 ] ) div 2;
  215. srcrect.y := 1;
  216. dstrect.x := x - ( Font.CharPos[ ofs ] - Font.CharPos[ ofs - 1 ] ) div 2;
  217. dstrect.y := y;
  218. SDL_AddSurface( Font.Surface, @srcrect, Surface_, @dstrect );
  219. x := x + Font.CharPos[ ofs + 1 ] - Font.CharPos[ ofs ];
  220. inc( i );
  221. end;
  222. end;
  223. end;
  224. procedure SFont_WriteSub2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; x : integer;
  225. y : integer; text : pchar );
  226. var
  227. ofs : Integer;
  228. i : Integer;
  229. srcrect, dstrect : SDL_Rect;
  230. begin
  231. i := 0;
  232. while text[ i ] <> chr( 0 ) do
  233. begin
  234. if text[ i ] = ' ' then
  235. begin
  236. x := x + Font.CharPos[ 2 ] - Font.CharPos[ 1 ];
  237. inc( i );
  238. end
  239. else
  240. begin
  241. ofs := ( ( integer( text[ i ] ) - 33 ) * 2 ) + 1;
  242. srcrect.w := ( Font.CharPos[ ofs + 2 ] + Font.CharPos[ ofs + 1 ] ) div 2 -
  243. ( Font.CharPos[ ofs ] + Font.CharPos[ ofs - 1 ] ) div 2;
  244. dstrect.w := srcrect.w;
  245. srcrect.h := Font.Surface.h - 1;
  246. dstrect.h := srcrect.h;
  247. srcrect.x := ( Font.CharPos[ ofs ] + Font.CharPos[ ofs - 1 ] ) div 2;
  248. srcrect.y := 1;
  249. dstrect.x := x - ( Font.CharPos[ ofs ] - Font.CharPos[ ofs - 1 ] ) div 2;
  250. dstrect.y := y;
  251. SDL_SubSurface( Font.Surface, @srcrect, Surface_, @dstrect );
  252. x := x + Font.CharPos[ ofs + 1 ] - Font.CharPos[ ofs ];
  253. inc( i );
  254. end;
  255. end;
  256. end;
  257. procedure SFont_Write2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; x : integer;
  258. y : integer; text : pchar );
  259. var
  260. ofs : Integer;
  261. i : Integer;
  262. srcrect, dstrect : SDL_Rect;
  263. begin
  264. i := 0;
  265. while text[ i ] <> chr( 0 ) do
  266. begin
  267. if text[ i ] = ' ' then
  268. begin
  269. x := x + Font.CharPos[ 2 ] - Font.CharPos[ 1 ];
  270. inc( i );
  271. end
  272. else
  273. begin
  274. ofs := ( ( integer( text[ i ] ) - 33 ) * 2 ) + 1;
  275. srcrect.w := ( Font.CharPos[ ofs + 2 ] + Font.CharPos[ ofs + 1 ] ) div 2 -
  276. ( Font.CharPos[ ofs ] + Font.CharPos[ ofs - 1 ] ) div 2;
  277. dstrect.w := srcrect.w;
  278. srcrect.h := Font.Surface.h - 1;
  279. dstrect.h := srcrect.h;
  280. srcrect.x := ( Font.CharPos[ ofs ] + Font.CharPos[ ofs - 1 ] ) div 2;
  281. srcrect.y := 1;
  282. dstrect.x := x - ( Font.CharPos[ ofs ] - Font.CharPos[ ofs - 1 ] ) div 2;
  283. dstrect.y := y;
  284. SDL_BlitSurface( Font.Surface, @srcrect, Surface_, @dstrect );
  285. x := x + Font.CharPos[ ofs + 1 ] - Font.CharPos[ ofs ];
  286. inc( i );
  287. end;
  288. end;
  289. end;
  290. procedure SFont_Write( Surface_ : PSDL_Surface; x : Integer; y : Integer; text :
  291. pchar );
  292. begin
  293. SFont_Write2( Surface_, @InternalFont, x, y, text );
  294. end;
  295. procedure SFont_WriteAdd( Surface_ : PSDL_Surface; x : Integer; y : Integer; text :
  296. pchar );
  297. begin
  298. SFont_WriteAdd2( Surface_, @InternalFont, x, y, text );
  299. end;
  300. procedure SFont_WriteSub( Surface_ : PSDL_Surface; x : Integer; y : Integer; text :
  301. pchar );
  302. begin
  303. SFont_WriteSub2( Surface_, @InternalFont, x, y, text );
  304. end;
  305. function SFont_TextWidth2( Font : PSFont_FontInfo; Text : pchar ) : integer;
  306. var
  307. x, i, ofs : integer;
  308. begin
  309. x := 0;
  310. i := 0;
  311. ofs := 0;
  312. while text[ i ] <> chr( 0 ) do
  313. begin
  314. if text[ i ] = ' ' then
  315. begin
  316. x := x + Font.CharPos[ 2 ] - Font.CharPos[ 1 ];
  317. inc( i );
  318. end
  319. else
  320. begin
  321. ofs := ( integer( text[ i ] ) - 33 ) * 2 + 1;
  322. x := x + Font.CharPos[ ofs + 1 ] - Font.CharPos[ ofs ];
  323. inc( i );
  324. end;
  325. end;
  326. result := ( x + Font.CharPos[ ofs + 2 ] - Font.CharPos[ ofs + 1 ] );
  327. end;
  328. function SFont_TextWidth( Text : pchar ) : integer;
  329. begin
  330. result := SFont_TextWidth2( @InternalFont, Text );
  331. end;
  332. procedure SFont_WriteCentered2( Surface_ : PSDL_Surface; Font : PSFont_FontInfo; y :
  333. integer; text : pchar );
  334. begin
  335. SFont_Write2( Surface_, @InternalFont, Surface_.w div 2 - SFont_TextWidth( text ) div 2,
  336. y, text );
  337. end;
  338. procedure SFont_WriteCentered( Surface_ : PSDL_Surface; y : Integer; text : pchar );
  339. begin
  340. SFont_WriteCentered2( Surface_, @InternalFont, y, text );
  341. end;
  342. procedure SFont_Input3( Destination : PSDL_Surface; Font : PSFont_FontInfo; x :
  343. integer; y : integer; Width : integer; text : pchar; MaxChars : Cardinal );
  344. var
  345. event : TSDL_Event;
  346. ch, ofs, leftshift : integer;
  347. Back : PSDL_Surface;
  348. rect : SDL_Rect;
  349. begin
  350. ch := 0; //Just to shut the compiler up
  351. ofs := ( integer( text[ 0 ] ) - 33 ) * 2 + 1;
  352. leftshift := ( Font.CharPos[ ofs ] - Font.CharPos[ ofs - 1 ] ) div 2;
  353. Back := SDL_AllocSurface( Destination.flags,
  354. Width,
  355. Font.MaxPos,
  356. Destination.format.BitsPerPixel,
  357. Destination.format.Rmask,
  358. Destination.format.Gmask,
  359. Destination.format.Bmask, 0 );
  360. rect.x := x - leftshift;
  361. rect.y := y;
  362. rect.w := Width;
  363. rect.h := Font.Surface.h;
  364. SDL_BlitSurface( Destination, @rect, Back, nil );
  365. SFont_Write2( Destination, Font, x, y, text );
  366. SDL_UpdateRect( Destination, x - leftshift, y, Width, Font.MaxPos );
  367. // start input
  368. SDL_EnableUNICODE( 1 );
  369. while ( ( ch <> SDLK_RETURN ) and ( SDL_WaitEvent( @event ) > 0 ) ) do
  370. begin
  371. if event.type_ = SDL_KEYDOWN then
  372. begin
  373. ch := event.key.keysym.unicode;
  374. if ( ch = SDLK_BACKSPACE ) and ( strlen( text ) > 0 ) then
  375. begin
  376. text[ strlen( text ) - 1 ] := chr( 0 );
  377. end
  378. else
  379. begin
  380. if strlen( text ) < MaxChars then
  381. begin
  382. if ch <> SDLK_BACKSPACE then
  383. begin
  384. text[ strlen( text ) ] := chr( ch );
  385. text[ strlen( text ) ] := chr( 0 );
  386. end;
  387. if ( SFont_TextWidth2( Font, text ) > Width ) then
  388. text[ strlen( text ) ] := chr( 0 );
  389. end;
  390. end;
  391. SDL_BlitSurface( Back, nil, Destination, @rect );
  392. SFont_Write2( Destination, Font, x, y, text );
  393. SDL_UpdateRect( Destination, x - ( Font.CharPos[ ofs ] - Font.CharPos[ ofs - 1 ] )
  394. div 2, y, Width, Font.Surface.h );
  395. end;
  396. end;
  397. text[ strlen( text ) ] := chr( 0 );
  398. SDL_FreeSurface( Back );
  399. end;
  400. procedure SFont_Input2( Destination : PSDL_Surface; Font : PSFont_FontInfo; x :
  401. integer; y : integer; Width : integer; text : pchar );
  402. var
  403. MaxChars : Cardinal;
  404. begin
  405. MaxChars := length( text ); // Just to make sure that we don't spill into
  406. // memory that doesn't belong to us.
  407. // We can't test the array as we use it
  408. // Because we're putting the 0 at the current
  409. // position.
  410. SFont_Input3( Destination, Font, x, y, Width, Text, MaxChars );
  411. end;
  412. procedure SFont_Input( Destination : PSDL_Surface; x : Integer; y : integer; Width :
  413. integer; text : pchar );
  414. begin
  415. SFont_Input2( Destination, @InternalFont, x, y, Width, text );
  416. end;
  417. end.