PDF document creator based on TCPDF/FPDF

There are many PDF creators written in PHP : Zend Framework has one (Zend_Pdf), FPDF, TCPDF...
But no one or them is able to create final document based on "source" PDF template, by populating it with user data. (or maub i did not find it).

This class, CPrintfromPdf, written for automaying that process: basically it can load "source" PDF file as template, fill it with data, prepared in your program, and send final document to the clietn (or saves it to the disc).
This class is a wrapper for the famous class TCPDF, (it was chosen as most powerful and still "growing"), with "a little help" of FPDF / FPDFI classes, used for loading source PDF template file.

Main class features:

Installing on the web server

The main module is printform-pdf.php, so you need to copy it into one of "include_path" folders. Besides, You have to download and install following open source modules:
  1. TCPDF - PHP classes for creating PDF documents. Here is a link: tcpdf.org
  2. Modules FPDF-FPDFI also needed, as they can parse existing PDF file contents and make it a part of TCPDF object. Can be found on site http://www.setasign.de/
  3. If you're going to generate Sudoku puzzles, you have to download and install a module class.Sudoku.php
If You use specific national language, You have to generate some "font" modules from your TTF font files, and put them into tcpdf/fonts folder.
TCPDF distributive has utility that can do it, so You can find it and using instructions inside TCPDF contents (fonts/utils folder).
Don't forget, you'll have to create font modules for ALL fonts You're goung to use. Base default font for CPrintformPDF is arial, so it is a good idea to firstly create font modules for Your language from this truetype font.

Using the class

Below is a simple example that shows the main functionality: it creates PDF file from source template file 'pdf-template.pdf'. It will receive your data and place it "over" the template, to generate "final" PDF :
if(!class_exists('TCPDF',false)) {
    require_once('tcpdf/config/lang/rus.php'); // Here we need to include module for our language, russian in my case
    require_once 'tcpdf/tcpdf.php';
    require_once 'fpdf/fpdi2tcpdf_bridge.php';
    require_once 'fpdf/fpdi.php';
}
require_once('printform-pdf.php');

$xmlcfg = "pdf-config.xml"; // your config file

$pdf = new CPrintFormPdf(array(
    'configfile' => $xmlcfg
   ,'outname' => "output-file.pdf"
   ,'author'  => 'Some clever guy'
   ,'creator' => 'Test program'
   ,'title'   => 'Generated test PDF'
   ,'subject' => 'Testing PDF creation filled by user data'
   ,'compression' => true
));

$userdata = array(
    'cityname' => 'Moscow'
   ,'personname' => 'Dow'
   ,'person_firstname' => 'John'
   ,'person_birthdate' => '04/15/1970'
   ,'person_document' => 'Passport 0034 010203'
   ,'demostring' => 'DEMONSTATION!'
);
$pdf->AddData($userdata);
$pdf->Render(); // generated PDF wiil be sent to the client, so the browser will ask to open or save it.

Configuration XML file format

