Font, DrawText, "wahre" Breite ermitteln

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Re: Font, DrawText, "wahre" Beite ermitteln

Beitrag von bobobo »

STARGÅTE hat geschrieben:Das hat mit Monospace nix zu tun bobobo!

Denn selbst wenn die Breite eines Zeichens immer gleich wäre, gibt mir auch dort TextWidth() die Breite im Text-Fluss zurück.
Damit werden auch bei diesen Fonts Serifen und Tropfen abgeschnitten, falls dieser außerhalb der Text-Fluss-Breite liegen.
aha .. dann bin ich ja gottseidank nur blind

Code: Alles auswählen

Enumeration
  #Window : #Gadget : #Image
EndEnumeration
Global Font_vv = FontID(LoadFont(#PB_Any, "Times New Roman", 32,#PB_Font_Italic))
Global Font_ms = FontID(LoadFont(#PB_Any, "Courier", 32, #PB_Font_Italic))
CreateImage(#Image, 256, 256)
StartDrawing(ImageOutput(#Image))
  DrawingFont(Font_vv)
  DrawingMode(#PB_2DDrawing_Transparent)
  t.s="f"
  Box(10, 10, TextWidth(t), TextHeight(t), $808080)
  DrawText(10, 10, t, $FFFFFF)
  DrawingFont(Font_ms)
  t.s="f"
  Box(10, 110, TextWidth(t), TextHeight(t), $808080)
  DrawText(10, 110, t, $FFFFFF)
StopDrawing()
SetClipboardImage(#Image)
OpenWindow(#Window, 0, 0, ImageWidth(#Image), ImageHeight(#Image), "Image", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(#Gadget, 0, 0, ImageWidth(#Image), ImageHeight(#Image), ImageID(#Image))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Font, DrawText, "wahre" Beite ermitteln

Beitrag von STARGÅTE »

Dein Beispiel funktioniert nur, weil dort eh immer jeweils 8px an jede Seite addiert werden wenn diese Schift Kursiv ist ...

Code: Alles auswählen

Enumeration
 #Image
EndEnumeration
Font_ms = FontID(LoadFont(#PB_Any, "Courier", 32))
Font_ms2 = FontID(LoadFont(#PB_Any, "Courier", 32, #PB_Font_Italic))
CreateImage(#Image, 256, 256)
StartDrawing(ImageOutput(#Image))
  DrawingFont(Font_ms)
  Debug TextWidth(" ")
  Debug TextWidth("  ")
  Debug TextWidth("   ")
  Debug "---"
  DrawingFont(Font_ms2)
  Debug TextWidth(" ")
  Debug TextWidth("  ")
  Debug TextWidth("   ")
StopDrawing()
24
48
72
---
40
64
88
und normal hat Courier ja keine Serifen die außerhalb der Text-Fluss-Breite liegen :wink:

Wie gesagt, das Problem wird dadurch nicht behoben, sonden nur umgangen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Re: Font, DrawText, "wahre" Beite ermitteln

Beitrag von bobobo »

also ein walkaround statt workaround .. und das ist besser als besser als nix :)
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: Font, DrawText, "wahre" Beite ermitteln

Beitrag von c4s »

Stargate, mir ist gerade aufgefallen, dass du den Titel für die Forensuche anpassen solltest, denn nach Beite sucht bestimmt keiner. ;)
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Re: Font, DrawText, "wahre" Breite ermitteln

Beitrag von bobobo »

ohne r hat die deutsche spache kaum saft und kaft
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
Kukulkan
Beiträge: 1066
Registriert: 09.09.2004 07:07
Wohnort: Süddeutschland
Kontaktdaten:

Re: Font, DrawText, "wahre" Breite ermitteln

Beitrag von Kukulkan »

Hallo,

ich habe eine Lösung gefunden, die ganz ohne API auskommt:

Code: Alles auswählen

; Returns the width (pixel) of a char respecting it's surrounding chars...
; IMPORTANT: This needs a current StartDrawing() context and a defined font!
Procedure.l GetCharWidth(Text.s, CharPos.l)
  If CharPos.l < 2
    ; first char
    Char1.s = Left(Text.s, 2) ; the first two
    Char2.s = Mid(Text.s, 2, 1); without the needed
    ProcedureReturn TextWidth(Char1.s) - TextWidth(Char2.s)
  EndIf
  If CharPos.l > Len(Text.s) - 1
    ; last char
    Char1.s = Right(Text.s, 2) ; the last two
    Char2.s = Right(Text.s, 1); without the needed
    ProcedureReturn TextWidth(Char1.s) - TextWidth(Char2.s)
  EndIf
  If CharPos.l > 1 And CharPos.l < Len(Text.s)
    ; all other chars
    Char1.s = Mid(Text.s, CharPos.l - 1, 3) ; all three
    Char2.s = Left(Char1.s, 1) + Right(Char1.s, 1); without the needed
    ProcedureReturn TextWidth(Char1.s) - TextWidth(Char2.s)
  EndIf
EndProcedure

; ---------------- test routine ------------------
If OpenWindow(0, 100, 200, 595, 160, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  TestText.s = "Für diese Waffel braucht es Zucker!"
  
  LoadFont(0, "Times New Roman", 22, #PB_Font_Italic)
  
  StartDrawing(WindowOutput(0))
  DrawingMode(#PB_2DDrawing_Transparent)
  FrontColor(#Black)
  BackColor(#White)
  
  ; set font
  DrawingFont(FontID(0))
  
  For x.l = 1 To Len(TestText.s)
    
    ; standard method
    Char.s = Mid(TestText.s, x.l, 1)
    Wi.l = TextWidth(Char.s)
    DrawText(TextWidth1.l, 10, Char.s)
    TextWidth1.l = TextWidth1.l + Wi.l
    Debug "Originalbreite für " + Char.s + ": " + Str(Wi.l)
    
    ; new method
    Wi.l = GetCharWidth(TestText.s, x.l)
    DrawText(TextWidth2.l, 40, Char.s)
    TextWidth2.l = TextWidth2.l + Wi.l
    Debug "Neu für " + Char.s + ": " + Str(Wi.l)
    
    Debug "------------------------------------------"
  Next 
  
  StopDrawing()
  FreeFont(0)
  
  Repeat
    Event = WaitWindowEvent()
    If Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
      Quit = 1
    EndIf
  Until Quit = 1
EndIf
End
Der Test zeigt zweimal die Zeichenkette. Die erste Zeile wird Zeichen für Zeichen mit der TextWidth() Methode berechnet. In der zweiten Zeile wird meine Routine verwendet.

Es funktioniert so, dass ich ja die Breite eines Zeichens aus einer Zeichenkette suche. Ich berechne zuerst die Breite incl. der beiden umgebenden Zeichen und entferne dann das gesuchte Zeichen. Die Differenz ist die gesuchte Breite. Klappt hier ganz gut (Verschiedene Schriften und Stile). Ich weiss, dass das nicht 100% klappt (hängt vom Zusammenpassen der umgebenden Zeichen ab), aber es ist eine gute Näherung.

Volker
Antworten