name = $name; $this->price = $price; } }; class addressdata_s { function __construct($firstname, $lastname, $flat, $street, $city) { $this->firstname = $firstname; $this->lastname = $lastname; $this->flat = $flat; $this->street = $street; $this->city = $city; } }; $seed = 0x1234; define('MAXRECORD', 100); $stationeryfilename = "stationery_pdfx4p.pdf"; $salesrepfilename = "sales_rep%d.jpg"; $fontname = "NotoSerif-Regular"; // This is where font/image/PDF input files live. Adjust as necessary. $searchpath = dirname(__FILE__,3)."/input"; /* By default annotations are also imported. In some cases this * requires the Noto fonts for creating annotation appearance streams. * We therefore set the searchpath to also point to the font directory. */ $fontpath = dirname(__FILE__,3)."/resource/font"; $title = "Create PDF/VT-1 with Blocks"; $outfile = "pdfvt1_with_blocks.pdf"; $left = 55; $right = 530; $bottom = 822; $fontsize = 11; $leading = $fontsize + 2; $closingtext = "Terms of payment: 30 days net. " . "90 days warranty starting at the day of sale. " . "This warranty covers defects in workmanship only. " . "Kraxi Systems, Inc. will, at its option, repair or replace the " . "product under the warranty. This warranty is not transferable. " . "No returns or exchanges will be accepted for wet products."; $articledata = array( new articledata_s("Super Kite", 20), new articledata_s("Turbo Flyer", 40), new articledata_s("Giga Trash", 180), new articledata_s("Bare Bone Kit", 50), new articledata_s("Nitty Gritty", 20), new articledata_s("Pretty Dark Flyer", 75), new articledata_s("Large Hadron Glider", 85), new articledata_s("Flying Bat", 25), new articledata_s("Simple Dimple", 40), new articledata_s("Mega Sail", 95), new articledata_s("Tiny Tin", 25), new articledata_s("Monster Duck", 275), new articledata_s("Free Gift", 0) ); $addressdata = array( new addressdata_s("Edith", "Poulard", "Suite C", "Main Street", "New York"), new addressdata_s("Max", "Huber", "", "Lipton Avenue", "Albuquerque"), new addressdata_s("Herbert", "Pakard", "App. 29", "Easel", "Duckberg"), new addressdata_s("Charles", "Fever", "Office 3", "Scenic Drive", "Los Angeles"), new addressdata_s("D.", "Milliband", "", "Old Harbour", "Westland"), new addressdata_s("Lizzy", "Tin", "Workshop", "Ford", "Detroit"), new addressdata_s("Patrick", "Black", "Backside", "Woolworth Street", "Clover") ); $salesrepnames = array( "Charles Ragner", "Hugo Baldwin", "Katie Blomock", "Ernie Bastel", "Lucy Irwin", "Bob Montagnier", "Chuck Hope", "Pierre Richard" ); $headers = array( "ITEM", "DESCRIPTION", "QUANTITY", "PRICE", "AMOUNT" ); $alignments = array( "right", "left", "right", "right", "right" ); /** * Simulate a datamatrix barcode */ define('MATRIXROWS', 32); $MATRIXDATASIZE = (4*MATRIXROWS); function create_datamatrix($record) { $datastring = ""; for ($i=0; $ibegin_document("", "pdfx=PDF/X-4 pdfvt=PDF/VT-1 usestransparency=false " . "nodenamelist={root recipient} recordlevel=1") == 0) { echo("Error: " . $p->get_errmsg()); exit(1); } /* * Set errorpolicy to return, this means we must check return values * of load_font() etc. Set the search path for fonts and images etc. */ $p->set_option("errorpolicy=return SearchPath={" . $searchpath . "}"); $p->set_option("SearchPath={" . $fontpath . "}"); $p->set_info("Creator", "PDFlib Cookbook"); $p->set_info("Title", $title); $fontoptions = "fontname=" . $fontname . " fontsize=" . $fontsize; // Define output intent profile */ if ($p->load_iccprofile("ISOcoated_v2_eci.icc", "usage=outputintent") == 0) { printf("Error: %s\n", $p->get_errmsg()); echo("See www.pdflib.com for ICC profiles.\n"); exit(1); } /* * Load company stationery as background (used on first page for * each recipient) */ $stationery = $p->open_pdi_document($stationeryfilename, ""); if ($stationery == 0) { throw new Exception("Error: " . $p->get_errmsg()); } $page = $p->open_pdi_page($stationery, 1, "pdfvt={scope=global environment={Kraxi Systems}}"); if ($page == 0) { throw new Exception("Error: " . $p->get_errmsg()); } /* * Preload images of all local sales reps (used on first page * for each recipient). To get encapsulated image XObjects, the * renderingintent option is used. */ for ($i = 0; $i < count($salesrepnames); $i++) { $buf = sprintf($salesrepfilename, $i); $salesrepimage[$i] = $p->load_image("auto", $buf, "pdfvt={scope=file} renderingintent=Perceptual"); if ($salesrepimage[$i] == 0) { echo("Error: " . $p->get_errmsg()); exit(1); } } /* * Construct DPM metadata for the DPart root node */ $cip4_metadata = $p->poca_new("containertype=dict usage=dpm"); $p->poca_insert($cip4_metadata, "type=string key=CIP4_Conformance value=base"); $p->poca_insert($cip4_metadata, "type=string key=CIP4_Creator value=pdfvt1_with_blocks"); $p->poca_insert($cip4_metadata, "type=string key=CIP4_JobID value={Kraxi Systems invoice}"); $optlist = sprintf("containertype=dict usage=dpm " . "type=dict key=CIP4_Metadata value=%d", $cip4_metadata); $cip4_root = $p->poca_new($optlist); $optlist = sprintf("containertype=dict usage=dpm " . "type=dict key=CIP4_Root value=%d", $cip4_root); $dpm = $p->poca_new($optlist); // Create root node in the DPart hierarchy and add DPM metadata */ $optlist = sprintf("dpm=%d", $dpm); $p->begin_dpart($optlist); $p->poca_delete($dpm, "recursive=true"); for ($record = 0; $record < MAXRECORD; $record++) { $pagecount = 0; $firstname = $addressdata[get_random(count($addressdata))]->firstname; $lastname = $addressdata[get_random(count($addressdata))]->lastname; // ----------------------------------- // Construct DPM metadata for the next DPart node (i.e. the page) // ----------------------------------- $dpm = $p->poca_new("containertype=dict usage=dpm"); $cip4_root = $p->poca_new("containertype=dict usage=dpm"); $cip4_recipient = $p->poca_new("containertype=dict usage=dpm"); $cip4_contact = $p->poca_new("containertype=dict usage=dpm"); $cip4_person = $p->poca_new("containertype=dict usage=dpm"); $optlist = sprintf("type=dict key=CIP4_Root value=%d", $cip4_root); $p->poca_insert($dpm, $optlist); $optlist = sprintf("type=dict key=CIP4_Recipient value=%d", $cip4_recipient); $p->poca_insert($cip4_root, $optlist); $optlist = sprintf("type=string key=CIP4_UniqueID value={ID_%d}", $record); $p->poca_insert($cip4_recipient, $optlist); $optlist = sprintf("type=dict key=CIP4_Contact value=%d", $cip4_contact); $p->poca_insert($cip4_recipient, $optlist); $optlist = sprintf("type=dict key=CIP4_Person value=%d", $cip4_person); $p->poca_insert($cip4_contact, $optlist); $optlist = sprintf("type=string key=CIP4_Firstname value={%s}", $firstname); $p->poca_insert($cip4_person, $optlist); $optlist = sprintf("type=string key=CIP4_Lastname value={%s}", $lastname); $p->poca_insert($cip4_person, $optlist); /* * Create a new node in the document part hierarchy and add DPM * metadata */ $optlist = "dpm=" . $dpm; $p->begin_dpart($optlist); $p->poca_delete($dpm, "recursive=true"); /* * Create and place table with article list */ // ----------------------------------- // Create and place table with article list // ----------------------------------- // // ---------- Header row $row = 1; $tbl = 0; for ($col = 1; $col <= count($headers); $col++) { $optlist = sprintf( "fittextline={position={%s center} %s} margin=2", $alignments[$col-1], $fontoptions); $tbl = $p->add_table_cell($tbl, $col, $row, $headers[$col-1], $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } } $row++; // ---------- Data rows: one for each article $total = 0; // ----------------------------------- // Print variable-length article list // ----------------------------------- for ($i = 0, $item = 0; $i < count($articledata); $i++) { $quantity = get_random(9) + 1; if ($item > 0 && get_random(100) > 50) continue; $col = 1; $item++; $sum = $articledata[$i]->price * $quantity; // column 1: ITEM $buf = sprintf("%d", $item); $optlist = sprintf( "fittextline={position={%s center} %s} colwidth=5%% margin=2", $alignments[$col-1], $fontoptions); $tbl = $p->add_table_cell($tbl, $col++, $row, $buf, $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } // column 2: DESCRIPTION $optlist = sprintf( "fittextline={position={%s center} %s} colwidth=50%% " . "margin=2", $alignments[$col-1], $fontoptions); $tbl = $p->add_table_cell($tbl, $col++, $row, $articledata[$i]->name, $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } // column 3: QUANTITY $buf = sprintf("%d", $quantity); $optlist = sprintf( "fittextline={position={%s center} %s} margin=2", $alignments[$col-1], $fontoptions); $tbl = $p->add_table_cell($tbl, $col++, $row, $buf, $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } // column 4: PRICE $buf = number_format($articledata[$i]->price, 2, ".", ","); $optlist = sprintf( "fittextline={position={%s center} %s} margin=2", $alignments[$col-1], $fontoptions); $tbl = $p->add_table_cell($tbl, $col++, $row, $buf, $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } // column 5: AMOUNT $buf = number_format($sum, 2, ".", ","); $optlist = sprintf( "fittextline={position={%s center} %s} margin=2", $alignments[$col-1], $fontoptions); $tbl = $p->add_table_cell($tbl, $col++, $row, $buf, $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } $total += $sum; $row++; } // ---------- Print total in the rightmost column $buf = number_format($total, 2, ".", ","); $optlist = sprintf( "fittextline={position={%s center} %s} margin=2", $alignments[count($alignments) - 1], $fontoptions); $tbl = $p->add_table_cell($tbl, count($headers), $row++, $buf, $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } // ---------- Footer row with terms of payment $optlist = sprintf("%s alignment=justify leading=120%%", $fontoptions); $tf = $p->create_textflow($closingtext, $optlist); if ($tf == 0) { throw new Exception("Error: " . $p->get_errmsg()); } $optlist = sprintf( "rowheight=1 margin=2 margintop=%f textflow=%d colspan=%d", 2*$fontsize, $tf, count($headers)); $tbl = $p->add_table_cell($tbl, 1, $row++, "", $optlist); if ($tbl == 0) { throw new Exception("Error: " . $p->get_errmsg()); } /* Place the table instance(s), creating pages as required */ do { $p->begin_page_ext(0, 0, "topdown=true width=a4.width height=a4.height"); if (++$pagecount == 1) { /* * Place company stationery as background on first page * for each recipient */ $p->fit_pdi_page($page, 0, 842, ""); /* * Fill Blocks with name and image of local sales rep on * first page for each recipient */ $optlist = ""; $buf = "Local sales rep:\n" . $salesrepnames[$record % count($salesrepnames)]; if ($p->fill_textblock($page, "salesrepname", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); if ($p->fill_imageblock($page, "salesrepimage", $salesrepimage[$record % count($salesrepnames)], "") == 0) print("Warning: " . $p->get_errmsg()); /* * Fill Text Blocks with recipient's address */ $optlist = ""; $buf = $firstname . " " . $lastname; if ($p->fill_textblock($page, "name", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); $buf = $addressdata[get_random(count($addressdata))]->flat; if ($p->fill_textblock($page, "flat", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); $buf = sprintf("%d %s", get_random(999), $addressdata[get_random(count($addressdata))]->street); if ($p->fill_textblock($page, "street", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); $buf = sprintf("%05d %s", get_random(99999), $addressdata[get_random(count($addressdata))]->city); if ($p->fill_textblock($page, "city", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); /* * Fill image Block with barcode image for each * recipient. To get encapsulated image XObjects the * renderingintent option is used. */ $datamatrix = create_datamatrix($record); $p->create_pvf("barcode", $datamatrix, ""); $barcodeimage = $p->load_image("raw", "barcode", "bpc=1 components=1 width=32 height=32 invert " . "pdfvt={scope=singleuse} " . "renderingintent=Saturation"); if ($barcodeimage == 0) { throw new Exception("Error: " . $p->get_errmsg()); } if ($p->fill_imageblock($page, "barcode", $barcodeimage, "") == 0) print("Warning: " . $p->get_errmsg()); $p->close_image($barcodeimage); $p->delete_pvf("barcode"); /* * Fill Text Blocks with header and date */ date_default_timezone_set('Europe/Berlin'); $optlist = ""; $buf = sprintf("INVOICE %d-%d", date("Y"), $record+1); if ($p->fill_textblock($page, "invoice_number", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); $buf = date("F j, Y"); if ($p->fill_textblock($page, "date", $buf, $optlist) == 0) print("Warning: " . $p->get_errmsg()); /* * Retrieve y coordinate of the lowest Block * "invoice_number" so that we know where subsequent * data can be placed. */ $top = $p->pcos_get_number($stationery, "pages[0]/blocks/invoice_number/Rect[1]"); // adjust for topdown coordinate system $top = 842 - $top + 2 * $leading; } else { $top = 50; } /* * Place the table on the page. Shade every other row, * except the footer row. */ $result = $p->fit_table($tbl, $left, $bottom, $right, $top, "header=1 " . "fill={{area=rowodd fillcolor={gray 0.9}} " . "{area=rowlast fillcolor={gray 1}}} " . "rowheightdefault=auto colwidthdefault=auto"); if ($result == "_error") { throw new Exception( "Couldn't place table: " . $p->get_errmsg()); } $p->end_page_ext(""); } while ($result == "_boxfull"); $p->delete_table($tbl, ""); /* Close node in the document part hierarchy */ $p->end_dpart(""); } $p->close_pdi_page($page); $p->close_pdi_document($stationery); for ($i = 0; $i < count($salesrepimage); $i++) { $p->close_image($salesrepimage[$i]); } /* Close root node in the document part hierarchy */ $p->end_dpart(""); $p->end_document(""); $buf = $p->get_buffer(); $len = strlen($buf); header("Content-type: application/pdf"); header("Content-Length: $len"); header("Content-Disposition: inline; filename=" . $outfile); print $buf; } catch (PDFlibException $e) { echo("PDFlib exception occurred in pdfvt1_with_blocks sample:\n" . "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " . $e->get_errmsg() . "\n"); exit(1); } catch (Throwable $e) { echo($e); exit(1); } $p = 0; /** * Get a pseudo random number between 0 and n-1 */ function get_random($n) { global $seed; $seed = ($seed *0xDEECE66D + 11) & 0x7FFFFFFF; return ($seed % $n); } ?>