\pdfoutput=1
\pdfcompresslevel=0
\hoffset-1in
\voffset-1in
\pdfpageheight=200mm
\pdfpagewidth=300mm
\vsize=100mm
\hsize=200mm
\topskip=0pt
\maxdepth=0pt
% This output routine centres \box255 horizontally and vertically
% on the PDF page and ships out 4 boxes (2000--2003) onto every page.
% These boxes contain the crop mark graphic, suitably rotated.
% The \output routine is described in the article text.
\output={\shipout\vbox to \pdfpageheight{%
\vfill%
\vbox to \vsize{\offinterlineskip%
\vfill%
\hbox to\pdfpagewidth{\hfill\hbox to \hsize{\copy2000\hfill\copy2001}\hfill}%
\hbox to \pdfpagewidth{\hfill\box255 \hfill}%
\hbox to \pdfpagewidth{\hfill\hbox to \hsize{\copy2003\hfill\copy2002}\hfill}%
\vfill}%
\vfill%
}%pdfpageheight
}%output
% Load the mpnodes.lua module
\directlua{require("mpnodes")}
% Here we redefine the macros in luamplib to
% work with nodes.
% \mplibstarttoPDF simply stores the coordinates of the bounding box of the MetaPost
% graphic in 4 TeX tokens, but they are not used in the code below.
\def\mplibstarttoPDF#1#2#3#4{%
\directlua{
tex.toks[500]=#1
tex.toks[501]=#2
tex.toks[502]=#3
tex.toks[503]=#4
%tex.print(tex.toks[500],tex.toks[501],tex.toks[502],tex.toks[503])
}}
% \mplibtoPDF stores each line of PDF data generated from Lua
% and builds it up into one long string. Note I am adding a carriage
% return to each line (string.char(10))
\def\mplibtoPDF#1{%
\directlua{
buffy= buffy or ""
buffy=buffy..string.char(10).."#1"
}}
% Here's the main work. Once the PDF data describing the crop mark has been collected
% the final macro call made by the Lua code is to \mplibstoptoPDF. In this macro
% we create 4 pdf_literal nodes which only differ by adding extra PDF data to rotate the
% crop mark in increments of 90 degrees. The PDF data has been collected by \mplibtoPDF
% in a text string called "buffy".
\def\mplibstoptoPDF{%
\directlua{
rad=math.rad
sin=math.sin
cos=math.cos
% Function to generate PDF transformation (rotation) matrices.
function rotate(angle)
local d=string.format("q 0 0 m \%3.3f \%3.3f \%3.3f \%3.3f 0 0 cm ",
cos(rad(angle)),
sin(rad(angle)),
-sin(rad(angle)),
cos(rad(angle)))
return d
end
% The names of the pdf_literal nodes reflect their position on the page.
% Note: PDF rotations are counter-clockwise hence negative angles used
% in the code below.
pdftopleft = node.new("whatsit","pdf_literal")
pdftopleft.mode=0
pdftopleft.data=buffy
pdftopright = node.new("whatsit","pdf_literal")
pdftopright.mode=0
rot90=rotate(-90)
print(rot90)%..buffy.." Q")
pdftopright.data= rot90..buffy.." Q"
pdfbottomright = node.new("whatsit","pdf_literal")
pdfbottomright.mode=0
rot180=rotate(180)
pdfbottomright.data=rot180..buffy.." Q"
pdfbottomleft = node.new("whatsit","pdf_literal")
pdfbottomleft.mode=0
rot270=rotate(-270)
pdfbottomleft.data=rot270..buffy.." Q"
% We have our nodes now pack them into boxes for shipping
% out via the \output routine as \copy2000....\copy2003
tex.box[2000]= node.hpack(pdftopleft)
tex.box[2001]= node.hpack(pdftopright)
tex.box[2002]= node.hpack(pdfbottomright)
tex.box[2003]= node.hpack(pdfbottomleft)
}}
% Macro to create an instance of the MPlib interpreter and execute
% the MetaPost code collected by the \startbuffer and \stopbuffer macros.
% Lua code is stored in the mpnodes.lua module hence you prefix the functions
% with "mpnodes" to call them: mpnodes.function_name(...)
\def\runmpcode{%
\directlua{
%print(buffer)
%Error checking could be improved here...
mp=mpnodes.newmpx("plain")
res,err=mp:execute(buffer)
%print(res,err)
if res then
mpnodes.outputpdf(res) %core function to produce PDF data
else
print("No figures")
end
}}
% Code to implement buffering the inline MetaPost code
\directlua{
function addline(line)
line=line..string.char(10)
%print("called with "..line)
buffer = buffer..line
end}
% Code to implement buffering the inline MetaPost code
\directlua{
buffer=""
function dobuffer(line)
if string.match(line,"stopbuffer") then
callback.register("process_input_buffer",nil)
return ""
end
addline(line)
% print(line)
return ""
end
}
% Code to implement buffering the inline MetaPost code through
% process_input_buffer callback
\def\startbuffer{\directlua{callback.register("process_input_buffer",dobuffer)}}
\def\stopbuffer{\directlua{callback.register("process_input_buffer",nil)}}
% Here's the inline MetaPost code
\startbuffer
beginfig(1);
numeric n,g,tl, alpha;
pair dl,zc,zl,zr,zt,zb,db;
path c, t;
alpha:=0.75;
n:=2;
g:=72*(3/25.4);
tl:=(n+1)*g;
pickup pensquare scaled 0.5bp;
draw (0,g)--(0,tl);
draw (-g,0)--(-tl,0);
rd:=0.5*tl;
rc:=0.5*rd;
dl=(-(1+alpha)*rc,0);
db=(0,-(1+alpha)*rc);
zc=(-rd,rd);
zl=zc+dl;
zr=zc-dl;
zt=zc+db;
zb=zc-db;
t=zc+(0.9*rc,0)--zc-(0.9*rc,0);
c = fullcircle scaled 2rc shifted(-rd,rd);
pickup pensquare scaled 0.5bp;
draw zl--zr;
draw zt--zb;
fill c withcolor black;
pickup pensquare scaled 1bp;
draw t withcolor white;
draw t rotatedabout(zc, 90) withcolor white;
endfig;
end;
\stopbuffer%
\runmpcode
\def\apar{Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet.."\par}%
\apar\apar\apar\apar\apar\apar\apar\apar\apar\apar\apar\apar
\bye