Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fonts (Größe und Namen) (https://www.delphipraxis.net/90624-fonts-groesse-und-namen.html)

Alter Mann 20. Apr 2007 19:26


Fonts (Größe und Namen)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich werkel seit ein paar Tagen (Länger als mir lieb ist) daran herum,
die Schriftgrößen eines 'gesetzten' Font zuermitteln.
Dazu habe ich hier im Forum einiges gefunden, aber auch bei Delphi-Treff.
Dazu kommt das in der MSDN auch noch steht, dass ab
Windows 2000/XP die jeweiligen Strukturen andere sind
die bei der jeweiligen Callback-Routine aufgerufen werden.

Im Anhang befindet sich der Code eines kleinen Prog, indem allen bekannten Funktionen
genutzt werden können, aber es kommen so irrsinnige Werte dabei raus.
Vielleicht könnte ja der Eine oder Andere Mal raufschauen und schreiben woran es liegt.

Für Verbesserungen wäre ich sehr dankbar.

w.i.

Gruß
Alter Mann

TonyR 21. Apr 2007 17:16

Re: Fonts (Größe und Namen)
 
Ich versteh noch nicht ganz, was die Ergebnisse darstellen...
Sorry, aber kannst du mir nochmal erklären worum es geht oder einen Link posten wo das evtl. zum nachlesen ist???

Alter Mann 21. Apr 2007 21:37

Re: Fonts (Größe und Namen)
 
Hi TonyR,

zum besseren Verständnis:

Es wird in einer ComboBox die Schriftart (sprich Name) ausgewählt und anschliessend die dazugehörigen
Schriftgrößen ermittelt. Nur leider bekomme ich zB. bei Arial ca. 15 x 36; und bei einer Anderen
Schriftart zB. 2 x 6.

Alles klar? eigendlich sollte das Prog zeigen was ich meine...

Gruß

TonyR 22. Apr 2007 10:19

Re: Fonts (Größe und Namen)
 
Ok (nachdem ich die Theorie jetzt weiß....)

wöllte ich gern mal wissen, was das Programm anzeigt!?
Arial Narrow hat höhere Werte als Courier New (ist aber viel "schmaler"... narrow eben...)

Was mir aufgefallen ist: Bei ich sag mal "bekannteren" Schriften... also solche die öfter in Gebrauch sind, werden mehr Werte angezeigt (Menge ist höher)...

Alter Mann 22. Apr 2007 13:26

Re: Fonts (Größe und Namen)
 
Hallo,

das Programm im Anhang verdeutlicht nur den Umstand, dass die Ermittlung der möglichen Schriftgößen einer Schriftart
nicht klappt.

Die Auflistung der Schriftarten ist der RichEdit-Demo entnommen:
Delphi-Quellcode:
function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
  FontType: Integer; Data: Pointer): Integer; stdcall;
begin
  TStrings(Data).Add(LogFont.lfFaceName);
  Result := 1;
end;

procedure GetFontNames(Items : TStrings);
var
  DC: HDC;
begin
  DC := GetDC(0);
  EnumFonts(DC, nil, @EnumFontsProc, Pointer(Items));
  ReleaseDC(0, DC);
end;
und wird wie folgt genutzt:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  GetFontNames(ComboBox1.Items);
end;
Abhängig von der jeweiligen ausgewählten Schriftart sollen die Schriftgrößen bestimmt werden.
Delphi-Quellcode:
procedure TForm1.ComboBox1Select(Sender: TObject);
begin
  ListBox1.Items.Clear;
  if CheckBox1.Checked then
  ListFonts(ComboBox1.Text, ListBox1.Items)
  else
  GetFontFamilies(ComboBox1.Text, ListBox1.Items);
end;
Für die Ermittlung der Schriftgrößen verwende ich (mit kleinen Änderungen) den Code von GetFontFamilies
und Installierte Schriftarten ermitteln.

