{"id":1733,"date":"2011-04-01T17:21:40","date_gmt":"2011-04-01T23:21:40","guid":{"rendered":"http:\/\/bililite.nfshost.com\/blog\/?p=1733"},"modified":"2013-02-27T12:01:47","modified_gmt":"2013-02-27T18:01:47","slug":"creating-pdfs-with-php-part-5","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2011\/04\/01\/creating-pdfs-with-php-part-5\/","title":{"rendered":"Creating PDFs with PHP, part 5: Text"},"content":{"rendered":"<p>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.<p>\r\n<p><a href=\"\/blog\/blogfiles\/pdf\/pdftest.php?which=4&output=source\">See the code<\/a>.<\/p>\r\n<!--more-->\r\n<h3>Text, the easy part<\/h3>\r\n<p>The easy part is putting the text on the page. Use the same <code>cm<\/code> 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 <code>BT<\/code> (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 <code class=\"language-pdf\">(string to print) Tj<\/code> (Tj for Text just-print-it? I don't know), then  <code>ET<\/code> (end text).<\/p>\r\n<h3>Text, the hard part<\/h3>\r\n<p>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 <a href=\"http:\/\/fpdf.org\">FPDF<\/a> and <a href=\"http:\/\/www.fpdf.org\/en\/script\/script92.php\">tFPDF<\/a> for details. In short, the process is similar to using images:<\/p>\r\n<dl>\r\n<dt>Define the font<\/dt>\r\n<dd>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.<\/dd>\r\n<dd>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:\r\n<ul>\r\n     <li>Courier<\/li>\r\n     <li>Courier-Bold<\/li>\r\n     <li>Courier-Oblique<\/li>\r\n     <li>Courier-BoldOblique<\/li>\r\n     <li>Helvetica<\/li>\r\n     <li>Helvetica-Bold<\/li>\r\n     <li>Helvetica-Oblique<\/li>\r\n     <li>Helvetica-BoldOblique<\/li>\r\n     <li>Times-Roman<\/li>\r\n     <li>Times-Bold<\/li>\r\n     <li>Times-Italic<\/li>\r\n     <li>Times-BoldItalic<\/li>\r\n     <li>Symbol<\/li>\r\n     <li>ZapfDingbats<\/li>\r\n<\/ul>\r\nFor any of these (and they only have the Ascii characters!) the font descriptor is simple:<\/dd>\r\n<dd><pre><code class=\"language-pdf\">10 0 obj\r\n&lt;&lt;\r\n\/Type \/Font\r\n\/Subtype \/Type1 % they're type 1 fonts. They just are\r\n\/BaseFont \/Helvetica % or whatever the font name is\r\n&gt;&gt;\r\nendobj\r\n<\/code><\/pre><\/dd>\r\n<dt>Define a name for the font<\/dt>\r\n<dd>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 <code class=\"language-pdf\">\/XObject<\/code> subdictionary:<\/dd>\r\n<dd><pre><code class=\"language-pdf\">2 0 obj\r\n&lt;&lt;\r\n  % ... other resource definitions\r\n  \/Font &lt;&lt; \r\n    \/Helvetica 10 0 R % the name of object 6, defined above\r\n    % ... other font descriptors\r\n  &gt;&gt;\r\n&gt;&gt;<\/code><\/pre><\/dd>\r\n<dt>Use the font<\/dt>\r\n<dd>In the content stream for the page, include the command<\/dd>\r\n<dd><pre><code class=\"language-pdf\">\/Helvetica 12 Tf<\/code><\/pre> to set the font to Helvetica, 12 point<\/dd>\r\n<\/dl>\r\n<p>So the total commands to print Hello World in green 12 point Helvetica at <code>(100,100)<\/code> is:<\/p>\r\n<pre><code class=\"language-pdf\">q % push the graphics state\r\n1 0 0 1 100 100 cm % translate origin\r\n0 1 0 rg % set the fill color (text is filled, by default)\r\nBT % start text\r\n\/Helvetica 12 Tf % set the font\r\n(Hello, World) Tj % draw the text\r\nET % end text\r\nQ % restore graphic state\r\n<\/code><\/pre>\r\n<h3>Example<\/h3>\r\n<p><a href=\"\/blog\/blogfiles\/pdf\/pdftest.php?count=1&which=4\">See the example<\/a>.<\/p>\r\n<pre><code class=\"language-php\">$pdf = new bililitePDF_4();\r\n$pdf-&gt;newpage();\r\n$count = 8;\r\nfor ($i = 0; $i &lt; $count; ++$i){\r\n\t$pdf-&gt;placetext('Hello, world', 'Helvetica-Bold', 30, 200, 600, 2*M_PI*$i\/$count, 255*$i\/$count, 255*$i\/$count, 255*$i\/$count);\r\n}\r\n$pdf-&gt;placetext('ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\nabcdefghijklmnopqrstuvwxyz', 'ZapfDingbats', 12, 10, 200);\r\n$pdf-&gt;output();<\/code><\/pre>\r\n<p>This ends the use of my toy class. All further discussion and development will be with the  real <a href=\"http:\/\/fpdf.org\">FPDF<\/a>.\r\n\r\n","protected":false},"excerpt":{"rendered":"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.","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,9],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/1733"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=1733"}],"version-history":[{"count":10,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/1733\/revisions"}],"predecessor-version":[{"id":2852,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/1733\/revisions\/2852"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=1733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=1733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=1733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}