PDFlib Cookbook

cookbook

pdfua/inline_tags_in_textflow_pdfua1

Create Tagged PDF with Textflow where the tags are supplied inline in the text.

Download PHP Code  Switch to Java Code  Show Output 

<?php
/*
 * Inline tags in Textflow:
 * Create Tagged PDF with Textflow where the tags are supplied inline in the
 * text.
 *
 * Create multi-column text output which may span multiple pages;
 * The Textflow uses inline option lists with tagging information.
 * The inline tags demonstrate common tagging constructs like headings, links
 * and lists.
 *
 * Required software: PDFlib/PDFlib+PDI/PPS 10
 * Required data: font file
 */


$outfile = "";
$title = "Inline tags in Textflow";
$searchpath = "../input";
$tf = 0;
$llx1= 50; $lly1=50; $urx1=250; $ury1=800;
$llx2=300; $lly2=50; $urx2=500; $ury2=800;
$exitcode = 0;

/* Repeat the dummy text to produce more contents */
$count = 10;

/* Macros for various kinds of begin and end tags using "tagbegin" and "tagend" options */
$macros =
    "macro {" .
            "basefont {fontname=NotoSerif-Regular charref fontsize=11 leading=120%} " .

    "H1 {&basefont fontsize=16 leading=150%  fillcolor=red " .
    "    tagbegin={tagname=H1 Title = {Heading}} } " .
    "/H1 {tagend leading=40% nextparagraph} " .

    "P {&basefont alignment=justify " .
    "     tagbegin={tagname=P} fillcolor=black alignment=justify} " .
    "/P {nextline leading=80% nextparagraph tagend} " .

    "L {tagbegin={tagname=L ListNumbering=Disc} fillcolor=black alignment=justify} " .
    "/L {tagend} " .

    // Here we supply a nested "P" tag as child of "Caption"
    // as they bracket the same content
    "Caption {&basefont tagbegin={tagname=Caption tag={tagname=P}} } " .
    "/Caption {tagend} " .

    "LI {tagbegin={tagname=LI} } " .
    "/LI {tagend} " .

    "Lbl {&basefont tagbegin={tagname=Lbl}} " .
    "/Lbl {tagend} " .

    "LBody {&basefont tagbegin={tagname=LBody} } " .
    "/LBody {tagend} " .

    // Create a named matchbox for links; it will be used to create Link annotations 
    "Link {tagbegin={tagname=Link Title={Kraxi on the Web} Alt={Kraxi on the Web} } " .
    "matchbox={name=kraxi fillcolor=deepskyblue boxheight={capheight descender}} } " .
    "/Link {tagend matchbox=end} " .
    "}";

/* Dummy text for filling the columns. Soft hyphens are marked with the
 * character reference "&shy;" (character references are enabled by the
 * charref option).
 */
$text_P = 
    "<&P>Lorem ipsum dolor sit amet, consectetur adi&shy;pi&shy;sicing elit, " .
    "sed do eius&shy;mod tempor incidi&shy;dunt ut labore et dolore " .
    "magna ali&shy;qua. Ut enim ad minim ve&shy;niam, quis nostrud " .
    "exer&shy;citation ull&shy;amco la&shy;bo&shy;ris nisi ut " .
    "ali&shy;quip ex ea commodo con&shy;sequat. Duis aute irure dolor " .
    "in repre&shy;henderit in voluptate velit esse cillum dolore eu " .
    "fugiat nulla pari&shy;atur. Excep&shy;teur sint occae&shy;cat " .
    "cupi&shy;datat non proident, sunt in culpa qui officia " .
    "dese&shy;runt mollit anim id est laborum.<&/P>";

// Caption text including a tagged Link
// Important: do not combine the &Caption and &P macros in a single option
// list since each list can hold only a single "tagbegin" option
$text_Caption = 
    "<&Caption>Visit our <&Link>Web site<&/Link> " .
    "for more infor&shy;ma&shy;tion about the following products:<&/Caption>\n";

$productlist = array( "Apple", "Orange", "Banana" );

