PDFlib Cookbook

cookbook

fonts/font_lister

Create a list of all fonts available in the 'searchpath' directories.

Download PHP Code  Switch to Java Code  Show Output 

<?php
/* This is where the data files are. Adjust as necessary. */
/*
 * Font lister:
 * Create a list of all fonts available in the "searchpath" directories.
 * 
 * Also create a UPR file which can be used for PDFlib font configuration.
 * 
 * Required software: PDFlib/PDFlib+PDI/PPS 10
 * Required data: font file
 */

$title = "Font Lister";
$searchpath = dirname(__FILE__,3)."/input";
$fontdirectories = array();
$searchpathdirectory = array();
$fonts = array();

/* Typical font directories on Linux systems */
$fontdirectories[] = "/usr/share/fonts/";
$fontdirectories[] = "/usr/share/fonts/truetype/";
$fontdirectories[] = "/usr/share/fonts/opentype/";
$fontdirectories[] = "/usr/local/share/fonts/";
$fontdirectories[] = "/usr/local/share/fonts/truetype/";
$fontdirectories[] = "/usr/local/share/fonts/opentype/";

/* Typical font directory on macOS */
$fontdirectories[] = "/Library/Fonts/";

/* Typical font directory on Windows */
$fontdirectories[] = "C:\\Windows\\Fonts";

$fontresource = 0;
$count=0;
$row=1;
$tbl = 0;
$llx = 50; $lly = 50; $urx = 550; $ury = 800;
$text = "The quick brown fox jumps over the lazy dog";
$headeropt = 
    "fittextline {fontname {NotoSerif-Bold} fontsize=10 }";
$exitcode = 0;

try {
    $p = new PDFlib();

    $p->set_option("errorpolicy=exception");

    /* Get all subdirectories from input paths */
    for($i=0; $i< count($fontdirectories); $i++){
        $searchpathdirectory[] = $fontdirectories[$i];
        $dirs = array_filter(glob($fontdirectories[$i]), 'is_dir');
        foreach ($dirs as $dir){
            $searchpathdirectory[] = $dir;
        }
    }
            
    /* Add font directories to the search path */
    for ($i=0; $i < count($searchpathdirectory); $i++) {
        $p->set_option("searchpath={{" . $searchpathdirectory[$i] . "}}");
    }
    
    /* enumerate all fonts on the searchpath and create a UPR file */
    $p->set_option("enumeratefonts saveresources={filename={font_lister_pdflib.upr}}");

    /* Retrieve the names of all enumerated fonts */
    do{
        $fontresource = $p->get_option("FontOutline", "resourcenumber=" . ++$count);
        if ($fontresource == -1) { 
            break;
        }
        $resourceentry = $p->get_string($fontresource, "");
        $fonts[] = explode(" = " , $resourceentry)[0];
    } while ($fontresource != -1);

    /* create output document */
    $p->begin_document("", "");

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

    /* Add the Cookbook input directory which is required for the
     * NotoSerif-Bold font used in the table.
     */
    $p->set_option("searchpath={../input}");

    /* create table header */
    $tbl = $p->add_table_cell($tbl, 1, 1, "Fontname", 
        "colwidth=150 margin=3 " . $headeropt);
    $tbl = $p->add_table_cell($tbl, 2, 1, "Sample text", 
        "colwidth=350 margin=3 " . $headeropt);

    if (!empty($fonts)){
        for ($idx=0; $idx< count($fonts); $idx++){
            $sampletext = "";
            $font = $p->load_font($fonts[$idx], "unicode", " errorpolicy=return");
            if ($font == 0){
                /* Emit a warning if the font couldn't be loaded */
                error_log("'" . $fonts[$idx] . 
                    "'' skipped. load_font() failed: [" . $p->get_errnum() . 
                    "] " . $p->get_errmsg());
                continue;
            }
            $row++;
            $tbl = $p->add_table_cell($tbl, 1, $row, $fonts[$idx], 
                "fittextline {fontname {NotoSerif-Regular} " .
                "fontsize=10 position {left top}} margin=3");

            /* Emit sample text for text fonts. If we have a symbol
             * font or a font which contains only very few glyphs
             * we emit the first available glyphs.
             */

            if ($p->info_font($font, "symbolfont", "") == 1  || 
                $p->info_textline($text, "unknownchars", 
                    "font=" . $font . " fontsize=10") >10){
                /* Retrieve Unicode values for the first few glyphs and 
                 * build a sample text string.
                 */

                for ($i = 1; $i <= 20; $i++){
                    $uv = $p->info_font($font, "unicode", "glyphid=" . $i);
                    $sampletext .=  "&#" . intval($uv) . ";";
                }
            }else{
                $sampletext = $text;
            }
            $tf = $p->add_textflow(0, $sampletext, "font=" . $font . 
                " fontsize=12 charref");
            $tbl = $p->add_table_cell($tbl, 2, $row, "", "margin=3 textflow=" . $tf);
        } 
    } else {
        $tbl = $p->add_table_cell($tbl, 1, 2, "No fonts have been found.",
            "fittextline {fontname {NotoSerif-Regular} " .
            "fontsize=10 position {left top}} margin=3 colspan=2");
    }
    /* ---------- Place the table on one or more pages ---------- */

    /*
     * Loop until all of the table is placed; create new pages as long
     * as more table instances need to be placed.
     */
    do {
        $p->begin_page_ext(0, 0, "width=a4.width height=a4.height");

        /*
         * Shade every other row; draw lines for all table cells. Add
         * "showcells showborder" to visualize cell borders
         */
        $optlist = "header=1 rowheightdefault=auto "
            . "fill={{area=rowodd fillcolor={gray 0.9}}} "
            . "stroke={{line=other}} ";

        /* Place the table instance */
        $result = $p->fit_table($tbl, $llx, $lly, $urx, $ury, $optlist);

        if ($result == "_error")
            throw new Exception("Couldn't place table : "
                . $p->get_errmsg());

        $p->end_page_ext("");

    }
    while ($result == "_boxfull");

    /* Check the result; "_stop" means all is ok. */
    if ($result != "_stop") {
        if ($result == "_error") {
            throw new Exception("Error when placing table: "
                . $p->get_errmsg());
        }
        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 found in table");
        }
    }

    /* This will also delete Textflow handles used in the table */
    $p->delete_table($tbl, "");

    $p->end_document("");

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

    header("Content-type: application/pdf");
    header("Content-Length: $len");
    header("Content-Disposition: inline; filename=font_lister.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;

?>