You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

610 regels
22 KiB

  1. unit utsFontCreatorGDI;
  2. {$IFDEF FPC}
  3. {$mode delphi}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. Classes, SysUtils,
  8. utsTextSuite, utsTypes, utsGDI;
  9. type
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  11. TtsFontGDI = class(TtsFont)
  12. private
  13. fHandle: THandle;
  14. fMat2: TMat2;
  15. protected
  16. {%H-}constructor Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator; const aProperties: TtsFontProperties; const aHandle: THandle);
  17. public
  18. destructor Destroy; override;
  19. end;
  20. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. TtsFontRegistration = class(TObject)
  22. protected
  23. fIsRegistered: Boolean;
  24. fFontname: String;
  25. procedure UnregisterFont; virtual; abstract;
  26. public
  27. property IsRegistered: Boolean read fIsRegistered;
  28. property Fontname: String read fFontname;
  29. destructor Destroy; override;
  30. end;
  31. TtsFontRegistrationFile = class(TtsFontRegistration)
  32. private
  33. fFilename: String;
  34. protected
  35. procedure UnregisterFont; override;
  36. public
  37. constructor Create(const aFilename: String);
  38. end;
  39. TtsFontRegistrationStream = class(TtsFontRegistration)
  40. private
  41. fHandle: THandle;
  42. protected
  43. procedure UnregisterFont; override;
  44. public
  45. constructor Create(const aStream: TStream);
  46. end;
  47. TtsRegistredFontGDI = class(TtsFontGDI)
  48. private
  49. fRegistration: TtsFontRegistration;
  50. public
  51. constructor Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator;
  52. const aRegistration: TtsFontRegistration; const aProperties: TtsFontProperties; const aHandle: THandle);
  53. destructor Destroy; override;
  54. end;
  55. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  56. TtsFontGeneratorGDI = class(TtsFontGenerator)
  57. private
  58. function ConvertFont(const aFont: TtsFont): TtsFontGDI;
  59. function GetGlyphIndex(const aFont: TtsFontGDI; const aCharCode: WideChar): Integer;
  60. procedure GetCharImageAANone(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage);
  61. procedure GetCharImageAANormal(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage);
  62. function CreateFont(const aFontname: String; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing; out aProperties: TtsFontProperties): THandle;
  63. protected
  64. function GetGlyphMetrics(const aFont: TtsFont; const aCharCode: WideChar; out aGlyphOrigin, aGlyphSize: TtsPosition; out aAdvance: Integer): Boolean; override;
  65. procedure GetCharImage(const aFont: TtsFont; const aCharCode: WideChar; const aCharImage: TtsImage); override;
  66. public
  67. function GetFontByName(const aFontname: String; const aRenderer: TtsRenderer; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload;
  68. function GetFontByFile(const aFilename: String; const aRenderer: TtsRenderer; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload;
  69. function GetFontByStream(const aStream: TStream; const aRenderer: TtsRenderer; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload;
  70. constructor Create(const aContext: TtsContext);
  71. destructor Destroy; override;
  72. end;
  73. implementation
  74. uses
  75. math, utsTtfUtils;
  76. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  77. //TtsFontGDI////////////////////////////////////////////////////////////////////////////////////////////////////////////
  78. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  79. constructor TtsFontGDI.Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator; const aProperties: TtsFontProperties; const aHandle: THandle);
  80. begin
  81. inherited Create(aRenderer, aCreator, aProperties);
  82. FillChar(fMat2, SizeOf(fMat2), #0);
  83. fMat2.eM11.value := 1;
  84. fMat2.eM22.value := 1;
  85. fHandle := aHandle;
  86. end;
  87. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  88. destructor TtsFontGDI.Destroy;
  89. begin
  90. DeleteObject(fHandle);
  91. inherited Destroy;
  92. end;
  93. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. //TtsFontRegistration///////////////////////////////////////////////////////////////////////////////////////////////////
  95. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  96. destructor TtsFontRegistration.Destroy;
  97. begin
  98. if fIsRegistered then
  99. UnregisterFont;
  100. inherited Destroy;
  101. end;
  102. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  103. //TtsFontRegistrationFile///////////////////////////////////////////////////////////////////////////////////////////////
  104. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  105. procedure TtsFontRegistrationFile.UnregisterFont;
  106. begin
  107. if Assigned(RemoveFontResourceExA) then
  108. RemoveFontResourceExA(PAnsiChar(AnsiString(fFilename)), 0, nil)
  109. else if Assigned(RemoveFontResourceA) then
  110. RemoveFontResourceA(PAnsiChar(AnsiString(fFilename)));
  111. end;
  112. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  113. constructor TtsFontRegistrationFile.Create(const aFilename: String);
  114. var
  115. lang: AnsiString;
  116. begin
  117. inherited Create;
  118. fFilename := aFilename;
  119. // get Fontname
  120. SetLength(lang, 4);
  121. GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, @lang[1], 4);
  122. fFontname := GetTTFontFullNameFromFile(aFilename, StrToInt('$' + String(lang)));
  123. // register font
  124. if Assigned(AddFontResourceExA) then
  125. fIsRegistered := (AddFontResourceExA(PAnsiChar(AnsiString(fFilename)), 0, nil) > 0)
  126. else if Assigned(AddFontResourceA) then
  127. fIsRegistered := (AddFontResourceA(PAnsiChar(AnsiString(fFilename))) > 0)
  128. else
  129. fIsRegistered := false;
  130. end;
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. //TtsFontRegistrationStream/////////////////////////////////////////////////////////////////////////////////////////////
  133. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  134. procedure TtsFontRegistrationStream.UnregisterFont;
  135. begin
  136. if Assigned(RemoveFontMemResourceEx) then
  137. RemoveFontMemResourceEx(fHandle);
  138. end;
  139. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. constructor TtsFontRegistrationStream.Create(const aStream: TStream);
  141. var
  142. lang: AnsiString;
  143. ms: TMemoryStream;
  144. cnt: DWORD;
  145. begin
  146. inherited Create;
  147. fHandle := 0;
  148. fIsRegistered := false;
  149. // get Fontname
  150. SetLength(Lang, 4);
  151. GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, @lang[1], 4);
  152. fFontname := GetTTFontFullNameFromStream(aStream, StrToInt('$' + String(Lang)));
  153. // register font
  154. ms := TMemoryStream.Create;
  155. try
  156. ms.CopyFrom(aStream, 0);
  157. if Assigned(AddFontMemResourceEx) then
  158. fHandle := AddFontMemResourceEx(ms.Memory, ms.Size, nil, @cnt);
  159. fIsRegistered := (fHandle > 0);
  160. finally
  161. FreeAndNil(ms);
  162. end;
  163. end;
  164. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  165. //TtsRegistredFontGDI///////////////////////////////////////////////////////////////////////////////////////////////////
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. constructor TtsRegistredFontGDI.Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator;
  168. const aRegistration: TtsFontRegistration; const aProperties: TtsFontProperties; const aHandle: THandle);
  169. begin
  170. inherited Create(aRenderer, aCreator, aProperties, aHandle);
  171. fRegistration := aRegistration;
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. destructor TtsRegistredFontGDI.Destroy;
  175. begin
  176. FreeAndNil(fRegistration);
  177. inherited Destroy;
  178. end;
  179. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  180. //TtsFontCreatorGDIFontFace/////////////////////////////////////////////////////////////////////////////////////////////
  181. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. function TtsFontGeneratorGDI.ConvertFont(const aFont: TtsFont): TtsFontGDI;
  183. begin
  184. if not (aFont is TtsFontGDI) then
  185. raise EtsException.Create('aFont need to be a TtsFontGDI object');
  186. result := (aFont as TtsFontGDI);
  187. end;
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. function TtsFontGeneratorGDI.GetGlyphIndex(const aFont: TtsFontGDI; const aCharCode: WideChar): Integer;
  190. var
  191. DC: HDC;
  192. GCPRes: TGCPResultsW;
  193. begin
  194. result := -1;
  195. DC := CreateCompatibleDC(0);
  196. try
  197. SelectObject(DC, aFont.fHandle);
  198. if Assigned(GetCharacterPlacementW) then begin
  199. FillChar(GCPRes{%H-}, SizeOf(GCPRes), #0);
  200. GetMem(GCPRes.lpGlyphs, SizeOf(Cardinal));
  201. try
  202. GCPRes.lStructSize := SizeOf(GCPRes);
  203. GCPRes.lpGlyphs^ := 0;
  204. GCPRes.nGlyphs := 1;
  205. if (GetCharacterPlacementW(DC, @aCharCode, 1, GCP_MAXEXTENT, @GCPRes, 0) <> GDI_ERROR) and
  206. (GCPRes.nGlyphs = 1) and
  207. (GCPRes.lpGlyphs <> nil) then
  208. begin
  209. result := GCPRes.lpGlyphs^;
  210. end;
  211. finally
  212. FreeMem(GCPRes.lpGlyphs);
  213. end;
  214. end;
  215. finally
  216. DeleteDC(DC);
  217. end;
  218. end;
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. procedure TtsFontGeneratorGDI.GetCharImageAANone(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage);
  221. var
  222. Metric: TGlyphMetrics;
  223. GlyphIndex, srcW, srcX, w, h, x, y: Integer;
  224. Size, OutlineRes: Cardinal;
  225. Buffer, pSrc, pDst: PByte;
  226. procedure ExpandByte;
  227. var
  228. i, cnt, srcCnt: Integer;
  229. c: TtsColor4f;
  230. begin
  231. srcCnt := min(8, srcX);
  232. cnt := min(8, x);
  233. for i := 1 to cnt do begin
  234. c := tsColor4f(1, 1, 1, 1);
  235. if ((pSrc^ and $80) > 0) then
  236. c.a := 1.0
  237. else
  238. c.a := 0.0;
  239. pSrc^ := (pSrc^ and not $80) shl 1;
  240. tsFormatMap(aFont.Renderer.Format, pDst, c);
  241. end;
  242. dec(srcX, srcCnt);
  243. dec(x, cnt);
  244. inc(pSrc);
  245. end;
  246. begin
  247. if (aFont.fMat2.eM11.value <> 1) then
  248. raise EtsException.Create('invalid value');
  249. FillChar(Metric{%H-}, SizeOf(Metric), #0);
  250. GlyphIndex := GetGlyphIndex(aFont, aCharCode);
  251. if (GlyphIndex < 0) then
  252. exit;
  253. Size := GetGlyphOutlineA(aDC, GlyphIndex, GGO_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @aFont.fMat2);
  254. if (Size = GDI_ERROR) or (Size = 0) then
  255. exit;
  256. GetMem(Buffer, Size);
  257. try
  258. OutlineRes := GetGlyphOutlineA(aDC, GlyphIndex, GGO_BITMAP or GGO_GLYPH_INDEX, @Metric, Size, Buffer, @aFont.fMat2);
  259. if (OutlineRes = GDI_ERROR) then
  260. exit;
  261. w := Metric.gmBlackBoxX;
  262. h := Metric.gmBlackBoxY;
  263. srcW := (Integer(Size) div h) * 8;
  264. if (w <= 0) or (h <= 0) then
  265. exit;
  266. aImage.CreateEmpty(aFont.Renderer.Format, w, h);
  267. pSrc := Buffer;
  268. for y := 0 to h-1 do begin
  269. pDst := aImage.Scanline[y];
  270. srcX := srcW;
  271. x := w;
  272. while (srcX > 0) do
  273. ExpandByte;
  274. end;
  275. finally
  276. Freemem(Buffer);
  277. end;
  278. end;
  279. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  280. procedure TtsFontGeneratorGDI.GetCharImageAANormal(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage);
  281. var
  282. Metric: TGlyphMetrics;
  283. OutlineRes: DWORD;
  284. GlyphIndex, tmp, Spacer, x, y, w, h: Integer;
  285. Size: Cardinal;
  286. Buffer, pSrc, pDst: PByte;
  287. procedure CopyPixel;
  288. var
  289. i: Integer;
  290. tmp, cnt: Cardinal;
  291. c: TtsColor4f;
  292. begin
  293. cnt := min(x, aFont.fMat2.eM11.value);
  294. tmp := 0;
  295. for i := 0 to cnt-1 do begin
  296. tmp := tmp + pSrc^;
  297. inc(pSrc, 1);
  298. end;
  299. dec(x, cnt);
  300. c := tsColor4f(1, 1, 1, tmp / $40);
  301. tsFormatMap(aFont.Renderer.Format, pDst, c);
  302. end;
  303. begin
  304. FillChar(Metric{%H-}, SizeOf(Metric), #0);
  305. GlyphIndex := GetGlyphIndex(aFont, aCharCode);
  306. if (GlyphIndex < 0) then
  307. exit;
  308. Size := GetGlyphOutlineA(aDC, GlyphIndex, GGO_GRAY8_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @aFont.fMat2);
  309. if (Size = GDI_ERROR) or (Size = 0) then
  310. exit;
  311. GetMem(Buffer, Size);
  312. try
  313. OutlineRes := GetGlyphOutlineA(aDC, GlyphIndex, GGO_GRAY8_BITMAP or GGO_GLYPH_INDEX, @Metric, Size, Buffer, @aFont.fMat2);
  314. if (OutlineRes = GDI_ERROR) then
  315. exit;
  316. w := Integer(Metric.gmBlackBoxX) div aFont.fMat2.eM11.value;
  317. h := Metric.gmBlackBoxY;
  318. tmp := Integer(Metric.gmBlackBoxX) mod aFont.fMat2.eM11.value;
  319. if (tmp <> 0) then
  320. w := w + aFont.fMat2.eM11.value - tmp;
  321. if (w <= 0) or (h <= 0) then
  322. exit;
  323. // spacer
  324. Spacer := Metric.gmBlackBoxX mod 4;
  325. if (Spacer <> 0) then
  326. Spacer := 4 - Spacer;
  327. // copy image
  328. aImage.CreateEmpty(aFont.Renderer.Format, w, h);
  329. pSrc := Buffer;
  330. for y := 0 to h-1 do begin
  331. pDst := aImage.Scanline[y];
  332. x := Metric.gmBlackBoxX;
  333. while (x > 0) do
  334. CopyPixel;
  335. inc(pSrc, Spacer);
  336. end;
  337. finally
  338. FreeMem(Buffer);
  339. end;
  340. end;
  341. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  342. function TtsFontGeneratorGDI.CreateFont(const aFontname: String; const aSize: Integer; const aStyle: TtsFontStyles;
  343. const aAntiAliasing: TtsAntiAliasing; out aProperties: TtsFontProperties): THandle;
  344. var
  345. LogFont: TLogFontA;
  346. i: Integer;
  347. DC: HDC;
  348. TableName, BufSize: Cardinal;
  349. Buffer: PByte;
  350. Lang, tmpName: AnsiString;
  351. TextMetric: TTextMetricW;
  352. OutlineMetric: TOutlineTextmetricW;
  353. function _(e: Boolean; a, b: Integer): Integer;
  354. begin
  355. if e then
  356. result := a
  357. else
  358. result := b;
  359. end;
  360. begin
  361. FillChar(aProperties{%H-}, SizeOf(aProperties), #0);
  362. aProperties.Size := aSize;
  363. aProperties.Style := aStyle;
  364. aProperties.AntiAliasing := aAntiAliasing;
  365. aProperties.Fontname := aFontname;
  366. // prepare font attribs
  367. FillChar(LogFont{%H-}, SizeOf(LogFont), #0);
  368. tmpName := AnsiString(aFontname);
  369. for i := 1 to min(Length(aFontname), Length(LogFont.lfFaceName)) do
  370. LogFont.lfFaceName[i-1] := tmpName[i];
  371. LogFont.lfCharSet := DEFAULT_CHARSET;
  372. LogFont.lfHeight := -aSize;
  373. LogFont.lfWeight := _(tsStyleBold in aStyle, FW_BOLD, FW_NORMAL);
  374. LogFont.lfItalic := _(tsStyleItalic in aStyle, 1, 0);
  375. LogFont.lfUnderline := _(tsStyleUnderline in aStyle, 1, 0);
  376. LogFont.lfQuality := _(aAntiAliasing = tsAANormal, ANTIALIASED_QUALITY, NONANTIALIASED_QUALITY);
  377. result := CreateFontIndirectA(LogFont);
  378. DC := CreateCompatibleDC(0);
  379. try try
  380. SelectObject(DC, result);
  381. TableName := MakeTTTableName('n', 'a', 'm', 'e');
  382. BufSize := GetFontData(DC, TableName, 0, nil, 0);
  383. if (BufSize <> GDI_ERROR) then begin
  384. GetMem(Buffer, BufSize);
  385. try
  386. if (GetFontData(DC, TableName, 0, Buffer, BufSize) <> GDI_ERROR) then begin
  387. SetLength(Lang, 4);
  388. GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, @Lang[1], 4);
  389. GetTTString(Buffer, BufSize, NAME_ID_COPYRIGHT, StrToInt('$' + String(Lang)), aProperties.Copyright);
  390. GetTTString(Buffer, BufSize, NAME_ID_FACE_NAME, StrToInt('$' + String(Lang)), aProperties.FaceName);
  391. GetTTString(Buffer, BufSize, NAME_ID_STYLE_NAME, StrToInt('$' + String(Lang)), aProperties.StyleName);
  392. GetTTString(Buffer, BufSize, NAME_ID_FULL_NAME, StrToInt('$' + String(Lang)), aProperties.FullName);
  393. end;
  394. finally
  395. FreeMem(Buffer);
  396. end;
  397. end;
  398. if GetTextMetricsW(DC, TextMetric{%H-}) then begin
  399. aProperties.Ascent := TextMetric.tmAscent;
  400. aProperties.Descent := TextMetric.tmDescent;
  401. aProperties.ExternalLeading := TextMetric.tmExternalLeading;
  402. aProperties.DefaultChar := TextMetric.tmDefaultChar;
  403. end;
  404. if (GetOutlineTextMetricsW(DC, SizeOf(OutlineMetric), OutlineMetric{%H-}) > 0) then begin
  405. aProperties.UnderlinePos := OutlineMetric.otmsUnderscorePosition;
  406. aProperties.UnderlineSize := Min(1, OutlineMetric.otmsUnderscoreSize);
  407. aProperties.StrikeoutPos := OutlineMetric.otmsStrikeoutPosition;
  408. aProperties.StrikeoutSize := Min(1, OutlineMetric.otmsStrikeoutSize);
  409. end;
  410. except
  411. DeleteObject(result);
  412. result := 0;
  413. end;
  414. finally
  415. DeleteDC(DC);
  416. end;
  417. end;
  418. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  419. function TtsFontGeneratorGDI.GetGlyphMetrics(const aFont: TtsFont; const aCharCode: WideChar; out aGlyphOrigin, aGlyphSize: TtsPosition; out aAdvance: Integer): Boolean;
  420. var
  421. GlyphIndex: Integer;
  422. font: TtsFontGDI;
  423. DC: HDC;
  424. Metric: TGlyphMetrics;
  425. Size: Cardinal;
  426. begin
  427. result := false;
  428. aGlyphOrigin.x := 0;
  429. aGlyphOrigin.x := 0;
  430. aGlyphSize.x := 0;
  431. aGlyphSize.y := 0;
  432. aAdvance := 0;
  433. font := ConvertFont(aFont);
  434. GlyphIndex := GetGlyphIndex(font, aCharCode);
  435. if (GlyphIndex < 0) then
  436. exit;
  437. DC := CreateCompatibleDC(0);
  438. try
  439. SelectObject(DC, font.fHandle);
  440. case font.Properties.AntiAliasing of
  441. tsAANone: begin
  442. Size := GetGlyphOutlineA(DC, GlyphIndex, GGO_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @font.fMat2);
  443. end;
  444. tsAANormal: begin
  445. Size := GetGlyphOutlineA(DC, GlyphIndex, GGO_GRAY8_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @font.fMat2);
  446. end;
  447. else
  448. Size := GDI_ERROR;
  449. end;
  450. if (Size = GDI_ERROR) then
  451. Size := GetGlyphOutlineA(DC, GlyphIndex, GGO_METRICS or GGO_GLYPH_INDEX, @Metric, 0, nil, @font.fMat2);
  452. if (Size <> GDI_ERROR) then begin
  453. aGlyphOrigin.x := Metric.gmptGlyphOrigin.x;
  454. aGlyphOrigin.y := Metric.gmptGlyphOrigin.y;
  455. aGlyphSize.x := Metric.gmBlackBoxX;
  456. aGlyphSize.y := Metric.gmBlackBoxY;
  457. aAdvance := Metric.gmCellIncX;
  458. result := true;
  459. end;
  460. finally
  461. DeleteDC(DC);
  462. end;
  463. end;
  464. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  465. procedure TtsFontGeneratorGDI.GetCharImage(const aFont: TtsFont; const aCharCode: WideChar; const aCharImage: TtsImage);
  466. var
  467. DC: HDC;
  468. font: TtsFontGDI;
  469. begin
  470. font := ConvertFont(aFont);
  471. DC := CreateCompatibleDC(0);
  472. try
  473. SelectObject(DC, font.fHandle);
  474. case font.Properties.AntiAliasing of
  475. tsAANone:
  476. GetCharImageAANone(DC, font, aCharCode, aCharImage);
  477. tsAANormal:
  478. GetCharImageAANormal(DC, font, aCharCode, aCharImage);
  479. end;
  480. finally
  481. DeleteDC(DC);
  482. end;
  483. end;
  484. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  485. function TtsFontGeneratorGDI.GetFontByName(const aFontname: String; const aRenderer: TtsRenderer;
  486. const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont;
  487. var
  488. handle: THandle;
  489. prop: TtsFontProperties;
  490. begin
  491. handle := CreateFont(aFontname, aSize, aStyle, aAntiAliasing, prop);
  492. if (handle = 0) then
  493. raise EtsException.Create('unable to create font from name: ' + aFontname);
  494. result := TtsFontGDI.Create(aRenderer, self, prop, handle);
  495. end;
  496. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  497. function TtsFontGeneratorGDI.GetFontByFile(const aFilename: String; const aRenderer: TtsRenderer;
  498. const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont;
  499. var
  500. reg: TtsFontRegistrationFile;
  501. handle: THandle;
  502. prop: TtsFontProperties;
  503. begin
  504. reg := TtsFontRegistrationFile.Create(aFilename);
  505. try
  506. if not reg.IsRegistered then
  507. raise EtsException.Create('unable to register font file: ' + aFilename);
  508. handle := CreateFont(reg.Fontname, aSize, aStyle, aAntiAliasing, prop);
  509. if (handle = 0) then
  510. raise EtsException.Create('unable to create font from file: ' + aFilename);
  511. except
  512. FreeAndNil(reg);
  513. raise;
  514. end;
  515. result := TtsRegistredFontGDI.Create(aRenderer, self, reg, prop, handle);
  516. end;
  517. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  518. function TtsFontGeneratorGDI.GetFontByStream(const aStream: TStream; const aRenderer: TtsRenderer;
  519. const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont;
  520. var
  521. reg: TtsFontRegistrationStream;
  522. handle: THandle;
  523. prop: TtsFontProperties;
  524. begin
  525. reg := TtsFontRegistrationStream.Create(aStream);
  526. if not reg.IsRegistered then
  527. raise EtsException.Create('unable to register font from stream');
  528. handle := CreateFont(reg.Fontname, aSize, aStyle, aAntiAliasing, prop);
  529. if (handle = 0) then
  530. raise EtsException.Create('unable to create font from stream: ' + reg.Fontname);
  531. result := TtsRegistredFontGDI.Create(aRenderer, self, reg, prop, handle);
  532. end;
  533. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  534. constructor TtsFontGeneratorGDI.Create(const aContext: TtsContext);
  535. begin
  536. inherited Create(aContext);
  537. InitGDI;
  538. end;
  539. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  540. destructor TtsFontGeneratorGDI.Destroy;
  541. begin
  542. inherited Destroy; // first free all fonts (managed by parent class)
  543. QuitGDI;
  544. end;
  545. end.