set_option("searchpath={" . $searchpath . "}"); $p->set_option("searchpath={" . $fontpath . "}"); /* This means we must check return values of load_font() etc. */ $p->set_option("errorpolicy=return"); /* * Open the input PDF, preserve tags if present (for cloning * PDF/A-1/2/3a and PDF/UA) */ $indoc = $p->open_pdi_document($pdfinputfile, "usetags=true"); if ($indoc == 0) { throw new Exception("Error: " . $p->get_apiname() . ": " . $p->get_errmsg()); } /* * Read PDF/A, PDF/UA and PDF/X version of the input document */ $pdfaversion = $p->pcos_get_string($indoc, "pdfa"); $pdfuaversion = $p->pcos_get_string($indoc, "pdfua"); $pdfxversion = $p->pcos_get_string($indoc, "pdfx"); for ($i = 0; $i < count($supportedflavors); $i++) { if ($pdfaversion == $supportedflavors[$i]) { $optlist .= " pdfa=" . $pdfaversion; break; } } if ($i == count($supportedflavors)) throw new Exception("Error: Cannot clone " . $pdfaversion . " documents"); for ($i = 0; $i < count($supportedflavors); $i++) { if ($pdfuaversion == $supportedflavors[$i]) { $optlist .= " pdfua=" . $pdfuaversion; break; } } if ($i == count($supportedflavors)) throw new Exception("Error: Cannot clone " . $pdfuaversion . " documents"); for ($i = 0; $i < count($supportedflavors); $i++) { if ($pdfxversion == $supportedflavors[$i]) { $optlist .= " pdfx=" . $pdfxversion; break; } } if ($i == count($supportedflavors)) throw new Exception("Error: Cannot clone " . $pdfxversion . " documents"); /* * Read language entry of the input document if present */ if ($p->pcos_get_string($indoc, "type:/Root/Lang") == "string") { $inputlang = $p->pcos_get_string($indoc, "/Root/Lang"); $optlist .= " lang=" . $inputlang; } else if ($pdfuaversion == "PDF/UA-1") { /* PDF/UA documents don't necessarily need the /Lang entry * in the Catalog, but PDFlib requires the "lang" option. * We supply a default language (which may be wrong) to * ensure that such documents can be cloned nevertheless. */ define("DEFAULT_LANGUAGE", "en"); $optlist .= " lang=" . DEFAULT_LANGUAGE; } else $inputlang = ""; /* * Clone XMP metadata of input document if present */ if ($p->pcos_get_string($indoc, "type:/Root/Metadata") == "stream") { $xmp = $p->pcos_get_stream($indoc, "", "/Root/Metadata"); $p->create_pvf("/xmp/document.xmp", $xmp, ""); $optlist .= " metadata={filename=/xmp/document.xmp}"; } /* * Read Tagged status of input document */ $taggedinput = $p->pcos_get_string($indoc, "tagged") == "true"; if ($taggedinput) $optlist .= " tag={tagname=Document}"; /* * Create a new document and clone PDF/A, PDF/UA and PDF/X status */ if ($p->begin_document("", $optlist) == 0) throw new Exception("Error: " . $p->get_apiname() . ": " . $p->get_errmsg()); $p->set_info("Creator", "PDFlib Cookbook"); $p->set_info("Title", $title); /* * Clone PDF/A or PDF/X output intent */ if ($p->process_pdi($indoc, -1, "action=copyoutputintent")== 0){ throw new Exception("Error: " . $p->get_apiname() . ": " . $p->get_errmsg()); } /* Create a bookmark with the name of the input document */ $p->create_bookmark($pdfinputfile, ""); $endpage = (int) $p->pcos_get_number($indoc, "length:pages"); /* Copy all pages of the input document */ for ($pageno = 1; $pageno <= $endpage; $pageno++) { $lowerleftcorner = array( array( "x1", "y1" ), /* 0 degrees */ array( "x2", "y2" ), /* 90 degrees */ array( "x3", "y3" ), /* 180 degrees */ array( "x4", "y4" ), /* 270 degrees */ ); $page = $p->open_pdi_page($indoc, $pageno, "cloneboxes"); if ($page == 0) { throw new Exception("Error opening page: " . $p->get_errmsg()); } /* * Query the geometry of the cloned page. This is required to * account for translated or rotated pages if we want to add * more contents to the page. */ $phi = $p->info_pdi_page($page, "rotate", ""); /* * Select the lower left corner depending on the rotation angle */ $x = $p->info_pdi_page($page, $lowerleftcorner[intval($phi / 90)][0], ""); $y = $p->info_pdi_page($page, $lowerleftcorner[intval($phi / 90)][1], ""); $fittingpossible = true; $additionaltag = ""; if ($taggedinput) { $topleveltagcount = (int) $p->info_pdi_page($page, "topleveltagcount", ""); if ($topleveltagcount == 0) { /* * The page doesn't contain any structure elements, i.e. * it is empty or contains only Artifacts. Some * applications may decide to skip such pages. * * We add an "Artifact" tag to work around an Acrobat * bug. */ $additionaltag = "tag={tagname=Artifact} "; } else if ($p->info_pdi_page($page, "fittingpossible", "") == 0) { /* * Try to place the page without any additional tag; if * this doesn't work we insert another tag. */ $additionaltag = "tag={tagname=P} "; if ($p->info_pdi_page($page, "fittingpossible", $additionaltag) == 0) { $fittingpossible = false; } } } if ($fittingpossible) { /* Page size may be adjusted by "cloneboxes" option */ $p->begin_page_ext(0, 0, "width=a4.width height=a4.height"); $optlist = "cloneboxes "; if ($taggedinput) $optlist .= $additionaltag; $p->fit_pdi_page($page, 0, 0, $optlist); /* * Adjust the coordinate system to facilitate adding new * page content on top of the cloned page. */ $p->translate($x, $y); $p->rotate($phi); $width = $p->info_pdi_page($page, "pagewidth", ""); $height = $p->info_pdi_page($page, "pageheight", ""); /* * Add some text on each page and tag it as Artifact. */ $optlist = "fontname=NotoSerif-Regular " . "textrendering=1 stamp=ll2ur " . "boxsize={" . $width . " " . $height . "}"; if ($taggedinput) $optlist .= " tag={tagname=Artifact}"; $p->fit_textline("Cloned page", 0, 0, $optlist); $p->end_page_ext(""); } else { throw new Exception("Cannot fit page " . $pageno . " of '" . $pdfinputfile . "': " . $p->get_errmsg()); } $p->close_pdi_page($page); } $p->end_document(""); $p->delete_pvf("/xmp/document.xmp"); $p->close_pdi_document($indoc); $buf = $p->get_buffer(); $len = strlen($buf); header("Content-type: application/pdf"); header("Content-Length: $len"); header("Content-Disposition: inline; filename=clone_pdfa.pdf"); print $buf; } catch (PDFlibException $e) { echo("PDFlib exception occurred:\n". "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " . $e->get_errmsg() . "\n"); exit(1); } catch (Throwable $e) { echo("PHP exception occurred: " . $e->getMessage() . "\n"); exit(1); } $p = 0; ?>