Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Mär 29, 2024 12:25

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Re: Textlänge abschneiden
BeitragVerfasst: Di Jun 14, 2016 16:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Hi, dein Loader für den Font sollte dir eigentlich etwas für die Länge einzelner Glyphen geben. Wenn du z.B. mit 0815 GDI Font unter Windows (siehe Nehe) arbeitest musst du beim Erstellen schon ein Array von Glyphmetrics mit übergeben. Da musst du jetzt einfach nur noch einmal die gewünschten Zeichen durchschicken bis die jeweilige Länge erreicht ist.

alternativ geht natürlich auch irgendein Monospaced Font. Da sind dann alle Glyphen gleich lang.

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Textlänge abschneiden
BeitragVerfasst: Di Jun 14, 2016 16:59 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Das gehört zu den dingen, warum ich mein Texthandling inzwischen von Qt oder Pango machen lasse. Spätestens wenn merkwürdige Combining Characters im Spiel sind, hat man mit einfachen Metriken verloren. Aber in der Praxis ist schon bei Kerning das einfache "Ich addiere die Widths der Glyphen zusammen" vorbei.

Im Idealfall wird das also von der Library gelöst, mit der man Text Layouting macht. Leider habe ich keine detaillierte Ahnung von der TextSuite; ich habe mich trotzdem entschlossen zu Antworten um klar zu machen, dass so eine einfache Lösung nicht perfekt wird.

viele Grüße,
Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Textlänge abschneiden
BeitragVerfasst: Di Jun 14, 2016 18:29 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Nun ich würde zuerst die einzelnen Glyphmetrics durchgehen um eine grobe Idee von der Länge zu bekommen. Danach sollte man dann lieber auf solche Funktionen
wie etwa "GetTextExtentPoint" oder "DrawTextEx" zugreifen. Diese berücksichtigen dann die ganzen Details wie Character-Spacing, Kerning usw..

EWeiss hat geschrieben:
Zitat:
alternativ geht natürlich auch irgendein Monospaced Font. Da sind dann alle Glyphen gleich lang.

Welche Schriftart/en gehört dazu?
Wäre eventuell eine Möglichkeit solange ich die Schrift nicht selbst mit liefern muss.
Ginge es dann auch mit den VCL Bordmitteln, lösung wie im ersten Beitrag gezeigt?

gruss


Ich kenn leider keine gute Liste hier von. Die bekanntesten sind auf jeden Fall aber:
Courier
Consolas
DialogInput
Lucida Sans Typewriter

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Textlänge abschneiden
BeitragVerfasst: Fr Jun 17, 2016 15:09 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
EWeiss hat geschrieben:
Zitat:
GetTextExtentPoint

Da muss ich mir erst Infos einholen inwieweit mir das bei meinem Problem hilft.

Da kann ich dir nur wärmstens ans Herz legen, dass du das nicht weiter verfolgst. Das kann nur in einem Chaos enden. Hintergrund ist der, dass GetTextExtentPoint GDI ist und die TextSuite nur Teile der GDI benutzt um an die Glyphen der einzelnen Zeichen zu kommen. Aber die TextSuite arbeitet grundsätzlich komplett anders als die GDI und zeichnet auch anders.
Zum Beispiel Stichwort Kerning. Die GDI unterstützt Kerning (sofern in den Fonts die Informationen hinterlegt sind) und nutzt diese auch. Die TextSuite unterstützt das nicht. Wenn du jetzt also die TextBreite mit GetTextExtentPoint erfragst und dort Kerning verwendet wird, dann sind die Breiten unterschiedlich. Du kannst auch die Texte in der TextSuite anpassen (Rahmen etc.) dadurch werden die Glyphen in der TextSuite manipuliert und die Breiten passen nicht mehr zu der GDI.
Zusätzlich müssen auch die Fonts in allen beiden Bereichen 100%tig identisch sein. Das ist nahezu unmöglich so etwas sinnvoll gleich hinzubekommen.

