Having successfully built Knuthian TeX from WEB source code (using Visual Studio), and a couple of other TeX engines, I finally feel sufficiently “brave” (or perhaps masochistic…) to attempt “the big one”: LuaTeX. You may well ask “What’s the point when you have MinGW/MSYS to build LuaTeX on Windows for you, and so easily?” Good question! Anyone who has looked at the C code produced by the Web2C process will understand that it’s practically impossible to single-step through it with a debugger and understand what’s going on: it’s machine-generated C code for compilers, not humans! Having built CXTeX (which dates from 2004), it’s a joy to step through CXTeX’s clean C code in an attempt to understand the innards of TeX in more detail. However, CXTeX is nearly 10 years old so it would be nice to have a modern TeX-based engine to explore, hence building LuaTeX, with its CWEB-based C code base. Well, some 6 hours in I’ve managed to build about half the components as Windows .lib files – including Cairo, Kpathsea, FontForge, Poppler and a few others. I can’t say it’s been easy but it’s an interesting challenge to occupy the evenings over the next few days. No doubt I’m in for some interesting challenges as I try to assemble the parts into a working LuaTeX executable. Can’t wait to have LuaTeX running in Visual Studio’s debugging IDE!
Category Archives: PDF technical
Example: Importing a Cairo PDF into XeTeX
A quick example…
Just a quick example of importing the Cairo graphics clock into the latest XeTeX engine (using XeLaTeX). Crop marks were added using a raw \special{pdf: bop …} command.
Creating a clock with Arabic digits using the Cairo graphics library
Cairo graphics
Cairo is an excellent graphics library, albeit a little tricky to build on Windows. After successfully compiling it as a static library (.lib) I wanted to explore using it to create PDFs containing Arabic. Cairo is a graphics engine, not a text layout engine, so with complex scripts like Arabic you need to take care of the shaping and text placement yourself. Naturally, this is pretty fiddly but it’s certainly quite possible. So, here are a couple of clocks as examples – note that the positioning of the numbers is not quite perfect so I have a little tweaking to do on that. Additionally, the resulting PDF imports nicely into the latest XeTeX engine. For the digits I used the font ScheherazadeRegOT, available from SIL.
Quick and dirty method for creating spot colours in PDFs
Introduction
Just a 10-minute hack to explore putting spot colours into a PDF via pdf_colorstack nodes. I don’t have access to Acrobat Professional at the moment to check the separations properly, so treat this as an “alpha” method (i.e., not fully tested…). The colour defined below is lifted straight from an early PDF specification and implemented via LuaTeX nodes. As it says “on the tin”: a quick and dirty method :-).
\pdfoutput=1 \hoffset-1in \voffset-1in \nopagenumbers \pdfcompresslevel=0 \directlua { n = pdf.immediateobj("stream", "{ dup 0.84 mul exch 0.00 exch dup 0.44 mul exch 0.21 mul }", "/FunctionType 4 /Domain [0.0 1.0] /Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0] ") o = pdf.immediateobj("[ /Separation /LogoGreen /DeviceCMYK".." "..n.." 0 R]") pdf.pageresources = " /ColorSpace << /LogoGreen "..o.." 0 R >> " pdf_colstart = node.new("whatsit","pdf_colorstack") pdf_end = node.new("whatsit","pdf_colorstack") pdf_colstart.data="/LogoGreen CS /LogoGreen cs 1 SC 1 sc " pdf_colstart.cmd=1 pdf_end.data= " " pdf_end.cmd = 2 tex.box[1999]= node.hpack(pdf_colstart) tex.box[2000]= node.hpack(pdf_end) } \def\makeitgreen#1{\copy1999\relax#1\copy2000\relax} There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything \makeitgreen{embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to} repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc. \bye
Resulting PDF
As usual, through the Google Docs viewer or download here.
Creating PDF pattern fills with LuaTeX nodes
Introduction
This is a short example to introduce two very useful LuaTeX API functions which let you work with low-level PDF objects. Here we’ll use them to explore a PDF feature called pattern fills which (from the PDF specification) are a way to
“… apply “paint” that consists of a repeating graphical figure or a smoothly varying color gradient instead of a simple color. Such a repeating figure or smooth gradient is called a pattern. Patterns are quite general, and have many uses; for example, they can be used to create various graphical textures, such as weaves, brick walls, sunbursts, and similar geometrical and chromatic effects”
I’m not going to attempt any explanation of pattern fills because the PDF specification explains them, and their many options, in great detail. Hopefully, these small code examples will be helpful should you want to explore using them in your work with LuaTeX.
LuaTeX API
Here are the functions we’ll be using:
pdf.immediateobj(…)
Quoting from The LuaTeX Reference Manual: This function creates a pdf object and immediately writes it to the pdf file. It is modelled after pdfTEX’s \immediate\pdfobj primitives. All function variants return the object number of the newly generated object.
n = pdf.immediateobj( objtext)
n = pdf.immediateobj("file", filename)
n = pdf.immediateobj("stream", streamtext, attrtext) pdf.pageresources =…
This lets you add named resources to the page /Resources dictionary so that they can be used within page content streams.
In outline…
There are two parts to the approach:
- Writing the appropriate pattern fill objects and data to the PDF file.
- Creating a pdf_literal node to use our newly defined pattern fills.
The code
Here’s the \directlua code with in-line comments.
\directlua{ % If you want to quickly view the LuaTeX PDF data in a text editor you should % set the compression level to 0. tex.pdfobjcompresslevel=0 % We'll use the object number o to store the object reference in the page /Resources dictionary. o = pdf.immediateobj("[/Pattern /DeviceRGB] ") % Here we use pdf.immediateobj(...) write the data which actually defines the pattern fill. % We'll use the object number n to store the object reference in the page /Resources dictionary. n = pdf.immediateobj("stream", "1 J .5 w 1 1 4 4 re 5 5 3 3 re f", "/Type /Pattern /PatternType 1 /PaintType 2 /TilingType 1 /BBox [0 0 10 10] /XStep 5 /YStep 5 /Resources << >>") % Here we add the appropriate named resources (for the pattern fill) to the page /Resources dictionary so % that we can use the pattern fill in content streams within any page. pdf.pageresources = "/Pattern << /P1 "..n.." 0 R >> /ColorSpace << /Cs12 "..o.." 0 R >> " % Here we create a pdf_literal node which simply draws a box (0 0 12 12 re) % and fills it using our pattern. Note that if you omit the q ... Q construct to save and % restore then the pattern fill will affect other content on your page, with very strange % results... pdfdata = node.new("whatsit","pdf_literal") pdfdata.mode=0 pdfdata.data=" q 0 0 12 12 re /Cs12 cs 0.77 0.20 0.00 /P1 scn f Q" % Package our pdf_literal into a box so that we can use it with TeX % code such as \copy999 tex.box[999]= node.vpack(pdfdata) }
Full example minus comments
\pdfoutput=1 \pdfcompresslevel=0 \hoffset-1in \voffset-1in \pdfpageheight=200mm \pdfpagewidth=300mm \vsize=100mm \hsize=200mm \directlua{ tex.pdfobjcompresslevel=0 o = pdf.immediateobj("[/Pattern /DeviceRGB] ") n = pdf.immediateobj("stream", "1 J .5 w 1 1 4 4 re 5 5 3 3 re f", "/Type /Pattern /PatternType 1 /PaintType 2 /TilingType 1 /BBox [0 0 10 10] /XStep 5 /YStep 5 /Resources << >>") pdf.pageresources = "/Pattern << /P1 "..n.." 0 R >> /ColorSpace << /Cs12 "..o.." 0 R >> " pdfdata = node.new("whatsit","pdf_literal") pdfdata.mode=0 pdfdata.data=" q 0 0 12 12 re /Cs12 cs 0.77 0.20 0.00 /P1 scn f Q" tex.box[999]= node.vpack(pdfdata) } Hip \copy999 Hip Hooray \copy999 \bye
Resulting PDF
You can download the PDF output from the above example. It displays OK with my version of Adobe Reader (8.2.1 for Windows) and Evince (2.28 for Windows).
Evince PDF viewer: a Windows productivity tool
Adobe’s PDF reader (Adobe Reader) is certainly a very nice tool for viewing PDFs but it has one annoying “feature” (certainly on Windows): it puts some form of “lock” on the PDF file you are viewing. If you have the file open in Adobe Reader then LuaTeX will see the file is non-writable and will output the PDF in another location using settings in texmf.cnf: TEXMFOUTPUT. This behaviour of Adobe Reader forces you to tediously close and re-open the PDF file each time you update the PDF from a fresh run of LuaTeX.
If, like me, you are doing a lot of “edit–run LuaTeX–view PDF” cycles then you may find that the free Evince PDF viewer can save you a lot of time, and tedium. Evince does not lock the PDF file it is displaying so that LuaTeX can overwrite it and Evince will automatically refresh the display with the new PDF.
For sure, a number of TeX/LaTeX editors have in-built PDF viewers but sometimes you may prefer, or need, to use a standalone PDF viewer; if so, Evince is a nice solution and the Windows version can be downloaded from http://live.gnome.org/Evince/Downloads.