Beide haben jedoch den Nachteil, das sie unter XP nicht die richtigen(lt. MSDN) Strukturen verwenden und wurden
entsprechend angepasst.

Aus dem ersten Beispiel wurde dadurch:
Delphi-Quellcode:
procedure GetFontFamilies(const FontName : String; Items : TStrings);
var
   FN : PChar;
   DC :HDC;
begin
   if FontName <> '' then FN := PChar(FontName)
                     else FN := nil;
   Assert(Assigned(Items));
   Items.BeginUpdate;
   try
      DC := GetDC(0);
      if (Win32MajorVersion < 5) then
        EnumFontFamilies(DC, FN, @EnumFontsizes, Integer(Items))
      else
        EnumFontFamilies(DC, FN, @EnumFontsizes2K_XP, Integer(Items)); // <- hier Aufruf ab Windows 2000 und höher
      ReleaseDC(0, DC);
   finally
      Items.EndUpdate;
   end;
end;
die dazu gehörenden Callback-Routinen sehen eigendlich gleich aus, nur die Parameter unterscheiden sich:
Delphi-Quellcode:
function EnumFontSizes(var EnumLogFont: TEnumLogFont;
                       PTextMetric: PNewTextMetric;
                       FontType: Integer;
                       Data: LPARAM): Integer; stdcall;
var
   list : TStrings;
begin
   if Data <> 0 then
   begin
      list := TStrings(Data);
      list.Add(IntToStr(EnumLogFont.elfLogFont.lfHeight));
      Result := 1;
   end
   else Result := 0;
end;

function EnumFontSizes2K_XP(var EnumLogFont: TEnumLogFontEx;
                       PTextMetric: PTextMetric;
                       FontType: Integer;
                       Data: LPARAM): Integer; stdcall;
var
   list : TStrings;
begin
   if Data <> 0 then
   begin
      list := TStrings(Data);
      list.Add(IntToStr(EnumLogFont.elfLogFont.lfHeight));
      Result := 1;
   end
   else Result := 0;
end;
Das zweite Beispiel verwendet die EnumFontFamiliesEx-Routine, mit der gleichen Beschränkung:
Delphi-Quellcode:
procedure ListFonts(const FontName : String; const ADest: TStrings);
var
  Log: TLogFont;
  DC : HDC;
begin
  FillChar(Log, SizeOf(Log), 0);
  Log.lfCharSet := Default_Charset;
  StrPCopy(Log.lfFaceName, FontName);
  Log.lfPitchAndFamily := 0;
  DC := GetDC(0);
  if (Win32MajorVersion < 5) then
  EnumFontFamiliesEx(DC, Log, @_EnumFontFamExProc, Integer(ADest), 0)
  else
  EnumFontFamiliesEx(DC, Log, @_EnumFontFamExProc2K, Integer(ADest), 0); // <- hier Aufruf ab Windows 2000 und höher
  ReleaseDC(0, DC);
end;

function _EnumFontFamExProc(EnumLogFontEx: PEnumLogFontEx;
                            NewTextMetric: PNewTextMetric;
                            FontType: Longword;
                            LParam: Longword): integer; stdcall;
begin
  Result := 1;
  TStrings(LParam).Add(IntToStr(NewTextMetric.tmHeight));
end;

function _EnumFontFamExProc2K(EnumLogFontExDv: PEnumLogFontExDv;
                              EnumTextMetric: PEnumTextMetric;
                              FontType: Longword;
                              LParam: Longword): integer; stdcall;
begin
  Result := 1;
  TStrings(LParam).Add(IntToStr(EnumTextMetric.etmNewTextMetricEx.ntmTm.tmHeight));
end;
Für mich stellt sich nun die Frage warum werden nicht die richtigen Schriftgrößen ermittelt?

Bei der Schrfitart 'Alaska' bekomme ich nur die Größe '40' angezeigt, obwohl Alaska ein TrueTypeFont ist
und somit von 8 -72 skalierbar sein sollte.

