Skip to content

Creating PDFs with PHP, part 5: Text

Now we need to add text. That's the most useful part of a PDF, and the easiest. Also the hardest. Sometimes life is like that.

See the code.

Text, the easy part

The easy part is putting the text on the page. Use the same cm command to set the origin (there is another transformation matrix just for text which is useful for long runs of text, but we're just putting in a line at a time), then BT (begin text) to start PDF thinking about text (I don't know why you can't just use the text commands, but this is one of the rules), then (string to print) Tj (Tj for Text just-print-it? I don't know), then ET (end text).

Text, the hard part

If you do this, you'll get nothing showing. That's because we haven't told PDF what font we want to use, and describing fonts is an arcane art that I haven't begun to understand. You can look at the code for FPDF and tFPDF for details. In short, the process is similar to using images:

Define the font
This is called the "font descriptor", and involves listing the drawing commands for each glyph (the printed representation of a character) and the font metrics (the dimensions of each glyph and how they interact with their neighbors). PDF only can handle 256 characters per font, so real Unicode fonts need "composite fonts" with multiple subsets of each font.
Luckily for us, Adobe Reader comes with 14 fonts built-in (and, since Reader is the reference standard for PDF readers, you can count on them being built-in for any reader). These are:
  • Courier
  • Courier-Bold
  • Courier-Oblique
  • Courier-BoldOblique
  • Helvetica
  • Helvetica-Bold
  • Helvetica-Oblique
  • Helvetica-BoldOblique
  • Times-Roman
  • Times-Bold
  • Times-Italic
  • Times-BoldItalic
  • Symbol
  • ZapfDingbats
For any of these (and they only have the Ascii characters!) the font descriptor is simple:
10 0 obj
<<
/Type /Font
/Subtype /Type1 % they're type 1 fonts. They just are
/BaseFont /Helvetica % or whatever the font name is
>>
endobj
Define a name for the font
In the resource dictionary, determine a name for the font (this is arbitrary, but there's no reason not to use the real font name) in the /XObject subdictionary:
2 0 obj
<<
  % ... other resource definitions
  /Font << 
    /Helvetica 10 0 R % the name of object 6, defined above
    % ... other font descriptors
  >>
>>
Use the font
In the content stream for the page, include the command
/Helvetica 12 Tf
to set the font to Helvetica, 12 point

So the total commands to print Hello World in green 12 point Helvetica at (100,100) is:

q % push the graphics state
1 0 0 1 100 100 cm % translate origin
0 1 0 rg % set the fill color (text is filled, by default)
BT % start text
/Helvetica 12 Tf % set the font
(Hello, World) Tj % draw the text
ET % end text
Q % restore graphic state

Example

See the example.

$pdf = new bililitePDF_4();
$pdf->newpage();
$count = 8;
for ($i = 0; $i < $count; ++$i){
	$pdf->placetext('Hello, world', 'Helvetica-Bold', 30, 200, 600, 2*M_PI*$i/$count, 255*$i/$count, 255*$i/$count, 255*$i/$count);
}
$pdf->placetext('ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz', 'ZapfDingbats', 12, 10, 200);
$pdf->output();

This ends the use of my toy class. All further discussion and development will be with the real FPDF.

{ 2 } Comments

  1. ramki | January 16, 2013 at 3:36 am | Permalink

    Hi Danny, It was really an interesting blog.I had learn to
    design step by step how PDF structure gets generated behind the
    scenes.I have query regarding password protection to PDF. How your
    going to do the same in PHP and what will be PDF syntax? Thanks for
    your time. Regards Rama

  2. Danny | January 16, 2013 at 6:32 am | Permalink

    @Ramki:
    I honestly don’t know about password protecting PDFs. The initial post in the series included the link to the official ISO (standard) PDF documentation which should include everything you need to know. You could also look at the source to tcpdf to see how they handle password protection. I don’t use it so I haven’t looked into it..
    –Danny

Post a Comment

Your email is never published nor shared. Required fields are marked *