Skip to content

Instantly share code, notes, and snippets.

@pgundlach
Created July 3, 2011 07:41
Show Gist options
  • Save pgundlach/1062041 to your computer and use it in GitHub Desktop.
Save pgundlach/1062041 to your computer and use it in GitHub Desktop.
Sample Lua Document to create a two page PDF document with hyperlinks
do
-- this will hold the items that go onto the page
local pagelist
-- Call tex.shipout() with the contents of the pagelist
function shipout()
local vbox,b = node.vpack(pagelist) -- we ignore the badness 'b'
tex.box[666] = vbox
tex.shipout(666)
pagelist = nil
-- Not strictly necessary. TeX holds the current page number in counter 0.
-- TeX displays the contents of this counter when it puts a page into
-- the pdf (tex.shipout()). If we don't change the counter, TeX will
-- display [1] [1], instead of [1] [2] for our two page document.
tex.count[0] = tex.count[0] + 1
end
function add_to_page( list )
-- We attach the nodelist 'list' to the end of the pagelist
-- if pagelist doesn't exist, 'list' is our new pagelist
-- if it exists, we go to the end with node.tail() and adjust
-- the prev and next pointers, so list becomes part
-- of pagelist.
if not pagelist then pagelist = list
else
local tail = node.tail(pagelist)
tail.next = list
list.prev = tail
end
end
end
-- This creates a new square rule and returns the pointer to it.
function mkrule( size )
local r = node.new("rule")
r.width = size
r.height = size / 2
r.depth = size / 2
return r
end
do
local destcounter = 0
-- Create a pdf anchor (dest object). It returns a whatsit node and the
-- number of the anchor, so it can be used in a pdf link or an outline.
function mkdest()
destcounter = destcounter + 1
local d = node.new("whatsit","pdf_dest")
d.named_id = 0
d.dest_id = destcounter
d.dest_type = 3
return d, destcounter
end
end
-- Take a list of nodes and put them into an hbox. The prev and next fields
-- of the nodes will be set automatically. Return a pointer to the hbox.
function hpack( ... )
local start, tmp, cur
start = select(1,...)
tmp = start
for i=2,select("#",...) do
cur = select(i,...)
tmp.next = cur
cur.prev = tmp
tmp = cur
end
local h,b = node.hpack(start) -- ignore badness
return h
end
local tenpt = 10 * 2^16
---------------------------
-- page 1
---------------------------
local n,dest = mkdest() -- dest is needed for the link to this anchor
add_to_page(n)
add_to_page(mkrule(2 * tenpt))
-- The pagelist contains a pdf dest node (a link destination) and a rule of size 20pt x 20pt.
shipout()
---------------------------
-- page 2
---------------------------
-- This is the page with the link to the anchor (dest) on page one. A
-- link consists of three nodes: a pdf_start_link, a pdf_end_link and and
-- action node that specifies the action to perform when the user clicks on
-- the link.
-- The pdf link must be inside a horizontal box, that's why we hpack() it.
-- The link_attr (link attributes) is optional, here it draws a yellowish border
-- around the link.
local start_link = node.new("whatsit","pdf_start_link")
local end_link = node.new("whatsit","pdf_end_link")
start_link.width = tenpt
start_link.height = tenpt / 2
start_link.depth = tenpt / 2
start_link.link_attr = "/C [0.9 1 0] /Border [0 0 2]"
start_link.action = node.new("action")
start_link.action.action_type = 1
start_link.action.action_id = dest
local rule = mkrule(tenpt)
local hbox = hpack(start_link, rule, end_link)
add_to_page(hbox)
-- This pagelist consists of an hbox whose contents is "start_link",
-- the 10pt x 10pt rule and the "end_link" node.
shipout()
---------------------------
-- Just to show you that you can get some memory usage statistics:
print(string.format("\nnode_mem_usage=%s",status.node_mem_usage))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment