/usr/src/castle-game-engine-4.1.1/fonts/windows/castlewindowsfonts.pas is in castle-game-engine-src 4.1.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | {
Copyright 2002-2013 Michalis Kamburelis.
This file is part of "Castle Game Engine".
"Castle Game Engine" is free software; see the file COPYING.txt,
included in this distribution, for details about the copyright.
"Castle Game Engine" is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------------------------------
}
{ Windows-specific font utilities. }
unit CastleWindowsFonts;
interface
uses Windows, SysUtils, CastleUtils;
type
{ Windows font charset values. For each value csXxx below,
WinAPI defines constant XXX_CHARSET.
Useful for enumerating available charsets, displaying charset name etc. }
TWinCharSet = (
wcsANSI, wcsDEFAULT, wcsSYMBOL, wcsSHIFTJIS,
wcsHANGEUL, wcsGB2312, wcsCHINESEBIG5, wcsOEM,
wcsHEBREW, wcsARABIC, wcsGREEK,
wcsTURKISH, wcsTHAI, wcsEASTEUROPE,
wcsRUSSIAN, wcsBALTIC);
{ A wrapper for CreateFont WinAPI function.
Create an instance of this class, setup some attributes, and call GetHandle.
In the future this class may be extended to something less trivial.
For the meaning of properties see WinAPI documentation for CreateFont
function. }
TWindowsFont = class
private
FHeight: Integer;
FAngle: Integer;
FWeight: Integer;
FItalic: boolean;
FUnderline: boolean;
FStrikeOut: boolean;
FCharSet: TWinCharSet;
FOutputPrecision: DWord;
FClipPrecision: DWord;
FQuality: DWord;
FPitch: DWord;
FFamily: DWord;
FFaceName: string;
public
property Height: Integer read FHeight write FHeight;
{ Value for both nEscapement and nOrientation parameters for
CreateFont. The only portable way is to set them both to the same
values. }
property Angle: Integer read FAngle write FAngle default 0;
property Weight: Integer read FWeight write FWeight default FW_REGULAR;
property Italic: boolean read FItalic write FItalic default false;
property Underline: boolean read FUnderline write FUnderline default false;
property StrikeOut: boolean read FStrikeOut write FStrikeOut default false;
property CharSet: TWinCharSet read FCharSet write FCharSet default wcsDEFAULT;
property OutputPrecision: DWord read FOutputPrecision write FOutputPrecision
default OUT_DEFAULT_PRECIS;
property ClipPrecision: DWord read FClipPrecision write FClipPrecision
default CLIP_DEFAULT_PRECIS;
property Quality: DWord read FQuality write FQuality default DEFAULT_QUALITY;
{ Font pitch and family. They will be combined to create
fdwPitchAndFamily param, i.e. fdwPitchAndFamily := Pitch or Family.
Pitch is for XXX_PITCH consts, Family is for FF_XXX consts.
@groupBegin }
property Pitch: DWord read FPitch write FPitch default DEFAULT_PITCH;
property Family: DWord read FFamily write FFamily default FF_DONTCARE;
{ @groupEnd }
{ Font face name. Default is ''. }
property FaceName: string read FFaceName write FFaceName;
{ Create a font with given properties. Calls WinAPI CreateFont.
Rememeber to free result somewhere by DeleteObject.
Remeber that you may not get the font you asked for.
Windows.CreateFont will try to return something as close as possible,
but if exact match will not be possible -- it can return something else.
E.g. specifying FaceName = 'some non-existing font name' will not
cause some error (like EOSError).
Instead it will result in default Windows font ("MS Sans Serif" usually)
being returned.
@raises(EOSError If font cannot be created
(when WinAPI CreateFont returned error)) }
function GetHandle: HFont;
{ Constructor, takes initial Height value.
We require the height value to be passed to constructor,
simply because there's no "generally sensible" default value
for Height. }
constructor Create(AHeight: Integer);
end;
const
CharSetsNames: array [TWinCharSet] of string=(
'ANSI_CHARSET', 'DEFAULT_CHARSET', 'SYMBOL_CHARSET', 'SHIFTJIS_CHARSET',
'HANGEUL_CHARSET', 'GB2312_CHARSET', 'CHINESEBIG5_CHARSET', 'OEM_CHARSET',
'HEBREW_CHARSET', 'ARABIC_CHARSET', 'GREEK_CHARSET',
'TURKISH_CHARSET', 'THAI_CHARSET', 'EASTEUROPE_CHARSET',
'RUSSIAN_CHARSET', 'BALTIC_CHARSET');
{ TODO:
Funcs below are a little old.
They probably could use some improvements. }
{ Is given Windows font possibly true-type. }
function IsFontTrueType( Font: HFONT ): boolean;
type
TEnumFontCharsetsProc_ByObject = procedure( FontCharset: byte ) of object;
TEnumFontCharsetsProc = procedure( FontCharset: byte );
{ Enumerate charsets handled by given font. Warning: enumerated values
may be repeated.
@groupBegin }
procedure EnumFontCharsetsObj(const FontName: string; EnumProc : TEnumFontCharsetsProc_ByObject);
procedure EnumFontCharsets(const FontName: string; EnumProc : TEnumFontCharsetsProc);
{ @groupEnd }
function WinCharSetFromName(const Name: string): TWinCharSet;
implementation
uses CastleStringUtils;
const
CharSetsValues: array [TWinCharSet] of DWord = (
ANSI_CHARSET, DEFAULT_CHARSET, SYMBOL_CHARSET, SHIFTJIS_CHARSET,
HANGEUL_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, OEM_CHARSET,
HEBREW_CHARSET, ARABIC_CHARSET, GREEK_CHARSET,
TURKISH_CHARSET, THAI_CHARSET, EASTEUROPE_CHARSET,
RUSSIAN_CHARSET, BALTIC_CHARSET);
{ TWindowsFont ------------------------------------------------------------ }
constructor TWindowsFont.Create(AHeight: Integer);
begin
FHeight := AHeight;
FAngle := 0;
FWeight := FW_REGULAR;
FItalic := false;
FUnderline := false;
FStrikeOut := false;
FCharSet := wcsDEFAULT;
FOutputPrecision := OUT_DEFAULT_PRECIS;
FClipPrecision := CLIP_DEFAULT_PRECIS;
FQuality := DEFAULT_QUALITY;
FPitch := DEFAULT_PITCH;
FFamily := FF_DONTCARE;
FFaceName := '';
end;
function TWindowsFont.GetHandle: HFont;
const
BoolTo01: array[boolean]of Cardinal = (0, 1);
begin
Result := CreateFont(FHeight, 0, FAngle, FAngle,
FWeight, BoolTo01[FItalic], BoolTo01[FUnderline], BoolTo01[FStrikeOut],
CharSetsValues[FCharSet], FOutputPrecision, FClipPrecision, FQuality,
FPitch or FFamily, PCharOrNil(FaceName));
OSCheck( Result <> 0, 'CreateFont');
end;
{ Windows font query ------------------------------------------------------- }
function EnumFontFamProc_IsTrueType(var EnumLogfont: TEnumLogFont;
var NewTextMetric: TNewTextMetric;
FontType: Integer;
FuncResultPtr: LongInt): integer; stdcall;
begin
{ powinnismy sprawdzic czy znaleziony EnumLogFont.LogFont zgadza sie z szukanym
LogFontem. Skoro moze byc wiele fontow o tej samej nazwie ... wiemy ze do tej
procedury trafiaja tylko te ktorych nazwa sie zgadza. Ale co z reszta ?
Czysto teoretycznie np. wersja regular fontu moze byc realizowana bitmapowo,
a wersja Italic - jako TrueType. Nietesty - trudno rozstrzygnac czy znaleiony font
"pasuje" do naszego LogFontu - bo jesli np. wersja Italic zostala wygenerowana z
wersji regular to w naszym LogFoncie moze byc ustawione Italic a w EnumLogFoncie - nie,
ale to bedzie ten sam font ! W zasadzie powinnismy zapamietywac wszystkie
znalezione Logfonty a potem sprawdzac czy ten z nich ktory jest "najblizszy"
naszgeo szukanego jest czy nie jest true-type. Niestety, kompletny algorytm na
to czym jest "najblizszy" zna tylko Microsoft (zaimplementowali go chociazby w
CreateFont).
wiec co robimy ? Przeszukujemy wszystkie fonty o naszej nazwie. Jesli chociaz jeden
jest true type to uznajemy nasz font za true-type. }
if (FontType and TRUETYPE_FONTTYPE) <> 0 then
PBoolean(FuncResultPtr)^ := true;
Result := 1;
end;
function IsFontTrueType( Font: HFONT ): boolean;
{ See EnumFontFamProc_IsTrueType implementation comments for more information. }
var
LogFont: TLogFont;
wynik: integer;
dc: HDC;
savedObj: HGDIOBJ;
begin
wynik := GetObject(Font, SizeOf(TLogFont), @LogFont);
if wynik = 0 then RaiseLastOSError else
if wynik <> SizeOf(TLogFont) then
raise Exception.Create('IsFontTrueType function : parameter is not a font !');
Result := false;
dc := GetDC(0);
SavedObj := SelectObject(dc, Font);
try
EnumFontFamilies(dc, @LogFont.lfFaceName, @EnumFontFamProc_IsTrueType, PtrUInt(@Result));
finally
ReleaseDC(0, dc);
SelectObject(dc, SavedObj);
end;
end;
{ EnumFontCharsets ----------------------------------------------------------------------}
type
TEnumCharsetsInternalInfo_ByObject = record
UserEnumProc : TEnumFontCharsetsProc_ByObject;
end;
PEnumCharsetsInternalInfo_ByObject = ^TEnumCharsetsInternalInfo_ByObject;
function EnumFontFamExProc_ByObject(var LogFontData : TEnumLogFontEx;
var PhysFontData: TNewTextMetricEx;
FontType: Integer;
InternalInfo: LongInt): integer; stdcall;
begin
PEnumCharsetsInternalInfo_ByObject(InternalInfo)^.
UserEnumProc( PhysFontData.NtmENtm.tmCharset );
result := 1;
end;
procedure EnumFontCharsetsObj(const FontName: string; EnumProc : TEnumFontCharsetsProc_ByObject);
var
InternalInfo: TEnumCharsetsInternalInfo_ByObject;
DC: HDC;
LogFont: TLogFont;
begin
DC := GetDC(0); { device context desktopu }
try
FillChar(LogFont, SizeOf(LogFont), 0);
LogFont.lfCharSet := DEFAULT_CHARSET;
StrCopy(@LogFont.lfFaceName, PChar(FontName));
InternalInfo.UserEnumProc := EnumProc;
EnumFontFamiliesEx(Dc, {$ifdef FPC} @ {$endif} LogFont,
{ TODO: temporary, I just make this unchecked } @EnumFontFamExProc_ByObject,
Integer(@InternalInfo), 0);
finally ReleaseDC(0, DC) end;
end;
type
TEnumCharsetsDisp = class
NonObjectEnumProc : TEnumFontCharsetsProc;
procedure ObjectEnumProc( FontCharset: byte );
end;
procedure TEnumCharsetsDisp.ObjectEnumProc(FontCharset: byte);
begin { ObjectEnumProc przekazuje po prostu swoj argument do NonObjectenumProc }
NonObjectEnumProc( FontCharset );
end;
procedure EnumFontCharsets(const FontName: string; EnumProc : TEnumFontCharsetsProc);
var
EnumObj: TEnumCharsetsDisp;
begin
EnumObj := TEnumCharsetsDisp.Create;
EnumObj.NonObjectEnumProc := EnumProc;
try
EnumFontCharsetsObj(FontName, @EnumObj.ObjectEnumProc );
finally EnumObj.Free end;
end;
function WinCharSetFromName(const Name: string): TWinCharSet;
begin
for Result := Low(Result) to High(Result) do
if Name = CharSetsNames[Result] then
Exit;
raise Exception.CreateFmt('Invalid charset name "%s"', [Name]);
end;
end.
|