Vielleicht ist ja auch im Code ein Fehler, aber wo?

Gruß

Reinhard Kern 22. Apr 2007 14:05

Re: Fonts (Größe und Namen)
 
Zitat:

Zitat von Alter Mann
Hallo,

ich werkel seit ein paar Tagen (Länger als mir lieb ist) daran herum,
die Schriftgrößen eines 'gesetzten' Font zuermitteln.
Dazu habe ich hier im Forum einiges gefunden, aber auch bei Delphi-Treff.
Dazu kommt das in der MSDN auch noch steht, dass ab
Windows 2000/XP die jeweiligen Strukturen andere sind
die bei der jeweiligen Callback-Routine aufgerufen werden.

Im Anhang befindet sich der Code eines kleinen Prog, indem allen bekannten Funktionen
genutzt werden können, aber es kommen so irrsinnige Werte dabei raus.
Vielleicht könnte ja der Eine oder Andere Mal raufschauen und schreiben woran es liegt.

Für Verbesserungen wäre ich sehr dankbar.

w.i.

Gruß
Alter Mann

Hallo,

da keine EXE dabei ist, war es mir zuviel Arbeit, das ganze zu installieren und neu zu übersetzen, aber ich füge dir einige Tabellenausdrucke für ArialN bei, vielleicht kannst du ja deine Werte damit überprüfen. Verwendet habe ich die ArialN aus Windows2000, liegt sicherheitshalber ebenfalls bei. Zum Beipiel die Tabelle "OS/2":

'OS/2' Table - OS/2 and Windows Metrics
---------------------------------------
Size = 86 bytes (expecting 78 bytes)
'OS/2' version: 1
xAvgCharWidth: 741
usWeightClass: 400
usWidthClass: 3
fsType: 0x0000
ySubscriptXSize: 1434
ySubscriptYSize: 1331
ySubscriptXOffset: 0
ySubscriptYOffset: 147
ySuperscriptXSize: 1434
ySuperscriptYSize: 1331
ySuperscriptXOffset: 0
ySuperscriptYOffset: 523
yStrikeoutSize: 102
yStrikeoutPosition: 530
sFamilyClass: 8 subclass = 5
PANOSE: 2 11 5 6 2 2 2 3 2 4
Character Range: 0x87020000000000000000000000000000
achVendID: 'MONO'
fsSelection 0x0040
usFirstCharIndex: 0x0020
usLastCharIndex: 0xFB02
sTypoAscender 1491
sTypoDescender -431
sTypoLineGap 269
usWinAscent 1888
usWinDescent 431

Gruss Reinhard

himitsu 22. Apr 2007 17:15

Re: Fonts (Größe und Namen)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mal einfach die weiteren Werte mit anzeigen lassen.

Es gibt zwar oftmals Werte mehrfach, allerdings liegen da die Unterschiede wo Anders ... siehe Binärausgabe.
Es wäre zuviel Arbeit gewesen und hätte eh überlange Zeilen ergeben, wenn alles einzeln angezeigt werden würde.

Ich vermute einfach mal, daß es sich hier nicht um die möglichen Schriftgrößen, sondern eher um mögliche Varianten handelt.

Bei den Matrix-Fonts (wie Terminal) gibt es da natürlich mehrere größen, aber bei den "normalen" TTFs welche scalierbar sind, werden doch nicht unbedingt verschíedene Schriftgrößen benötigt ... die gewünschte Größe wird dann einfach durch vergrößern/verkleiner aus einer möglichst passenden Variante errechnet.

Alter Mann 22. Apr 2007 18:00

Re: Fonts (Größe und Namen)
 
Hallo,

vielen Dank für die Mühe.

Zitat:

