fonts/opentype_features_for_cjk
Demonstrate the use of OpenType features for CJK fonts and text.
Download PHP Code Switch to Java Code Show Output
<?php
/*
* Demonstrate OpenType font features for Chinese, Japanese, and Korean text
*
* Demonstrate various CJK OpenType features after checking
* whether a particular feature is supported in a font.
*
* Required software: PDFlib/PDFlib+PDI/PPS 10
* Required data: CJK font with OpenType CJK features
*
* Note that even if a particular OpenType feature is present in the font
* it may not necessarily affect the characters provided in the test strings
* below. In this case you must replace the test strings with content which
* is suited to your font.
*/
/* This is where the data files are. Adjust as necessary. */
$searchpath = dirname(__FILE__,3)."/input";
$outfile = "";
$i; $table; $font;
$llx = 25; $lly = 20; $urx = 825; $ury = 580;
$result;
$testfont = "NotoSerifCJKjp-Regular";
$headers = array( "Description", "Option list",
"Font name", "Raw input (feature disabled)", "Feature enabled" );
class testcase {
function __construct($description, $optlist,
$feature, $text) {
$this->description = $description;
$this->optlist = $optlist;
$this->feature = $feature;
$this->text = $text;
}
}
$testcases = array(
new testcase("Localized forms for simplified Chinese",
"features={locl} script=hang language=ZHS", "locl",
"\u{2E95}\u{2EDD}\u{38C0}"),
new testcase("Localized forms for traditional Chinese",
"features={locl} script=hang language=ZHT", "locl",
"\u{328B}\u{35EB}\u{3B35}"),
new testcase("Localized forms for Korean",
"features={locl} script=hang language=KOR", "locl",
"\u{4E73}\u{52E4}\u{52FB}"),
new testcase("Simplified forms",
"features={smpl}", "smpl",
"\u{6AAF} \u{81FA} \u{98B1}"),
new testcase("Traditional forms",
"features={trad}", "trad",
"\u{53F0}\u{4E03}\u{4E0E}\u{4E31}\u{7D1B}\u{9912}\u{96B8}" .
"\u{9698}\u{966A}\u{939A}"),
new testcase("Expert forms",
"features={expt}", "expt",
"\u{5516}\u{82A6}\u{98F4}\u{9E78}\u{9D60}\u{6F23}\u{84EE}\u{7BDD}"),
new testcase("Full widths",
"features={fwid}", "fwid",
"0123-456(789)=25"),
new testcase("Horizontal kana alternates",
"features={hkna}", "hkna",
"\u{3041}\u{3042}\u{3043}\u{3044} \u{30A1}\u{30A2}\u{30A3}" .
"\u{30A4}\u{30E5}\u{30E4}\u{30B4}\u{30A7}"),
new testcase("Hangul",
"features={hngl}", "hngl",
"\u{4F3D}"),
new testcase("Hojo kanji forms (JIS X 0212-1990)",
"features={hojo}", "hojo",
"\u{6FF9}\u{9B35}\u{8200}\u{9CE6}\u{9B2D}\u{9721}\u{884B}"),
new testcase("Half widths",
"features={hwid}", "hwid",
"0123-456(789)=25"),
new testcase("Italics",
"features={ital}", "ital",
"ABCD abcd 1234"),
new testcase("JIS2004 forms",
"features={jp04}", "jp04",
"\u{9022}\u{98F4}\u{6EA2}\u{8328}\u{9C2F}\u{6DEB}\u{8FC2}"),
new testcase("JIS78 forms",
"features={jp78}", "jp78",
"\u{5516}\u{53F1}\u{63B4}\u{8000}"),
new testcase("JIS83 forms",
"features={jp83}", "jp83",
"\u{4E08}\u{51A4}"),
new testcase("JIS90 forms",
"features={jp90}", "jp90",
"\u{5026}\u{6994}"),
new testcase("Alternate annotation forms",
"features={nalt}", "nalt",
"ABC123\u{002F}\u{30B4}\u{217B}\u{4E0B}\u{7981}\u{2F29}\u{4E2D}\u{2F42}"),
new testcase("NLC kanji forms",
"features={nlck}", "nlck",
"\u{4FA0}\u{64B9}"),
new testcase("Proportional kana",
"features={pkna}", "pkna",
"\u{3041}\u{3042} \u{30A1}\u{30A2} \u{FF66} \u{FF67}"),
new testcase("Proportional widths",
"features={pwid}", "pwid",
"\u{3041}\u{3042} \u{30A1}\u{30A2} \u{301C}\u{FF21}\u{FF23}\u{FF28}" .
"\u{FF29}\u{FF2D} ABCD abcd 1234"),
new testcase("Quarter widths",
"features={qwid}", "qwid",
"0123-456(789)=25"),
new testcase("Ruby notation forms",
"features={ruby}", "ruby",
"\u{3042}\u{304A}\u{307D}\u{30AA}\u{30BC}\u{30F1}\u{25C9}\u{31F0}\u{31FF}"),
new testcase("Traditional name forms",
"features={tnam}", "tnam",
"\u{4E9C}"),
new testcase("Third widths",
"features={twid}", "twid",
"0123-456(789)=25"),
new testcase("Vertical kana alternates",
"vertical features={vkna}", "vkna",
"\u{3041}\u{3042}\u{3043}\u{3044}\u{31FF}\u{31F8}\u{30CB}\u{30BB}"),
// "vrt2" and "vert" are activated automatically in vertical mode
new testcase("Vertical alternates and rotation (vrt2)",
"vertical", "vrt2",
"\u{FF08}ab\u{FF09}\u{FF1A}\u{300C}ab\u{300D}\u{3348}"),
new testcase("Vertical alternates (vert)",
"vertical", "vert",
"\u{FF08}ab\u{FF09}\u{FF1A}\u{300C}ab\u{300D}\u{3348}"),
);
try {
$p = new pdflib();
$p->set_option("searchpath={" . $searchpath . "}");
$p->set_option("charref=true");
$p->set_option("escapesequence=true");
/*
* 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");
/* Set an output path according to the name of the topic */
if ($p->begin_document($outfile, "") == 0) {
throw new Exception("Error: " . $p->get_errmsg());
}
$p->set_info("Creator", "PDFlib Cookbook");
$p->set_info("Title", "opentype_features_for_cjk");
$table = 0;
/* Table header */
for ($i = 0; $i < count($headers); $i++) {
$col = $i + 1;
$optlist =
"fittextline={fontname=NotoSerif-Bold fontsize=12} "
. "margin=4";
$table = $p->add_table_cell($table, $col, 1, $headers[$i], $optlist);
}
/* Create a table with feature samples, one feature per table row */
for ($i = 0; $i < count($testcases); $i += 1) {
$testcase = $testcases[$i];
$row = $i + 2;
$col = 1;
/* Common option list for columns 1-3 */
$optlist =
"fittextline={fontname=NotoSerif-Regular fontsize=12} "
. "margin=4";
/* Column 1: feature description */
$table = $p->add_table_cell($table, $col++, $row,
$testcase->description, $optlist);
/* Column 2: option list */
$table = $p->add_table_cell($table, $col++, $row, $testcase->optlist,
$optlist);
/* Column 3: font name */
$table = $p->add_table_cell($table, $col++, $row, $testfont, $optlist);
/* Column 4: raw input text with feature disabled */
$optlist = "fittextline={fontname={" . $testfont
. "} fontsize=12 } margin=4";
$table = $p->add_table_cell($table, $col++, $row, $testcase->text,
$optlist);
/*
* Column 5: text with enabled feature, or warning if the
* feature is not available in the font
*/
$font = $p->load_font($testfont, "unicode", "");
/* Check whether font contains the required feature table */
$optlist = "name=" . $testcase->feature;
if ($p->info_font($font, "feature", $optlist) == 1) {
/* feature is available: apply it to the text */
$optlist = "margin=4 fittextline={fontname={" . $testfont
. "} fontsize=12 " . $testcase->optlist . "}";
$table = $p->add_table_cell($table, $col++, $row, $testcase->text,
$optlist);
}
else {
/* feature is not available: emit a warning */
$optlist = "fittextline={fontname=NotoSerif-Regular "
. "fontsize=12 fillcolor=red} margin=4";
$table = $p->add_table_cell($table, $col++, $row,
"(feature not available in this font)", $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}} debugshow";
/* 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=opentype_features_for_cjk.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;
?>