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.
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
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
to set the font to Helvetica, 12 point/Helvetica 12 Tf
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
$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.
ramki says:
Hi Danny, It was really an interesting blog.I had learn to
January 16, 2013, 3:36 amdesign 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
Danny says:
@Ramki:
January 16, 2013, 6:32 amI 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