Hier solltest du grundsätzlich die TextBreite etc. nur mit der Bibliothek erfragen mit der du die Texte auch zeichnest. Alles andere kann nicht funktionieren. Bzw. Birgt einfach zu viele Risiken.

EWeiss hat geschrieben:
tsSetParameteri(TS_FONT_CHAR_SPACING, 1);

Aus dem Crossposting. TS_FONT_CHAR_SPACING setzt nicht den Abstand zwischen Zeichen auf einen gleichen Wert sondern ändert die Abstände relativ. Normal musst du das nur anpassen, wenn du findest, dass die Schrift zu gequetscht wirkt. Dadurch kannst den normalen Abstand zwischen allen Zeichen vergrößern oder verkleinern. Aber normal musst du das nicht machen.

Monotype Fonts. Das könnte man wohl machen. Aber ehrlich gesagt sehen die dann eher auch bescheiden aus. Abgesehen davon muss man trotzdem berücksichtigen, dass die Texte nicht zu groß werden. Nur hier kann man das etwas einfacher Berechnen.

Also Lösung.
Du könntest mit tsFontGetCharParameter die internen Werte der einzelnen Gylphen erfragen und dann selbst berechnen wie lang der Text sein würde. Das bedeutet aber, dass du sehr genau wissen musst wie sich die einzelnen Werte auswirken und was da sonst noch alles mit reinspielen könnte.

Einfacher wäre es mit der Methode tsTextGetWidthA. Die ist auch das Einzige die du bräuchtest. Du müsstet du mit tsTextGetWidthA erfragen, ob der Text zu lang für deine Anzeige ist. Wenn nein, dann kannst du den einfach so nehmen. Und wenn ja, dann würde ich den Text so lange beschneiden und ein '...' anhängen bis er passt. Also in einer Schleife. Das könnte man sicherlich besser machen. Allerdings um noch auf die Argumente von oben zurück zu kommen. Da kann dann nichts draus werden. Aber die TextSuite muss diese Länge auch nicht total umständlich berechnen sondern relativ einfach. Nichts desto trotz solltest du den errechneten Wert, dann in jedem Fall in einer Variabel zwischen Speichern, damit du du das nicht bei jedem Zeichnen neu berechnen musst. Ein mal pro SongTitel ist der Aufwand aber überhaupt kein Problem. Wenn doch könnte man hier auch mit anderen Verfahren die Anzahl an Versuchen noch reduzieren.

Grundsätzlich sollte es eher so wie folgt funktionieren. Da ich nicht weiß welche Variablen wie und wo verwendet und welchen Typ diese haben (und ich etwas aus Delphi raus bin) kann ich dir nur einen schematischen Ansatz geben. Rest müsstest du selbst machen.
Code:
  1. if fMaxStrLen = 0 then begin
  2.   fMaxStrLen := tsTextGetWidthA(SongName);
  3.   if fMaxStrLen >= 635 then begin // eventuell reicht die while-schleife auch aus.
  4.     // eventuell hier eine Kopie des Songnamens erstellen.
  5.     while fMaxStrLen >= 635 do
  6.       // string kürzen und '...' anhängen
  7.       fMaxStrLen := tsTextGetWidthA(>gekürzter string<);
  8.     end;
  9.   end;
  10. end;


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Textlänge abschneiden
BeitragVerfasst: Sa Jun 18, 2016 18:07 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Versteh mich bitte nicht falsch. Aber was zum Teufel versuchst du da? ;) Nur damit ich das richtig verstehe. Es geht doch nur darum, dass dieser eine Text (SongName) abgeschnitten wird, wenn diese nicht in den verfügbaren Platz passt. Richtig?

Zu erst einmal.
Code:
  1. tsFontSetCharParameteri(Char[I], TS_CHAR_GLYPHRECT_RIGHT, I);

