123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXS.SpaceText;
- (*
- 3D Text component.
- Note: You can get valid extents (including AABB's) of this component only
- after it has been rendered for the first time. It means if you ask its
- extents during / after its creation, you will get zeros.
- Also extents are valid only when SpaceText has one line.
- *)
- interface
- {$I Stage.Defines.inc}
- uses
- Winapi.OpenGL,
- Winapi.Windows,
- WinApi.Messages,
- System.Classes,
- System.UITypes,
- System.SysUtils,
- FMX.Graphics,
- Stage.VectorGeometry,
- Stage.Strings,
- Stage.VectorTypes,
- GXS.Scene,
- GXS.Texture,
- GXS.Context,
- GXS.RenderContextInfo,
- GXS.State;
- type
- TgxSpaceTextCharRange = (stcrDefault, stcrAlphaNum, stcrNumbers, stcrWide);
- // Note: haAligned, haCentrically, haFitIn have not been implemented!
- TgxTextHorzAdjust = (haLeft, haCenter, haRight, haAligned,
- haCentrically, haFitIn);
- TgxTextVertAdjust = (vaTop, vaCenter, vaBottom, vaBaseLine);
- TgxTextAdjust = class(TPersistent)
- private
- FHorz: TgxTextHorzAdjust;
- FVert: TgxTextVertAdjust;
- FOnChange: TNotifyEvent;
- procedure SetHorz(const Value: TgxTextHorzAdjust);
- procedure SetVert(const Value: TgxTextVertAdjust);
- public
- constructor Create;
- procedure Assign(Source: TPersistent); override;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- published
- property Horz: TgxTextHorzAdjust read FHorz write SetHorz default haLeft;
- property Vert: TgxTextVertAdjust read FVert write SetVert default vaBaseLine;
- end;
- // Holds an entry in the font manager list (used in TgxSpaceText)
- PFontEntry = ^TFontEntry;
- TFontEntry = record
- Name: string;
- FVirtualHandle: TgxVirtualHandleTransf;
- Styles: TFontStyles;
- Extrusion: Single;
- RefCount: Integer;
- allowedDeviation: Single;
- firstChar, lastChar: Integer;
- glyphMetrics: array of TGlyphMetricsFloat;
- FClients: TList;
- end;
- // Renders a text in 3D.
- TgxSpaceText = class(TgxSceneObject)
- private
- FFont: TFont;
- FExtrusion: Single;
- FAllowedDeviation: Single;
- FCharacterRange: TgxSpaceTextCharRange;
- FAdjust: TgxTextAdjust;
- FAspectRatio: Single;
- FOblique: Single;
- FTextHeight: Single;
- FLines: TStringList;
- procedure SetCharacterRange(const val: TgxSpaceTextCharRange);
- procedure SetAllowedDeviation(const val: Single);
- procedure SetExtrusion(AValue: Single);
- procedure SetFont(AFont: TFont);
- function GetText: WideString;
- procedure SetLines(const Value: TStringList);
- procedure SetText(const AText: WideString);
- procedure SetAdjust(const Value: TgxTextAdjust);
- procedure SetAspectRatio(const Value: Single);
- procedure SetOblique(const Value: Single);
- procedure SetTextHeight(const Value: Single);
- protected
- FTextFontEntry: PFontEntry;
- FontChanged: Boolean;
- procedure DestroyHandle; override;
- procedure OnFontChange(sender: TObject);
- procedure GetFirstAndLastChar(var firstChar, lastChar: Integer);
- procedure DoOnLinesChange(sender: TObject); virtual;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure BuildList(var rci: TgxRenderContextInfo); override;
- procedure DoRender(var ARci: TgxRenderContextInfo;
- ARenderSelf, ARenderChildren: Boolean); override;
- function TextWidth(const str: WideString = ''): Single;
- function TextMaxHeight(const str: WideString = ''): Single;
- function TextMaxUnder(const str: WideString = ''): Single;
- (* Note: this fuction is valid only after text has been rendered
- the first time. Before that it returns zeros. *)
- procedure TextMetrics(const str: WideString; out width, maxHeight, maxUnder: Single);
- procedure NotifyFontChanged;
- procedure NotifyChange(sender: TObject); override;
- procedure DefaultHandler(var Message); override;
- function AxisAlignedDimensionsUnscaled: TVector4f; override;
- function BarycenterAbsolutePosition: TVector4f; override;
- published
- (* Adjusts the 3D font extrusion.
- If Extrusion=0, the characters will be flat (2D), values >0 will
- give them a third dimension. *)
- property Extrusion: Single read FExtrusion write SetExtrusion;
- property Font: TFont read FFont write SetFont;
- property Text: WideString read GetText write SetText stored False;
- property Lines: TStringList read FLines write SetLines;
- // Quality related, see Win32 help for wglUseFontOutlines
- property allowedDeviation: Single read FAllowedDeviation write SetAllowedDeviation;
- // Character range to convert. Converting less characters saves time and memory...
- property CharacterRange: TgxSpaceTextCharRange read FCharacterRange
- write SetCharacterRange default stcrDefault;
- property AspectRatio: Single read FAspectRatio write SetAspectRatio;
- property TextHeight: Single read FTextHeight write SetTextHeight;
- property Oblique: Single read FOblique write SetOblique;
- property Adjust: TgxTextAdjust read FAdjust write SetAdjust;
- end;
- // Manages a list of fonts for which display lists were created.
- TFontManager = class(TList)
- private
- FCurrentBase: Integer;
- protected
- procedure NotifyClients(Clients: TList);
- procedure VirtualHandleAlloc(sender: TgxVirtualHandle; var handle: Cardinal);
- procedure VirtualHandleDestroy(sender: TgxVirtualHandle; var handle: Cardinal);
- public
- constructor Create;
- destructor Destroy; override;
- function FindFont(AName: string; FStyles: TFontStyles; FExtrusion: Single;
- FAllowedDeviation: Single; FFirstChar, FLastChar: Integer): PFontEntry;
- function GetFontBase(AName: string; FStyles: TFontStyles; FExtrusion: Single;
- allowedDeviation: Single; firstChar, lastChar: Integer; client: TObject): PFontEntry;
- procedure Release(entry: PFontEntry; client: TObject);
- end;
- function FontManager: TFontManager;
- procedure ReleaseFontManager;
- var
- vFontManagerMsgID: Cardinal;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- const
- cFontManagerMsg = 'Scene FontManagerMessage';
- var
- vFontManager: TFontManager;
- function FontManager: TFontManager;
- begin
- if not Assigned(vFontManager) then
- vFontManager := TFontManager.Create;
- Result := vFontManager;
- end;
- procedure ReleaseFontManager;
- begin
- if Assigned(vFontManager) then
- begin
- vFontManager.Free;
- vFontManager := nil;
- end;
- end;
- // ------------------
- // ------------------ TgxTextAdjust ------------------
- // ------------------
- constructor TgxTextAdjust.Create;
- begin
- inherited;
- FHorz := haLeft;
- FVert := vaBaseLine;
- end;
- procedure TgxTextAdjust.Assign(Source: TPersistent);
- begin
- if Source is TgxTextAdjust then
- begin
- FHorz := TgxTextAdjust(Source).Horz;
- FVert := TgxTextAdjust(Source).Vert;
- if Assigned(FOnChange) then
- FOnChange(Self);
- end
- else
- inherited Assign(Source);
- end;
- procedure TgxTextAdjust.SetHorz(const Value: TgxTextHorzAdjust);
- begin
- if FHorz <> Value then
- begin
- FHorz := Value;
- if Assigned(FOnChange) then
- FOnChange(Self);
- end;
- end;
- procedure TgxTextAdjust.SetVert(const Value: TgxTextVertAdjust);
- begin
- if Value <> FVert then
- begin
- FVert := Value;
- if Assigned(FOnChange) then
- FOnChange(Self);
- end;
- end;
- // ------------------
- // ------------------ TgxSpaceText ------------------
- // ------------------
- constructor TgxSpaceText.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FFont := TFont.Create;
- FFont.Family := 'Arial'; //in VCL FFont.Name
- FontChanged := True;
- CharacterRange := stcrDefault;
- FFont.OnChanged := OnFontChange;
- FAdjust := TgxTextAdjust.Create;
- FAdjust.OnChange := OnFontChange;
- FLines := TStringList.Create;
- FLines.OnChange := DoOnLinesChange;
- end;
- destructor TgxSpaceText.Destroy;
- begin
- FAdjust.OnChange := nil;
- FAdjust.Free;
- FFont.OnChanged := nil;
- FFont.Free;
- FLines.Free;
- FontManager.Release(FTextFontEntry, Self);
- inherited Destroy;
- end;
- procedure TgxSpaceText.TextMetrics(const str: WideString;
- out width, maxHeight, maxUnder: Single);
- var
- i, firstChar, lastChar, diff: Integer;
- buf: WideString;
- gmf: TGlyphMetricsFloat;
- begin
- width := 0;
- maxUnder := 0;
- maxHeight := 0;
- if Assigned(FTextFontEntry) then
- begin
- GetFirstAndLastChar(firstChar, lastChar);
- if str = '' then
- buf := GetText
- else
- buf := str;
- for i := 1 to Length(buf) do
- begin
- diff := Integer(buf[i]) - firstChar;
- if diff > High(FTextFontEntry^.glyphMetrics) then
- continue;
- gmf := FTextFontEntry^.glyphMetrics[diff];
- width := width + gmf.gmfCellIncX;
- if gmf.gmfptGlyphOrigin.y > maxHeight then
- maxHeight := gmf.gmfptGlyphOrigin.y;
- if gmf.gmfptGlyphOrigin.y - gmf.gmfBlackBoxY < maxUnder then
- maxUnder := gmf.gmfptGlyphOrigin.y - gmf.gmfBlackBoxY;
- end;
- end;
- end;
- function TgxSpaceText.TextWidth(const str: WideString = ''): Single;
- var
- mh, mu: Single;
- begin
- TextMetrics(str, Result, mh, mu);
- end;
- function TgxSpaceText.TextMaxHeight(const str: WideString = ''): Single;
- var
- w, mu: Single;
- begin
- TextMetrics(str, w, Result, mu);
- end;
- function TgxSpaceText.TextMaxUnder(const str: WideString = ''): Single;
- var
- w, mh: Single;
- begin
- TextMetrics(str, w, mh, Result);
- end;
- procedure TgxSpaceText.Assign(Source: TPersistent);
- begin
- inherited Assign(Source);
- if Source is TgxSpaceText then
- begin
- FAdjust.Assign(TgxSpaceText(Source).FAdjust);
- FFont.Assign(TgxSpaceText(Source).FFont);
- FAllowedDeviation := TgxSpaceText(Source).allowedDeviation;
- FAspectRatio := TgxSpaceText(Source).FAspectRatio;
- FCharacterRange := TgxSpaceText(Source).CharacterRange;
- FExtrusion := TgxSpaceText(Source).FExtrusion;
- FOblique := TgxSpaceText(Source).FOblique;
- FLines.Text := TgxSpaceText(Source).FLines.Text;
- FTextHeight := TgxSpaceText(Source).FTextHeight;
- StructureChanged;
- end;
- end;
- procedure TgxSpaceText.BuildList(var rci: TgxRenderContextInfo);
- var
- textL, maxUnder, maxHeight: Single;
- charScale: Single;
- i, j, k, c: Integer;
- glBase: GLuint;
- dirtyLine, cleanLine: WideString;
- begin
- if Length(GetText) > 0 then
- begin
- glPushMatrix;
- // FAspectRatio ignore
- if FAspectRatio <> 0 then
- glScalef(FAspectRatio, 1, 1);
- if FOblique <> 0 then
- glRotatef(FOblique, 0, 0, 1);
- glBase := FTextFontEntry^.FVirtualHandle.handle;
- case FCharacterRange of
- stcrAlphaNum:
- glListBase(GLuint(Integer(glBase) - 32));
- stcrNumbers:
- glListBase(GLuint(Integer(glBase) - Integer('0')));
- else
- glListBase(glBase);
- end;
- glPushAttrib(GL_POLYGON_BIT);
- for i := 0 to FLines.Count - 1 do
- begin
- glPushMatrix;
- TextMetrics(FLines.Strings[i], textL, maxHeight, maxUnder);
- if (FAdjust.Horz <> haLeft) or (FAdjust.Vert <> vaBaseLine) or
- (FTextHeight <> 0) then
- begin
- if FTextHeight <> 0 then
- begin
- charScale := FTextHeight / maxHeight;
- glScalef(charScale, charScale, 1);
- end;
- case FAdjust.Horz of
- haLeft:
- ; // nothing
- haCenter:
- glTranslatef(-textL * 0.5, 0, 0);
- haRight:
- glTranslatef(-textL, 0, 0);
- end;
- case FAdjust.Vert of
- vaBaseLine:
- ; // nothing;
- vaBottom:
- glTranslatef(0, abs(maxUnder), 0);
- vaCenter:
- glTranslatef(0, abs(maxUnder) * 0.5 - maxHeight * 0.5, 0);
- vaTop:
- glTranslatef(0, -maxHeight, 0);
- end;
- end;
- glTranslatef(0, -i * (maxHeight + FAspectRatio), 0);
- if FCharacterRange = stcrWide then
- begin
- dirtyLine := FLines.Strings[i];
- SetLength(cleanLine, Length(dirtyLine));
- k := 1;
- for j := 1 to Length(dirtyLine) do
- begin
- c := Integer(dirtyLine[j]);
- if (c >= FTextFontEntry^.firstChar) and
- (c <= FTextFontEntry^.lastChar) then
- begin
- cleanLine[k] := dirtyLine[j];
- Inc(k);
- end;
- end;
- if k > 1 then
- glCallLists(k - 1, GL_UNSIGNED_SHORT, PWideChar(cleanLine))
- end
- else
- glCallLists(Length(FLines.Strings[i]), GL_UNSIGNED_BYTE,
- PChar(String(FLines.Strings[i])));
- glPopMatrix;
- end;
- rci.gxStates.PopAttrib();
- glPopMatrix;
- end;
- end;
- procedure TgxSpaceText.DestroyHandle;
- begin
- FontChanged := True;
- inherited;
- end;
- procedure TgxSpaceText.GetFirstAndLastChar(var firstChar, lastChar: Integer);
- begin
- case FCharacterRange of
- stcrAlphaNum:
- begin
- firstChar := 32;
- lastChar := 127;
- end;
- stcrNumbers:
- begin
- firstChar := Integer('0');
- lastChar := Integer('9');
- end;
- stcrDefault:
- begin
- firstChar := 0;
- lastChar := 255;
- end;
- stcrWide:
- begin
- firstChar := 0;
- lastChar := $077F;
- end;
- end;
- end;
- procedure TgxSpaceText.DoRender(var ARci: TgxRenderContextInfo;
- ARenderSelf, ARenderChildren: Boolean);
- var
- firstChar, lastChar: Integer;
- begin
- if GetText <> '' then
- begin
- if Assigned(FTextFontEntry) then
- FTextFontEntry^.FVirtualHandle.AllocateHandle;
- if FontChanged or (Assigned(FTextFontEntry) and
- (FTextFontEntry^.FVirtualHandle.IsDataNeedUpdate)) then
- with FFont do
- begin
- FontManager.Release(FTextFontEntry, Self);
- GetFirstAndLastChar(firstChar, lastChar);
- FTextFontEntry := FontManager.GetFontBase(Name, Style, FExtrusion,
- FAllowedDeviation, firstChar, lastChar, Self);
- FontChanged := False;
- FTextFontEntry^.FVirtualHandle.NotifyDataUpdated;
- end;
- end;
- inherited;
- end;
- // SetExtrusion
- //
- procedure TgxSpaceText.SetExtrusion(AValue: Single);
- begin
- Assert(AValue >= 0, 'Extrusion must be >=0');
- if FExtrusion <> AValue then
- begin
- FExtrusion := AValue;
- OnFontChange(nil);
- end;
- end;
- procedure TgxSpaceText.SetAllowedDeviation(const val: Single);
- begin
- if FAllowedDeviation <> val then
- begin
- if val > 0 then
- FAllowedDeviation := val
- else
- FAllowedDeviation := 0;
- OnFontChange(nil);
- end;
- end;
- procedure TgxSpaceText.SetCharacterRange(const val: TgxSpaceTextCharRange);
- begin
- if FCharacterRange <> val then
- begin
- FCharacterRange := val;
- OnFontChange(nil);
- end;
- end;
- procedure TgxSpaceText.SetFont(AFont: TFont);
- begin
- FFont.Assign(AFont);
- OnFontChange(nil);
- end;
- procedure TgxSpaceText.OnFontChange(sender: TObject);
- begin
- FontChanged := True;
- StructureChanged;
- end;
- procedure TgxSpaceText.SetText(const AText: WideString);
- begin
- if GetText <> AText then
- begin
- FLines.Text := AText;
- // StructureChanged is Called in DoOnLinesChange.
- end;
- end;
- procedure TgxSpaceText.DoOnLinesChange(sender: TObject);
- begin
- StructureChanged;
- end;
- function TgxSpaceText.GetText: WideString;
- begin
- if FLines.Count = 1 then
- Result := FLines[0]
- else
- Result := FLines.Text;
- end;
- procedure TgxSpaceText.SetLines(const Value: TStringList);
- begin
- FLines.Assign(Value);
- end;
- procedure TgxSpaceText.SetAdjust(const Value: TgxTextAdjust);
- begin
- FAdjust.Assign(Value);
- StructureChanged;
- end;
- procedure TgxSpaceText.SetAspectRatio(const Value: Single);
- begin
- if FAspectRatio <> Value then
- begin
- FAspectRatio := Value;
- StructureChanged;
- end;
- end;
- procedure TgxSpaceText.SetOblique(const Value: Single);
- begin
- if FOblique <> Value then
- begin
- FOblique := Value;
- StructureChanged;
- end;
- end;
- procedure TgxSpaceText.SetTextHeight(const Value: Single);
- begin
- if Value <> FTextHeight then
- begin
- FTextHeight := Value;
- StructureChanged;
- end;
- end;
- procedure TgxSpaceText.NotifyFontChanged;
- begin
- FTextFontEntry := nil;
- FontChanged := True;
- end;
- procedure TgxSpaceText.NotifyChange(sender: TObject);
- begin
- if sender is TFontManager then
- NotifyFontChanged
- else
- inherited;
- end;
- procedure TgxSpaceText.DefaultHandler(var Message);
- begin
- with TMessage(Message) do
- begin
- if Msg = vFontManagerMsgID then
- NotifyFontChanged
- else
- inherited;
- end;
- end;
- function TgxSpaceText.BarycenterAbsolutePosition: TVector4f;
- var
- lWidth, lHeightMax, lHeightMin: Single;
- AdjustVector: TVector4f;
- begin
- TextMetrics(Text, lWidth, lHeightMax, lHeightMin);
- case FAdjust.FHorz of
- haLeft:
- AdjustVector.X := lWidth / 2;
- haCenter:
- AdjustVector.X := 0; // Nothing.
- haRight:
- AdjustVector.X := -lWidth / 2;
- else
- begin
- AdjustVector.X := 0;
- Assert(False, strErrorEx + strUnknownType); // Not implemented...
- end;
- end;
- case FAdjust.FVert of
- vaTop:
- AdjustVector.Y := -(abs(lHeightMin) * 0.5 + lHeightMax * 0.5);
- vaCenter:
- AdjustVector.Y := 0; // Nothing.
- vaBottom:
- AdjustVector.Y := (abs(lHeightMin) * 0.5 + lHeightMax * 0.5);
- vaBaseLine:
- AdjustVector.Y := -(abs(lHeightMin) * 0.5 - lHeightMax * 0.5);
- else
- begin
- AdjustVector.Y := 0;
- Assert(False, strErrorEx + strUnknownType); // Not implemented...
- end;
- end;
- AdjustVector.Z := -(FExtrusion / 2);
- AdjustVector.W := 1;
- Result := LocalToAbsolute(AdjustVector);
- end;
- function TgxSpaceText.AxisAlignedDimensionsUnscaled: TVector4f;
- var
- lWidth, lHeightMax, lHeightMin: Single;
- charScale: Single;
- begin
- TextMetrics(Text, lWidth, lHeightMax, lHeightMin);
- if FTextHeight = 0 then
- charScale := 1
- else
- charScale := FTextHeight / lHeightMax;
- Result.X := lWidth / 2 * charScale;
- Result.Y := (lHeightMax + abs(lHeightMin)) / 2 * charScale;
- Result.Z := FExtrusion / 2;
- Result.W := 0;
- end;
- // ------------------
- // ------------------ TFontManager ------------------
- // ------------------
- constructor TFontManager.Create;
- begin
- inherited;
- end;
- destructor TFontManager.Destroy;
- var
- i: Integer;
- begin
- for i := 0 to Count - 1 do
- begin
- TFontEntry(Items[i]^).FVirtualHandle.Free;
- NotifyClients(TFontEntry(Items[i]^).FClients);
- TFontEntry(Items[i]^).FClients.Free;
- TFontEntry(Items[i]^).Name := '';
- FreeMem(Items[i], SizeOf(TFontEntry));
- end;
- inherited Destroy;
- end;
- procedure TFontManager.VirtualHandleAlloc(sender: TgxVirtualHandle;
- var handle: Cardinal);
- begin
- handle := FCurrentBase;
- end;
- procedure TFontManager.VirtualHandleDestroy(sender: TgxVirtualHandle;
- var handle: Cardinal);
- begin
- if handle <> 0 then
- glDeleteLists(handle, sender.Tag);
- end;
- function TFontManager.FindFont(AName: string; FStyles: TFontStyles;
- FExtrusion: Single; FAllowedDeviation: Single; FFirstChar, FLastChar: Integer)
- : PFontEntry;
- var
- i: Integer;
- begin
- Result := nil;
- // try to find an entry with the required attributes
- for i := 0 to Count - 1 do
- with TFontEntry(Items[i]^) do
- if (CompareText(Name, AName) = 0) and (Styles = FStyles) and
- (Extrusion = FExtrusion) and (allowedDeviation = FAllowedDeviation) and
- (firstChar = FFirstChar) and (lastChar = FLastChar) then
- begin
- // entry found
- Result := Items[i];
- Break;
- end;
- end;
- function TFontManager.GetFontBase(AName: string; FStyles: TFontStyles;
- FExtrusion: Single; allowedDeviation: Single; firstChar, lastChar: Integer;
- client: TObject): PFontEntry;
- var
- NewEntry: PFontEntry;
- MemDC: HDC;
- AFont: TFont;
- nbLists: Integer;
- success: Boolean;
- begin
- NewEntry := FindFont(AName, FStyles, FExtrusion, allowedDeviation, firstChar,
- lastChar);
- if Assigned(NewEntry) then
- begin
- Inc(NewEntry^.RefCount);
- if NewEntry^.FClients.IndexOf(client) < 0 then
- NewEntry^.FClients.Add(client);
- Result := NewEntry;
- end
- else
- Result := nil;
- if (Result = nil) or (Assigned(Result) and
- (Result^.FVirtualHandle.handle = 0)) then
- begin
- // no entry found, or entry was purged
- nbLists := lastChar - firstChar + 1;
- if not Assigned(NewEntry) then
- begin
- // no entry found, so create one
- New(NewEntry);
- NewEntry^.Name := AName;
- NewEntry^.FVirtualHandle := TgxVirtualHandleTransf.Create;
- NewEntry^.FVirtualHandle.OnAllocate := VirtualHandleAlloc;
- NewEntry^.FVirtualHandle.OnDestroy := VirtualHandleDestroy;
- NewEntry^.FVirtualHandle.Tag := nbLists;
- NewEntry^.Styles := FStyles;
- NewEntry^.Extrusion := FExtrusion;
- NewEntry^.RefCount := 1;
- NewEntry^.firstChar := firstChar;
- NewEntry^.lastChar := lastChar;
- SetLength(NewEntry^.glyphMetrics, nbLists);
- NewEntry^.allowedDeviation := allowedDeviation;
- NewEntry^.FClients := TList.Create;
- NewEntry^.FClients.Add(client);
- Add(NewEntry);
- end;
- // create a font to be used while display list creation
- AFont := TFont.Create;
- MemDC := CreateCompatibleDC(0);
- try
- AFont.Family := AName;
- AFont.Style := FStyles;
- { TODO : E2003 Undeclared identifier: 'handle' }
- (*SelectObject(MemDC, AFont.handle);*)
- FCurrentBase := glGenLists(nbLists);
- if FCurrentBase = 0 then
- raise Exception.Create('FontManager: no more display lists available');
- NewEntry^.FVirtualHandle.AllocateHandle;
- if lastChar < 256 then
- begin
- success := wglUseFontOutlinesA(MemDC, firstChar, nbLists, FCurrentBase,
- allowedDeviation, FExtrusion, WGL_FONT_POLYGONS,
- @NewEntry^.glyphMetrics[0]);
- end
- else
- begin
- success := wglUseFontOutlinesW(MemDC, firstChar, nbLists, FCurrentBase,
- allowedDeviation, FExtrusion, WGL_FONT_POLYGONS,
- @NewEntry^.glyphMetrics[0]);
- end;
- if not success then
- raise Exception.Create('FontManager: font creation failed');
- finally
- AFont.Free;
- DeleteDC(MemDC);
- end;
- Result := NewEntry;
- end;
- end;
- procedure TFontManager.Release(entry: PFontEntry; client: TObject);
- var
- hMsg: TMessage;
- begin
- if Assigned(entry) then
- begin
- Dec(entry^.RefCount);
- if Assigned(client) then
- begin
- hMsg.Msg := vFontManagerMsgID;
- client.DefaultHandler(hMsg);
- end;
- entry^.FClients.Remove(client);
- if entry^.RefCount = 0 then
- begin
- entry^.FVirtualHandle.Free;
- NotifyClients(entry^.FClients);
- entry^.FClients.Free;
- Remove(entry);
- Dispose(entry)
- end;
- end;
- end;
- procedure TFontManager.NotifyClients(Clients: TList);
- var
- i: Integer;
- hMsg: TMessage;
- begin
- hMsg.Msg := vFontManagerMsgID;
- for i := 0 to Clients.Count - 1 do
- TObject(Clients[i]).DefaultHandler(hMsg);
- end;
- // -------------------------------------------------------------
- initialization
- // -------------------------------------------------------------
- vFontManagerMsgID := RegisterWindowMessage(cFontManagerMsg);
- RegisterClass(TgxSpaceText);
- finalization
- ReleaseFontManager;
- end.
|