This file is indexed.

/usr/src/castle-game-engine-5.2.0/fonts/windows/castlewindowsfonts.pas is in castle-game-engine-src 5.2.0-2.

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-2014 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.