zgl_font_gen.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. {
  2. * Copyright (c) 2012 Andrey Kemka
  3. *
  4. * This software is provided 'as-is', without any express or
  5. * implied warranty. In no event will the authors be held
  6. * liable for any damages arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute
  10. * it freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented;
  13. * you must not claim that you wrote the original software.
  14. * If you use this software in a product, an acknowledgment
  15. * in the product documentation would be appreciated but
  16. * is not required.
  17. *
  18. * 2. Altered source versions must be plainly marked as such,
  19. * and must not be misrepresented as being the original software.
  20. *
  21. * 3. This notice may not be removed or altered from any
  22. * source distribution.
  23. }
  24. unit zgl_font_gen;
  25. {.$DEFINE USE_PNG}
  26. interface
  27. uses
  28. {$IFDEF LINUX}
  29. X, XLib, XRender,
  30. {$ENDIF}
  31. {$IFDEF WINDOWS}
  32. Windows,
  33. {$ENDIF}
  34. {$IFDEF USE_PNG}
  35. SysUtils,
  36. Imaging,
  37. ImagingTypes,
  38. {$ENDIF}
  39. zgl_types,
  40. zgl_math_2d,
  41. zgl_font;
  42. type
  43. zglPSymbolNode = ^zglTSymbolNode;
  44. zglTSymbolNode = record
  45. leaf : Boolean;
  46. ID : Integer;
  47. rect : zglTRect2D;
  48. child : array[0..1] of zglPSymbolNode;
  49. end;
  50. function fontgen_Init: Boolean;
  51. procedure fontgen_BuildFont(var Font: LongWord; const FontName: String );
  52. procedure fontgen_SaveFont(Font: LongWord; const FileName: String );
  53. var
  54. fg_Font : LongWord;
  55. fg_FontNodes : array of zglTSymbolNode;
  56. fg_CharsUse : array[ 0..65535 ] of Boolean;
  57. fg_CharsUID : array of WORD;
  58. fg_CharsSize : array of zglTRect2D;
  59. fg_CharsP : array of Integer;
  60. fg_CharsImage : array of array of Byte;
  61. fg_FontList : zglTStringList;
  62. fg_FontSize : Integer = 10;
  63. fg_FontBold : Boolean;
  64. fg_FontItalic : Boolean;
  65. fg_FontPack : Boolean = TRUE;
  66. fg_FontAA : Boolean = TRUE;
  67. fg_FontPadding : array[ 0..3 ] of Byte = (2, 2, 2, 2);
  68. fg_PageSize : Integer = 256;
  69. fg_PageChars : Integer = 17;
  70. {$IFDEF LINUX}
  71. const
  72. libxft = 'libXft';
  73. libfontconfig = 'libfontconfig';
  74. FC_FAMILY = 'family';
  75. FC_ANTIALIAS = 'antialias';
  76. FC_SIZE = 'size';
  77. FC_SLANT = 'slant';
  78. FC_WEIGHT = 'weight';
  79. FC_WEIGHT_LIGHT = 50;
  80. FC_WEIGHT_BLACK = 210;
  81. FC_SLANT_ROMAN = 0;
  82. FC_SLANT_ITALIC = 100;
  83. type
  84. PFcResult = ^TFcResult;
  85. TFcResult = (FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId, FcResultOutOfMemory);
  86. PFcConfig = ^TFcConfig;
  87. TFcConfig = record
  88. //dummy
  89. end;
  90. PFcCharset = ^TFcCharset;
  91. TFcCharset = record
  92. //dummy
  93. end;
  94. PFcPattern = ^TFcPattern;
  95. PPFcPattern = ^PFcPattern;
  96. TFcPattern = record
  97. //dummy
  98. end;
  99. PFcFontSet = ^TFcFontSet;
  100. TFcFontSet = record
  101. nfont : integer;
  102. sfont : integer;
  103. fonts : array of PFcPattern;
  104. end;
  105. PFcObjectSet = ^TFcObjectSet;
  106. TFcObjectSet = record
  107. nobject : longint;
  108. sobject : longint;
  109. objects : ppchar;
  110. end;
  111. PXftFont = ^TXftFont;
  112. TXftFont = record
  113. ascent : longint;
  114. descent : longint;
  115. height : longint;
  116. max_advance_width : longint;
  117. charset : ^TFcCharSet;
  118. pattern : ^TFcPattern;
  119. end;
  120. PXftDraw = ^TXftDraw;
  121. TXftDraw = record
  122. //dummy
  123. end;
  124. PXRenderColor = ^TXRenderColor;
  125. TXRenderColor = record
  126. red : word;
  127. green : word;
  128. blue : word;
  129. alpha : word;
  130. end;
  131. PXftColor = ^TXftColor;
  132. TXftColor = record
  133. pixel : dword;
  134. color : TXRenderColor;
  135. end;
  136. function XftInitFtLibrary: LongBool; cdecl; external libxft;
  137. function XftListFonts(dpy: PDisplay; screen: longint; args: array of const): PFcFontSet; cdecl; external libXft;
  138. function XftFontOpenPattern(dpy: PDisplay; pattern: PFcPattern): PXftFont; cdecl; external libXft;
  139. procedure XftFontClose(dpy: PDisplay; pub: PXftFont); cdecl; external libXft;
  140. function XftFontMatch(dpy: PDisplay; screen: longint; pattern: PFcPattern; result: PFcResult): PFcPattern; cdecl; external libXft;
  141. function XftCharExists(dpy: PDisplay; pub: PXftFont; ucs4: DWORD): LongBool; cdecl; external libXft;
  142. procedure XftTextExtents16(dpy: PDisplay; pub: PXftFont; _string: PByte; len: longint; extents: PXGlyphInfo); cdecl; external libXft;
  143. procedure XftDrawString16(draw: PXftDraw; color: PXftColor; pub: PXftFont; x, y: longint; _string: PByte; len: longint); cdecl; external libXft;
  144. function XftColorAllocValue(dpy: PDisplay; visual: PVisual; cmap: TColormap; color: PXRenderColor; result: PXftColor): LongBool; cdecl; external libXft;
  145. procedure XftColorFree(dpy: PDisplay; visual: PVisual; cmap: TColormap; color: PXftColor); cdecl; external libXft;
  146. function XftDrawCreate(dpy: PDisplay; drawable: TDrawable; visual: PVisual; colormap: TColormap): PXftDraw; cdecl; external libXft;
  147. procedure XftDrawDestroy(draw: PXftDraw); cdecl; external libXft;
  148. procedure XftDrawRect(draw: PXftDraw; color: PXftColor; x, y: longint; width, height: dword); cdecl; external libXft;
  149. // FontSet
  150. procedure FcFontSetDestroy(s: PFcFontSet); cdecl; external libfontconfig;
  151. // Pattern
  152. function FcPatternCreate: PFcPattern; cdecl; external libfontconfig;
  153. procedure FcPatternDestroy(p: PFcPattern); cdecl; external libfontconfig;
  154. function FcPatternAddBool(p: PFcPattern; _object: PChar; b: LongBool): LongBool; cdecl; external libfontconfig;
  155. function FcPatternGetBool(const p: PFcPattern; const _object: PChar; n: Integer; b: PLongBool): TFcResult; cdecl; external libfontconfig;
  156. function FcPatternAddInteger(p: PFcPattern; _object: PChar; i: LongInt): LongBool; cdecl; external libfontconfig;
  157. function FcPatternAddString(p: PFcPattern; _object: PChar; s: PAnsiChar): LongBool; cdecl; external libfontconfig;
  158. function FcPatternGetString(const p: PFcPattern; const _object: PChar; n: Integer; s: PPChar): TFcResult; cdecl; external libfontconfig;
  159. // ObjectSet
  160. function FcObjectSetCreate: PFcObjectSet; cdecl; external libfontconfig;
  161. procedure FcObjectSetDestroy(os: PFcObjectSet); cdecl; external libfontconfig;
  162. function FcObjectSetAdd(os: PFcObjectSet; _object: PChar): LongBool; cdecl; external libfontconfig;
  163. // FontList
  164. function FcFontList(config: PFcConfig; p: PFcPattern; os: PFcObjectSet): PFcFontSet; cdecl; external libfontconfig;
  165. {$ENDIF}
  166. implementation
  167. uses
  168. zgl_log,
  169. zgl_screen,
  170. zgl_window,
  171. zgl_textures,
  172. zgl_textures_tga,
  173. zgl_file,
  174. zgl_utils,
  175. math;
  176. procedure image_FlipVertically(var Data: Pointer; w, h, pixelSize: Integer);
  177. var
  178. i : Integer;
  179. scanLine : array of Byte;
  180. begin
  181. SetLength(scanLine, w * pixelSize);
  182. for i := 0 to h shr 1 - 1 do
  183. begin
  184. Move(Pointer(Ptr(Data) + i * w * pixelSize)^, scanLine[0], w * pixelSize);
  185. Move(Pointer(Ptr(Data) + (h - i - 1) * w * pixelSize)^, Pointer(Ptr(Data) + i * w * pixelSize)^, w * pixelSize);
  186. Move(scanLine[0], Pointer(Ptr(Data) + (h - i - 1) * w * pixelSize)^, w * pixelSize);
  187. end;
  188. end;
  189. function fontgen_InsertSymbol(node: zglPSymbolNode; const r: zglTRect2D; ID: Integer) : zglPSymbolNode;
  190. var
  191. dw, dh : Single;
  192. c1, c2 : zglPSymbolNode;
  193. begin
  194. if not node^.leaf Then
  195. begin
  196. Result := fontgen_InsertSymbol(node^.child[0], r, ID);
  197. if not Assigned(Result) Then
  198. Result := fontgen_InsertSymbol(node^.child[1], r, ID);
  199. end else
  200. begin
  201. if node^.ID <> -1 Then
  202. begin
  203. Result := nil;
  204. exit;
  205. end;
  206. if (r.W > node^.rect.W) or (r.H > node^.rect.H) Then
  207. begin
  208. Result := nil;
  209. exit;
  210. end;
  211. if (r.W = node^.rect.W) and (r.H = node^.rect.H) Then
  212. begin
  213. Result := node;
  214. node^.ID := ID;
  215. exit;
  216. end;
  217. zgl_GetMem(Pointer(node^.child[0]), SizeOf(zglTSymbolNode));
  218. zgl_GetMem(Pointer(node^.child[1]), SizeOf(zglTSymbolNode));
  219. node^.leaf := FALSE;
  220. c1 := node^.child[0];
  221. c2 := node^.child[1];
  222. dw := node^.rect.w - r.w;
  223. dh := node^.rect.h - r.h;
  224. if dw > dh Then
  225. begin
  226. c1^.leaf := TRUE;
  227. c1^.ID := -1;
  228. c1^.rect.X := node^.rect.X;
  229. c1^.rect.Y := node^.rect.Y;
  230. c1^.rect.W := r.W;
  231. c1^.rect.H := node^.rect.H;
  232. c2^.leaf := TRUE;
  233. c2^.ID := -1;
  234. c2^.rect.X := node^.rect.X + r.W;
  235. c2^.rect.Y := node^.rect.Y;
  236. c2^.rect.W := node^.rect.W - r.W;
  237. c2^.rect.H := node^.rect.H;
  238. end else
  239. begin
  240. c1^.leaf := TRUE;
  241. c1^.ID := -1;
  242. c1^.rect.X := node^.rect.X;
  243. c1^.rect.Y := node^.rect.Y;
  244. c1^.rect.W := node^.rect.W;
  245. c1^.rect.H := r.H;
  246. c2^.leaf := TRUE;
  247. c2^.ID := -1;
  248. c2^.rect.X := node^.rect.X;
  249. c2^.rect.Y := node^.rect.Y + r.H;
  250. c2^.rect.W := node^.rect.W;
  251. c2^.rect.H := node^.rect.H - r.H;
  252. end;
  253. Result := fontgen_InsertSymbol(Pointer(node^.child[0]), r, ID);
  254. end;
  255. end;
  256. procedure fontgen_FreeSymbolNode(node: zglPSymbolNode; root: Boolean );
  257. begin
  258. if Assigned(node^.child[0]) Then
  259. fontgen_FreeSymbolNode(node^.child[0], FALSE );
  260. if Assigned(node^.child[1]) Then
  261. fontgen_FreeSymbolNode(node^.child[1], FALSE);
  262. if not root Then
  263. FreeMem(node);
  264. end;
  265. {$IFDEF WINDOWS}
  266. {$IFNDEF FPC}
  267. type NEWTEXTMETRICEX = NEWTEXTMETRICEXW;
  268. {$ENDIF}
  269. function FontEnumProc(var _para1: ENUMLOGFONTEX; var _para2: NEWTEXTMETRICEX; _para3: longint; _para4: LPARAM): longint; stdcall;
  270. begin
  271. if not (_para1.elfLogFont.lfFaceName[0] in ['A'..'Z', 'a'..'z', '0'..'9']) Then
  272. exit;
  273. INC(fg_FontList.Count);
  274. SetLength(fg_FontList.Items, fg_FontList.Count);
  275. fg_FontList.Items[fg_FontList.Count - 1] := _para1.elfLogFont.lfFaceName;
  276. if fg_FontList.Count - 2 >= 0 Then
  277. if fg_FontList.Items[fg_FontList.Count - 1] = fg_FontList.Items[fg_FontList.Count - 2] Then
  278. begin
  279. SetLength(fg_FontList.Items, fg_FontList.Count - 1);
  280. DEC(fg_FontList.Count);
  281. end;
  282. Result := 1;
  283. end;
  284. procedure FontGetSize(pData: Pointer; W, H: Integer; var nW, nH, mX, mY: Integer);
  285. var
  286. i, j : Integer;
  287. maxX, minX : Integer;
  288. maxY, minY : Integer;
  289. begin
  290. maxX := 0;
  291. minX := W;
  292. maxY := 0;
  293. minY := H;
  294. for i := 0 to W - 1 do
  295. for j := 0 to H - 1 do
  296. if PByte(Ptr(pData) + i * 4 + j * W * 4)^ > 0 Then
  297. begin
  298. if i < minX Then
  299. minX := i;
  300. if i > maxX Then
  301. maxX := i;
  302. if j < minY Then
  303. minY := j;
  304. if j > maxY Then
  305. maxY := j;
  306. end;
  307. nW := maxX - minX;
  308. nH := maxY - minY;
  309. if nW < 0 Then nW := 0;
  310. if nH < 0 Then nH := 0;
  311. mX := minX;
  312. mY := minY;
  313. if mX = W Then mX := 0;
  314. if mY = H Then mY := 0;
  315. end;
  316. {$ENDIF}
  317. function fontgen_Init: Boolean;
  318. var
  319. i : Integer;
  320. {$IFDEF LINUX}
  321. Fonts : PFcFontSet;
  322. Pattern : PFcPattern;
  323. ObjectSet : PFcObjectSet;
  324. Family : PChar;
  325. {$ENDIF}
  326. {$IFDEF WINDOWS}
  327. LFont : LOGFONT;
  328. {$ENDIF}
  329. begin
  330. Result := FALSE;
  331. {$IFDEF LINUX}
  332. if not XftInitFtLibrary Then
  333. begin
  334. log_Add('ERROR: XftInitFtLibrary');
  335. exit;
  336. end;
  337. Pattern := FcPatternCreate;
  338. ObjectSet := FcObjectSetCreate;
  339. FcObjectSetAdd(ObjectSet, FC_FAMILY);
  340. Fonts := FcFontList(nil, Pattern, ObjectSet);
  341. fg_FontList.Count := 0;
  342. SetLength(fg_FontList.Items, 0);
  343. for i := 0 to Fonts^.nfont - 1 do
  344. begin
  345. FcPatternGetString(Fonts^.fonts[i], FC_FAMILY, 0, @Family);
  346. INC(fg_FontList.Count);
  347. SetLength(fg_FontList.Items, fg_FontList.Count);
  348. fg_FontList.Items[fg_FontList.Count - 1] := Family;
  349. Family := nil;
  350. end;
  351. FcFontSetDestroy(Fonts);
  352. FcObjectSetDestroy(ObjectSet);
  353. FcPatternDestroy(Pattern);
  354. {$ENDIF}
  355. {$IFDEF WINDOWS}
  356. FillChar(LFont, SizeOf(LFont), 0);
  357. LFont.lfCharSet := DEFAULT_CHARSET;
  358. EnumFontFamiliesEx(wndDC, LFont, @FontEnumProc, 0, 0);
  359. {$ENDIF}
  360. u_SortList(fg_FontList, 0, fg_FontList.Count - 1);
  361. Result := TRUE;
  362. end;
  363. procedure fontgen_PutChar(var pData : Pointer; X, Y, ID : Integer);
  364. var
  365. i, j : Integer;
  366. fw, fh : Integer;
  367. pixel : PByte;
  368. begin
  369. if length(fg_CharsImage[ID]) = 0 Then
  370. exit;
  371. fw := Round(fg_CharsSize[ID].W);
  372. fh := Round(fg_CharsSize[ID].H);
  373. for i := 0 to fw - 1 do
  374. for j := 0 to fh - 1 do
  375. begin
  376. pixel := PByte(Ptr(pData) + (i + X) * 4 + (j + Y) * fg_PageSize * 4);
  377. pixel^ := 255;
  378. INC(pixel);
  379. pixel^ := 255;
  380. INC(pixel);
  381. pixel^ := 255;
  382. INC(pixel);
  383. pixel^ := fg_CharsImage[ ID, i + j * fw ];
  384. end;
  385. end;
  386. procedure fontgen_BuildFont( var Font : LongWord; const FontName : String );
  387. var
  388. pData : Pointer;
  389. i, j : Integer;
  390. CharID : Integer;
  391. CharUID : WORD;
  392. cx, cy : Integer;
  393. sx, sy : Integer;
  394. cs : Integer;
  395. u, v : Single;
  396. MaxWidth : Integer;
  397. sn : zglPSymbolNode;
  398. sr : zglTRect2D;
  399. {$IFDEF LINUX}
  400. scrVisual : PVisual;
  401. Family : array[ 0..255 ] of Char;
  402. Pattern : PFcPattern;
  403. XFont : PXftFont;
  404. XFontMatch : PFcPattern;
  405. XGlyphInfo : TXGlyphInfo;
  406. FcResult : TFcResult;
  407. pixmap : TPixmap;
  408. draw : PXftDraw;
  409. rWhite : TXftColor;
  410. rBlack : TXftColor;
  411. cWhite : TXRenderColor = ( red: $FFFF; green: $FFFF; blue: $FFFF; alpha: $FFFF );
  412. cBlack : TXRenderColor = ( red: $0000; green: $0000; blue: $0000; alpha: $FFFF );
  413. image : PXImage;
  414. color : DWORD;
  415. r, g, b : DWORD;
  416. {$ENDIF}
  417. {$IFDEF WINDOWS}
  418. WDC : HDC;
  419. WFont : HFONT;
  420. Bitmap : BITMAPINFO;
  421. DIB : DWORD;
  422. CharSize : TSize;
  423. TextMetric : TTextMetricW;
  424. Rect : TRect;
  425. minX, minY : Integer;
  426. {$ENDIF}
  427. begin
  428. if (managerFont.Font[Font].Flags and Enable) > 0 then
  429. begin
  430. for i := 0 to Length(managerFont.Font[Font].Pages) - 1 do
  431. tex_Del(managerFont.Font[Font].Pages[i]);
  432. for i := 0 to 65535 do
  433. if Assigned(managerFont.Font[Font].CharDesc[i]) then
  434. begin
  435. Freememory(managerFont.Font[Font].CharDesc[i]);
  436. managerFont.Font[Font].CharDesc[i] := nil;
  437. end;
  438. SetLength(managerFont.Font[Font].Pages, 0);
  439. end;
  440. MaxWidth := 0;
  441. SetLength(fg_CharsSize, managerFont.Font[Font].Count.Chars);
  442. SetLength(fg_CharsUID, managerFont.Font[Font].Count.Chars);
  443. SetLength(fg_CharsImage, managerFont.Font[Font].Count.Chars);
  444. SetLength(fg_CharsP, managerFont.Font[Font].Count.Chars);
  445. j := 0;
  446. for i := 0 to 65535 do
  447. if fg_CharsUse[ i ] Then
  448. begin
  449. SetLength( fg_CharsUID, j + 1 );
  450. // log_Add(u_IntToStr(i) + ' ' + u_IntToStr(j));
  451. fg_CharsUID[ j ] := i;
  452. INC( j );
  453. end;
  454. {$IFDEF LINUX}
  455. scrVisual := DefaultVisual( scrDisplay, scrDefault );
  456. Family := FontName;
  457. Pattern := FcPatternCreate;
  458. FcPatternAddString( Pattern, FC_FAMILY, @Family[ 0 ] );
  459. FcPatternAddInteger( Pattern, FC_SIZE, fg_FontSize );
  460. FcPatternAddInteger( Pattern, FC_WEIGHT, ( FC_WEIGHT_BLACK * Byte( fg_FontBold ) ) or ( FC_WEIGHT_LIGHT * Byte( not fg_FontBold ) ) );
  461. FcPatternAddInteger( Pattern, FC_SLANT, ( FC_SLANT_ITALIC * Byte( fg_FontItalic ) ) or ( FC_SLANT_ROMAN * Byte( not fg_FontItalic ) ) );
  462. FcPatternAddBool( Pattern, FC_ANTIALIAS, fg_FontAA );
  463. XFontMatch := XftFontMatch( scrDisplay, scrDefault, Pattern, @FcResult );
  464. XFont := XftFontOpenPattern( scrDisplay, XFontMatch );
  465. XftColorAllocValue( scrDisplay, scrVisual, DefaultColormap( scrDisplay, scrDefault ), @cWhite, @rWhite );
  466. XftColorAllocValue( scrDisplay, scrVisual, DefaultColormap( scrDisplay, scrDefault ), @cBlack, @rBlack );
  467. for i := 0 to managerFont.Font[Font].Count.Chars - 1 do
  468. if XftCharExists( scrDisplay, XFont, fg_CharsUID[ i ] ) Then
  469. begin
  470. XftTextExtents16( scrDisplay, XFont, @fg_CharsUID[ i ], 1, @XGlyphInfo );
  471. cx := XGlyphInfo.width;
  472. cy := XGlyphInfo.height;
  473. sx := XGlyphInfo.xOff;
  474. sy := XFont^.ascent - XGlyphInfo.y + XGlyphInfo.height;
  475. if cx > sx Then sx := cx;
  476. if cy > sy Then sy := cy;
  477. fg_CharsSize[ i ].X := -XGlyphInfo.x;
  478. fg_CharsSize[ i ].Y := XGlyphInfo.height - XGlyphInfo.y;
  479. fg_CharsSize[ i ].W := cx;
  480. fg_CharsSize[ i ].H := cy;
  481. fg_CharsP [ i ] := XGlyphInfo.xOff;
  482. MaxWidth := Trunc( Max( MaxWidth, fg_CharsSize[ i ].W + fg_FontPadding[ 0 ] + fg_FontPadding[ 2 ] ) );
  483. MaxWidth := Trunc( Max( MaxWidth, fg_CharsSize[ i ].H + fg_FontPadding[ 1 ] + fg_FontPadding[ 3 ] ) );
  484. if ( sx = 0 ) or ( sy = 0 ) Then continue;
  485. pixmap := XCreatePixmap( scrDisplay, wndRoot, sx, sy, DefaultDepth( scrDisplay, scrDefault ) );
  486. draw := XftDrawCreate( scrDisplay, pixmap, scrVisual, DefaultColormap( scrDisplay, scrDefault ) );
  487. XftDrawRect( draw, @rBlack, 0, 0, sx, sy );
  488. XftDrawString16( draw, @rWhite, XFont, XGlyphInfo.x, XGlyphInfo.y, @fg_CharsUID[ i ], 1 );
  489. image := XGetImage( scrDisplay, pixmap, 0, 0, sx, sy, AllPlanes, ZPixmap );
  490. SetLength( fg_CharsImage[ i ], cx * cy );
  491. for sx := 0 to cx - 1 do
  492. for sy := 0 to cy - 1 do
  493. begin
  494. color := image^.f.get_pixel( image, sx, sy );
  495. r := color and scrVisual^.red_mask;
  496. g := color and scrVisual^.green_mask;
  497. b := color and scrVisual^.blue_mask;
  498. while r > $FF do r := r shr 8;
  499. while g > $FF do g := g shr 8;
  500. while b > $FF do b := b shr 8;
  501. fg_CharsImage[ i, sx + sy * cx ] := ( r + g + b ) div 3;
  502. end;
  503. image^.f.destroy_image( image );
  504. XftDrawDestroy( draw );
  505. XFreePixmap( scrDisplay, pixmap );
  506. end;
  507. XftColorFree( scrDisplay, scrVisual, DefaultColormap( scrDisplay, scrDefault ), @rWhite );
  508. XftColorFree( scrDisplay, scrVisual, DefaultColormap( scrDisplay, scrDefault ), @rBlack );
  509. XftFontClose( scrDisplay, XFont );
  510. FcPatternDestroy( Pattern );
  511. {$ENDIF}
  512. {$IFDEF WINDOWS}
  513. if fg_FontBold Then
  514. cs := FW_BOLD
  515. else
  516. cs := FW_NORMAL;
  517. WFont := CreateFont( -MulDiv( fg_FontSize, GetDeviceCaps( wndDC, LOGPIXELSY ), 72 ), 0, 0, 0,
  518. cs, Byte( fg_FontItalic ), 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  519. 5 * Byte( fg_FontAA ) or ANTIALIASED_QUALITY * Byte( not fg_FontAA ),
  520. DEFAULT_PITCH, PChar( FontName ) );
  521. WDC := CreateCompatibleDC( 0 );
  522. SelectObject( WDC, WFont );
  523. SetTextAlign( WDC, TA_LEFT or TA_TOP or TA_NOUPDATECP );
  524. SetTextColor( WDC, $FFFFFF );
  525. SetBkColor ( WDC, $000000 );
  526. {$IFDEF FPC}
  527. GetTextMetricsW( WDC, @TextMetric );
  528. {$ELSE}
  529. GetTextMetricsW( WDC, TextMetric );
  530. {$ENDIF}
  531. FillChar( Bitmap, SizeOf( BITMAPINFO ), 0 );
  532. Bitmap.bmiHeader.biWidth := TextMetric.tmMaxCharWidth * 2;
  533. Bitmap.bmiHeader.biHeight := -TextMetric.tmHeight * 2;
  534. Bitmap.bmiHeader.biBitCount := 32;
  535. Bitmap.bmiHeader.biCompression := BI_RGB;
  536. Bitmap.bmiHeader.biPlanes := 1;
  537. Bitmap.bmiHeader.biSize := Sizeof( BITMAPINFOHEADER );
  538. DIB := CreateDIBSection( WDC, Bitmap, DIB_RGB_COLORS, pData, 0, 0 );
  539. SelectObject( WDC, DIB );
  540. SetRect( Rect, 0, 0, Bitmap.bmiHeader.biWidth, -Bitmap.bmiHeader.biHeight );
  541. for i := 0 to managerFont.Font[Font].Count.Chars - 1 do
  542. begin
  543. Windows.FillRect( WDC, Rect, GetStockObject( BLACK_BRUSH ) );
  544. if (i >= 71) and (i <= 75) then
  545. log_Add(u_IntToStr(fg_CharsUID[i]));
  546. TextOutW( WDC, TextMetric.tmMaxCharWidth div 2, TextMetric.tmHeight div 2, @fg_CharsUID[ i ], 1 );
  547. GetTextExtentPoint32W( WDC, @fg_CharsUID[ i ], 1, CharSize ); // в CharSize возвращаются значения символа
  548. // Microsoft Sucks...
  549. FontGetSize( pData, Bitmap.bmiHeader.biWidth, -Bitmap.bmiHeader.biHeight, cx, cy, minX, minY );
  550. INC( cx, 1 + Byte( fg_FontAA ) );
  551. INC( cy, 1 + Byte( fg_FontAA ) );
  552. if (i >= 71) and (i <= 75) then
  553. log_Add('cx = ' + u_IntToStr(cx) + '; cy = ' + u_IntToStr(cy) + '; minX = ' + u_IntToStr(minX) + '; minY = ' + u_IntToStr(minY));
  554. fg_CharsSize[ i ].X := minX - TextMetric.tmMaxCharWidth div 2;
  555. fg_CharsSize[ i ].Y := cy - ( TextMetric.tmAscent - ( minY - TextMetric.tmHeight div 2 ) );
  556. fg_CharsSize[ i ].W := cx;
  557. fg_CharsSize[ i ].H := cy;
  558. if (i >= 71) and (i <= 75) then
  559. log_Add('x = ' + u_FloatToStr(fg_CharsSize[ i ].X) + '; y = ' + u_FloatToStr(fg_CharsSize[ i ].Y) + '; width = ' + u_FloatToStr(fg_CharsSize[ i ].W) + '; height = ' + u_FloatToStr(fg_CharsSize[ i ].H));
  560. if cx - minX > CharSize.cx then
  561. fg_CharsP[i] := cx - minX
  562. else
  563. fg_CharsP[i] := CharSize.cx;
  564. if (i >= 71) and (i <= 75) then
  565. log_Add(u_IntToStr(CharSize.cx));
  566. SetLength( fg_CharsImage[ i ], cx * cy );
  567. FillChar( fg_CharsImage[ i, 0 ], cx * cy, $FF );
  568. MaxWidth := Trunc( Max( MaxWidth, fg_CharsSize[ i ].W + fg_FontPadding[ 0 ] + fg_FontPadding[ 2 ] + Byte( fg_FontAA ) ) );
  569. MaxWidth := Trunc( Max( MaxWidth, fg_CharsSize[ i ].H + fg_FontPadding[ 1 ] + fg_FontPadding[ 3 ] + Byte( fg_FontAA ) ) );
  570. for sx := minX to cx + minX - 1 do
  571. for sy := minY to cy + minY - 1 do
  572. fg_CharsImage[ i, sx - minX + ( sy - minY ) * cx ] :=
  573. ( PByte( Ptr( pData ) + sx * 4 + sy * Bitmap.bmiHeader.biWidth * 4 + 0 )^ +
  574. PByte( Ptr( pData ) + sx * 4 + sy * Bitmap.bmiHeader.biWidth * 4 + 1 )^ +
  575. PByte( Ptr( pData ) + sx * 4 + sy * Bitmap.bmiHeader.biWidth * 4 + 2 )^ ) div 3;
  576. end;
  577. DeleteObject( DIB );
  578. DeleteDC( WDC );
  579. DeleteObject( WFont );
  580. {$ENDIF}
  581. if fg_FontPack Then
  582. begin
  583. for i := 0 to length( fg_FontNodes ) - 1 do
  584. fontgen_FreeSymbolNode( @fg_FontNodes[ i ], TRUE );
  585. managerFont.Font[Font].Count.Pages := 1;
  586. zgl_GetMem( pData, sqr( fg_PageSize ) * 4 );
  587. SetLength( managerFont.Font[Font].Pages , managerFont.Font[Font].Count.Pages );
  588. managerFont.Font[Font].Pages[0] := tex_Add;
  589. managerFont.Font[Font].Pages[0]^.Format := TEX_FORMAT_RGBA;
  590. managerFont.Font[Font].Pages[0]^.Width := fg_PageSize;
  591. managerFont.Font[Font].Pages[0]^.Height := fg_PageSize;
  592. managerFont.Font[Font].Pages[0]^.U := 1;
  593. managerFont.Font[Font].Pages[0]^.V := 1;
  594. managerFont.Font[Font].Pages[0]^.Flags := TEX_CLAMP or TEX_FILTER_LINEAR;
  595. SetLength( fg_FontNodes, managerFont.Font[Font].Count.Pages );
  596. fg_FontNodes[ 0 ].leaf := TRUE;
  597. fg_FontNodes[ 0 ].ID := -1;
  598. fg_FontNodes[ 0 ].rect.X := 0;
  599. fg_FontNodes[ 0 ].rect.Y := 0;
  600. fg_FontNodes[ 0 ].rect.W := fg_PageSize;
  601. fg_FontNodes[ 0 ].rect.H := fg_PageSize;
  602. u := 1 / fg_PageSize;
  603. v := 1 / fg_PageSize;
  604. managerFont.Font[Font].MaxHeight := 0;
  605. managerFont.Font[Font].MaxShiftY := 0;
  606. i := 0;
  607. sr.X := 0;
  608. sr.Y := 0;
  609. while i < managerFont.Font[Font].Count.Chars do
  610. begin
  611. CharUID := fg_CharsUID[ i ];
  612. sr.W := fg_CharsSize[ i ].W + fg_FontPadding[ 0 ] + fg_FontPadding[ 2 ];
  613. sr.H := fg_CharsSize[ i ].H + fg_FontPadding[ 1 ] + fg_FontPadding[ 3 ];
  614. sn := fontgen_InsertSymbol( @fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ], sr, CharUID );
  615. if not Assigned( sn ) Then
  616. begin
  617. image_FlipVertically( pData, fg_PageSize, fg_PageSize, 4 );
  618. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ] := tex_Create( pData, fg_PageSize, fg_PageSize, TEX_FORMAT_RGBA, TEX_DEFAULT_2D );
  619. zgl_FreeMem( pData );
  620. zgl_GetMem( pData, sqr( fg_PageSize ) * 4 );
  621. inc(managerFont.Font[Font].Count.Pages);
  622. SetLength(managerFont.Font[Font].Pages, managerFont.Font[Font].Count.Pages);
  623. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ] := tex_Add();
  624. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ]^.Format := TEX_FORMAT_RGBA;
  625. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ]^.Width := fg_PageSize;
  626. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ]^.Height := fg_PageSize;
  627. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ]^.U := 1;
  628. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ]^.V := 1;
  629. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ]^.Flags := TEX_CLAMP or TEX_FILTER_LINEAR;
  630. SetLength( fg_FontNodes, managerFont.Font[Font].Count.Pages );
  631. fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ].leaf := TRUE;
  632. fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ].ID := -1;
  633. fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ].rect.X := 0;
  634. fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ].rect.Y := 0;
  635. fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ].rect.W := fg_PageSize;
  636. fg_FontNodes[ managerFont.Font[Font].Count.Pages - 1 ].rect.H := fg_PageSize;
  637. end else
  638. begin
  639. fontgen_PutChar( pData, Round( sn^.rect.X + fg_FontPadding[ 0 ] ), Round( sn^.rect.Y + fg_FontPadding[ 1 ] ), i );
  640. SetLength( fg_CharsImage[ i ], 0 );
  641. zgl_GetMem( Pointer( managerFont.Font[Font].CharDesc[ CharUID ] ), SizeOf( zglTCharDesc ) );
  642. managerFont.Font[Font].CharDesc[ CharUID ]^.Page := managerFont.Font[Font].Count.Pages - 1;
  643. managerFont.Font[Font].CharDesc[ CharUID ]^.Width := Round( fg_CharsSize[ i ].W );
  644. managerFont.Font[Font].CharDesc[ CharUID ]^.Height := Round( fg_CharsSize[ i ].H );
  645. managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftX := Round( fg_CharsSize[ i ].X );
  646. managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftY := Round( fg_CharsSize[ i ].Y );
  647. managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftP := fg_CharsP[ i ];
  648. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 0 ].X := ( sn^.rect.X ) * u;
  649. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 0 ].Y := 1 - ( sn^.rect.Y ) * v;
  650. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 1 ].X := ( sn^.rect.X + sn^.rect.W ) * u;
  651. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 1 ].Y := 1 - ( sn^.rect.Y ) * v;
  652. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 2 ].X := ( sn^.rect.X + sn^.rect.W ) * u;
  653. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 2 ].Y := 1 - ( sn^.rect.Y + sn^.rect.H ) * v;
  654. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 3 ].X := ( sn^.rect.X ) * u;
  655. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 3 ].Y := 1 - ( sn^.rect.Y + sn^.rect.H ) * v;
  656. managerFont.Font[Font].MaxHeight := Round( Max( managerFont.Font[Font].MaxHeight, fg_CharsSize[ i ].H ) );
  657. managerFont.Font[Font].MaxShiftY := Round( Max( managerFont.Font[Font].MaxShiftY, managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftY ) );
  658. INC( i );
  659. end;
  660. end;
  661. image_FlipVertically( pData, fg_PageSize, fg_PageSize, 4 );
  662. managerFont.Font[Font].Pages[ managerFont.Font[Font].Count.Pages - 1 ] := tex_Create( pData, fg_PageSize, fg_PageSize, TEX_FORMAT_RGBA, TEX_DEFAULT_2D );
  663. zgl_FreeMem( pData );
  664. end else
  665. begin
  666. if MaxWidth = 0 Then MaxWidth := 1;
  667. fg_PageChars := fg_PageSize div MaxWidth;
  668. cs := fg_PageSize div fg_PageChars;
  669. managerFont.Font[Font].Count.Pages := managerFont.Font[Font].Count.Chars div sqr( fg_PageChars ) + 1;
  670. SetLength( managerFont.Font[Font].Pages, managerFont.Font[Font].Count.Pages );
  671. managerFont.Font[Font].MaxHeight := 0;
  672. managerFont.Font[Font].MaxShiftY := 0;
  673. for i := 0 to managerFont.Font[Font].Count.Pages - 1 do
  674. begin
  675. u := 1 / fg_PageSize;
  676. v := 1 / fg_PageSize;
  677. zgl_GetMem( pData, sqr( fg_PageSize ) * 4 );
  678. for j := 0 to sqr( fg_PageChars ) - 1 do
  679. begin
  680. CharID := j + i * sqr( fg_PageChars );
  681. if CharID > managerFont.Font[Font].Count.Chars - 1 Then break;
  682. cy := j div fg_PageChars;
  683. cx := j - cy * fg_PageChars;
  684. sx := Round( fg_CharsSize[ CharID ].W );
  685. sy := Round( fg_CharsSize[ CharID ].H );
  686. fontgen_PutChar( pData, cx * cs + ( cs - sx ) div 2, cy * cs + ( cs - sy ) div 2, CharID );
  687. SetLength( fg_CharsImage[ CharID ], 0 );
  688. CharUID := fg_CharsUID[ CharID ];
  689. zgl_GetMem( Pointer( managerFont.Font[Font].CharDesc[ CharUID ] ), SizeOf( zglTCharDesc ) );
  690. managerFont.Font[Font].CharDesc[ CharUID ]^.Page := i;
  691. managerFont.Font[Font].CharDesc[ CharUID ]^.Width := sx;
  692. managerFont.Font[Font].CharDesc[ CharUID ]^.Height := sy;
  693. managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftX := Round( fg_CharsSize[ CharID ].X );
  694. managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftY := Round( fg_CharsSize[ CharID ].Y );
  695. managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftP := fg_CharsP[ CharID ];
  696. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 0 ].X := ( cx * cs + ( cs - sx ) div 2 - fg_FontPadding[ 0 ] ) * u;
  697. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 0 ].Y := 1 - ( cy * cs + ( cs - sy ) div 2 - fg_FontPadding[ 1 ] ) * v;
  698. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 1 ].X := ( cx * cs + ( cs - sx ) div 2 + sx + fg_FontPadding[ 2 ] ) * u;
  699. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 1 ].Y := 1 - ( cy * cs + ( cs - sy ) div 2 - fg_FontPadding[ 1 ] ) * v;
  700. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 2 ].X := ( cx * cs + ( cs - sx ) div 2 + sx + fg_FontPadding[ 2 ] ) * u;
  701. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 2 ].Y := 1 - ( cy * cs + ( cs - sy ) div 2 + sy + fg_FontPadding[ 3 ] ) * v;
  702. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 3 ].X := ( cx * cs + ( cs - sx ) div 2 - fg_FontPadding[ 0 ] ) * u;
  703. managerFont.Font[Font].CharDesc[ CharUID ]^.TexCoords[ 3 ].Y := 1 - ( cy * cs + ( cs - sy ) div 2 + sy + fg_FontPadding[ 3 ] ) * v;
  704. managerFont.Font[Font].MaxHeight := Round( Max( managerFont.Font[Font].MaxHeight, fg_CharsSize[ CharID ].H ) );
  705. managerFont.Font[Font].MaxShiftY := Round( Max( managerFont.Font[Font].MaxShiftY, managerFont.Font[Font].CharDesc[ CharUID ]^.ShiftY ) );
  706. end;
  707. image_FlipVertically( pData, fg_PageSize, fg_PageSize, 4 );
  708. managerFont.Font[Font].Pages[i] := tex_Create( pData, fg_PageSize, fg_PageSize, TEX_FORMAT_RGBA, TEX_DEFAULT_2D );
  709. zgl_FreeMem( pData );
  710. end;
  711. end;
  712. managerFont.Font[Font].Padding[ 0 ] := fg_FontPadding[ 0 ];
  713. managerFont.Font[Font].Padding[ 1 ] := fg_FontPadding[ 1 ];
  714. managerFont.Font[Font].Padding[ 2 ] := fg_FontPadding[ 2 ];
  715. managerFont.Font[Font].Padding[ 3 ] := fg_FontPadding[ 3 ];
  716. end;
  717. procedure fontgen_SaveFont( Font: LongWord; const FileName : String );
  718. type
  719. zglPTGAHeader = ^zglTTGAHeader;
  720. zglTTGAHeader = packed record
  721. IDLength : Byte;
  722. CPalType : Byte;
  723. ImageType : Byte;
  724. CPalSpec : packed record
  725. FirstEntry : Word;
  726. Length : Word;
  727. EntrySize : Byte;
  728. end;
  729. ImgSpec : packed record
  730. X : Word;
  731. Y : Word;
  732. Width : Word;
  733. Height : Word;
  734. Depth : Byte;
  735. Desc : Byte;
  736. end;
  737. end;
  738. var
  739. TGA : zglTTGAHeader;
  740. F : zglTFile;
  741. i, c : Integer;
  742. Data : Pointer;
  743. {$IFDEF USE_PNG}
  744. Image : TImageData;
  745. {$ENDIF}
  746. begin
  747. file_Open( F, FileName + '.zfi', FOM_CREATE );
  748. file_Write( F, ZGL_FONT_INFO, 13 );
  749. file_Write( F, managerFont.Font[Font].Count.Pages, 2 );
  750. file_Write( F, managerFont.Font[Font].Count.Chars, 2 );
  751. file_Write( F, managerFont.Font[Font].MaxHeight, 4 );
  752. file_Write( F, managerFont.Font[Font].MaxShiftY, 4 );
  753. file_Write( F, fg_FontPadding[ 0 ], 4 );
  754. for i := 0 to managerFont.Font[Font].Count.Chars - 1 do
  755. begin
  756. c := fg_CharsUID[ i ];
  757. file_Write( F, c, 4 );
  758. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.Page, 4 );
  759. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.Width, 1 );
  760. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.Height, 1 );
  761. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.ShiftX, 4 );
  762. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.ShiftY, 4 );
  763. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.ShiftP, 4 );
  764. file_Write( F, managerFont.Font[Font].CharDesc[ c ]^.TexCoords[ 0 ], SizeOf( zglTPoint2D ) * 4 );
  765. end;
  766. file_Close( F );
  767. for i := 0 to managerFont.Font[Font].Count.Pages - 1 do
  768. begin
  769. FillChar( TGA, SizeOf( zglTTGAHeader ), 0 );
  770. TGA.ImageType := 2;
  771. TGA.ImgSpec.Width := fg_PageSize;
  772. TGA.ImgSpec.Height := fg_PageSize;
  773. TGA.ImgSpec.Depth := 32;
  774. TGA.ImgSpec.Desc := 8;
  775. tex_GetData( managerFont.Font[Font].Pages[i], Data );
  776. file_Open( F, FileName + '-page' + u_IntToStr( i ) + '.tga', FOM_CREATE );
  777. file_Write( F, TGA, SizeOf( zglTTGAHeader ) );
  778. file_Write( F, Data^, sqr( fg_PageSize ) * 4 );
  779. file_Close( F );
  780. FreeMemory( Data );
  781. {$IFDEF USE_PNG}
  782. LoadImageFromFile( FileName + '-page' + u_IntToStr( i ) + '.tga', Image );
  783. ConvertImage( Image, ifA8R8G8B8 );
  784. SaveImageToFile( FileName + '-page' + u_IntToStr( i ) + '.png', Image );
  785. DeleteFile( FileName + '-page' + u_IntToStr( i ) + '.tga' );
  786. {$ENDIF}
  787. end;
  788. end;
  789. end.