tsFontSetCharParameteri dient zum SETZEN von Parametern eines Chars. Und im Besonderen das GlyphRect enthält einen internen Wert. Um genau zu sein die Position des Zeichens innerhalb des Images des Zeichens. Als Beispiel kann ich nur das Bild aus der Hilfe (figure 4.1). Hierbei besitzt das Zeichen einen Schatten. Das gesamte Bild ist natürlich Größer als die reine Glyphe. Auf der Seite sind auch die ganzen Werte beschrieben.
Normal gibt es keinen Grund Werte von den Fonts zu verändern. Also Maximal nur, wenn du selbst etwas an den Bildern verändert hast. Und dann muss man auch aufpassen, dass man nichts kaputt macht. Ich bin ehrlich gesagt fasziniert, dass dein unterer Code überhaupt noch sinnvolle Zeichen darstellt.

Aber jetzt zu deinem Problem. Den Wert den du erfragen müsstest ist das Advance. Das Advance gibt an wann das nächste Zeichen hinter dem aktuellen Zeichen anfangen darf. Typischerweise ist das etwas größer als das aktuelle Zeichen breit ist. Damit zwischen den Zeichen etwas Luft ist. Wenn du die Advance aller Zeichen zusammenrechnest, dann bekommst du die Breite eines Textes.
Hierfür musst du aber sicherstellen, dass diese Zeichen alle in der TextSuite vorhanden sind. Wenn du einfach ein Font erstellst, dann enthalten diese in der TextSuite noch keine Zeichen. Muss aber gestehen, dass die Erinnerungen daran etwas nebelig sind. Und ich verschiedene Sachen jetzt auch nicht mehr so genau weiß. Also der "Code" ist eher mit Vorsicht zu genießen. Und ich auch nicht abschätzen kann welche Variablen welchen Typ hat.

Code:
  1. // Hinzufügen aller Zeichen die in dem Text vorhanden sind
  2. tsFontAddChars(@SongNameTmp[0]); // << Müsste so gehen.
  3.  
  4. // Get max length of String
  5. fMaxStrLen := tsTextGetWidthA(SongNameTmp);
  6.  
  7. if fMaxStrLen >= 635 then begin
  8.   // Da wir in jeden Fall '...' am Ende haben wollen brauchen wir diese Zeichen zu erst.
  9.   CharLen := tsFontGetCharParameteri('.', TS_CHAR_ADVANCE) * 3;
  10.  
  11.   // Parse width of Glyph
  12.   for I := 0 to High(SongNameTmp) do
  13.   begin
  14.     // Breite des aktuellen Zeichens auslesen und addieren
  15.     Char[I] := WideChar(SongNameTmp[I]);
  16.     CharLength := tsFontGetCharParameteri(Char[I], TS_CHAR_ADVANCE);
  17.     CharLen := CharLen + CharLength;
  18.     // Wenn die Breite größer als der verfügbare platz, dann schleife verlassen
  19.     if fMaxStrLen >= 635 then
  20.       break;
  21.   end;
  22.  
  23.   // Hier ist die Schleife durch und unser neuer Text ist von 1 bis i-1.
  24.   // Keine Ahnung, ob man diese Zeile nicht auch einfacher machen kann. Das scheint mir ziemlich umständlich zu sein.
  25.   // Copy auf String oder StrCopy auf Ansi Strings.
  26.   SongName := PAnsiChar(Ansistring(Ansimidstr(string(SongNameTmp), 1, i-1) + '...'));
  27. end;
  28.  
  29. // Hier könntest du SongName zeichnen.
  30.  


Grundsätzlich müsstest du nur solange Advance auslesen und addieren bis du die gewünschte Länge hast. Und anschließend einfach die berechnete Anzahl an Zeichen in einen neuen Text kopieren. Und den kannst du dann benutzen. Ich verstehe da auch nicht was du immer mit der 58 hast.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 21 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.110s | 17 Queries | GZIP : On ]