complex_scripts/starter_shaping
Demonstrate text shaping for Arabic, Hebrew, Hindi and Sanskrit scripts. Right-to-left text is reordered according to the Bidi algorithm.
Download PHP Code Switch to Java Code Show Output
<?php
/*
* Starter sample for text shaping features
* Demonstrate text shaping for Arabic, Hebrew and Devanagari scripts
* Right-to-left text is reordered according to the Bidi algorithm.
*
* Required software: PDFlib/PDFlib+PDI/PPS 10
* Required data: suitable fonts for the scripts
*/
/* This is where the data files are. Adjust as necessary. */
$searchpath = dirname(__FILE__,3)."/input";
$outfile = "";
$llx = 25; $lly = 50; $urx = 825; $ury = 550;
$header = array(
"Language", "Raw input", "Reordered and shaped output"
);
$MAXCOL = count($header);
class shaping {
public function __construct($fontopt, $optlist, $textflow, $language, $text) {
$this->fontopt = $fontopt;
$this->optlist = $optlist;
$this->textflow = $textflow;
$this->language = $language;
$this->text = $text;
}
public $fontopt; /* fontname and other font options */
public $optlist; /* text options */
public $textflow; /* can't use Textflow for Bidi text */
public $language; /* language name */
public $text; /* sample text */
}
$shapingsamples = array(
/* Dummys to compensate for header row and +/-1 indexing in C */
new shaping( "", "", 0, "", "" /* dummy1 */ ),
new shaping( "", "", 0, "", "" /* dummy2 */ ),
/* -------------------------- Arabic -------------------------- */
new shaping( "fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=arab", 0, "Arabic",
"\u{0627}\u{0644}\u{0639}\u{064E}\u{0631}\u{064E}\u{0628}\u{0650}" .
"\u{064A}\u{0629}" ),
new shaping( "fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=arab", 0, "Arabic",
"\u{0645}\u{0631}\u{062D}\u{0628}\u{0627}! (Hello)"),
new shaping(
"fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=arab", 0, "Arabic",
"\u{FEFF}\u{0627}\u{0644}\u{0645}\u{0627}\u{062F}\u{0629}\u{0020}" .
"\u{0031}\u{0020}\u{064A}\u{0648}\u{0644}\u{062F}\u{0020}\u{062C}" .
"\u{0645}\u{064A}\u{0639}\u{0020}\u{0627}\u{0644}\u{0646}\u{0627}" .
"\u{0633}\u{0020}\u{0623}\u{062D}\u{0631}\u{0627}\u{0631}\u{064B}" .
"\u{0627}\u{0020}\u{0645}\u{062A}\u{0633}\u{0627}\u{0648}\u{064A}" .
"\u{0646}\u{0020}\u{0641}\u{064A}\u{0020}\u{0627}\u{0644}\u{0643}" .
"\u{0631}\u{0627}\u{0645}\u{0629}\u{0020}\u{0648}\u{0627}\u{0644}" .
"\u{062D}\u{0642}\u{0648}\u{0642}\u{002E}\u{0020}"),
new shaping(
"fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=arab", 0, "Arabic",
"\u{0648}\u{0642}\u{062F}\u{0020}\u{0648}\u{0647}\u{0628}\u{0648}" .
"\u{0627}\u{0020}\u{0639}\u{0642}\u{0644}\u{0627}\u{064B}\u{0020}" .
"\u{0648}\u{0636}\u{0645}\u{064A}\u{0631}\u{064B}\u{0627}\u{0020}" .
"\u{0648}\u{0639}\u{0644}\u{064A}\u{0647}\u{0645}\u{0020}\u{0623}" .
"\u{0646}\u{0020}\u{064A}\u{0639}\u{0627}\u{0645}\u{0644}\u{0020}" .
"\u{0628}\u{0639}\u{0636}\u{0647}\u{0645}\u{0020}\u{0628}\u{0639}" .
"\u{0636}\u{064B}\u{0627}\u{0020}\u{0628}\u{0631}\u{0648}\u{062D}" .
"\u{0020}\u{0627}\u{0644}\u{0625}\u{062E}\u{0627}\u{0621}\u{002E}"),
/* -------------------------- Hebrew -------------------------- */
new shaping(
"fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=hebr", 0, "Hebrew",
"\u{05E2}\u{05B4}\u{05D1}\u{05B0}\u{05E8}\u{05B4}\u{05D9}\u{05EA}"),
new shaping(
"fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=hebr", 0, "Hebrew",
"\u{05E1}\u{05E2}\u{05D9}\u{05E3}\u{0020}\u{05D0}\u{002E}\u{0020}" .
"\u{05DB}\u{05DC}\u{0020}\u{05D1}\u{05E0}\u{05D9}\u{0020}\u{05D0}" .
"\u{05D3}\u{05DD}\u{0020}\u{05E0}\u{05D5}\u{05DC}\u{05D3}\u{05D5}" .
"\u{0020}\u{05D1}\u{05E0}\u{05D9}\u{0020}\u{05D7}\u{05D5}\u{05E8}" .
"\u{05D9}\u{05DF}\u{0020}\u{05D5}\u{05E9}\u{05D5}\u{05D5}\u{05D9}" .
"\u{05DD}\u{0020}\u{05D1}\u{05E2}\u{05E8}\u{05DB}\u{05DD}\u{0020}" .
"\u{05D5}\u{05D1}\u{05D6}\u{05DB}\u{05D5}\u{05D9}\u{05D5}\u{05EA}" .
"\u{05D9}\u{05D4}\u{05DD}\u{002E}\u{0020}"),
new shaping(
"fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=hebr", 0, "Hebrew",
"\u{05DB}\u{05D5}\u{05DC}\u{05DD}\u{0020}\u{05D7}\u{05D5}\u{05E0}" .
"\u{05E0}\u{05D5}\u{0020}\u{05D1}\u{05EA}\u{05D1}\u{05D5}\u{05E0}" .
"\u{05D4}\u{0020}\u{05D5}\u{05D1}\u{05DE}\u{05E6}\u{05E4}\u{05D5}" .
"\u{05DF}\u{002C}\u{0020}"),
new shaping(
"fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=hebr", 0, "Hebrew",
"\u{05DC}\u{05E4}\u{05D9}\u{05DB}\u{05DA}\u{0020}\u{05D7}\u{05D5}" .
"\u{05D1}\u{05D4}\u{0020}\u{05E2}\u{05DC}\u{05D9}\u{05D4}\u{05DD}" .
"\u{0020}\u{05DC}\u{05E0}\u{05D4}\u{05D5}\u{05D2}\u{0020}\u{05D0}" .
"\u{05D9}\u{05E9}\u{0020}\u{05D1}\u{05E8}\u{05E2}\u{05D4}\u{05D5}" .
"\u{0020}\u{05D1}\u{05E8}\u{05D5}\u{05D7}\u{0020}\u{05E9}\u{05DC}" .
"\u{0020}\u{05D0}\u{05D7}\u{05D5}\u{05D4}\u{002E}"),
/* -------------------------- Hindi -------------------------- */
new shaping(
"fontname=NotoSerifDevanagari-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=deva", 1, "Hindi",
"\u{0939}\u{093F}\u{0928}\u{094D}\u{0926}\u{0940}"),
new shaping(
"fontname=NotoSerifDevanagari-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=deva advancedlinebreak", 1, "Hindi",
"\u{0905}\u{0928}\u{0941}\u{091A}\u{094D}\u{091B}\u{0947}\u{0926}" .
"\u{0020}\u{0967}\u{002E}\u{0020}\u{0938}\u{092D}\u{0940}\u{0020}" .
"\u{092E}\u{0928}\u{0941}\u{0937}\u{094D}\u{092F}\u{094B}\u{0902}" .
"\u{0020}\u{0915}\u{094B}\u{0020}\u{0917}\u{094C}\u{0930}\u{0935}" .
"\u{0020}\u{0914}\u{0930}\u{0020}\u{0905}\u{0927}\u{093F}\u{0915}" .
"\u{093E}\u{0930}\u{094B}\u{0902}\u{0020}\u{0915}\u{0947}\u{0020}" .
"\u{092E}\u{093E}\u{092E}\u{0932}\u{0947}\u{0020}\u{092E}\u{0947}" .
"\u{0902}\u{0020}\u{091C}\u{0928}\u{094D}\u{092E}\u{091C}\u{093E}" .
"\u{0924}\u{0020}\u{0938}\u{094D}\u{0935}\u{0924}\u{0928}\u{094D}" .
"\u{0924}\u{094D}\u{0930}\u{0924}\u{093E}\u{0020}\u{0914}\u{0930}" .
"\u{0020}\u{0938}\u{092E}\u{093E}\u{0928}\u{0924}\u{093E}\u{0020}" .
"\u{092A}\u{094D}\u{0930}\u{093E}\u{092A}\u{094D}\u{0924}\u{0020}" .
"\u{0939}\u{0948}\u{0020}\u{0964}\u{0020}\u{0909}\u{0928}\u{094D}" .
"\u{0939}\u{0947}\u{0902}\u{0020}\u{092C}\u{0941}\u{0926}\u{094D}" .
"\u{0918}\u{093F}\u{0020}\u{0914}\u{0930}\u{0020}\u{0905}\u{0928}" .
"\u{094D}\u{0924}\u{0930}\u{093E}\u{0924}\u{094D}\u{092E}\u{093E}" .
"\u{0020}\u{0915}\u{0940}\u{0020}\u{0926}\u{0947}\u{0928}\u{0020}" .
"\u{092A}\u{094D}\u{0930}\u{093E}\u{092A}\u{094D}\u{0924}\u{0020}" .
"\u{0939}\u{0948}\u{0020}\u{0914}\u{0930}\u{0020}\u{092A}\u{0930}" .
"\u{0938}\u{094D}\u{092A}\u{0930}\u{0020}\u{0909}\u{0928}\u{094D}" .
"\u{0939}\u{0947}\u{0902}\u{0020}\u{092D}\u{093E}\u{0908}\u{091A}" .
"\u{093E}\u{0930}\u{0947}\u{0020}\u{0915}\u{0947}\u{0020}\u{092D}" .
"\u{093E}\u{0935}\u{0020}\u{0938}\u{0947}\u{0020}\u{092C}\u{0930}" .
"\u{094D}\u{0924}\u{093E}\u{0935}\u{0020}\u{0915}\u{0930}\u{0928}" .
"\u{093E}\u{0020}\u{091A}\u{093E}\u{0939}\u{093F}\u{090F}\u{0020}" .
"\u{0964}"),
/* -------------------------- Sanskrit -------------------------- */
new shaping(
"fontname=NotoSerifDevanagari-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }",
"shaping script=deva", 1, "Sanskrit",
"\u{0938}\u{0902}\u{0938}\u{094D}\u{0915}\u{0943}\u{0924}\u{092E}" .
"\u{094D}"),
);
$MAXROW = count($shapingsamples);
try {
$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");
/* 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 starter sample");
$p->set_info("Title", "starter_shaping");
$table = 0;
/* Create table header */
for ($row=1, $col=1; $col <= $MAXCOL; $col++)
{
$optlist = sprintf(
"fittextline={fontname=NotoSerif-Bold fontsize=14} " .
"colwidth=%s", $col==1 ? "10%" : "45%" );
$table = $p->add_table_cell($table, $col, $row, $header[$col-1],
$optlist);
}
/* Create shaping samples */
for ($row=2; $row < $MAXROW; $row++)
{
$col=1;
/* Column 1: language name */
$optlist = sprintf(
"fittextline={fontname=NotoSerif-Regular fontsize=12}");
$table = $p->add_table_cell($table, $col++, $row,
$shapingsamples[$row]->language, $optlist);
/* Column 2: raw text */
$optlist = sprintf("%s fontsize=12 leading=150%% alignment=left",
$shapingsamples[$row]->fontopt);
$tf = $p->create_textflow($shapingsamples[$row]->text, $optlist);
$optlist = sprintf(
"margin=4 fittextflow={verticalalign=top} textflow=%d", $tf);
$table = $p->add_table_cell($table, $col++, $row, "", $optlist);
/* Column 3: shaped and reordered text (Textline or Textflow) */
if ($shapingsamples[$row]->textflow)
{
$optlist = sprintf("%s %s fontsize=12 leading=150%% alignment=left",
$shapingsamples[$row]->fontopt, $shapingsamples[$row]->optlist );
$tf = $p->create_textflow($shapingsamples[$row]->text, $optlist);
$optlist = sprintf(
"margin=4 fittextflow={verticalalign=top} textflow=%d", $tf);
$table = $p->add_table_cell($table, $col++, $row, "", $optlist);
} else {
$optlist = sprintf( "fittextline={%s %s fontsize=12 }", $shapingsamples[$row]->fontopt,
$shapingsamples[$row]->optlist);
$table = $p->add_table_cell($table, $col++, $row,
$shapingsamples[$row]->text, $optlist);
}
}
/* ---------- 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.height height=a4.width");
/* Shade every other row; draw lines for all table cells. */
$optlist = sprintf( "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("Error: " . $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=starter_shaping.pdf");
print $buf;
}
catch (PDFlibException $e) {
echo("PDFlib exception occurred in starter_shaping sample:\n" .
"[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
$e->get_errmsg() . "\n");
exit(1);
}
catch (Throwable $e) {
echo($e);
exit(1);
}
$p = 0;
?>