Below is example of configuration file for our tyny program. (let's call it pdf-config.xml).
<?xml version="1.0" encoding="UTF-8"?>
<printdef>
  <version>1.0</version>
  <title>Testing PDF generation</title>
  <description>This is a test PDF document created by CPrintfromPDF class</description>
  <stringcharset>UTF-8</stringcharset>

  <baseparameters>
    <margins left="0" top="0" right="0" bottom="0" />
    <font name="arial" size="6" />
    <page orientation="P" size="A4" units="mm" />
    <templatefile src="pdf-template.pdf"  />
  </baseparameters>

  <pages>
   <page>
      <template page="1" />
      <field name="cityname" posx="143" posy="26" />
      <field name="personname" posx="42" posy="26" />
      <field name="person_firstname" posx="88" posy="26" width="20" />
      <field name="person_birthdate" posx="42" posy="32" width="70" />
      <field name="person_document" posx="143" posy="32" width="55" />
      <field name="demostring"     posx="50"  posy="110" rotate="45" size="40" color="#EE4040"/>
   </page>
  </pages>
</printdef>
As You see, XML code has a section for "base parameters", (title,description, stringcharset, templatefile), and a section that exactly describes how to output user data.
baseparameters contains base parameters that affect the whole document,
and section pages contains blocks <page> ... </page>, each of them holds coordinates, font sizes/names, color, rotation angle for passed user string data or images inside one page of the document.

templatefile tag in "baseparameters" section contains filename for the "main" template PDF file, that will be used as "background" for your document (src attribute). We'll see later what it is.

Page block can contain one more type of definition : datagrid. What's this ?
Imagine, You want to print a grid (table) with info about up to 30 employees on the PDF page, each one of them contains his/her name, birth date, duty and salary.
To implement this by ordinary way, you should describe 30 field blocks:

  ...
  <page>
      <field name="emp_name1" posx="10" posy="26" />
      <field name="emp_birthdate1" posx="50" posy="26" />
      <field name="emp_duty1" posx="80" posy="26" />
      <field name="emp_salary1" posx="120" posy="26" />

      <field name="emp_name2" posx="10" posy="32" />
      <field name="emp_birthdate2" posx="50" posy="32" />
      <field name="emp_duty2" posx="80" posy="32" />
      <field name="emp_salary2" posx="120" posy="32" />
      /**... and so on **/
  </page>
  ...

"datagrid" definition makes it much easier:
  ...
  <page>
      <field name="emp_name" posx="10" />
      <field name="emp_birthdate" posx="50" />
      <field name="emp_duty" posx="80" />
      <field name="emp_salary" posx="120" />
      <datagrid name="empl_grid" fields="emp_name,emp_birthdate,emp_duty,emp_salary" posy="26" step_y="6" rows="30" />
  </page>
  ...
"datagrid" definition contains : Remember, in XML file datagrid definition must be placed after definitions of all fields listed in it's "fields" attribute !

When generating PDF document, to populate this grid with your employee data, you can use following approaches:
  1. While preparing data array for AddData($data) method, You fill every "numbered" field value in it:
    $data[emp_name1'] = 'Joshua Gordon';
    $data['emp_birth1'] = '1980-04-20';
    ...
    $data['emp_name2'] = 'Alex Johnson';
    $data['emp_birth2'] = '1975-10-09';
    ...
    $pdf->AddData($data);
    
  2. You can prepare all other data except your grid, call AddData() to pass them, and after that you call special method AddDataGridRow():

    // we assume that each $employees element is an associative array with needed values
    foreach($employees as $oneempl) {
      $pdf->AddDataGridRow('empl_grid', $oneempl);
    }
    $pdf->AddData($data);
    
    AddDataGridRow() can be called as many times as needed to pass all employees info (up to 30 in our example).
  3. All "grid" data can be passed as a part of full user data while calling AddData() method.
    You have to use specific 'field name' for that case, that contains prefix 'grid:' and grid ID:
    $data['grid:empl_grid'] = array(
         array('emp_name'=>'Joshua Gordon', 'emp_birth'=>'1980-04-20')
        ,array('emp_name'=>'Alex Johnson', 'emp_birth'=>'1975-10-09')
    );
    $pdf->AddData($data);
    $pdf->Render();
      

Bonus features

Besides "main function" of formatted printing, class CPRintformPdf contains some experimental functions that can be useful for some people:

Class methods

Class constructor :

CPrintformPDF($param=''),
$param can be a filename of configuration XML file OR XML string containing all definition, OR associative array ('key'=>value form) :
KeyDescriptiondefault value
template The name of source PDF template file --
outnameoutput file name--
compression compression mode for created PDF (your PHP should have ZIP functions support !) false
tofile if not empty value, instead of echoing to user stream, generated file will be saved to the disc with the name passed in "outname" parameter false
configfile passes XML configuration file name  
subject Contents for Subject field in PDF document empty string
author Contents for Author field in PDF document CPrintFormPdf, TCPDF wrapper class
creator Contents for Creator field in PDF document printform-pdf module ...
stringcharset Character set name used in Your data. It's nessesary to correctly convert the, into UTF-8, and it must be one of charsets supported by PHP's iconv() function. No need to set this parameter if You will pass UTF-8 encoded data to CPrintFormPDF ''
Here is full description for configuration parameters in XML file.

ParameterDescriptionValue by default
stringcharsetUser data character set (described above)""
titleString for the respective PDF file properties field""
descriptionString for the respective PDF file properties field""
pageCommon page parameters:
orientationSheet orientation : 'P' (portrait) or 'L' - landscape'P'
sizeSheet size('A4', 'A5' etc.)'A4'
unitsBase units (all positions, sizes will use it)'mm'
Section "baseparameters"
fontSets "main" font parameters, used as default for all text output
Example: <font name="verdana" size="3.5" />
attribute namebase font namearial
attribute sizebase font size, in units (mm) 4
marginsPage margins
Example: <margins left="10" top="5" right="10" bottom="2" />
Attributes left,right, top, bottomindents from left, right etc.0
templatefile Attribute "src" contians main PDF template filename for all pages ''
Section "pages" - contains a set of <page> ... </page> blocks - each of them describes one printed page (positions and other parameters for printing user data)
templateTag <template> sets PDF file name, used as "source" for this page of document.
Example: <template src="template.pdf" page="1" />
attribute srcfull PDF filename with a path (if nessesary). If not set, "main" template PDF will be used for this page.
attribute pagesais what page of source file will be used as "template" for the current document page (numeration starts with 1). If you want draw PDF template for this page, you must pass non-zero page value.0
fieldSets parameters for printing one user data field
Example: <field name="cityname" posx="143" posy="26" />
attribute namefield name. User data array should have an element with the key identical to this name--
attribute typeField type. By default all fields treated as simple text. Supported types:
type="image" sets image file. Attribyte "src" should exist and contain existing image file name,
type="checkbox" - if user passed data for this field is not empty, turned on "checkbox" char will be printed
type="poly" draws open polygon, you should pass arrays of coordinates in attributes posx, posy. Amount of "x" znd "y" values should be equal, (the rest of values in "bigger" list will be ignored).
type="barcode", type="qrcode" - these types used to print bar code and QR-code, respectively. (See details here
--
Attributes posx, posySet exact start position for printing the field.
Attribute posx can be a comma delimited value list - see details later.
0,0
Attributes width, heightUsed to limit maximal width anf height for the text field. Zero values mean "no limit". TCPDF perform auto word wrapping, so long texts can be printed in more than one line. For the image and barcode/QR-code fields width and height set real picture size (auto-scaling will be performed).
Attention: If both parameters passed for image field, the printed image can be stretched.
0,0
attribute charstepSets a horizontal step - distance between printed shars of the string. If non-zero charstep passed, user data will be printed "by char" with this step. Useful if you print data into bordered "squares" on the blanc form that was designed for manual filling.0
attribute maxlengthSets limit for the printed string. Actual user data will be cut if it's longer then maxlength
attribute fontSets font name. By default "base" font is used for all fields.
attribute sizeSets font size.0
attribute colorColor for printed characters. Any values supported by TCPDF class ("rgb(n1,n2,n3)", "gray"/"black", 3- or 6-digit Hex-code) can be used. Default color is black.
It is possible to pass user function name (after the "@" char), so the color will be "calculated" right before printing : "@MyColorFunction"
attribute bgcolorSet background color. Any values supported by TCPDF class can be used.
It is possible to pass user function name (after the "@" char), so the color will be "calculated" right before printing : "@MyColorFunction".
When bgcolor set, filled rectangle is rendered first, and then text value is printed above it. If bgcolor used, Non-empty attributes width and height are amust, otherwise rectangle won't be drawn.
Use this attribute to "hide" some unwanted areas (usually came from pdf template) on the page and print something else instead.
attribute alignHorizontal aligning. Possible values (L,R,C,J) must conform TCPDF requirements
attribute optionsAdditional options string, it is used in barcode and QR-code fields.
It is possible to pass user function name (after the "@" char), so the options string will be "calculated" right before printing : "@MyOptionsFunction"
--
attribute srcused in "image" field to pass image file name. This must be one of graphic files supported by TCPDF
attribute rotateYou can rotate any element (text, image, barcode, QR-code) by desired angle (value in grads, counterclockwise)""


One user data value can be printed more than once on the page: to do this, you just describe additional <field ... > blocks in XML definition with the same name attribute.

Value array in posx

As mentioned, you can print strings using "charstep", so single chars will be printed with desired step. But there are cases when You need "different" positions for every char, or even omit some of them. For instanse, we're printing date field that is passed in "MM/DD/YYYY" format, into six "cells" (MM | DD | YY), si we need to cut "slashes" and two first year digits from source string. So we can form "posx" attribute like this:
<field name="date_entered" ... posx="50,54,0,70,74,0,0,0,90,94" />


Every zero value means "skip this char", so only month, day and two-digit year will be printed, and these chars will be placed on exact positions we passed.
As our posx array has only 10 values, all the rest source characters (if any) will be ignored.

LoadConfig([$cfgname]) - loads configuration from XML file with passed name. You can use it if you didn't pass that name in class constructor. You can pass the whole XML string instead of file name - it will be parsed the same way as xml file contents.

addPageDef($opts=array()) - programmatically adds definition for one PDF page. You can prepare associative array that contains the following items and pass it ti this method:
$opts['template'] - associative array, describes source PDF file parameters to use as "template" for the page (See template attributes for all supported values) $opts['fields'] - associative array, describes all fields on this page (See "field" attributes for all supported values)
$opts['repeat'] - array, describes "repetition" on the page. Equivalent to "repeat" tag in XML configuration file.

AddFieldDefinition($ipage, $parm) used to programmatically add one field definition for the page.
$ipage - page number, $parm - associative array with field definition, all possible keys described earlier for the field tag: posx, posy, width, height, type, etc.

setTitle($strg) sets Title attribute for the PDF.

setSubject($strg) sets Subject attribute for the PDF.

setAuthor($strg) sets Author attribute for the PDF.

setCreator($strg) sets Creator attribute for the PDF.

disableImages($par=true) - turns off drawing of all images on the docyment. May be useful if you want to hide stamps, logos or faximile signatures in the case of test printing or whatelse.

AddData($entitydata) passes whole user data block for one printed document. It's possible to call this more than once: every AddData() creates the full document in output PDF.
So you can create PDF file that contains "agreements" for many people, or many letter envelopes and so on.
Data array has a familiar structure - every key is one of field names described in printing configuration.

DrawMeasuringGrid($step = 10, $color = false) - function for fine-tuning : it draws a measuring grid, so you can find right posx and posy coordinates for all your data.
$step is a horizontal and vertical step, $color is grid color. By default step is 10mm. If you pass "1" value or TRUE, this interpreted as "Yes" (not 1mm), mean 'yes, print the grid with default step 10mm'. Default grid color - gray, (RGB: 80,80,80).

addPluginData($name, $data) : passes data that must be visualized in "plugin" field, by calling respective plugin methods. See details in plugins section.

setResourcePaths($pdfPath=null, $imgPath=null) : by default printformPdf treats all PDF templates and image file names in "current folder" context. But all these "resources" may be placed somewhere else, in special sub-folder "resources/" for example. If you don't want to add this (sometimes quite long) paths to ALL "src" attributes in your XML configuration file, just use this method to add "real folders" where these files located.
First parameter $pdfPath sets path for PDF template files, and $imgPath set the path for images.

Render($output=true) : Finally creates output PDF document and sends it to the client (http stream) or saves to the disc (depends on active mode). If you pass zero $output value, output/saving won't be done, and PDF "object" remains open for additional operations. For instanse, you may want to print some final strings that was not described in configuration, ar even add new page. All these operations can be done by direct calling methods from TCPDF class: to do this, you need a TCPDF object, right ? OK, call the method getPdfObject() to get it.
When all operations done, don't forget to call Output() method.
// Here we will draw horizontal line to our PDF
$pdf = new CPrintFormPdf(...);
...
$pdf->AddData($mydata);
$pdf->Render(false);
$tcpdf = $pdf->getPdfObject();
$tcpdf->Line(10,100,190, 100);
$pdf->Output(); // finally closing PDF and sending it to the client/storing to disc

Printing Bar codes

Due to Bar-code support in TCPDF, PrintFormPDF can also print any of bar codes supported by TCPDF.
Bar code Deninition fragment:
      ...
      <field name="barcode_crc" type="barcode:C128" posx="10"  posy="180" width="40" height="10" options="border,text" color="#EE4040"/>
      ...
Attribute type="..." sets "barcode" type and, after some "delimiter" char (":" in our case) we pass the desired barcode type. As You can guess, this type must be one of types supported by TCPDF class. If type omitted, default "C39" is used.
For TCPDF version 5.9.109 following barcode types supported (list is not full, it's just for give You a hint) :
C39, C39+, C39E, C39E+, C93, S25, S25+, I25, I25+, C128, C128A, C128B, C128C, EAN2, EAN5, EAN8, ...

See full supported types list in TCPDF documentation or PHP sources.

Attribute options has a special meaning for barcode field: it must be a comma-delimited string, containg combination of following "words":
WordWhat it does
borderTurns on drawing border around bar code
textTurns on printing textual presentation of user data to be coded (text is printed in the bottom of barcode)
Attributes color, rotate, width, height affect printed barcode by obvious way. Keep in mind that too small width can make "distorted" barcode, "unreadable" by barcode scanners !

Printing QR-codes

When You use field type "qrcode", user data passed in that field will be encoded to QR-code. It is a good idea to pass the same height and width for QR-code, isn't it ? Attributes color, rotation affect printed QR-code. Again, be careful with too small width and height.

Duplication of all data on the page : "repeat" tag

What if you want to have multiple identical blocks of data printed on the page ? Good example for this is business card printing. Of cource, you can create "complex" XML definition that will contain many replicas of the same field set, with changed x- and y- positions. You'll agree that it's not convenient: when you need to add a single field, you will have to make many instances of its definition, every position tuning will mean re-calculating and changing many X and Y coords.

Tag "repeat" was added to avoid this inconvenience : all you need is set two offsets (x and Y) for every instance of data block relative to the "original" definition.

You may guess how it works:
All printing elements, defined in the page (text fields, checkboxes, images, polygons, barcodes, QR-codes) are treated as one data block, so this block will be printed again on the same page, with respective X and Y offsets. You can set as many "repeat" tags for the page as needed.
Below is example of printing business card with using "repeat: feature". This example includes service lines (polygons in corners) that should be used for cutting printed sheet to cards.

Note: If you want to exclude some data fileds from repeating (they must be printed ONCE), just add in its attributes this element:
norepeat="1".
<?xml version="1.0" encoding="UTF-8"?>
<printdef>
  <version modified="2012-11-02">1.0</version>
  <title>Visit card template</title>
  <baseparameters>
    <margins left="0" top="0" right="0" bottom="0" />
    <font name="arial" size="8" />
    <page orientation="P" size="A4" units="mm" />
  </baseparameters>

  <pages>
   <page>
   <template page="1" />
    <field name="corner1" type="poly" posx="10,10,14" posy="14,10,10" color="#AAA" />
    <field name="corner2" type="poly" posx="91,95,95" posy="10,10,14" color="#AAA" />
    <field name="corner3" type="poly" posx="10,10,14" posy="61,65,65" color="#AAA" />
    <field name="corner4" type="poly" posx="91,95,95" posy="65,65,61" color="#AAA" />

    <field name="logo" type="image" posx="12" posy="12" width="26" height="26" src="logo.png" />
    <field name="lastname" posx="45" posy="20" width="35" color="#008" size="14" />
    <field name="firstname" posx="45" posy="28" width="35" size="12"/>
    <field name="middlename" posx="45" posy="35" width="35"  size="12" />
    <field name="duty"       posx="45" posy="42" width="35" size="7"/>
    <field name="phones"     posx="15" posy="52" width="75" align="C" size="7"/>
    <!-- duplicate card on the page -->
    <repeat offset_x="88" offset_y="0" />
    <repeat offset_x="0" offset_y="57" />
    <repeat offset_x="88" offset_y="57" />
    <repeat offset_x="0" offset_y="114" />
    <repeat offset_x="88" offset_y="114" />
    <repeat offset_x="0" offset_y="171" />
    <repeat offset_x="88" offset_y="171" />
    <repeat offset_x="0" offset_y="228" />
    <repeat offset_x="88" offset_y="228" />

   </page>
  </pages>
</printdef>
Save this definition in the XML file (call it, sat, "pdf-card.xml"), and now you can easily create PDF with ready-to-print business card with your personal data:
(We use sample logo file named "logo.png" - change it to your name or make sure you have a file with this name)
$pdfOptions = array('outname' =>'mycard.pdf', 'configfile' => 'pdf-card.xml');
$pdf = new CPrintFormPdf($pdfOptions);
$data = array(
     'lastname'=>'Stivenson'
    ,'firstname'=>'Alex'
    ,'middlename'=>'Jr'
    ,'duty'=>'Senior Sales Manager'
    ,'phones'=>'+1(555)111-2200, 111-2233'
);
$pdf->AddData($data);
$pdf->Render();

Fields printed on all pages

Sometimes we need to print one text, bar-code or image on the same place in every document page (with the same font, size, rotation etc.) Of cource you could insert this <field> definition in all "page" sections. But it would be more convenient to do it once, isn't it ? Here is "allpages" section top help us. <field>. It must be placed inside "root" element of XML configuration file, and should contain standard "field" definitions for every "all pages" field.
Below is example (we want a bar-code at the bottom ao all pages):
<?xml version="1.0" encoding="UTF-8"?>
<printdef>
  <version>1.0</version>
  <title>Testing PDF generation</title>
  <allpages>
    <field name="bar_code01" type="barcode" posx="100" posy="280" width="50" height="5" options="text" value="012345678" />
  </allpages>
  ...
</printdef>
the only difference in field tag is "value" attribute support - we can set desired text (value) for all pages right in XML file. And, you can change this value programmatically by calling method setAllPagesFieldValue($filename, $value), or by passing value with the same field name in "user data", passed in addData(). Remember: value from user data has a priority above "default" value from XML or passed in setAllPagesFieldValue().

And there is a method addAllPagesField($fdef, $value=null), that adds one field definition for "all pages", it is equivalent to one field sction in allpages block of your XML-config file.

Plugin support

Since version 1.1 printform-pdf supports new feature - plugins. There is a new abstract class definition, PfPdfPlugin, that is a skeleton for all plugins that can be connected to class CPrintformPdf.
In CPrintformPdf context plugin performs rendering inside rectangle area, specified by start coordinates and width and height. First you write your own php class file, that extends PfPdfPlugin and implements following methods:

__construct($tcpdfobj, $cfg = null, $x=0, $y=0, $w=0, $h=0) - class constructor, that should receive a TCPDF object reference as a context to output, optional array of configuration parameters ($cfg), and x-position, y-position, width and height of "plot area" (parameters $x,$y,$w,$h respectively).

Render($data) - the main method that will generate output inside plot area. It should receive one parameter, data to be visualised.

To use plugin, you should include it in your program module AFTER printform-pdf.php:
require_once('printform-pdf.php');
require_once('my-plugin.php');
Next, add a "plugin" definition in "page" area of your XML configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<printdef>
  ...
  <pages>
   <page>
      <template page="1" />
      <field name="cityname" posx="143" posy="26" />
      <field name="personname" posx="42" posy="26" />
      <field name="person_firstname" posx="88" posy="26" width="20" />
      <field name="person_birthdate" posx="42" posy="32" width="70" />
      <field name="person_document" posx="143" posy="32" width="55" />
      <plugin name="chart_gantt" type="my_plugin_classname" posx="10"  posy="160" width="180" height="80"
        options="dateformat=d.m,descr_width=0.25,arrow_color=#F22,shade_color=#BBB" />
   </page>
  </pages>
</printdef>
Note then "type" value ("my_plugin_classname" in our example) must be your plugin class name, that extends PfPdfPlugin. CPrintformPDF treats "plugin" item as a special "field" (that's why we place it between ordinary fields definition list) :
it renders it in order of appearance in the list, applies optional "bgcolor" an "rotate" values (so image created by plugin can have desired background color and beeng rotated to some angle).

And finally, somewhere in your code you prepare data to be visualized, and pass it to the CPrintformPdf object by method setPluginData($name, $data), before calling final Render() method.

$name is a name of your plugin "pseudo-field" as it set in the "name" attribute of "plugin" tag.
$data is your data to visualize. Type and structure of this parameter is fully at your choice, as it's you the plugin's author, aren't you ?

CPrintformPdf tries to create new instance of your class, passing to it's constructor a TCPDF object ref,current configuration parameters and position of plot area. Configuration parameters array is constructed from current CPRintformPdf common parameters (including current "stringcharset" value) and options defined in "options" attribute of plugin tag. "options" value must have a form of comma-delimited string, where each item is "optname=value". This options string is parsed to associative array ($options = array('optname =>value,...) ) and passed to the plugin constructor function.

Below is a simple example of plugin class
class PfPdf_Gantt extends PfPdfPlugin {
    private $_config = array();
    private $tcpdf_obj = null;
    private $xpos,$ypos,$width,$height;
    public function __construct($pdfobj, $config=null, $x=0,$y=0,$w=0,$h=0) {
        $this->tcpdf_obj = $pdfobj;
        $this->xpos = $x;
        $this->ypos = $x;
        $this->width = $w;
        $this->height = $h;
        $this->_config = $config;
    }
    public function Render($data) { // just draw a rectangle
        $this->tcpdf_obj->Rect($this->xpos,$this->ypos,$this->width,$this->height,'D');
    }
}

To see a working CPrintformPdf plugin, try to search in this site for "pdf_gantt" class. It draws Gantt charts and can work standalone and as a CPrintformPdf plugin.

Bonus (experimental) functions

AddPageLined($title='',$options=null) creates clean "lined" page (that has horisontal and/or vertical lines) with desired parameters like distance between lines and color.

$title - Optional page title, it is printed on the top.

$options : if passed, must be an associative array:
ElementMeaning
$options['step_y'] vertical step (distance between horizontal lines, alwais in millimeters). If omitted, default 5 mm used.
$options['step_x'] Horizontal step. If omitted, horizontal step will be equal to vertical step. If You want to draw only horizontal lines, you have to pass zero value for step_x element. (Similarly, if you want to draw only vertical lines, pass explicitly zero step_y element)
$options['color'] Setting line color. By default gray used - RGB(180,180,180)


Drawing Lined page example:
$pdf = new PrintFormPdf;
$pdf->AddPageLined('Lined page title',
    array(
        'step_y'=>12
       ,'step_x'=>12
       ,'color'=>'red'
   )
);
$pdf->Render();


AddPageMusicStaff($title='',$options=null) prints clean music staff sheet.
Called without parameters, it will draw a page without title, containing 10 separated "staves" (with black lines), without bar lines.

$title - page title
$options - associative array:
ElementMeaning
$options['merged_staves']"Linked" staves amount. If passed non-zero value, staves will be "merged" by vertical lines, having "merged_staves" in every block.
$options['measures']Measure ("bar" in U.S.) amount in each stave. If passed value greater than 1, staves will have bar lines, making NN measures.
$options['step_roll']Distanse between first line in every stave, mm. Default is 27 mm.
$options['step_line']Distanse between adjacent lines in one stave, mm. Default is 2 mm.
$options['accolade']If set to 1 (or any non-zero value), united staves will have accolades.
$options['color']Color to draw lines. Default is black.


AddPageSudoku($title='', $level=false, $options=null) depending on parameters, draws empty or "filled" Sudoku puzzle page. To generate random puzzle, the class class.Sudoku.php is used. автора Richard Munroe.
$title - Optional page title.
$level - Difficulty level for generated puzzles, must be an integer value in ranhe 1...10. If parameter omitted, no puzzle is generated, and empty sudoku grids will be drawn. Used puzzle generation algorithm sometimes may return empty puzzle, so some puzzle blocks may stay empty, so don't be surprized if that happens.

Optional third parameter, associative array $options can be used for colors tuning:

ElementMeaningDefault value
$options['color_grid']Grid colorBlack - RGB(0,0,0)
$options['color_cell']Printed Digits colorBlack - RGB(0,0,0)

Possible problems

1. Impossible to load template PDF. TCPDF shows warning.
Probably, you're trying to use "packed" PDF file, having unsupported packing (shrinking) algorithm, that is unsupported by classes FPDF / FPDFI. For example, ZIP packed PDF can't be loaded. It's because modules written on PHP cannot "understand" some PDF format features..
Solution: re-save Your template PDF without shrinking.

Change log

1.4.0023 (2014-04-16)
1.3.0020 (2014-02-01)
1.2 (2013-12-10)
1.1.0017 (2013-05-22)
1.1 (2013-04-26)
1.00 (2012-14-11)



Distributed under: BSD License


Copyright © 2012-2013 Alexander Selifonov, www.selifan.ru