boxesandglue

module
v0.0.0-...-3435f2a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 22, 2023 License: BSD-3-Clause

README

Go reference documentation Fund the development Homepage

Boxes and Glue

This is a PDF typesetting library/backend in the spirit of TeX's algorithms. TeX is a typesetting system which is well known for its superb output quality.

TeX packs each unit (glyph, image, heading, ...) in a rectangular box which can be packed into other rectangular boxes. A variable length called “glue” can be between each of these rectangles. This is why this repository is called “boxes and glue”.

Features

  • High speed (“Ludicrous mode”). A simple document is created within 10ms on a macBook. This includes loading an OpenType font, typesetting text and writing the PDF file.
  • High output quality. Boxes and glue uses TeX's line breaking algorithm to create the optimal line breaks.
  • Extensibility: See the API section below. Boxes and glue is split into a high level frontend and a low level backend to provide the API you need.
  • OpenType features and font shaping with harfbuzz. Harfbuzz is well known for its awesome language support.

API

The API has two layers, a high level frontend and a low level backend. Each layer is useful when using the library. I suggest to start using the high level API and switch to the backend when you need more control over the typesetting output.

bagstructure

Frontend

The frontend has high level methods to create a PDF document, load fonts, insert text which can be broken into lines and output objects at exact positions.

Backend

The backend has the small building blocks that are used to create documents. These building blocks are called “nodes” which can be chained together in linked lists, a node list.

See the architecture overview for a more detailed description.

Status

This library is still under development. Expect API changes.

Contact

Patrick Gundlach, gundlach@speedata.de
mastodon: @speedata, @boxesandglue

Sample code

See the bagme library and boxesandglue-examples for code using boxes and glue.

For a starter here is a simple main.go to play with. The result is

typeset text from the frog king
package main

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

	"github.com/speedata/boxesandglue/backend/bag"
	"github.com/speedata/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))
}

To get a PDF/UA (universal accessibility) document, insert the following lines before .OutputAt... and add "github.com/speedata/boxesandglue/backend/document" to the import section.

	f.Doc.RootStructureElement = &document.StructureElement{
		Role: "Document",
	}

	para := &document.StructureElement{
		Role:       "P",
		ActualText: str,
	}
	f.Doc.RootStructureElement.AddChild(para)

	vlist.Attributes = node.H{
		"tag": para,
	}

Directories

Path Synopsis
backend
bag
fonts
camingocodebold
Package camingocodebold provides the "CamingoCode" font
Package camingocodebold provides the "CamingoCode" font
camingocodebolditalic
Package camingocodebolditalic provides the "CamingoCode" font
Package camingocodebolditalic provides the "CamingoCode" font
camingocodeitalic
Package camingocodeitalic provides the "CamingoCode" font
Package camingocodeitalic provides the "CamingoCode" font
camingocoderegular
Package camingocoderegular provides the "CamingoCode" font
Package camingocoderegular provides the "CamingoCode" font
crimsonprobold
Package crimsonprobold provides the "Crimson Pro" font
Package crimsonprobold provides the "Crimson Pro" font
crimsonprobolditalic
Package crimsonprobolditalic provides the "Crimson Pro" font
Package crimsonprobolditalic provides the "Crimson Pro" font
crimsonproitalic
Package crimsonproitalic provides the "Crimson Pro" font
Package crimsonproitalic provides the "Crimson Pro" font
crimsonproregular
Package crimsonproregular provides the "Crimson Pro" font
Package crimsonproregular provides the "Crimson Pro" font
texgyreherosbold
Package texgyreherosbold provides the "TeXGyreHeros" font
Package texgyreherosbold provides the "TeXGyreHeros" font
texgyreherosbolditalic
Package texgyreherosbolditalic provides the "TeXGyreHeros" font
Package texgyreherosbolditalic provides the "TeXGyreHeros" font
texgyreherositalic
Package texgyreherositalic provides the "TeXGyreHeros" font
Package texgyreherositalic provides the "TeXGyreHeros" font
texgyreherosregular
Package texgyreherosregular provides the "TeXGyreHeros" font
Package texgyreherosregular provides the "TeXGyreHeros" font

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL