Giter Site home page Giter Site logo

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, [email protected]
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/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))
}

To get a PDF/UA (universal accessibility) document, insert the following lines before .OutputAt... and add "github.com/boxesandglue/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,
	}

boxes and glue's Projects

bagme icon bagme

boxes and glue made easy - a PDF rendering library for Go using boxes and glue

csshtml icon csshtml

CSS HTML module from boxes and glue

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.