PDFlib Cookbook

cookbook

complex_scripts/bidi_formatting

Create several variants of Bidirectional text output.

Download Java Code  Switch to PHP Code  Show Output 

/*
 * Starter sample for bidirectional text formatting
 * 
 * Demonstrate formatting of mixed left-to-right and right-to-left
 * (bidirectional) text with default settings and with user-supplied
 * Directional Formatting Codes as defined in Unicode.
 *  
 * Required software: PDFlib/PDFlib+PDI/PPS 10
 * Required data: Arabic font
 */

package com.pdflib.cookbook.pdflib.complex_scripts;

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

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

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

        String header[] = {
            "Bidi formatting topic",
            "Raw input",
            "Reordered and shaped output"
        };

        class shaping {
            shaping(String optlist, String language, String text) {
                // The font to be used for all examples
                this.fontopt =
                    "fontname=NotoNaskhArabic-Regular " +
                    "fallbackfonts={ {fontname=NotoSerif-Regular} }";
                this.optlist = optlist;
                this.language = language;
                this.text = text;
            }

            String fontopt;  /* fontname and other font options */
            String optlist; /* text options */
            String language; /* language name */
            String text; /* sample text */
        }

        shaping shapingsamples[] = {
            new shaping(
                "shaping script=_auto charref",
                "Mixed part number with default settings (wrong)",
                "\u0631\u0642\u0645:  XY \u0661\u0662\u0663 A"),
  
            new shaping(
                "shaping script=_auto charref",
                "Mixed part number forced as LTR sequence",
                "\u0631\u0642\u0645:  &LRO;XY \u0661\u0662\u0663 A&PDF;"),
                        
            new shaping(
                "shaping script=_auto charref",
                "Mixed text with default settings (wrong order in RTL context)",
                "He said '\u0645\u0631\u062D\u0628\u0627!' (Hello!) to me"),

            new shaping(
                "shaping script=_auto charref",
                "Mixed text with initial RLM (wrong parentheses)",
                "‏He said '\u0645\u0631\u062D\u0628\u0627!' " +
                "(Hello!) to me"),

            new shaping(
                "shaping script=_auto charref",
                "Mixed text with initial RLM and LRM after punctuation",
                "‏He said '\u0645\u0631\u062D\u0628\u0627!' " +
                "‎(Hello!) to me"),
                        
            new shaping(
                "shaping script=_auto",
                "Symmetrical swapping of mirrored glyphs",
                "[\u0646\u0644\u0627\u062D\u0638] 3<4"),
                        
            new shaping(
                "shaping script=_auto leader={alignment=left text=.}",
                "Dot leaders: leader={alignment=left text=.}",
                "\u0645\u0631\u062D\u0628\u0627"),
        };

        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.
             * "direction=r2l" instructs Acrobat to treat the document as
             * right-to-left document.
             */
            if (p.begin_document(outfile, "viewerpreferences={direction=r2l}") == -1) {
                throw new Exception("Error: " + p.get_errmsg());
            }

            p.set_info("Creator", "PDFlib Cookbook");
            p.set_info("Title", "bidi_formatting");

            table = -1;

            /* Create table header */
            for (col = 0; col < header.length; col++) {
                optlist =
                    "fittextline={fontname=NotoSerif-Bold encoding=winansi "
                    + "fontsize=14} colwidth=" + (col == 0 ? "40%" : "30%");
                table = p.add_table_cell(table, col + 1, 1, header[col],
                        optlist);
            }

            /* Create shaping samples */
            for (i = 0; i < shapingsamples.length; i++) {
                final shaping sample = shapingsamples[i];

                col = 1;
                final int row = i + 2;

                /* Column 1: description */
                optlist = "margin=4 fittextline={fontname=NotoSerif-Regular "
                        +  "fontsize=12 position={left center}}";
                table = p.add_table_cell(table, col++, row, sample.language,
                        optlist);

                /* Column 2: raw text */
                optlist = "margin=4 fittextline={" + sample.fontopt
                        + " fontsize=12 position={left center}}";
                table = p.add_table_cell(table, col++, row, sample.text,
                        optlist);
                
                /* Column 3: shaped and reordered text */
                optlist =
                    "margin=4 fittextline={" + sample.fontopt + " fontsize=12 "
                    + sample.optlist + " position={right center}}";
                table = p.add_table_cell(table, col++, row, sample.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 = "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);
        }
    }
}