The glu.frontend module
The glu.frontend module provides a high-level interface for creating PDF documents. It allows you to create and manipulate text, tables, and other elements. Fonts are organized in font families, and settings like font weight and style are handled automatically.
local frontend = require("glu.frontend")Module functions
| Name | Parameters | Description |
|---|---|---|
frontend.new() |
filename (string) | Create a new document |
frontend.text() |
[settings] (table) | Create a new Text object |
frontend.fontsource() |
options (table) | Create a new font source |
frontend.table() |
options (table) | Create a new Table object |
frontend.color() |
options (table) | Create a new Color object |
frontend.sp() |
points (number) | Create a ScaledPoint from points |
frontend.sp_string() |
dimension (string) | Create a ScaledPoint from string |
ScaledPoint
ScaledPoint is a type-safe dimension type that prevents confusion between raw numbers and dimensions. It wraps the internal scaled point unit (1/65536 of a DTP point).
Creating ScaledPoints
local frontend = require("glu.frontend")
-- From points (number)
local sp1 = frontend.sp(72) -- 72 points = 1 inch
-- From string with unit
local sp2 = frontend.sp_string("2cm")
local sp3 = frontend.sp_string("10mm")
local sp4 = frontend.sp_string("1in")
local sp5 = frontend.sp_string("72pt")Arithmetic operations
ScaledPoints support arithmetic with other ScaledPoints, strings with units, and numbers (interpreted as points):
local sp = frontend.sp_string("10cm")
-- ScaledPoint operations
local sp2 = frontend.sp_string("2cm")
local result = sp + sp2 -- ScaledPoint + ScaledPoint
local diff = sp - sp2 -- ScaledPoint - ScaledPoint
-- Mixed operations with strings
local wider = sp + "5mm" -- ScaledPoint + string
local narrower = sp - "1cm" -- ScaledPoint - string
-- Operations with numbers (interpreted as points)
local adjusted = sp + 72 -- adds 72 points (1 inch)
local half = sp / 2 -- ScaledPoint / number
local doubled = sp * 2 -- ScaledPoint * number
local neg = -sp -- unary minus
-- Division of two ScaledPoints returns a ratio (number)
local ratio = sp / sp2 -- returns 5.0Comparison operations
local a = frontend.sp_string("5cm")
local b = frontend.sp_string("50mm")
print(a == b) -- true (5cm equals 50mm)
print(a < b) -- false
print(a <= b) -- trueConversion methods
local sp = frontend.sp_string("2.54cm") -- 1 inch
-- Properties (read-only)
print(sp.pt) -- 72.0 (value in points)
print(sp.sp) -- 4718592 (raw scaled point value)
-- Methods
print(sp:to_pt()) -- 72.0
print(sp:to_mm()) -- 25.4
print(sp:to_cm()) -- 2.54
print(sp:to_in()) -- 1.0
-- String representation
print(sp) -- "72pt"Usage with dimensions
All dimension parameters (page sizes, positions, font sizes, etc.) accept ScaledPoints directly:
local page = doc:new_page()
page.width = frontend.sp_string("210mm")
page.height = frontend.sp_string("297mm")
-- Arithmetic in output_at
local margin = frontend.sp_string("2cm")
local y = frontend.sp_string("28cm")
page:output_at(margin, y - "1cm", vlist)
-- Reading dimensions returns ScaledPoints
local w = page.width -- ScaledPoint
local h = vlist.height -- ScaledPoint
local new_y = y - h - "5mm" -- arithmetic with ScaledPoints and stringsDocument
local frontend = require("glu.frontend")
local doc = frontend.new("output.pdf")Attributes
| Name | R/W | Type | Description |
|---|---|---|---|
title |
R/W | string | Document title |
author |
R/W | string | Document author |
subject |
R/W | string | Document subject |
creator |
R/W | string | Creator application |
keywords |
R/W | string | Document keywords |
format |
R/W | string | PDF format (see below) |
language |
W | Language | Default document language |
additional_xml_metadata |
R/W | string | Additional XMP metadata |
Format values: "PDF", "PDF/A-3b", "PDF/X-3", "PDF/X-4", "PDF/UA"
Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
new_font_family() |
name (string) | FontFamily | Create a new font family |
find_font_family() |
name (string) | FontFamily | Find an existing font family |
create_text() |
- | Text | Create a new Text object |
format_paragraph() |
text, width, [options] | VList, info | Format text into a paragraph |
build_table() |
table | VList array | Build a table |
define_color() |
name (string), color | - | Define a named color |
get_color() |
spec (string) | Color | Get color by name or CSS value |
get_language() |
name (string) | Language | Get language for hyphenation |
new_page() |
- | Page | Create a new page |
load_imagefile() |
filename, [page], [box] | Imagefile | Load an image or PDF file |
create_image_node() |
imagefile, [page], [box] | ImageNode | Create image node for placement |
load_colorprofile() |
filename | ColorProfile | Load ICC color profile |
attach_file() |
options (table) | - | Attach a file to the PDF |
finish() |
- | - | Finalize the PDF |
format_paragraph()
local vlist, info = doc:format_paragraph(text, width, options)| Parameter | Type | Description |
|---|---|---|
text |
Text object | The text to format |
width |
dimension | The width of the paragraph |
options |
table | Optional settings (see below) |
Options table:
| Name | Type | Description |
|---|---|---|
leading |
dimension | Line height |
font_size |
dimension | Font size |
font_family |
FontFamily | Font family to use |
language |
Language | Language for hyphenation |
halign |
string | Horizontal alignment |
indent_left |
dimension | Left indentation |
Text
local txt = frontend.text()Attributes
| Name | R/W | Type | Description |
|---|---|---|---|
items |
W | table | Set content items (strings, Text, etc.) |
settings |
R | proxy | Access settings via txt.settings.key |
Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
append() |
item, … | self | Append strings, Text, VList, or Table |
set() |
key, value | self | Set a single setting (chainable) |
apply() |
table | self | Set multiple settings at once (chainable) |
Setting text properties
There are several ways to set text properties:
-- 1. In the constructor (recommended)
local txt = frontend.text({
font_family = ff,
font_size = "12pt",
color = "black"
})
-- 2. Using set() with chaining
local txt = frontend.text()
:set("font_family", ff)
:set("font_size", "12pt")
:set("color", "black")
-- 3. Using settings proxy - for individual assignments
local txt = frontend.text()
txt.settings.font_family = ff
txt.settings.font_size = "12pt"
txt.settings.color = "black"
-- 4. Using apply() to add settings later
local txt = frontend.text()
txt:apply({
font_family = ff,
font_size = "12pt"
})You can set items directly or use append:
-- Using items property
txt.items = {"Hello, ", boldText, "!"}
-- Using append (chainable)
txt:append("Hello, ", boldText, "!")Text settings
| Name | Type | Description |
|---|---|---|
font_family |
FontFamily | The font family to use |
font_size |
dimension | Font size (e.g. 12 or "12pt") |
font_weight |
string or int | "regular", "bold", or 100-900 |
font_style |
string | "normal" or "italic" |
color |
string or Color | Text color |
leading |
dimension | Line height |
halign |
string | "left", "right", "center", "justified" |
valign |
string | "top", "middle", "bottom" |
margin_left |
dimension | Left margin |
margin_right |
dimension | Right margin |
margin_top |
dimension | Top margin |
margin_bottom |
dimension | Bottom margin |
padding_left |
dimension | Left padding |
padding_right |
dimension | Right padding |
padding_top |
dimension | Top padding |
padding_bottom |
dimension | Bottom padding |
background_color |
string or Color | Background color |
hyperlink |
string | URL for hyperlink |
underline |
boolean | Underline text |
line_through |
boolean | Strikethrough text |
Example:
local txt = frontend.text({
font_family = ff,
font_size = "12pt",
color = "rebeccapurple"
})
txt:append("Hello, ")
-- Nested styled text
local bold = frontend.text({ font_weight = "bold" })
bold:append("world")
txt:append(bold, "!")FontFamily
local ff = doc:new_font_family("body")Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
add_member() |
fontsource, weight, style | self | Add a font to the family |
FontSource
local fs = frontend.fontsource({
location = "path/to/font.ttf",
index = 0, -- optional, for font collections
size_adjust = 1.0, -- optional
features = {"kern", "liga"} -- optional OpenType features
})
ff:add_member(fs, "regular", "normal")
ff:add_member(fs_bold, "bold", "normal")
ff:add_member(fs_italic, "regular", "italic")
-- Alternative: table-based add_member
ff:add_member({ source = fs, weight = 400, style = "normal" })Weight values: "regular", "bold", or numbers 100 - 900
Style values: "normal", "italic"
Page
local page = doc:new_page()Attributes
| Name | R/W | Type | Description |
|---|---|---|---|
width |
R/W | ScaledPoint | Page width (returns ScaledPoint on read) |
height |
R/W | ScaledPoint | Page height (returns ScaledPoint on read) |
Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
output_at() |
x, y, vlist | self | Place VList at position |
shipout() |
- | - | Finalize the page |
Example:
local page = doc:new_page()
page.width = "21cm"
page.height = "29.7cm"
page:output_at("2cm", "27cm", vlist)
page:shipout()Table
local tbl = frontend.table({
max_width = "15cm",
stretch = true,
font_family = ff,
font_size = "10pt",
leading = "12pt"
})Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
set_columns() |
widths (table) | self | Set column widths |
add_row() |
- | TableRow | Add a new row |
TableRow Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
add_cell() |
- | TableCell | Add a new cell |
TableCell Attributes
| Name | R/W | Type | Description |
|---|---|---|---|
halign |
R/W | string | Horizontal alignment |
valign |
R/W | string | Vertical alignment |
colspan |
R/W | integer | Column span |
rowspan |
R/W | integer | Row span |
padding_left |
W | dimension | Left padding |
padding_right |
W | dimension | Right padding |
padding_top |
W | dimension | Top padding |
padding_bottom |
W | dimension | Bottom padding |
border_left_width |
W | dimension | Left border width |
border_right_width |
W | dimension | Right border width |
border_top_width |
W | dimension | Top border width |
border_bottom_width |
W | dimension | Bottom border width |
TableCell Methods
| Name | Parameters | Returns | Description |
|---|---|---|---|
set_contents() |
item, … | self | Set cell contents |
Example:
local tbl = frontend.table({ max_width = "15cm" })
tbl:set_columns({ "5cm", "10cm" })
local row = tbl:add_row()
local cell1 = row:add_cell()
cell1:set_contents("Column 1")
cell1.halign = "left"
local cell2 = row:add_cell()
cell2:set_contents("Column 2")
local vlists = doc:build_table(tbl)
for _, vl in ipairs(vlists) do
page:output_at("2cm", y, vl)
endVList
A VList (vertical list) is the result of formatting text or building tables. It contains the typeset content ready for placement on a page.
local vlist, info = doc:format_paragraph(text, "15cm", { leading = "14pt" })
page:output_at("2cm", "27cm", vlist)Attributes
| Name | R | Type | Description |
|---|---|---|---|
width |
R | ScaledPoint | Width of the VList |
height |
R | ScaledPoint | Height of the VList |
depth |
R | ScaledPoint | Depth of the VList |
The dimension attributes return ScaledPoint values, allowing arithmetic operations:
local vlist = doc:format_paragraph(text, "15cm")
local y = frontend.sp_string("28cm")
-- Position next element below the vlist
local next_y = y - vlist.height - "5mm"
page:output_at("2cm", next_y, next_vlist)Color
local red = frontend.color({
model = "rgb",
r = 1.0, g = 0.0, b = 0.0
})
local cyan = frontend.color({
model = "cmyk",
c = 1.0, m = 0.0, y = 0.0, k = 0.0
})
local gray = frontend.color({
model = "gray",
g = 0.5
})
doc:define_color("myred", red)
local col = doc:get_color("myred")
local blue = doc:get_color("#0000ff")Language
local en = doc:get_language("en") -- English
local de = doc:get_language("de") -- German
local fr = doc:get_language("fr") -- FrenchUse in format_paragraph options or text settings for hyphenation.
Imagefile
Represents a loaded image or PDF file.
local imgfile = doc:load_imagefile("image.pdf", 1, "/MediaBox")Attributes
| Name | R | Type | Description |
|---|---|---|---|
filename |
R | string | Original filename |
format |
R | string | Image format |
width |
R | integer | Image width in pixels |
height |
R | integer | Image height in pixels |
scale_x |
R | number | X scale factor |
scale_y |
R | number | Y scale factor |
number_of_pages |
R | integer | Number of pages (for PDFs) |
internal_name |
R | string | Internal PDF name |
ImageNode
An image node ready for placement on a page.
local imgnode = doc:create_image_node(imgfile, 1, "/MediaBox")
imgnode.width = "5cm"
imgnode.height = "3cm"
-- Use node.vpack to create a VList
local node = require("glu.node")
local vl = node.vpack(imgnode)
page:output_at("2cm", "25cm", vl)Attributes
| Name | R/W | Type | Description |
|---|---|---|---|
width |
R/W | ScaledPoint | Image width (returns ScaledPoint on read) |
height |
R/W | ScaledPoint | Image height (returns ScaledPoint on read) |
ColorProfile
ICC color profile for PDF/A and PDF/X compliance.
local cp = doc:load_colorprofile("AdobeRGB1998.icc")
cp.identifier = "AdobeRGB1998"
cp.registry = "Adobe"
cp.info = "Adobe RGB (1998)"
cp.condition = "RGB"
cp.colors = 3Attributes
| Name | R/W | Type | Description |
|---|---|---|---|
identifier |
R/W | string | Profile identifier |
registry |
R/W | string | Registry name |
info |
R/W | string | Profile description |
condition |
R/W | string | Color condition (e.g. “RGB”) |
colors |
R/W | integer | Number of color components |