2
// This unit is part of the GLScene Engine https://github.com/glscene
7
Note: You can get valid extents (including AABB's) of this component only
8
after it has been rendered for the first time. It means if you ask its
9
extents during / after its creation, you will get zeros.
11
Also extents are valid only when SpaceText has one line.
14
25/03/11 - Yar - Fixed issue with unsharable virtual handle of font entry
15
22/09/10 - Yar - Added unicode support (Delphi 2009 & up only)
16
23/08/10 - Yar - Added OpenGLTokens to uses, replaced OpenGL1x functions to OpenGLAdapter
17
22/04/10 - Yar - Fixes after GLState revision
18
05/03/10 - DanB - More state added to TGLStateCache
19
25/12/07 - DaStr - Added MultiLine support (thanks Lexer)
20
Fixed Memory leak in TFontManager.Destroy
21
(Bugtracker ID = 1857814)
22
19/09/07 - DaStr - Added some comments
23
Optimized TGLSpaceText.BarycenterAbsolutePosition
24
12/09/07 - DaStr - Bugfixed TGLSpaceText.BarycenterAbsolutePosition
25
(Didn't consider rotations)
26
08/09/07 - DaStr - Implemented AxisAlignedDimensionsUnscaled and
27
BarycenterAbsolutePosition for TGLSpaceText
28
28/03/07 - DaStr - Renamed parameters in some methods
29
(thanks Burkhard Carstens) (Bugtracker ID = 1678658)
30
17/03/07 - DaStr - Dropped Kylix support in favor of FPC (BugTracekrID=1681585)
31
16/03/07 - DaStr - Added explicit pointer dereferencing
32
(thanks Burkhard Carstens) (Bugtracker ID = 1678644)
33
19/10/06 - LC - Added TGLSpaceText.Assign. Bugtracker ID=1576445 (thanks Zapology)
34
16/09/06 - NC - TGLVirtualHandle update (thx Lionel Reynaud)
35
03/06/02 - EG - VirtualHandle notification fix (Sören Mühlbauer)
36
07/03/02 - EG - GetFontBase fix (Sören Mühlbauer)
37
30/01/02 - EG - Text Alignment (Sören Mühlbauer),
38
TFontManager now GLContext compliant (RenderToBitmap ok!)
39
28/12/01 - EG - Event persistence change (GliGli / Dephi bug)
40
12/12/01 - EG - Creation (split from GLScene.pas)
48
{$IFDEF UNIX}{$MESSAGE Error 'Unit not supported'}{$ENDIF}
51
Windows, Messages, Classes,
52
Dialogs, Graphics, Controls,
54
GLScene, OpenGLTokens, GLTexture, GLContext, GLVectorGeometry, GLStrings,
55
GLRenderContextInfo, GLState;
59
// TSpaceTextCharRange
61
TSpaceTextCharRange = (stcrDefault, stcrAlphaNum, stcrNumbers, stcrWide);
65
// Note: haAligned, haCentrically, haFitIn have not been implemented!
67
TGLTextHorzAdjust = (haLeft, haCenter, haRight, haAligned,
68
haCentrically, haFitIn);
72
TGLTextVertAdjust = (vaTop, vaCenter, vaBottom, vaBaseLine);
76
TGLTextAdjust = class(TPersistent)
79
FHorz: TGLTextHorzAdjust;
80
FVert: TGLTextVertAdjust;
81
FOnChange: TNotifyEvent;
82
procedure SetHorz(const Value: TGLTextHorzAdjust);
83
procedure SetVert(const Value: TGLTextVertAdjust);
88
procedure Assign(Source: TPersistent); override;
90
property OnChange: TNotifyEvent read FOnChange write FOnChange;
94
property Horz: TGLTextHorzAdjust read FHorz write SetHorz default haLeft;
95
property Vert: TGLTextVertAdjust read FVert write SetVert
99
// holds an entry in the font manager list (used in TGLSpaceText)
100
PFontEntry = ^TFontEntry;
104
FVirtualHandle: TGLVirtualHandleTransf;
108
allowedDeviation: Single;
109
firstChar, lastChar: Integer;
110
glyphMetrics: array of TGlyphMetricsFloat;
116
{ : Renders a text in 3D. }
117
TGLSpaceText = class(TGLSceneObject)
122
FAllowedDeviation: Single;
123
FCharacterRange: TSpaceTextCharRange;
124
FAdjust: TGLTextAdjust;
125
FAspectRatio: Single;
129
procedure SetCharacterRange(const val: TSpaceTextCharRange);
130
procedure SetAllowedDeviation(const val: Single);
131
procedure SetExtrusion(AValue: Single);
132
procedure SetFont(AFont: TFont);
133
function GetText: WideString;
134
procedure SetLines(const Value: TStringList);
135
procedure SetText(const AText: WideString);
136
procedure SetAdjust(const Value: TGLTextAdjust);
137
procedure SetAspectRatio(const Value: Single);
138
procedure SetOblique(const Value: Single);
139
procedure SetTextHeight(const Value: Single);
142
FTextFontEntry: PFontEntry;
143
FontChanged: Boolean;
144
procedure DestroyHandle; override;
145
procedure OnFontChange(sender: TObject);
146
procedure GetFirstAndLastChar(var firstChar, lastChar: Integer);
147
procedure DoOnLinesChange(sender: TObject); virtual;
150
constructor Create(AOwner: TComponent); override;
151
destructor Destroy; override;
153
procedure Assign(Source: TPersistent); override;
155
procedure BuildList(var rci: TGLRenderContextInfo); override;
156
procedure DoRender(var ARci: TGLRenderContextInfo;
157
ARenderSelf, ARenderChildren: Boolean); override;
159
function TextWidth(const str: WideString = ''): Single;
160
function TextMaxHeight(const str: WideString = ''): Single;
161
function TextMaxUnder(const str: WideString = ''): Single;
163
{ : Note: this fuction is valid only after text has been rendered
164
the first time. Before that it returns zeros. }
165
procedure TextMetrics(const str: WideString;
166
out width, maxHeight, maxUnder: Single);
167
procedure NotifyFontChanged;
168
procedure NotifyChange(sender: TObject); override;
169
procedure DefaultHandler(var Message); override;
170
function AxisAlignedDimensionsUnscaled: TVector; override;
171
function BarycenterAbsolutePosition: TVector; override;
174
{ : Adjusts the 3D font extrusion.
175
If Extrusion=0, the characters will be flat (2D), values >0 will
176
give them a third dimension. }
177
property Extrusion: Single read FExtrusion write SetExtrusion;
178
property Font: TFont read FFont write SetFont;
179
property Text: WideString read GetText write SetText stored False;
180
property Lines: TStringList read FLines write SetLines;
181
{ : Quality related, see Win32 help for wglUseFontOutlines }
182
property allowedDeviation: Single read FAllowedDeviation
183
write SetAllowedDeviation;
184
{ : Character range to convert.
185
Converting less characters saves time and memory... }
186
property CharacterRange: TSpaceTextCharRange read FCharacterRange
187
write SetCharacterRange default stcrDefault;
188
property AspectRatio: Single read FAspectRatio write SetAspectRatio;
189
property TextHeight: Single read FTextHeight write SetTextHeight;
190
property Oblique: Single read FOblique write SetOblique;
191
property Adjust: TGLTextAdjust read FAdjust write SetAdjust;
196
{ : Manages a list of fonts for which display lists were created. }
197
TFontManager = class(TList)
200
FCurrentBase: Integer;
204
procedure NotifyClients(Clients: TList);
205
procedure VirtualHandleAlloc(sender: TGLVirtualHandle;
206
var handle: Cardinal);
207
procedure VirtualHandleDestroy(sender: TGLVirtualHandle;
208
var handle: Cardinal);
213
destructor Destroy; override;
215
function FindFont(AName: string; FStyles: TFontStyles; FExtrusion: Single;
216
FAllowedDeviation: Single; FFirstChar, FLastChar: Integer): PFontEntry;
217
function GetFontBase(AName: string; FStyles: TFontStyles;
218
FExtrusion: Single; allowedDeviation: Single;
219
firstChar, lastChar: Integer; client: TObject): PFontEntry;
220
procedure Release(entry: PFontEntry; client: TObject);
223
function FontManager: TFontManager;
224
procedure ReleaseFontManager;
227
vFontManagerMsgID: Cardinal;
229
// ------------------------------------------------------------------
230
// ------------------------------------------------------------------
231
// ------------------------------------------------------------------
234
// ------------------------------------------------------------------
235
// ------------------------------------------------------------------
236
// ------------------------------------------------------------------
242
cFontManagerMsg = 'GLScene FontManagerMessage';
245
vFontManager: TFontManager;
250
function FontManager: TFontManager;
252
if not Assigned(vFontManager) then
253
vFontManager := TFontManager.Create;
254
Result := vFontManager;
260
procedure ReleaseFontManager;
262
if Assigned(vFontManager) then
270
// ------------------ TGLTextAdjust ------------------
276
constructor TGLTextAdjust.Create;
286
procedure TGLTextAdjust.Assign(Source: TPersistent);
288
if Source is TGLTextAdjust then
290
FHorz := TGLTextAdjust(Source).Horz;
291
FVert := TGLTextAdjust(Source).Vert;
292
if Assigned(FOnChange) then
296
inherited Assign(Source);
302
procedure TGLTextAdjust.SetHorz(const Value: TGLTextHorzAdjust);
304
if FHorz <> Value then
307
if Assigned(FOnChange) then
315
procedure TGLTextAdjust.SetVert(const Value: TGLTextVertAdjust);
317
if Value <> FVert then
320
if Assigned(FOnChange) then
326
// ------------------ TGLSpaceText ------------------
332
constructor TGLSpaceText.Create(AOwner: TComponent);
334
inherited Create(AOwner);
335
FFont := TFont.Create;
336
FFont.Name := 'Arial';
338
CharacterRange := stcrDefault;
339
FFont.OnChange := OnFontChange;
340
FAdjust := TGLTextAdjust.Create;
341
FAdjust.OnChange := OnFontChange;
342
FLines := TStringList.Create;
343
FLines.OnChange := DoOnLinesChange;
349
destructor TGLSpaceText.Destroy;
351
FAdjust.OnChange := nil;
353
FFont.OnChange := nil;
356
FontManager.Release(FTextFontEntry, Self);
363
procedure TGLSpaceText.TextMetrics(const str: WideString;
364
out width, maxHeight, maxUnder: Single);
366
i, firstChar, lastChar, diff: Integer;
368
gmf: TGlyphMetricsFloat;
373
if Assigned(FTextFontEntry) then
375
GetFirstAndLastChar(firstChar, lastChar);
380
for i := 1 to Length(buf) do
382
diff := Integer(buf[i]) - firstChar;
383
if diff > High(FTextFontEntry^.glyphMetrics) then
385
gmf := FTextFontEntry^.glyphMetrics[diff];
386
width := width + gmf.gmfCellIncX;
387
if gmf.gmfptGlyphOrigin.y > maxHeight then
388
maxHeight := gmf.gmfptGlyphOrigin.y;
389
if gmf.gmfptGlyphOrigin.y - gmf.gmfBlackBoxY < maxUnder then
390
maxUnder := gmf.gmfptGlyphOrigin.y - gmf.gmfBlackBoxY;
398
function TGLSpaceText.TextWidth(const str: WideString = ''): Single;
402
TextMetrics(str, Result, mh, mu);
408
function TGLSpaceText.TextMaxHeight(const str: WideString = ''): Single;
412
TextMetrics(str, w, Result, mu);
418
function TGLSpaceText.TextMaxUnder(const str: WideString = ''): Single;
422
TextMetrics(str, w, mh, Result);
427
procedure TGLSpaceText.Assign(Source: TPersistent);
429
inherited Assign(Source);
430
if Source is TGLSpaceText then
432
FAdjust.Assign(TGLSpaceText(Source).FAdjust);
433
FFont.Assign(TGLSpaceText(Source).FFont);
434
FAllowedDeviation := TGLSpaceText(Source).allowedDeviation;
435
FAspectRatio := TGLSpaceText(Source).FAspectRatio;
436
FCharacterRange := TGLSpaceText(Source).CharacterRange;
437
FExtrusion := TGLSpaceText(Source).FExtrusion;
438
FOblique := TGLSpaceText(Source).FOblique;
439
FLines.Text := TGLSpaceText(Source).FLines.Text;
440
FTextHeight := TGLSpaceText(Source).FTextHeight;
448
procedure TGLSpaceText.BuildList(var rci: TGLRenderContextInfo);
450
textL, maxUnder, maxHeight: Single;
454
dirtyLine, cleanLine: WideString;
456
if Length(GetText) > 0 then
460
// FAspectRatio ignore
461
if FAspectRatio <> 0 then
462
GL.Scalef(FAspectRatio, 1, 1);
463
if FOblique <> 0 then
464
GL.Rotatef(FOblique, 0, 0, 1);
466
glBase := FTextFontEntry^.FVirtualHandle.handle;
467
case FCharacterRange of
469
GL.ListBase(TGLuint(Integer(glBase) - 32));
471
GL.ListBase(TGLuint(Integer(glBase) - Integer('0')));
476
rci.GLStates.PushAttrib([sttPolygon]);
477
for i := 0 to FLines.Count - 1 do
481
TextMetrics(FLines.Strings[i], textL, maxHeight, maxUnder);
482
if (FAdjust.Horz <> haLeft) or (FAdjust.Vert <> vaBaseLine) or
483
(FTextHeight <> 0) then
485
if FTextHeight <> 0 then
487
charScale := FTextHeight / maxHeight;
488
GL.Scalef(charScale, charScale, 1);
494
GL.Translatef(-textL * 0.5, 0, 0);
496
GL.Translatef(-textL, 0, 0);
502
GL.Translatef(0, abs(maxUnder), 0);
504
GL.Translatef(0, abs(maxUnder) * 0.5 - maxHeight * 0.5, 0);
506
GL.Translatef(0, -maxHeight, 0);
510
GL.Translatef(0, -i * (maxHeight + FAspectRatio), 0);
511
if FCharacterRange = stcrWide then
513
dirtyLine := FLines.Strings[i];
514
SetLength(cleanLine, Length(dirtyLine));
516
for j := 1 to Length(dirtyLine) do
518
c := Integer(dirtyLine[j]);
519
if (c >= FTextFontEntry^.firstChar) and
520
(c <= FTextFontEntry^.lastChar) then
522
cleanLine[k] := dirtyLine[j];
527
GL.CallLists(k - 1, GL_UNSIGNED_SHORT, PWideChar(cleanLine))
530
GL.CallLists(Length(FLines.Strings[i]), GL_UNSIGNED_BYTE,
531
PGLChar(TGLString(FLines.Strings[i])));
534
rci.GLStates.PopAttrib();
542
procedure TGLSpaceText.DestroyHandle;
548
// GetFirstAndLastChar
551
procedure TGLSpaceText.GetFirstAndLastChar(var firstChar, lastChar: Integer);
553
case FCharacterRange of
561
firstChar := Integer('0');
562
lastChar := Integer('9');
580
procedure TGLSpaceText.DoRender(var ARci: TGLRenderContextInfo;
581
ARenderSelf, ARenderChildren: Boolean);
583
firstChar, lastChar: Integer;
585
if GetText <> '' then
587
if Assigned(FTextFontEntry) then
588
FTextFontEntry^.FVirtualHandle.AllocateHandle;
589
if FontChanged or (Assigned(FTextFontEntry) and
590
(FTextFontEntry^.FVirtualHandle.IsDataNeedUpdate)) then
593
FontManager.Release(FTextFontEntry, Self);
594
GetFirstAndLastChar(firstChar, lastChar);
595
FTextFontEntry := FontManager.GetFontBase(Name, Style, FExtrusion,
596
FAllowedDeviation, firstChar, lastChar, Self);
597
FontChanged := False;
598
FTextFontEntry^.FVirtualHandle.NotifyDataUpdated;
607
procedure TGLSpaceText.SetExtrusion(AValue: Single);
609
Assert(AValue >= 0, 'Extrusion must be >=0');
610
if FExtrusion <> AValue then
612
FExtrusion := AValue;
617
// SetAllowedDeviation
620
procedure TGLSpaceText.SetAllowedDeviation(const val: Single);
622
if FAllowedDeviation <> val then
625
FAllowedDeviation := val
627
FAllowedDeviation := 0;
635
procedure TGLSpaceText.SetCharacterRange(const val: TSpaceTextCharRange);
637
if FCharacterRange <> val then
639
FCharacterRange := val;
647
procedure TGLSpaceText.SetFont(AFont: TFont);
656
procedure TGLSpaceText.OnFontChange(sender: TObject);
665
procedure TGLSpaceText.SetText(const AText: WideString);
667
if GetText <> AText then
669
FLines.Text := AText;
670
// StructureChanged is Called in DoOnLinesChange.
674
procedure TGLSpaceText.DoOnLinesChange(sender: TObject);
682
function TGLSpaceText.GetText: WideString;
684
if FLines.Count = 1 then
687
Result := FLines.Text;
693
procedure TGLSpaceText.SetLines(const Value: TStringList);
695
FLines.Assign(Value);
701
procedure TGLSpaceText.SetAdjust(const Value: TGLTextAdjust);
703
FAdjust.Assign(Value);
710
procedure TGLSpaceText.SetAspectRatio(const Value: Single);
712
if FAspectRatio <> Value then
714
FAspectRatio := Value;
722
procedure TGLSpaceText.SetOblique(const Value: Single);
724
if FOblique <> Value then
734
procedure TGLSpaceText.SetTextHeight(const Value: Single);
736
if Value <> FTextHeight then
738
FTextHeight := Value;
746
procedure TGLSpaceText.NotifyFontChanged;
748
FTextFontEntry := nil;
755
procedure TGLSpaceText.NotifyChange(sender: TObject);
757
if sender is TFontManager then
766
procedure TGLSpaceText.DefaultHandler(var Message);
768
with TMessage(Message) do
770
if Msg = vFontManagerMsgID then
777
// BarycenterAbsolutePosition
780
function TGLSpaceText.BarycenterAbsolutePosition: TVector;
782
lWidth, lHeightMax, lHeightMin: Single;
783
AdjustVector: TVector;
785
TextMetrics(Text, lWidth, lHeightMax, lHeightMin);
787
case FAdjust.FHorz of
789
AdjustVector.V[0] := lWidth / 2;
791
AdjustVector.V[0] := 0; // Nothing.
793
AdjustVector.V[0] := -lWidth / 2;
796
AdjustVector.V[0] := 0;
797
Assert(False, glsErrorEx + glsUnknownType); // Not implemented...
801
case FAdjust.FVert of
803
AdjustVector.V[1] := -(abs(lHeightMin) * 0.5 + lHeightMax * 0.5);
805
AdjustVector.V[1] := 0; // Nothing.
807
AdjustVector.V[1] := (abs(lHeightMin) * 0.5 + lHeightMax * 0.5);
809
AdjustVector.V[1] := -(abs(lHeightMin) * 0.5 - lHeightMax * 0.5);
812
AdjustVector.V[1] := 0;
813
Assert(False, glsErrorEx + glsUnknownType); // Not implemented...
817
AdjustVector.V[2] := -(FExtrusion / 2);
818
AdjustVector.V[3] := 1;
819
Result := LocalToAbsolute(AdjustVector);
822
// AxisAlignedDimensionsUnscaled
825
function TGLSpaceText.AxisAlignedDimensionsUnscaled: TVector;
827
lWidth, lHeightMax, lHeightMin: Single;
830
TextMetrics(Text, lWidth, lHeightMax, lHeightMin);
832
if FTextHeight = 0 then
835
charScale := FTextHeight / lHeightMax;
837
Result.V[0] := lWidth / 2 * charScale;
838
Result.V[1] := (lHeightMax + abs(lHeightMin)) / 2 * charScale;
839
Result.V[2] := FExtrusion / 2;
844
// ------------------ TFontManager ------------------
850
constructor TFontManager.Create;
858
destructor TFontManager.Destroy;
862
for i := 0 to Count - 1 do
864
TFontEntry(Items[i]^).FVirtualHandle.Free;
865
NotifyClients(TFontEntry(Items[i]^).FClients);
866
TFontEntry(Items[i]^).FClients.Free;
867
TFontEntry(Items[i]^).Name := '';
868
FreeMem(Items[i], SizeOf(TFontEntry));
876
procedure TFontManager.VirtualHandleAlloc(sender: TGLVirtualHandle;
877
var handle: Cardinal);
879
handle := FCurrentBase;
882
// VirtualHandleDestroy
885
procedure TFontManager.VirtualHandleDestroy(sender: TGLVirtualHandle;
886
var handle: Cardinal);
889
GL.DeleteLists(handle, sender.Tag);
895
function TFontManager.FindFont(AName: string; FStyles: TFontStyles;
896
FExtrusion: Single; FAllowedDeviation: Single; FFirstChar, FLastChar: Integer)
902
// try to find an entry with the required attributes
903
for i := 0 to Count - 1 do
904
with TFontEntry(Items[i]^) do
905
if (CompareText(Name, AName) = 0) and (Styles = FStyles) and
906
(Extrusion = FExtrusion) and (allowedDeviation = FAllowedDeviation) and
907
(firstChar = FFirstChar) and (lastChar = FLastChar) then
918
function TFontManager.GetFontBase(AName: string; FStyles: TFontStyles;
919
FExtrusion: Single; allowedDeviation: Single; firstChar, lastChar: Integer;
920
client: TObject): PFontEntry;
922
NewEntry: PFontEntry;
928
NewEntry := FindFont(AName, FStyles, FExtrusion, allowedDeviation, firstChar,
930
if Assigned(NewEntry) then
932
Inc(NewEntry^.RefCount);
933
if NewEntry^.FClients.IndexOf(client) < 0 then
934
NewEntry^.FClients.Add(client);
939
if (Result = nil) or (Assigned(Result) and
940
(Result^.FVirtualHandle.handle = 0)) then
942
// no entry found, or entry was purged
943
nbLists := lastChar - firstChar + 1;
944
if not Assigned(NewEntry) then
946
// no entry found, so create one
948
NewEntry^.Name := AName;
949
NewEntry^.FVirtualHandle := TGLVirtualHandleTransf.Create;
950
NewEntry^.FVirtualHandle.OnAllocate := VirtualHandleAlloc;
951
NewEntry^.FVirtualHandle.OnDestroy := VirtualHandleDestroy;
952
NewEntry^.FVirtualHandle.Tag := nbLists;
953
NewEntry^.Styles := FStyles;
954
NewEntry^.Extrusion := FExtrusion;
955
NewEntry^.RefCount := 1;
956
NewEntry^.firstChar := firstChar;
957
NewEntry^.lastChar := lastChar;
958
SetLength(NewEntry^.glyphMetrics, nbLists);
959
NewEntry^.allowedDeviation := allowedDeviation;
960
NewEntry^.FClients := TList.Create;
961
NewEntry^.FClients.Add(client);
964
// create a font to be used while display list creation
965
AFont := TFont.Create;
966
MemDC := CreateCompatibleDC(0);
969
AFont.Style := FStyles;
970
SelectObject(MemDC, AFont.handle);
971
FCurrentBase := GL.GenLists(nbLists);
972
if FCurrentBase = 0 then
973
raise Exception.Create('FontManager: no more display lists available');
974
NewEntry^.FVirtualHandle.AllocateHandle;
975
if lastChar < 256 then
977
success := wglUseFontOutlinesA(MemDC, firstChar, nbLists, FCurrentBase,
978
allowedDeviation, FExtrusion, WGL_FONT_POLYGONS,
979
@NewEntry^.glyphMetrics[0]);
983
success := wglUseFontOutlinesW(MemDC, firstChar, nbLists, FCurrentBase,
984
allowedDeviation, FExtrusion, WGL_FONT_POLYGONS,
985
@NewEntry^.glyphMetrics[0]);
988
raise Exception.Create('FontManager: font creation failed');
1000
procedure TFontManager.Release(entry: PFontEntry; client: TObject);
1004
if Assigned(entry) then
1006
Dec(entry^.RefCount);
1007
if Assigned(client) then
1009
hMsg.Msg := vFontManagerMsgID;
1010
client.DefaultHandler(hMsg);
1012
entry^.FClients.Remove(client);
1013
if entry^.RefCount = 0 then
1015
entry^.FVirtualHandle.Free;
1016
NotifyClients(entry^.FClients);
1017
entry^.FClients.Free;
1027
procedure TFontManager.NotifyClients(Clients: TList);
1032
hMsg.Msg := vFontManagerMsgID;
1033
for i := 0 to Clients.Count - 1 do
1034
TObject(Clients[i]).DefaultHandler(hMsg);
1037
// -------------------------------------------------------------
1038
// -------------------------------------------------------------
1039
// -------------------------------------------------------------
1042
// -------------------------------------------------------------
1043
// -------------------------------------------------------------
1044
// -------------------------------------------------------------
1046
vFontManagerMsgID := RegisterWindowMessage(cFontManagerMsg);
1047
RegisterClass(TGLSpaceText);