die gewünschte Größe wird dann einfach durch vergrößern/verkleiner aus einer möglichst passenden Variante errechnet.
Und um genau diese Variante geht es. Wenn als Ausgangspunkt die RichEdit-Demo dient und man sich das Verfahren zum Vergrößern/Verkleinern der Schrift ansieht,
stellt man sehr schnell fest, dass es 'Sub-Optimal' gelöst wurde. Es ist nicht schön eine Anwendung bereit zu stellen
in der Schriftgröße durch incrementieren eines Wertes verändert werden kann,
wo allerdings eine Veränderung nur bei jedem x'ten Wert erfolgt.
In Word oder auch anderen Anwendungen gibt es doch auch eine Combobox wo die möglichen Schriftgrößen zur Auswahl stehen.
Soll heißen das die Werte die keine Veränderung der Schriftgröße ermöglichen, auch garnicht gelistet werden sollen.
Was der Benutzer letzendlich einträgt, ist egal.

@himitsu

Danke ersteinmal. Es hilft nur nicht richtig weiter; Bei Arial steht 36:14, also Höhe 36 und Weite 14, dazu 6 Einträge je
Fett, Kursiv usw.

Das Problem ist mehr oder weniger geblieben. Aber vielleicht ist auch der Ansatz falsch und ich sollte über eine andere Lösungsmöglichkeit nachdenken.

Gruß

himitsu 22. Apr 2007 20:21

Re: Fonts (Größe und Namen)
 
Vielleicht gibt es da ja noch andere WinAPIs, welche die optimalen Werte aus den Dateien auslesen können.


Denn bei vielen TTFs ist es ja so, daß es nur ein paar wenige Grundformen der Schrift gibt und dann die Zwichengrößen nur noch passend scaliert werden.

Bei einer kleinen Schriftgröße werden ja weniger/schärfere Strukturen benötigt, wärend große Schriftgrößen mit vielen Schnörkeln und/oder feinen Strukturen versehen sein können.

Aber oftmals haben es sich die Fontersteller einfach gemacht und liefern eh nur einen Schriftsatz mit und dann höchstens noch die Fett- und Kursivvarianten. (auf verschiedene Schriftgrößen achten viele garnicht)

Reinhard Kern 23. Apr 2007 02:59

Re: Fonts (Größe und Namen)
 
Zitat:

Zitat von himitsu
Vielleicht gibt es da ja noch andere WinAPIs, welche die optimalen Werte aus den Dateien auslesen können.


Denn bei vielen TTFs ist es ja so, daß es nur ein paar wenige Grundformen der Schrift gibt und dann die Zwichengrößen nur noch passend scaliert werden.

Bei einer kleinen Schriftgröße werden ja weniger/schärfere Strukturen benötigt, wärend große Schriftgrößen mit vielen Schnörkeln und/oder feinen Strukturen versehen sein können.

Aber oftmals haben es sich die Fontersteller einfach gemacht und liefern eh nur einen Schriftsatz mit und dann höchstens noch die Fett- und Kursivvarianten. (auf verschiedene Schriftgrößen achten viele garnicht)

Hallo,

das ist ein grundlegendes Missverständnis: TrueType-Schriften sind als Vektoren definiert und daher vollkommen grössenunabhängig - ein A kann auch 5km hoch sein oder beliebig klein. Es gibt keine verschiedenen Grössen, die interpoliert werden, sondern nur einen einzigen Satz "Glyphen". Ein Renderer, der i.A. Bestandteil des Betriebssystems ist oder einer Grafiksoftware (XWindow bei Unix) errechnet daraus die Pixel für jede beliebige Schriftgrösse, wenn das erforderlich ist, also zur Ausgabe auf dem Bildschirm oder Laserdrucker. Daher kann man auch etwa in Coreldraw einen (TTF-)Buchstaben in Kurven auflösen.

Gruss Reinhard

Nachtrag: bei Postscript ist das genauso, die Datei enthält die notwendigen Angaben für jede Grösse.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:27 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz