# libs/bidiEngine.js

    /**
     * @license
     * Unicode Bidi Engine based on the work of Alex Shensis (@asthensis)
     * MIT License
     */

    import { jsPDF } from "../jspdf.js";

    (function(jsPDF) {
      "use strict";
      /**
       * Table of Unicode types.
       *
       * Generated by:
       *
       * var bidi = require("./bidi/index");
       * var bidi_accumulate = bidi.slice(0, 256).concat(bidi.slice(0x0500, 0x0500 + 256 * 3)).
       * concat(bidi.slice(0x2000, 0x2000 + 256)).concat(bidi.slice(0xFB00, 0xFB00 + 256)).
       * concat(bidi.slice(0xFE00, 0xFE00 + 2 * 256));
       *
       * for( var i = 0; i < bidi_accumulate.length; i++) {
       * 	if(bidi_accumulate[i] === undefined || bidi_accumulate[i] === 'ON')
       * 		bidi_accumulate[i] = 'N'; //mark as neutral to conserve space and substitute undefined
       * }
       * var bidiAccumulateStr = 'return [ "' + bidi_accumulate.toString().replace(/,/g, '", "') + '" ];';
       * require("fs").writeFile('unicode-types.js', bidiAccumulateStr);
       *
       * Based on:
       * https://github.com/mathiasbynens/unicode-8.0.0
       */
      var bidiUnicodeTypes = [
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "S",
        "B",
        "S",
        "WS",
        "B",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "B",
        "B",
        "B",
        "S",
        "WS",
        "N",
        "N",
        "ET",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "N",
        "ES",
        "CS",
        "ES",
        "CS",
        "CS",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "CS",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "N",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "B",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "CS",
        "N",
        "ET",
        "ET",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "L",
        "N",
        "N",
        "BN",
        "N",
        "N",
        "ET",
        "ET",
        "EN",
        "EN",
        "N",
        "L",
        "N",
        "N",
        "N",
        "EN",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "ET",
        "N",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "R",
        "NSM",
        "R",
        "NSM",
        "NSM",
        "R",
        "NSM",
        "NSM",
        "R",
        "NSM",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "N",
        "N",
        "N",
        "N",
        "N",
        "R",
        "R",
        "R",
        "R",
        "R",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "N",
        "N",
        "AL",
        "ET",
        "ET",
        "AL",
        "CS",
        "AL",
        "N",
        "N",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "AL",
        "AL",
        "N",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "AN",
        "ET",
        "AN",
        "AN",
        "AL",
        "AL",
        "AL",
        "NSM",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "AN",
        "N",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "AL",
        "AL",
        "NSM",
        "NSM",
        "N",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "AL",
        "AL",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "N",
        "AL",
        "AL",
        "NSM",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "N",
        "N",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "AL",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "R",
        "R",
        "N",
        "N",
        "N",
        "N",
        "R",
        "N",
        "N",
        "N",
        "N",
        "N",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "WS",
        "BN",
        "BN",
        "BN",
        "L",
        "R",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "WS",
        "B",
        "LRE",
        "RLE",
        "PDF",
        "LRO",
        "RLO",
        "CS",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "CS",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "WS",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "N",
        "LRI",
        "RLI",
        "FSI",
        "PDI",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "BN",
        "EN",
        "L",
        "N",
        "N",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "ES",
        "ES",
        "N",
        "N",
        "N",
        "L",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "ES",
        "ES",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "R",
        "NSM",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "ES",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "N",
        "R",
        "R",
        "R",
        "R",
        "R",
        "N",
        "R",
        "N",
        "R",
        "R",
        "N",
        "R",
        "R",
        "N",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "R",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "NSM",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "CS",
        "N",
        "CS",
        "N",
        "N",
        "CS",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "ET",
        "N",
        "N",
        "ES",
        "ES",
        "N",
        "N",
        "N",
        "N",
        "N",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "N",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "N",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "AL",
        "N",
        "N",
        "BN",
        "N",
        "N",
        "N",
        "ET",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "N",
        "ES",
        "CS",
        "ES",
        "CS",
        "CS",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "EN",
        "CS",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "L",
        "L",
        "L",
        "L",
        "L",
        "L",
        "N",
        "N",
        "L",
        "L",
        "L",
        "N",
        "N",
        "N",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "ET",
        "ET",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N",
        "N"
      ];

      /**
       * Unicode Bidi algorithm compliant Bidi engine.
       * For reference see http://unicode.org/reports/tr9/
       */

      /**
       * constructor ( options )
       *
       * Initializes Bidi engine
       *
       * @param {Object} See 'setOptions' below for detailed description.
       * options are cashed between invocation of 'doBidiReorder' method
       *
       * sample usage pattern of BidiEngine:
       * var opt = {
       * 	isInputVisual: true,
       * 	isInputRtl: false,
       * 	isOutputVisual: false,
       * 	isOutputRtl: false,
       * 	isSymmetricSwapping: true
       * }
       * var sourceToTarget = [], levels = [];
       * var bidiEng = Globalize.bidiEngine(opt);
       * var src = "text string to be reordered";
       * var ret = bidiEng.doBidiReorder(src, sourceToTarget, levels);
       */

      jsPDF.__bidiEngine__ = jsPDF.prototype.__bidiEngine__ = function(options) {
        var _UNICODE_TYPES = _bidiUnicodeTypes;

        var _STATE_TABLE_LTR = [
          [0, 3, 0, 1, 0, 0, 0],
          [0, 3, 0, 1, 2, 2, 0],
          [0, 3, 0, 0x11, 2, 0, 1],
          [0, 3, 5, 5, 4, 1, 0],
          [0, 3, 0x15, 0x15, 4, 0, 1],
          [0, 3, 5, 5, 4, 2, 0]
        ];

        var _STATE_TABLE_RTL = [
          [2, 0, 1, 1, 0, 1, 0],
          [2, 0, 1, 1, 0, 2, 0],
          [2, 0, 2, 1, 3, 2, 0],
          [2, 0, 2, 0x21, 3, 1, 1]
        ];

        var _TYPE_NAMES_MAP = { L: 0, R: 1, EN: 2, AN: 3, N: 4, B: 5, S: 6 };

        var _UNICODE_RANGES_MAP = {
          0: 0,
          5: 1,
          6: 2,
          7: 3,
          0x20: 4,
          0xfb: 5,
          0xfe: 6,
          0xff: 7
        };

        var _SWAP_TABLE = [
          "\u0028",
          "\u0029",
          "\u0028",
          "\u003C",
          "\u003E",
          "\u003C",
          "\u005B",
          "\u005D",
          "\u005B",
          "\u007B",
          "\u007D",
          "\u007B",
          "\u00AB",
          "\u00BB",
          "\u00AB",
          "\u2039",
          "\u203A",
          "\u2039",
          "\u2045",
          "\u2046",
          "\u2045",
          "\u207D",
          "\u207E",
          "\u207D",
          "\u208D",
          "\u208E",
          "\u208D",
          "\u2264",
          "\u2265",
          "\u2264",
          "\u2329",
          "\u232A",
          "\u2329",
          "\uFE59",
          "\uFE5A",
          "\uFE59",
          "\uFE5B",
          "\uFE5C",
          "\uFE5B",
          "\uFE5D",
          "\uFE5E",
          "\uFE5D",
          "\uFE64",
          "\uFE65",
          "\uFE64"
        ];

        var _LTR_RANGES_REG_EXPR = new RegExp(
          /^([1-4|9]|1[0-9]|2[0-9]|3[0168]|4[04589]|5[012]|7[78]|159|16[0-9]|17[0-2]|21[569]|22[03489]|250)$/
        );

        var _lastArabic = false,
          _hasUbatAl,
          _hasUbatB,
          _hasUbatS,
          DIR_LTR = 0,
          DIR_RTL = 1,
          _isInVisual,
          _isInRtl,
          _isOutVisual,
          _isOutRtl,
          _isSymmetricSwapping,
          _dir = DIR_LTR;

        this.__bidiEngine__ = {};

        var _init = function(text, sourceToTargetMap) {
          if (sourceToTargetMap) {
            for (var i = 0; i < text.length; i++) {
              sourceToTargetMap[i] = i;
            }
          }
          if (_isInRtl === undefined) {
            _isInRtl = _isContextualDirRtl(text);
          }
          if (_isOutRtl === undefined) {
            _isOutRtl = _isContextualDirRtl(text);
          }
        };

        // for reference see 3.2 in http://unicode.org/reports/tr9/
        //
        var _getCharType = function(ch) {
          var charCode = ch.charCodeAt(),
            range = charCode >> 8,
            rangeIdx = _UNICODE_RANGES_MAP[range];

          if (rangeIdx !== undefined) {
            return _UNICODE_TYPES[rangeIdx * 256 + (charCode & 0xff)];
          } else if (range === 0xfc || range === 0xfd) {
            return "AL";
          } else if (_LTR_RANGES_REG_EXPR.test(range)) {
            //unlikely case
            return "L";
          } else if (range === 8) {
            // even less likely
            return "R";
          }
          return "N"; //undefined type, mark as neutral
        };

        var _isContextualDirRtl = function(text) {
          for (var i = 0, charType; i < text.length; i++) {
            charType = _getCharType(text.charAt(i));
            if (charType === "L") {
              return false;
            } else if (charType === "R") {
              return true;
            }
          }
          return false;
        };

        // for reference see 3.3.4 & 3.3.5 in http://unicode.org/reports/tr9/
        //
        var _resolveCharType = function(chars, types, resolvedTypes, index) {
          var cType = types[index],
            wType,
            nType,
            i,
            len;
          switch (cType) {
            case "L":
            case "R":
              _lastArabic = false;
              break;
            case "N":
            case "AN":
              break;

            case "EN":
              if (_lastArabic) {
                cType = "AN";
              }
              break;

            case "AL":
              _lastArabic = true;
              _hasUbatAl = true;
              cType = "R";
              break;

            case "WS":
              cType = "N";
              break;

            case "CS":
              if (
                index < 1 ||
                index + 1 >= types.length ||
                ((wType = resolvedTypes[index - 1]) !== "EN" && wType !== "AN") ||
                ((nType = types[index + 1]) !== "EN" && nType !== "AN")
              ) {
                cType = "N";
              } else if (_lastArabic) {
                nType = "AN";
              }
              cType = nType === wType ? nType : "N";
              break;

            case "ES":
              wType = index > 0 ? resolvedTypes[index - 1] : "B";
              cType =
                wType === "EN" &&
                index + 1 < types.length &&
                types[index + 1] === "EN"
                  ? "EN"
                  : "N";
              break;

            case "ET":
              if (index > 0 && resolvedTypes[index - 1] === "EN") {
                cType = "EN";
                break;
              } else if (_lastArabic) {
                cType = "N";
                break;
              }
              i = index + 1;
              len = types.length;
              while (i < len && types[i] === "ET") {
                i++;
              }
              if (i < len && types[i] === "EN") {
                cType = "EN";
              } else {
                cType = "N";
              }
              break;

            case "NSM":
              if (_isInVisual && !_isInRtl) {
                //V->L
                len = types.length;
                i = index + 1;
                while (i < len && types[i] === "NSM") {
                  i++;
                }
                if (i < len) {
                  var c = chars[index];
                  var rtlCandidate = (c >= 0x0591 && c <= 0x08ff) || c === 0xfb1e;
                  wType = types[i];
                  if (rtlCandidate && (wType === "R" || wType === "AL")) {
                    cType = "R";
                    break;
                  }
                }
              }
              if (index < 1 || (wType = types[index - 1]) === "B") {
                cType = "N";
              } else {
                cType = resolvedTypes[index - 1];
              }
              break;

            case "B":
              _lastArabic = false;
              _hasUbatB = true;
              cType = _dir;
              break;

            case "S":
              _hasUbatS = true;
              cType = "N";
              break;

            case "LRE":
            case "RLE":
            case "LRO":
            case "RLO":
            case "PDF":
              _lastArabic = false;
              break;
            case "BN":
              cType = "N";
              break;
          }
          return cType;
        };

        var _handleUbatS = function(types, levels, length) {
          for (var i = 0; i < length; i++) {
            if (types[i] === "S") {
              levels[i] = _dir;
              for (var j = i - 1; j >= 0; j--) {
                if (types[j] === "WS") {
                  levels[j] = _dir;
                } else {
                  break;
                }
              }
            }
          }
        };

        var _invertString = function(text, sourceToTargetMap, levels) {
          var charArray = text.split("");
          if (levels) {
            _computeLevels(charArray, levels, { hiLevel: _dir });
          }
          charArray.reverse();
          sourceToTargetMap && sourceToTargetMap.reverse();
          return charArray.join("");
        };

        // For reference see 3.3 in http://unicode.org/reports/tr9/
        //
        var _computeLevels = function(chars, levels, params) {
          var action,
            condition,
            i,
            index,
            newLevel,
            prevState,
            condPos = -1,
            len = chars.length,
            newState = 0,
            resolvedTypes = [],
            stateTable = _dir ? _STATE_TABLE_RTL : _STATE_TABLE_LTR,
            types = [];

          _lastArabic = false;
          _hasUbatAl = false;
          _hasUbatB = false;
          _hasUbatS = false;
          for (i = 0; i < len; i++) {
            types[i] = _getCharType(chars[i]);
          }
          for (index = 0; index < len; index++) {
            prevState = newState;
            resolvedTypes[index] = _resolveCharType(
              chars,
              types,
              resolvedTypes,
              index
            );
            newState = stateTable[prevState][_TYPE_NAMES_MAP[resolvedTypes[index]]];
            action = newState & 0xf0;
            newState &= 0x0f;
            levels[index] = newLevel = stateTable[newState][5];
            if (action > 0) {
              if (action === 0x10) {
                for (i = condPos; i < index; i++) {
                  levels[i] = 1;
                }
                condPos = -1;
              } else {
                condPos = -1;
              }
            }
            condition = stateTable[newState][6];
            if (condition) {
              if (condPos === -1) {
                condPos = index;
              }
            } else {
              if (condPos > -1) {
                for (i = condPos; i < index; i++) {
                  levels[i] = newLevel;
                }
                condPos = -1;
              }
            }
            if (types[index] === "B") {
              levels[index] = 0;
            }
            params.hiLevel |= newLevel;
          }
          if (_hasUbatS) {
            _handleUbatS(types, levels, len);
          }
        };

        // for reference see 3.4 in http://unicode.org/reports/tr9/
        //
        var _invertByLevel = function(
          level,
          charArray,
          sourceToTargetMap,
          levels,
          params
        ) {
          if (params.hiLevel < level) {
            return;
          }
          if (level === 1 && _dir === DIR_RTL && !_hasUbatB) {
            charArray.reverse();
            sourceToTargetMap && sourceToTargetMap.reverse();
            return;
          }
          var ch,
            high,
            end,
            low,
            len = charArray.length,
            start = 0;

          while (start < len) {
            if (levels[start] >= level) {
              end = start + 1;
              while (end < len && levels[end] >= level) {
                end++;
              }
              for (low = start, high = end - 1; low < high; low++, high--) {
                ch = charArray[low];
                charArray[low] = charArray[high];
                charArray[high] = ch;
                if (sourceToTargetMap) {
                  ch = sourceToTargetMap[low];
                  sourceToTargetMap[low] = sourceToTargetMap[high];
                  sourceToTargetMap[high] = ch;
                }
              }
              start = end;
            }
            start++;
          }
        };

        // for reference see 7 & BD16 in http://unicode.org/reports/tr9/
        //
        var _symmetricSwap = function(charArray, levels, params) {
          if (params.hiLevel !== 0 && _isSymmetricSwapping) {
            for (var i = 0, index; i < charArray.length; i++) {
              if (levels[i] === 1) {
                index = _SWAP_TABLE.indexOf(charArray[i]);
                if (index >= 0) {
                  charArray[i] = _SWAP_TABLE[index + 1];
                }
              }
            }
          }
        };

        var _reorder = function(text, sourceToTargetMap, levels) {
          var charArray = text.split(""),
            params = { hiLevel: _dir };

          if (!levels) {
            levels = [];
          }
          _computeLevels(charArray, levels, params);
          _symmetricSwap(charArray, levels, params);
          _invertByLevel(DIR_RTL + 1, charArray, sourceToTargetMap, levels, params);
          _invertByLevel(DIR_RTL, charArray, sourceToTargetMap, levels, params);
          return charArray.join("");
        };

        // doBidiReorder( text, sourceToTargetMap, levels )
        // Performs Bidi reordering by implementing Unicode Bidi algorithm.
        // Returns reordered string
        // @text [String]:
        // - input string to be reordered, this is input parameter
        // $sourceToTargetMap [Array] (optional)
        // - resultant mapping between input and output strings, this is output parameter
        // $levels [Array] (optional)
        // - array of calculated Bidi levels, , this is output parameter
        this.__bidiEngine__.doBidiReorder = function(
          text,
          sourceToTargetMap,
          levels
        ) {
          _init(text, sourceToTargetMap);
          if (!_isInVisual && _isOutVisual && !_isOutRtl) {
            // LLTR->VLTR, LRTL->VLTR
            _dir = _isInRtl ? DIR_RTL : DIR_LTR;
            text = _reorder(text, sourceToTargetMap, levels);
          } else if (_isInVisual && _isOutVisual && _isInRtl ^ _isOutRtl) {
            // VRTL->VLTR, VLTR->VRTL
            _dir = _isInRtl ? DIR_RTL : DIR_LTR;
            text = _invertString(text, sourceToTargetMap, levels);
          } else if (!_isInVisual && _isOutVisual && _isOutRtl) {
            // LLTR->VRTL, LRTL->VRTL
            _dir = _isInRtl ? DIR_RTL : DIR_LTR;
            text = _reorder(text, sourceToTargetMap, levels);
            text = _invertString(text, sourceToTargetMap);
          } else if (_isInVisual && !_isInRtl && !_isOutVisual && !_isOutRtl) {
            // VLTR->LLTR
            _dir = DIR_LTR;
            text = _reorder(text, sourceToTargetMap, levels);
          } else if (_isInVisual && !_isOutVisual && _isInRtl ^ _isOutRtl) {
            // VLTR->LRTL, VRTL->LLTR
            text = _invertString(text, sourceToTargetMap);
            if (_isInRtl) {
              //LLTR -> VLTR
              _dir = DIR_LTR;
              text = _reorder(text, sourceToTargetMap, levels);
            } else {
              //LRTL -> VRTL
              _dir = DIR_RTL;
              text = _reorder(text, sourceToTargetMap, levels);
              text = _invertString(text, sourceToTargetMap);
            }
          } else if (_isInVisual && _isInRtl && !_isOutVisual && _isOutRtl) {
            //  VRTL->LRTL
            _dir = DIR_RTL;
            text = _reorder(text, sourceToTargetMap, levels);
            text = _invertString(text, sourceToTargetMap);
          } else if (!_isInVisual && !_isOutVisual && _isInRtl ^ _isOutRtl) {
            // LRTL->LLTR, LLTR->LRTL
            var isSymmetricSwappingOrig = _isSymmetricSwapping;
            if (_isInRtl) {
              //LRTL->LLTR
              _dir = DIR_RTL;
              text = _reorder(text, sourceToTargetMap, levels);
              _dir = DIR_LTR;
              _isSymmetricSwapping = false;
              text = _reorder(text, sourceToTargetMap, levels);
              _isSymmetricSwapping = isSymmetricSwappingOrig;
            } else {
              //LLTR->LRTL
              _dir = DIR_LTR;
              text = _reorder(text, sourceToTargetMap, levels);
              text = _invertString(text, sourceToTargetMap);
              _dir = DIR_RTL;
              _isSymmetricSwapping = false;
              text = _reorder(text, sourceToTargetMap, levels);
              _isSymmetricSwapping = isSymmetricSwappingOrig;
              text = _invertString(text, sourceToTargetMap);
            }
          }
          return text;
        };

        /**
         * @name setOptions( options )
         * @function
         * Sets options for Bidi conversion
         * @param {Object}:
         * - isInputVisual {boolean} (defaults to false): allowed values: true(Visual mode), false(Logical mode)
         * - isInputRtl {boolean}: allowed values true(Right-to-left direction), false (Left-to-right directiion), undefined(Contectual direction, i.e.direction defined by first strong character of input string)
         * - isOutputVisual {boolean} (defaults to false): allowed values: true(Visual mode), false(Logical mode)
         * - isOutputRtl {boolean}: allowed values true(Right-to-left direction), false (Left-to-right directiion), undefined(Contectual direction, i.e.direction defined by first strong characterof input string)
         * - isSymmetricSwapping {boolean} (defaults to false): allowed values true(needs symmetric swapping), false (no need in symmetric swapping),
         */
        this.__bidiEngine__.setOptions = function(options) {
          if (options) {
            _isInVisual = options.isInputVisual;
            _isOutVisual = options.isOutputVisual;
            _isInRtl = options.isInputRtl;
            _isOutRtl = options.isOutputRtl;
            _isSymmetricSwapping = options.isSymmetricSwapping;
          }
        };

        this.__bidiEngine__.setOptions(options);
        return this.__bidiEngine__;
      };

      var _bidiUnicodeTypes = bidiUnicodeTypes;

      var bidiEngine = new jsPDF.__bidiEngine__({ isInputVisual: true });

      var bidiEngineFunction = function(args) {
        var text = args.text;
        var x = args.x;
        var y = args.y;
        var options = args.options || {};
        var mutex = args.mutex || {};
        var lang = options.lang;
        var tmpText = [];

        options.isInputVisual =
          typeof options.isInputVisual === "boolean" ? options.isInputVisual : true;
        bidiEngine.setOptions(options);

        if (Object.prototype.toString.call(text) === "[object Array]") {
          var i = 0;
          tmpText = [];
          for (i = 0; i < text.length; i += 1) {
            if (Object.prototype.toString.call(text[i]) === "[object Array]") {
              tmpText.push([
                bidiEngine.doBidiReorder(text[i][0]),
                text[i][1],
                text[i][2]
              ]);
            } else {
              tmpText.push([bidiEngine.doBidiReorder(text[i])]);
            }
          }
          args.text = tmpText;
        } else {
          args.text = bidiEngine.doBidiReorder(text);
        }
        bidiEngine.setOptions({ isInputVisual: true });
      };

      jsPDF.API.events.push(["postProcessText", bidiEngineFunction]);
    })(jsPDF);