/**
 * @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);
