/* * 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 9 * Required data: CJK font with OpenType CJK features * * For better results you should replace the default font with a suitable * commercial font. Depending on the implementation of the features in * the font you may have to replace the sample text below in order to * see some effect of the 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. */ package com.pdflib.cookbook.pdflib.fonts; import com.pdflib.pdflib; import com.pdflib.PDFlibException; class opentype_features_for_cjk { public static void main(String argv[]) { /* This is where the data files are. Adjust as necessary. */ final String searchpath = "../input"; final String outfile = "opentype_features_for_cjk.pdf"; String optlist; pdflib p = null; int i, table, font; final double llx = 25, lly = 20, urx = 825, ury = 580; String result; int exitcode = 0; final String testfont = "NotoSerifCJKjp-Regular"; final String headers[] = { "Description", "Option list", "Font name", "Raw input (feature disabled)", "Feature enabled" }; class testcase { testcase(String description, String optlist, String feature, String text) { this.description = description; this.optlist = optlist; this.feature = feature; this.text = text; } String description; String optlist; String feature; String text; } final testcase testcases[] = { new testcase("Localized forms for simplified Chinese", "features={locl} script=hang language=ZHS", "locl", "\u2E95\u2EDD\u38C0"), new testcase("Localized forms for traditional Chinese", "features={locl} script=hang language=ZHT", "locl", "\u328B\u35EB\u3B35"), new testcase("Localized forms for Korean", "features={locl} script=hang language=KOR", "locl", "\u4E73\u52E4\u52FB"), new testcase("Simplified forms", "features={smpl}", "smpl", "\u6AAF \u81FA \u98B1"), new testcase("Traditional forms", "features={trad}", "trad", "\u53F0\u4E03\u4E0E\u4E31\u7D1B\u9912\u96B8" + "\u9698\u966A\u939A"), new testcase("Expert forms", "features={expt}", "expt", "\u5516\u82A6\u98F4\u9E78\u9D60\u6F23\u84EE\u7BDD"), new testcase("Full widths", "features={fwid}", "fwid", "0123-456(789)=25"), new testcase("Horizontal kana alternates", "features={hkna}", "hkna", "\u3041\u3042\u3043\u3044 \u30A1\u30A2\u30A3" + "\u30A4\u30E5\u30E4\u30B4\u30A7"), new testcase("Hangul", "features={hngl}", "hngl", "\u4F3D"), new testcase("Hojo kanji forms (JIS X 0212-1990)", "features={hojo}", "hojo", "\u6FF9\u9B35\u8200\u9CE6\u9B2D\u9721\u884B"), 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", "\u9022\u98F4\u6EA2\u8328\u9C2F\u6DEB\u8FC2"), new testcase("JIS78 forms", "features={jp78}", "jp78", "\u5516\u53F1\u63B4\u8000"), new testcase("JIS83 forms", "features={jp83}", "jp83", "\u4E08\u51A4"), new testcase("JIS90 forms", "features={jp90}", "jp90", "\u5026\u6994"), new testcase("Alternate annotation forms", "features={nalt}", "nalt", "ABC123\u002F\u30B4\u217B\u4E0B\u7981\u2F29\u4E2D\u2F42"), new testcase("NLC kanji forms", "features={nlck}", "nlck", "\u4FA0\u64B9"), new testcase("Proportional kana", "features={pkna}", "pkna", "\u3041\u3042 \u30A1\u30A2 \uFF66 \uFF67"), new testcase("Proportional widths", "features={pwid}", "pwid", "\u3041\u3042 \u30A1\u30A2 \u301C\uFF21\uFF23\uFF28" + "\uFF29\uFF2D ABCD abcd 1234"), new testcase("Quarter widths", "features={qwid}", "qwid", "0123-456(789)=25"), new testcase("Ruby notation forms", "features={ruby}", "ruby", "\u3042\u304A\u307D\u30AA\u30BC\u30F1\u25C9\u31F0\u31FF"), new testcase("Traditional name forms", "features={tnam}", "tnam", "\u4E9C"), new testcase("Third widths", "features={twid}", "twid", "0123-456(789)=25"), new testcase("Vertical kana alternates", "features={vkna} vertical", "vkna", "\u3041\u3042\u3043\u3044\u31FF\u31F8\u30CB\u30BB"), new testcase("Vertical writing (option 'vertical' activates feature 'vert')", "vertical", "vert", "(a.b)\uFF1A-12/"), new testcase("Vertical alternates and rotation", "features={vrt2} vertical", "vrt2", "(a.b)\uFF1A-12/"), }; try { p = new pdflib(); p.set_option("searchpath={" + searchpath + "}"); p.set_option("charref=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, "") == -1) { throw new Exception("Error: " + p.get_errmsg()); } p.set_info("Creator", "PDFlib Cookbook"); p.set_info("Title", "opentype_features_for_cjk"); table = -1; /* Table header */ for (i = 0; i < headers.length; i++) { final int col = i + 1; optlist = "fittextline={fontname=NotoSerif-Bold encoding=unicode 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 < testcases.length; i += 1) { final testcase testcase = testcases[i]; final int row = i + 2; int col = 1; /* Common option list for columns 1-3 */ optlist = "fittextline={fontname=NotoSerif-Regular encoding=unicode 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 + "} encoding=unicode fontsize=12 embedding} 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", "embedding"); /* 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 + "} encoding=unicode fontsize=12 embedding " + 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 encoding=unicode " + "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}} "; /* Place the table instance */ result = p.fit_table(table, llx, lly, urx, ury, optlist); if (result.equals("_error")) throw new Exception("Couldn't place table: " + p.get_errmsg()); p.end_page_ext(""); } while (result.equals("_boxfull")); p.end_document(""); } catch (PDFlibException e) { System.err.println("PDFlib exception occurred:"); System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() + ": " + e.get_errmsg()); exitcode = 1; } catch (Exception e) { System.err.println(e); exitcode = 1; } finally { if (p != null) { p.delete(); } System.exit(exitcode); } } }