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 encoding=unicode} }", "\u{0646}", "U+0646 ARABIC LETTER NOON"), new testcase("NotoNaskhArabic-Regular", "fallbackfonts={ {fontname=NotoSerif-Regular encoding=unicode} }", "\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 encoding=unicode " . "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("stringformat=utf8 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 " . "encoding=unicode 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 " . "encoding=unicode 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 (Exception $e) { echo($e->getMessage()); exit(1); } $p = 0; ?>