PDFlib Cookbook

cookbook

fonts/starter_opentype

Demonstrate various typographic OpenType features after checking whether a particular feature is supported in a font.

Download Java Code  Switch to PHP Code  Show Output 

/*
 * Starter sample for OpenType font features
 *
 * Demonstrate various typographic OpenType features after checking
 * whether a particular feature is supported in a font.
 *
 * Required software: PDFlib/PDFlib+PDI/PPS 10
 * Required data: suitable font with OpenType feature tables
 *
 * This sample uses a default font which includes various features.
 * Depending on the implementation of the features you
 * may have to replace the sample text below.
 */

package com.pdflib.cookbook.pdflib.fonts;

import com.pdflib.pdflib;
import com.pdflib.PDFlibException;

class starter_opentype {
    public static void main(String argv[]) {
        /* This is where the data files are. Adjust as necessary. */
        final String searchpath = "../input";
        final String outfile = "starter_opentype.pdf";

        String optlist;
        pdflib p = null;
        int i, table, font;
        final double llx = 50, lly = 50, urx = 800, ury = 550;
        String result;
        int exitcode = 0;

        /* This font will be used unless another one is specified in the table */
        final String defaulttestfont = "NotoSerif-Regular";

        final String headers[] = { "OpenType feature", "Option list",
            "Font name", "Raw input (feature disabled)", "Feature enabled" };

        class testcase {
            testcase(String description, String fontname, String feature,
                    String text) {
                this.description = description;
                this.fontname = fontname;
                this.feature = feature;
                this.text = text;
            }

            String description;
            /* the default test font above will be used if this string is empty */
            String fontname;
            String feature;
            String text;
        }

        final testcase testcases[] = {
            new testcase("ligatures", "", "liga", "ff fi fl ffi ffl"),
            new testcase("discretionary ligatures", "", "dlig", "ch tz"),
            new testcase("small capitals", "", "smcp", "PostScript"),
            new testcase("ordinals", "", "ordn", "1o 2a 3o"),
            new testcase("fractions", "", "frac", "1/2 1/4 3/4"),
            new testcase("slashed zero", "", "zero", "0"),
            new testcase("historical forms", "", "hist", "s"),
            new testcase("proportional figures", "", "pnum", "0123456789"),
            new testcase("old-style figures", "", "onum", "0123456789"),
            new testcase("lining figures", "", "lnum", "0123456789"),
            new testcase("superscript", "", "sups", "123"),
            new testcase("subscript", "", "subs", "H2SO4") };

        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 starter sample");
            p.set_info("Title", "starter_opentype");

            table = -1;

            /* Table header */
            for (i = 0; i < headers.length; i++) {
                final int 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 < testcases.length; i += 1) {
                final testcase testcase = testcases[i];
                final int row = i + 2;

                /*
                 * Use the entry in the test table if available, and the default
                 * test font otherwise. This way we can easily check a font for
                 * all features, as well as insert suitable fonts for individual
                 * features.
                 */
                final String testfont = 
                    testcase.fontname.length() > 0 
                        ? testcase.fontname
                        : defaulttestfont;

                int 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 */
                final String buf = "features={" + testcase.feature + "}";
                table = p.add_table_cell(table, col++, row, buf, 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 = "fittextline={fontname={" + testfont
                            + "} fontsize=12 "
                            + "features={" + testcase.feature + "}} margin=4";
                    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=2 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);
        }
    }
}