try {
    $p = new PDFlib();

    /*
     * errorpolicy=exception means that the program will stop
     * if one of the API function runs into a problem.
     */
    $p->set_option("errorpolicy=exception searchpath={" . $searchpath . "}");         

    $p->begin_document($outfile,
            "pdfua=PDF/UA-1 lang=en tag={tagname=Document Title={" . $title . "}}");

    $p->set_info("Creator", "PDFlib Cookbook");
    $p->set_info("Title", $title);

    /* Automatically create spaces between chunks of text */
    $p->set_option("autospace=true");

    // Feed macros and general options to the Textflow
    $tf = $p->add_textflow($tf, "", $macros . " inlineoptions minlinecount=2");

    // Create some chapters
    for ($i=1; $i<=$count; $i++)
    {
        // Tagged heading
        $tf = $p->add_textflow($tf, "<&H1>Chapter " . $i . "<&/H1>\n", "");

        // Tagged paragraph text with inline tags
        $tf = $p->add_textflow($tf, $text_P, "");

        // Start a tagged list
        $tf = $p->add_textflow($tf, "", "&L");

        // The list Caption contains a tagged Link element
        $tf = $p->add_textflow($tf, $text_Caption, "");

        // List items
        for ($item=0; $item < count($productlist); $item++)
        {
            $tf = $p->add_textflow($tf, "", "&LI");
            $tf = $p->add_textflow($tf, "<&Lbl>&#x2022; <&/Lbl>", ""); 
            $tf = $p->add_textflow($tf, "<&LBody>" . $productlist[$item] . "<&/LBody>\n", "");
            $tf = $p->add_textflow($tf, "", "&/LI");
        }

        $tf = $p->add_textflow($tf, "", "&/L");
    }

    // Action for use in Web links
    $act = $p->create_action("URI", "url={http://www.kraxi.com}");

    /* Loop until all of the text is placed; create new pages
     * as long as more text needs to be placed. Two columns will
     * be created on all pages.
     */
    do
    {
        $optlist = "verticalalign=justify linespreadlimit=120% ";

        $p->begin_page_ext(0, 0, "width=a4.width height=a4.height");

        /* Fill the first column */
        $result = $p->fit_textflow($tf, $llx1, $lly1, $urx1, $ury1, $optlist);

        /* Fill the second column if we have more text*/
        if ($result != "_stop")
            $result = $p->fit_textflow($tf, $llx2, $lly2, $urx2, $ury2, $optlist);

        /* Create Link annotations on all matchboxes named "kraxi"
            * (if present on the page, otherwise the call doesn't have any effect)
            */
        $p->create_annotation(0, 0, 0, 0, "Link",
                "action={activate " . $act . "} linewidth=0 " .
                "usematchbox={kraxi} contents={Link to Kraxi Web site}");

        $p->end_page_ext("");

        /* "_boxfull" means we must continue because there is more text;
         * "_nextpage" is interpreted as "start new column"
         */
    } while ($result == "_boxfull" || $result == "_nextpage");

    /* Check for errors */
    if ($result != "_stop")
    {
        /* "_boxempty" happens if the box is very small and doesn't
         * hold any text at all.
         */
        if ($result ==  "_boxempty")
            throw new Exception ("Error: Textflow box too small");
        else
        {
            /* Any other return value is a user exit caused by
             * the "return" option; this requires dedicated code to
             * deal with.
             */
            throw new Exception ("User return '" . $result .
                    "' found in Textflow");
        }
    }

    $p->delete_textflow($tf);

    $p->end_document("");
    $buf = $p->get_buffer();
    $len = strlen($buf);

    header("Content-type: application/pdf");
    header("Content-Length: $len");
    header("Content-Disposition: inline; filename=inline_tags_in_textflow_pdfua1.pdf");
    print $buf;
}
catch (PDFlibException $e) {
    print("PDFlib exception occurred:\n" .
        "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
        $e->get_errmsg() . "\n");
    exit(1);
}
catch (Exception $e) {
    print($e);
    exit(1);
}

$p = 0;

?>