Archive for March, 2011

Now that we can create blank PDF's, it's time to add some stuff. Vector drawing commands (lines and shapes) are simple; you just add the commands to the page content stream. In terms of the original class that would be:

$this->pages[count($this->pages)-1]->contents .= "the command\n";
// we just need some whitespace at the end, but the newline makes it easier to read the resulting PDF

But to make things easier, we can keep track of the last page:

function newpage(){
  parent::newpage();
  $this->currentPage = $this->pages[count($this->pages)-1];
}
// and now adding commands is:
$this->currentPage->contents .= "the command\n";
// this also has the advantage that we can manipulate currentPage to add commands to other content streams

There are lots of commands, all of which are postfix (parameters come before operators). There are no math operators or stack manipulation operators; any calculation has to be done before generating the PDF and numbers inserted directly.

See the code.

Continue reading ‘Creating PDFs with PHP, part 3: Drawing’ »

Continuing my attempt to dissect FDPF to understand PDF's, we'll create the simplest PDF: a blank page.

We need a couple of objects:

Catalog
This serves as the root object and describes the data structures in the document, which for our purposes is just the collection of printed pages. Other things, like the data for interactive forms, Javascript routines and metadata (author, subject, keywords) would go here.
1 0 obj
<<
  /Type /Catalog
  /Pages 0 2 R % reference to object number 2
>>
endobj
One useful optional entry in the catalog is the /OpenAction that can be used to set the zoom level and opening page. /OpenAction [3 0 R /Fit] starts at the page described in object 3 and zooms in to fit the page on the screen.

See the code.

Continue reading ‘Creating PDFs with PHP, part 2: A Blank Page’ »

I wanted to allow my webservices to create PDF files, and I figured it couldn't be too hard—after all, it's just a bunch of graphics commands in a text file, right? Foolish me. The reference manual is 756 pages long, not including the javascript reference, another 769 pages. The place to start is fPDF, which is open source and pretty easy to understand, and its derivative tFPDF that lets you use and embed True Type fonts (it's the 21st century; who uses anything but True Type fonts?). Using it is simple:

define('_SYSTEM_TTFONTS', '/path/to/your/truetype/fonts/'); // Took a bit of experimenting to find the right values for these
define('FPDF_FONTPATH', _SYSTEM_TTFONTS);
putenv('GDFONTPATH='._SYSTEM_TTFONTS); // so we can use GD images as well
$pdf=new tFPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello World!');
$pdf->Output();

One gotcha is that you need to create the unifont directory within the fonts folder, and copy tFPDF's ttfonts.php file into that.

The result is here.

Continue reading ‘Creating PDFs with PHP: Syntax’ »

I've been trying on and off to get my head around continuations in Scheme, which is the language that gnucash uses for reports. It's one of the modern versions of Lisp. And then I came across a throwaway line in the YQL documentation about JSONP with a callback is a also called continuation-passing style. A little Googling finds this fascinating lecture by Douglas Crockford, a short summary by John Lam that makes it clear that the continuation idea is obvious to anyone who's done any asynchronous Javascript like AJAX, and a more intellectual discussion by Matt Might that goes through the Lisp side.

Now that it turns out that I already understand continuations, I'll have to go back and prove that to myself. And yes, Javascript is Lisp in C's clothing.