Skip to content

Installation#

You need Go version 1.21 or later.

Let’s start with an empty directory and a new Go module:

go mod init bagtest

and create a file main.go which looks like this:

main.go
package main

import (
    "fmt"
    "log"
    "strings"
    "time"

    "github.com/boxesandglue/boxesandglue/backend/bag"
    "github.com/boxesandglue/boxesandglue/frontend"
)

var (
    str = `In olden times when wishing still helped one, there lived a king whose daughters
    were all beautiful; and the youngest was so beautiful that the sun itself, which
    has seen so much, was astonished whenever it shone in her face.
    Close by the king's castle lay a great dark forest, and under an old lime-tree in the forest
    was a well, and when the day was very warm, the king's child went out into the
    forest and sat down by the side of the cool fountain; and when she was bored she
    took a golden ball, and threw it up on high and caught it; and this ball was her
    favorite plaything.`
)

func typesetSample() error {
    f, err := frontend.New("sample.pdf")
    if err != nil {
        return err
    }

    f.Doc.Title = "The frog king"

    if f.Doc.DefaultLanguage, err = frontend.GetLanguage("en"); err != nil {
        return err
    }

    // Load a font, define a font family, and add this font to the family.
    ff := f.NewFontFamily("text")
    ff.AddMember(
        &frontend.FontSource{Location: "fonts/CrimsonPro-Regular.ttf"},
        frontend.FontWeight400,
        frontend.FontStyleNormal,
    )

    // Create a recursive data structure for typesetting initialized with the
    // text from the top (but with space normalized).
    para := frontend.NewText()
    para.Items = []any{strings.Join(strings.Fields(str), " ")}

    // Format the text into a paragraph. Some of these settings (font family and
    // font size) can be part of the typesetting element.
    vlist, _, err := f.FormatParagraph(para, bag.MustSP("125pt"),
        frontend.Leading(bag.MustSP("14pt")),
        frontend.FontSize(bag.MustSP("12pt")),
        frontend.Family(ff),
    )
    if err != nil {
        return err
    }

    // Output the text and finish the page and the PDF file.
    p := f.Doc.NewPage()
    p.OutputAt(bag.MustSP("1cm"), bag.MustSP("26cm"), vlist)
    p.Shipout()
    if err = f.Doc.Finish(); err != nil {
        return err
    }
    return nil
}

func main() {
    starttime := time.Now()
    err := typesetSample()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("finished in ", time.Now().Sub(starttime))
}

Run go mod tidy to let Go download all required libraries. Then you can run the program by calling go run main.go. You will see output such as:

finished in 11.1745ms

The result is a file called sample.pdf which looks like this:

sample pdf