Seite 2 von 2

Re: Font, DrawText, "wahre" Beite ermitteln

Verfasst: 29.09.2010 16:18
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

Re: Font, DrawText, "wahre" Beite ermitteln

Verfasst: 29.09.2010 17:24
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.

Re: Font, DrawText, "wahre" Beite ermitteln

Verfasst: 29.09.2010 18:59
von bobobo
also ein walkaround statt workaround .. und das ist besser als besser als nix :)

Re: Font, DrawText, "wahre" Beite ermitteln

Verfasst: 29.09.2010 19:19
von c4s
Stargate, mir ist gerade aufgefallen, dass du den Titel für die Forensuche anpassen solltest, denn nach Beite sucht bestimmt keiner. ;)

Re: Font, DrawText, "wahre" Breite ermitteln

Verfasst: 29.09.2010 19:29
von bobobo
ohne r hat die deutsche spache kaum saft und kaft

Re: Font, DrawText, "wahre" Breite ermitteln

Verfasst: 30.09.2010 16:41
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