' Gambas class file

Public sPfadPDFDatei As String

Public Const MARGIN_LEFT As Float = 20
Public Const MARGIN_TOP As Float = 20
Public Const MARGIN_RIGHT As Float = 15
Public Const MARGIN_BOTTOM As Float = 20

Public Const PDF_WEIGHT As Integer = 210
Public Const PDF_HEIGHT As Integer = 297

Public Sub Form_Open()
  FMain.Center()
  FMain.Resizable = False
  sPfadPDFDatei = Temp("TEXT")
End ' Form_Open

Public Sub btnShowPreViewPDF_Click()
  GeneratePDF()
  Desktop.Open(sPfadPDFDatei)
End ' btnShowPreViewPDF_Click()

Private Sub GeneratePDF()
  Dim PDFSurface As CairoPdfSurface
  Dim X, Y, W, H As Float

  PDFSurface = New CairoPdfSurface(sPfadPDFDatei, PDF_WEIGHT, PDF_HEIGHT) ' -->> DIN A4

  Cairo.Begin(PDFSurface)
    Cairo.Source = Cairo.ColorPattern(Color.DarkBlue)
    Cairo.Font.Name = "Monospace" ' "Sans Serif"
    Cairo.Font.Size = 8

    X = MMToPoints(MARGIN_LEFT)
    Y = MMToPoints(MARGIN_RIGHT)
    W = MMToPoints(PDF_WEIGHT - MARGIN_LEFT - MARGIN_RIGHT)
    H = MMToPoints(PDF_HEIGHT - MARGIN_TOP - MARGIN_BOTTOM)
    DrawMultilineText(File.Load("source1.txt"), Rect(X, Y, W, H), True)
  Cairo.End()
End ' GeneratePDF()

Private Sub DrawMultilineText(Text As String, Optional Box As Rect, Optional Wrap As Boolean = False)
  Dim aLine As String[] = Split(Text, "\n"), aNext As String[]
  Dim iLine As Integer = 0, iWord As Integer
  Dim fLeft, fUsed As Float = 0
  Dim sLine As String

#If Debug
  If Box Then ' Rechteck zeichnen, in dem der Text stehen soll
    Cairo.Rectangle(Box.X, Box.Y, Box.Width, Box.Height)
    Cairo.AntiAlias = Cairo.AntiAliasNone
    Cairo.LineWidth = 0.1
    Cairo.Dash = [1, 1]
    Cairo.Stroke()
  Endif
#Endif

  If Box Then
    Cairo.Save()
    Cairo.Rectangle(Box.X, Box.Y, Box.Width, Box.Height)
    Cairo.Clip()
    Cairo.MoveTo(Box.X, Box.Y)
  Endif

  While iLine < aLine.Count
    sLine = aLine[iLine]
    Cairo.RelMoveTo(- fUsed, Cairo.Font.Extents.Height)
    fUsed = 0

  ' Keine Zeile in der Box übrig?
    If Box And If iLine + 2 < aLine.Count And If (iLine + 2) * Cairo.Font.Extents.Height >= Box.Height Then
      DrawWord("[...]")
      Break
    Endif

  ' Eine Leerzeile?
    If Not sLine Then
      Inc iLine
      Continue
    Endif

  ' Automatische Zeilenumbrüche berechnen oder in der Breite begrenzen?
    If Box Then
      fLeft = Box.Width
      aNext = New String[]
      With Split(sLine, " ")
        For iWord = 0 To .Max
          fLeft -= Cairo.TextExtents(.[iWord]).XAdvance
        ' Endlosschleife verhindern, wenn ein einziges Wort nicht in eine Zeile passt. In diesem
        ' Fall verletzen wir die Zeilenumbruchregel.
          If fLeft >= 0 Or If Not iWord Then
            fLeft -= Cairo.TextExtents(" ").XAdvance
            fUsed += DrawWord(.[iWord] & " ")
          Else
            aNext.Add(.[iWord])
            If Not Wrap Then fUsed += DrawWord(.[iWord] & " ")
          Endif
        Next
      End With
    ' Wörter übrig, die in die nächste Zeile umgebrochen werden müssen?  
      If Wrap And If aNext.Count Then 
        aLine.Add(aNext.Join(" "), iLine + 1)
      Endif
    Else ' Keine Begrenzung, keine Umbrueche
      fUsed = DrawWord(sLine)
    Endif
    Inc iLine
  Wend
  If Box Then Cairo.Restore()
End '  DrawMultilineText(..)

Private Function DrawWord(sWord As String) As Float
  Cairo.DrawText(sWord)
  Return Cairo.TextExtents(sWord).XAdvance
End ' DrawWord(..)

Private Function MMToPoints(Value As Float) As Float
  Return Value * 2.83527
End ' MMToPoints(..)

Private Function PointsToMM(Value As Float) As Float
  Return Value * 0.3527
End ' MMToPoints(..)

Public Sub btnEnde_Click()
  FMain.Close()
End ' btnEnde_Click()
