github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/pdf.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/jung-kurt/gofpdf"
     9  	"github.com/xyproto/files"
    10  )
    11  
    12  // SavePDF can save the text as a PDF document. It's pretty experimental.
    13  func (e *Editor) SavePDF(title, filename string) error {
    14  	// Check if the file exists
    15  	if files.Exists(filename) {
    16  		return fmt.Errorf("%s already exists", filename)
    17  	}
    18  
    19  	// Build a large string with the document contents, while expanding tabs.
    20  	// Also count the maximum line length.
    21  	var sb strings.Builder
    22  	maxLineLength := 0
    23  	for i := 0; i < e.Len(); i++ {
    24  		line := e.Line(LineIndex(i))
    25  		// Expand tabs for each line
    26  		sb.WriteString(strings.ReplaceAll(line, "\t", strings.Repeat(" ", e.indentation.PerTab)) + "\n")
    27  		// Count the maximum line length
    28  		if len(line) > maxLineLength {
    29  			maxLineLength = len(line)
    30  		}
    31  	}
    32  	contents := sb.String()
    33  
    34  	// If the lines are long, make the font smaller
    35  	var smallFontSize, largeFontSize float64
    36  	if maxLineLength > 100 {
    37  		smallFontSize = 8 // the text should never be smaller than 8
    38  		largeFontSize = 14
    39  	} else if maxLineLength > 80 {
    40  		smallFontSize = 9
    41  		largeFontSize = 14
    42  	} else {
    43  		smallFontSize = 10.0
    44  		largeFontSize = 14
    45  	}
    46  
    47  	// Create a timestamp for the current date, using the "2006-01-02" format
    48  	timestamp := time.Now().Format("2006-01-02")
    49  
    50  	// Use A4 and Unicode
    51  	pdf := gofpdf.New("P", "mm", "A4", "")
    52  	tr := pdf.UnicodeTranslatorFromDescriptor("") // "" defaults to "cp1252"
    53  
    54  	pdf.SetTopMargin(30)
    55  
    56  	// Top text
    57  	pdf.SetHeaderFunc(func() {
    58  		pdf.SetY(5)
    59  		pdf.SetFont("Helvetica", "", 8)
    60  		// Top right corner
    61  		pdf.CellFormat(0, 0, timestamp, "", 0, "R", false, 0, "")
    62  	})
    63  
    64  	// Bottom text
    65  	pdf.SetFooterFunc(func() {
    66  		pdf.SetY(-15)
    67  		pdf.SetFont("Helvetica", "", 8)
    68  		// Bottom center
    69  		pdf.CellFormat(0, 10, fmt.Sprintf("%d", pdf.PageNo()), "", 0, "C", false, 0, "")
    70  	})
    71  
    72  	pdf.AddPage()
    73  	pdf.SetY(20)
    74  	ht := pdf.PointConvert(8.0)
    75  
    76  	// Header
    77  	pdf.SetFont("Courier", "B", largeFontSize)
    78  	pdf.MultiCell(190, ht, tr(title+"\n\n"), "", "L", false)
    79  	pdf.Ln(ht)
    80  
    81  	// Body
    82  	pdf.SetFont("Courier", "", smallFontSize)
    83  	pdf.MultiCell(190, ht, tr(contents+"\n"), "", "L", false)
    84  	pdf.Ln(ht)
    85  
    86  	// Save to file
    87  	return pdf.OutputFileAndClose(filename)
    88  }