{"id":17025795,"url":"https://github.com/boxesandglue/boxesandglue","last_synced_at":"2026-01-12T02:39:54.750Z","repository":{"id":41410285,"uuid":"375354387","full_name":"boxesandglue/boxesandglue","owner":"boxesandglue","description":"PDF rendering library for Go using TeX algorithms.","archived":false,"fork":false,"pushed_at":"2025-03-04T09:42:35.000Z","size":4866,"stargazers_count":229,"open_issues_count":1,"forks_count":7,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-28T09:04:20.338Z","etag":null,"topics":["pdf","pdf-generation","tex","typesetting"],"latest_commit_sha":null,"homepage":"https://boxesandglue.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boxesandglue.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"License.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-09T12:53:13.000Z","updated_at":"2025-03-12T23:04:09.000Z","dependencies_parsed_at":"2024-06-18T22:59:30.438Z","dependency_job_id":"510a1478-08af-462e-b776-8127c6ad3b99","html_url":"https://github.com/boxesandglue/boxesandglue","commit_stats":{"total_commits":142,"total_committers":2,"mean_commits":71.0,"dds":0.007042253521126751,"last_synced_commit":"65006ae98b90fef3a000527c2f0368a8a179eca1"},"previous_names":["speedata/texperiments","boxesandglue/boxesandglue"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxesandglue%2Fboxesandglue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxesandglue%2Fboxesandglue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxesandglue%2Fboxesandglue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxesandglue%2Fboxesandglue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boxesandglue","download_url":"https://codeload.github.com/boxesandglue/boxesandglue/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247156283,"owners_count":20893197,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pdf","pdf-generation","tex","typesetting"],"created_at":"2024-10-14T07:30:00.489Z","updated_at":"2026-01-12T02:39:54.743Z","avatar_url":"https://github.com/boxesandglue.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"[![Go reference documentation](https://img.shields.io/badge/doc-go%20reference-73FA79)](https://pkg.go.dev/github.com/boxesandglue/boxesandglue)\u0026nbsp;[![Homepage](https://img.shields.io/badge/homepage-boxesandglue.dev-blue)](https://boxesandglue.dev)\n\n\n# Boxes and Glue\n\nThis 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.\n\nTeX packs each unit (glyph, image, heading, ...) in a rectangular box which can be packed into other rectangular boxes.\nA variable length called “glue” can be between each of these rectangles.\nThis is why this repository is called “boxes and glue”.\n\n## Features\n\n* 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.\n* High output quality. Boxes and glue uses TeX's line breaking algorithm to create the optimal line breaks.\n* 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.\n* OpenType features and font shaping with harfbuzz. Harfbuzz is well known for its awesome language support.\n\n## API\n\nThe 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.\n\n\n![bagstructure](https://user-images.githubusercontent.com/209434/150811091-1432ac91-ef3d-44be-9953-7556ce254874.png)\n\n### Frontend\n\nThe 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.\n\n### Backend\n\nThe 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.\n\nSee the [architecture overview](https://github.com/boxesandglue/boxesandglue/discussions/2) for a more detailed description.\n\n## Status\n\nThis library is still under development. Expect API changes.\n\n## Contact\n\nPatrick Gundlach, \u003cgundlach@speedata.de\u003e\u003cbr\u003e\nmastodon: [@speedata](https://typo.social/@speedata), [@boxesandglue](https://typo.social/@boxesandglue)\n\n## Sample code\n\nSee the [boxesandglue-examples](https://github.com/boxesandglue/boxesandglue-examples) for code using boxes and glue.\n\nFor a starter here is a simple `main.go` to play with. The result is\n\n\u003cimg src=\"https://i.imgur.com/cwGQTzQ.png\" alt=\"typeset text from the frog king\" width=\"200\"/\u003e\n\n\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/boxesandglue/boxesandglue/backend/bag\"\n\t\"github.com/boxesandglue/boxesandglue/frontend\"\n)\n\nvar (\n\tstr = `In olden times when wishing still helped one, there lived a king whose daughters\n\twere all beautiful; and the youngest was so beautiful that the sun itself, which\n\thas seen so much, was astonished whenever it shone in her face.\n\tClose by the king's castle lay a great dark forest, and under an old lime-tree in the forest\n\twas a well, and when the day was very warm, the king's child went out into the\n\tforest and sat down by the side of the cool fountain; and when she was bored she\n\ttook a golden ball, and threw it up on high and caught it; and this ball was her\n\tfavorite plaything.`\n)\n\nfunc typesetSample() error {\n\tf, err := frontend.New(\"sample.pdf\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tf.Doc.Title = \"The frog king\"\n\n\tif f.Doc.DefaultLanguage, err = frontend.GetLanguage(\"en\"); err != nil {\n\t\treturn err\n\t}\n\n\t// Load a font, define a font family, and add this font to the family.\n\tff := f.NewFontFamily(\"text\")\n\tff.AddMember(\n\t\t\u0026frontend.FontSource{Location: \"fonts/CrimsonPro-Regular.ttf\"},\n\t\tfrontend.FontWeight400,\n\t\tfrontend.FontStyleNormal,\n\t)\n\n\t// Create a recursive data structure for typesetting initialized with the\n\t// text from the top (but with space normalized).\n\tpara := frontend.NewText()\n\tpara.Items = []any{strings.Join(strings.Fields(str), \" \")}\n\n\t// Format the text into a paragraph. Some of these settings (font family and\n\t// font size) can be part of the typesetting element.\n\tvlist, _, err := f.FormatParagraph(para, bag.MustSP(\"125pt\"),\n\t\tfrontend.Leading(bag.MustSP(\"14pt\")),\n\t\tfrontend.FontSize(bag.MustSP(\"12pt\")),\n\t\tfrontend.Family(ff),\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Output the text and finish the page and the PDF file.\n\tp := f.Doc.NewPage()\n\tp.OutputAt(bag.MustSP(\"1cm\"), bag.MustSP(\"26cm\"), vlist)\n\tp.Shipout()\n\tif err = f.Doc.Finish(); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tstarttime := time.Now()\n\terr := typesetSample()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(\"finished in \", time.Now().Sub(starttime))\n}\n```\n\n\nTo 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.\n\n```go\n\tf.Doc.RootStructureElement = \u0026document.StructureElement{\n\t\tRole: \"Document\",\n\t}\n\n\tpara := \u0026document.StructureElement{\n\t\tRole:       \"P\",\n\t\tActualText: str,\n\t}\n\tf.Doc.RootStructureElement.AddChild(para)\n\n\tvlist.Attributes = node.H{\n\t\t\"tag\": para,\n\t}\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxesandglue%2Fboxesandglue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboxesandglue%2Fboxesandglue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxesandglue%2Fboxesandglue/lists"}