fonts/glyph_availability
Check the availability of glyphs in a font.
Download PHP Code Switch to Java Code Show Output
<?php
/*
*
* Glyph availability:
* Check the availability of glyphs in a font
*
* Load a font with "encoding=unicode" (default). Then, for a specific Unicode
* character, output a row in a table containing the following information:
*
* 1) Font name
* 2) Unicode codepoint and character name
* 3) Glyph if available in the font
* 4) Glyph name if available in the font
*
* Required software: PDFlib/PDFlib+PDI/PPS 10
* Required data: Font files
*/
/* This is where the data files are. Adjust as necessary. */
$searchpath = dirname(__FILE__,3)."/input";
$title = "Glyph Availability";
class testcase {
function __construct($font_name, $font_optlist, $character, $character_desc) {
$this->font_name = $font_name;
$this->font_optlist = $font_optlist;
$this->character = $character;
$this->character_desc = $character_desc;
}
}
$headers = array( "Font name", "Unicode character", "Glyph", "Glyph name");
$testcases = array(
new testcase("NotoSerif-Regular", "", "a", "U+0061 LATIN LETTER A"),
new testcase("NotoSerif-Regular", "", "\u{20AC}", "U+20AC EURO SIGN"),
new testcase("NotoSerif-Regular", "", "\u{017A}", "U+017A LATIN SMALL LETTER Z WITH ACUTE"),
new testcase("NotoSerif-Regular", "", "\u{2D33}", "U+2D33 TIFINAGH LETTER YAG"),
new testcase("NotoNaskhArabic-Regular", "fallbackfonts={ {fontname=NotoSerif-Regular} }",
"\u{0646}", "U+0646 ARABIC LETTER NOON"),
new testcase("NotoNaskhArabic-Regular", "fallbackfonts={ {fontname=NotoSerif-Regular} }",
"\u{017A}", "U+017A LATIN SMALL LETTER Z WITH ACUTE"),
/*
* Demonstration of Unicode characters beyond U+FFFF. The Unicode
* character U+2000B (surrogate representation \uD840\DC0B) is
* checked using a CJK font. The surrogates are resolved
* by the Java compiler.
* Languages which don't support surrogates or backslash syntax for
* characters outside the BMP must use PDFlib character references
* instead, e.g. 𠀋
*/
new testcase("NotoSerifCJKjp-Regular", "", "\u{2000B}",
"U+2000B CJK UNIFIED IDEOGRAPH"),
);
/*
* Output one row with information regarding one specific character
*/
function put_row($p, $table, $row, $font, $t) {
$col = 1;
/*
* Common option list for all columns except the "Actual glyph" column
*/
$common_optlist = "fittextline={fontname=NotoSerif-Regular "
. "fontsize=12} margin=4";
/*
* Column 1: Font name
*/
$table = $p->add_table_cell($table, $col++, $row, $t->font_name,
$common_optlist);
/*
* Column 2: Unicode character
*/
$table = $p->add_table_cell($table, $col++, $row, $t->character_desc, $common_optlist);
/* The data type "Unichar" in option list expects character references
* without the &...; decoration, while the decoration is required in
* text output functions.
* We don't use charrefs in the examples, but if you need them and
* want to pass them e.g. to info_font() you can resolve charrefs
* as follows:
*
* $t_plain = $p->convert_to_unicode("utf8",
* $t->character, "outputformat=utf8 charref=true");
*
* Conversion from UTF-8 to UTF-8 may look a bit silly, but we use
* the convert_to_unicode() method to resolve character references.
* The result can be used in both option lists and text output functions.
* This is only required if character references are used in the text.
*/
/*
* Determine whether a glyph is available, and if so, determine
* the glyph name, if available.
*/
$gid = (int) $p->info_font($font, "glyphid", "unicode=" . $t->character);
if ($gid != -1) {
$display_character = $t->character;
$gn_idx = (int) $p->info_font($font, "glyphname", "unicode=" . $t->character);
if ($gn_idx != -1) {
$gn = $p->get_string($gn_idx, "");
}
else {
$gn = "n/a";
}
}
else {
$display_character = "n/a";
$gn = "n/a";
}
/*
* Column 3: Actual glyph, if available
*/
$testfont_optlist = "fittextline={font=" . $font . " fontsize=12} margin=4";
$table = $p->add_table_cell($table, $col++, $row, $display_character,
$testfont_optlist);
/*
* Column 4: Glyph name
*/
$table = $p->add_table_cell($table, $col++, $row, $gn, $common_optlist);
return $table;
}
try {
$llx = 50; $lly = 50; $urx = 800; $ury = 550;
$p = new PDFlib();
$p->set_option("searchpath={" . $searchpath . "}");
/*
* This means that formatting and other errors will raise an
* exception. This simplifies our sample code, but is not
* recommended for production code.
*/
$p->set_option("errorpolicy=exception");
$p->set_option("charref=true");
if ($p->begin_document("", "") == 0)
throw new Exception("Error: " . $p->get_errmsg());
$p->set_info("Creator", "PDFlib Cookbook");
$p->set_info("Title", $title);
$table = 0;
/* Table header */
$optlist = "fittextline={fontname=NotoSerif-Bold "
. "fontsize=12} margin=4";
for ($i = 0; $i < count($headers); $i++) {
$table = $p->add_table_cell($table, $i + 1, 1, $headers[$i], $optlist);
}
/* Create a table with feature samples, one feature per table row */
for ($i = 0; $i < count($testcases); $i++) {
$testcase = $testcases[$i];
$row = $i + 2;
/*
* Try to load the fonts, output a row that shows the missing
* font if a font can't be loaded.
*/
$error_optlist = "fittextline={fontname=NotoSerif-Regular "
. "fontsize=12 fillcolor=red} "
. "margin=4";
$font_optlist = $testcase->font_optlist . " errorpolicy=return";
$font = $p->load_font($testcase->font_name, "unicode", $font_optlist);
if ($font != 0) {
$table = put_row($p, $table, $row, $font, $testcase);
}
else {
$table = $p->add_table_cell($table, 1, $row,
$testcase->font_name . ": font not available",
$error_optlist);
}
}
/*
* 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.height height=a4.width");
$optlist = "header=1 fill={{area=rowodd fillcolor={gray 0.9}}} "
. "stroke={{line=other}} ";
/* Place the table instance */
$result = $p->fit_table($table, $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");
$p->end_document("");
$buf = $p->get_buffer();
$len = strlen($buf);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=glyph_availability.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;
?>