ArabicShaping.java revision 836e6b40a94ec3fb7545a76cb072960442b7eee9
12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
22ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
32ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*******************************************************************************
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*   Copyright (C) 2001-2012, International Business Machines
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*   Corporation and others.  All Rights Reserved.
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*******************************************************************************
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*/
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.text;
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.impl.UBiDiProps;
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.lang.UCharacterDirection;
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Shape Arabic text on a character basis.
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>ArabicShaping performs basic operations for "shaping" Arabic text. It is most
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * useful for use with legacy data formats and legacy display technology
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (simple terminals). All operations are performed on Unicode characters.</p>
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Text-based shaping means that some character code points in the text are
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * replaced by others depending on the context. It transforms one kind of text
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * into another. In comparison, modern displays for Arabic text select
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * appropriate, context-dependent font glyphs for each text element, which means
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that they transform text into a glyph vector.</p>
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Text transformations are necessary when modern display technology is not
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * available or when text needs to be transformed to or from legacy formats that
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * use "shaped" characters. Since the Arabic script is cursive, connecting
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * adjacent letters to each other, computers select images for each letter based
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * on the surrounding letters. This usually results in four images per Arabic
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * letter: initial, middle, final, and isolated forms. In Unicode, on the other
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * hand, letters are normally stored abstract, and a display system is expected
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to select the necessary glyphs. (This makes searching and other text
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * processing easier because the same letter has only one code.) It is possible
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to mimic this with text transformations because there are characters in
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Unicode that are rendered as letters with a specific shape
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (or cursive connectivity). They were included for interoperability with
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * legacy systems and codepages, and for unsophisticated display systems.</p>
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>A second kind of text transformations is supported for Arabic digits:
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * For compatibility with legacy codepages that only include European digits,
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * it is possible to replace one set of digits by another, changing the
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * character code points. These operations can be performed for either
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Arabic-Indic Digits (U+0660...U+0669) or Eastern (Extended) Arabic-Indic
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * digits (U+06f0...U+06f9).</p>
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Some replacements may result in more or fewer characters (code points).
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * By default, this means that the destination buffer may receive text with a
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * length different from the source length. Some legacy systems rely on the
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * length of the text to be constant. They expect extra spaces to be added
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * or consumed either next to the affected character or at the end of the
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * text.</p>
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @stable ICU 2.0
55836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
56704056c96cc5de08c2425fa1679a5c0a92c5a88eNeil Fuller * @hide All android.icu classes are currently hidden
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic final class ArabicShaping {
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private final int options;
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private boolean isLogical; // convenience
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private boolean spacesRelativeToTextBeginEnd;
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private char tailChar;
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convert a range of text in the source array, putting the result
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * into a range of text in the destination array, and return the number
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * of characters written.
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param source An array containing the input text
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param sourceStart The start of the range of text to convert
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param sourceLength The length of the range of text to convert
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param dest The destination array that will receive the result.
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   It may be <code>NULL</code> only if  <code>destSize</code> is 0.
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param destStart The start of the range of the destination buffer to use.
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param destSize The size (capacity) of the destination buffer.
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   If <code>destSize</code> is 0, then no output is produced,
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   but the necessary buffer size is returned ("preflighting").  This
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   does not validate the text against the options, for example,
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   if letters are being unshaped, and spaces are being consumed
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   following lamalef, this will not detect a lamalef without a
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   corresponding space.  An error will be thrown when the actual
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   conversion is attempted.
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return The number of chars written to the destination buffer.
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   If an error occurs, then no output was written, or it may be
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *   incomplete.
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @throws ArabicShapingException if the text cannot be converted according to the options.
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int shape(char[] source, int sourceStart, int sourceLength,
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                     char[] dest, int destStart, int destSize) throws ArabicShapingException {
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (source == null) {
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("source can not be null");
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (sourceStart < 0 || sourceLength < 0 || sourceStart + sourceLength > source.length) {
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("bad source start (" + sourceStart +
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                               ") or length (" + sourceLength +
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                               ") for buffer of length " + source.length);
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (dest == null && destSize != 0) {
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("null dest requires destSize == 0");
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((destSize != 0) &&
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            (destStart < 0 || destSize < 0 || destStart + destSize > dest.length)) {
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("bad dest start (" + destStart +
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                               ") or size (" + destSize +
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                               ") for buffer of length " + dest.length);
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* Validate input options */
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ( ((options&TASHKEEL_MASK) > 0) &&
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             !(((options & TASHKEEL_MASK)==TASHKEEL_BEGIN)  ||
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               ((options & TASHKEEL_MASK)==TASHKEEL_END )   ||
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               ((options & TASHKEEL_MASK)==TASHKEEL_RESIZE )||
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               ((options & TASHKEEL_MASK)==TASHKEEL_REPLACE_BY_TATWEEL)) ){
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("Wrong Tashkeel argument");
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       ///CLOVER:OFF
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       //According to Steven Loomis, the code is unreachable when you OR all the constants within the if statements
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       if(((options&LAMALEF_MASK) > 0)&&
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              !(((options & LAMALEF_MASK)==LAMALEF_BEGIN)  ||
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                ((options & LAMALEF_MASK)==LAMALEF_END )   ||
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                ((options & LAMALEF_MASK)==LAMALEF_RESIZE )||
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                 ((options & LAMALEF_MASK)==LAMALEF_AUTO)  ||
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                 ((options & LAMALEF_MASK)==LAMALEF_NEAR))){
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller           throw new IllegalArgumentException("Wrong Lam Alef argument");
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       }
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       ///CLOVER:ON
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       /* Validate Tashkeel (Tashkeel replacement options should be enabled in shaping mode only)*/
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       if(((options&TASHKEEL_MASK) > 0) && (options&LETTERS_MASK) == LETTERS_UNSHAPE) {
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("Tashkeel replacement should not be enabled in deshaping mode ");
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       }
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       return internalShape(source, sourceStart, sourceLength, dest, destStart, destSize);
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convert a range of text in place.  This may only be used if the Length option
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * does not grow or shrink the text.
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param source An array containing the input text
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param start The start of the range of text to convert
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param length The length of the range of text to convert
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @throws ArabicShapingException if the text cannot be converted according to the options.
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public void shape(char[] source, int start, int length) throws ArabicShapingException {
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((options & LAMALEF_MASK) == LAMALEF_RESIZE) {
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new ArabicShapingException("Cannot shape in place with length option resize.");
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        shape(source, start, length, source, start, length);
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convert a string, returning the new string.
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param text the string to convert
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return the converted string
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @throws ArabicShapingException if the string cannot be converted according to the options.
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String shape(String text) throws ArabicShapingException {
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        char[] src = text.toCharArray();
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        char[] dest = src;
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (((options & LAMALEF_MASK) == LAMALEF_RESIZE) &&
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ((options & LETTERS_MASK) == LETTERS_UNSHAPE)) {
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            dest = new char[src.length * 2]; // max
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int len = shape(src, 0, src.length, dest, 0, dest.length);
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new String(dest, 0, len);
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Construct ArabicShaping using the options flags.
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The flags are as follows:<br>
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * 'LENGTH' flags control whether the text can change size, and if not,
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * how to maintain the size of the text when LamAlef ligatures are
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * formed or broken.<br>
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * 'TEXT_DIRECTION' flags control whether the text is read and written
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * in visual order or in logical order.<br>
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * 'LETTERS_SHAPE' flags control whether conversion is to or from
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * presentation forms.<br>
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * 'DIGITS' flags control whether digits are shaped, and whether from
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * European to Arabic-Indic or vice-versa.<br>
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * 'DIGIT_TYPE' flags control whether standard or extended Arabic-Indic
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * digits are used when performing digit conversion.
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public ArabicShaping(int options) {
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        this.options = options;
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((options & DIGITS_MASK) > 0x80) {
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("bad DIGITS options");
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        isLogical = ( (options & TEXT_DIRECTION_MASK) == TEXT_DIRECTION_LOGICAL );
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* Validate options */
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        spacesRelativeToTextBeginEnd = ( (options & SPACES_RELATIVE_TO_TEXT_MASK) == SPACES_RELATIVE_TO_TEXT_BEGIN_END );
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ( (options&SHAPE_TAIL_TYPE_MASK) == SHAPE_TAIL_NEW_UNICODE){
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            tailChar = NEW_TAIL_CHAR;
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            tailChar = OLD_TAIL_CHAR;
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* Seen Tail options */
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping mode: The SEEN family character will expand into two characters using space near
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               the SEEN family character(i.e. the space after the character).
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               if there are no spaces found, ArabicShapingException will be thrown
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping mode: Any Seen character followed by Tail character will be
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *                  replaced by one cell Seen and a space will replace the Tail.
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: Seen options
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SEEN_TWOCELL_NEAR = 0x200000;
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Bit mask for Seen memory options.
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SEEN_MASK = 0x700000;
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* YehHamza options */
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping mode: The YEHHAMZA character will expand into two characters using space near it
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *              (i.e. the space after the character)
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               if there are no spaces found, ArabicShapingException will be thrown
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping mode: Any Yeh (final or isolated) character followed by Hamza character will be
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *                  replaced by one cell YehHamza and space will replace the Hamza.
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: YehHamza options
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int YEHHAMZA_TWOCELL_NEAR  = 0x1000000;
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Bit mask for YehHamza memory options.
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int YEHHAMZA_MASK = 0x3800000;
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* New Tashkeel options */
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping mode: Tashkeel characters will be replaced by spaces.
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               Spaces will be placed at beginning of the buffer
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping mode: N/A
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: Tashkeel options
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TASHKEEL_BEGIN = 0x40000;
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping mode: Tashkeel characters will be replaced by spaces.
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               Spaces will be placed at end of the buffer
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping mode: N/A
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: Tashkeel options
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TASHKEEL_END = 0x60000;
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: allow the result to have a different length than the source.
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping mode: Tashkeel characters will be removed, buffer length will shrink.
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping mode: N/A
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: Tashkeel options
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TASHKEEL_RESIZE = 0x80000;
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping mode: Tashkeel characters will be replaced by Tatweel if it is connected to adjacent
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               characters (i.e. shaped on Tatweel) or replaced by space if it is not connected.
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping mode: N/A
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: YehHamza options
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TASHKEEL_REPLACE_BY_TATWEEL = 0xC0000;
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Bit mask for Tashkeel replacement with Space or Tatweel memory options.
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *  @stable ICU 4.2
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TASHKEEL_MASK  = 0xE0000;
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* Space location Control options */
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This option effects the meaning of BEGIN and END options. if this option is not used the default
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * for BEGIN and END will be as following:
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The Default (for both Visual LTR, Visual RTL and Logical Text)
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           1. BEGIN always refers to the start address of physical memory.
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           2. END always refers to the end address of physical memory.
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If this option is used it will swap the meaning of BEGIN and END only for Visual LTR text.
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The affect on BEGIN and END Memory Options will be as following:
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *    A. BEGIN For Visual LTR text: This will be the beginning (right side) of the visual text
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *       (corresponding to the physical memory address end, same as END in default behavior)
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *    B. BEGIN For Logical text: Same as BEGIN in default behavior.
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *    C. END For Visual LTR text: This will be the end (left side) of the visual text. (corresponding to
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *      the physical memory address beginning, same as BEGIN in default behavior)
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *    D. END For Logical text: Same as END in default behavior.
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: All LamAlef BEGIN, END and AUTO options.
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SPACES_RELATIVE_TO_TEXT_BEGIN_END = 0x4000000;
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Bit mask for swapping BEGIN and END for Visual LTR text
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SPACES_RELATIVE_TO_TEXT_MASK = 0x4000000;
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If this option is used, shaping will use the new Unicode code point for TAIL (i.e. 0xFE73).
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If this option is not specified (Default), old unofficial Unicode TAIL code point is used (i.e. 0x200B)
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping will not use this option as it will always search for both the new Unicode code point for the
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * TAIL (i.e. 0xFE73) or the old unofficial Unicode TAIL code point (i.e. 0x200B) and de-shape the
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Seen-Family letter accordingly.
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping Mode: Only shaping.
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * De-shaping Mode: N/A.
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: All Seen options
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SHAPE_TAIL_NEW_UNICODE = 0x8000000;
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Bit mask for new Unicode Tail option
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SHAPE_TAIL_TYPE_MASK = 0x8000000;
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: allow the result to have a different length than the source.
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LENGTH_GROW_SHRINK = 0;
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: allow the result to have a different length than the source.
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: LamAlef options
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This option is an alias to LENGTH_GROW_SHRINK
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LAMALEF_RESIZE   = 0;
3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If more room is necessary, then try to consume spaces next to modified characters.
3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LENGTH_FIXED_SPACES_NEAR = 1;
3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If more room is necessary, then try to consume spaces next to modified characters.
3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: LamAlef options
3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This option is an alias to LENGTH_FIXED_SPACES_NEAR
3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LAMALEF_NEAR = 1 ;
3692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If more room is necessary, then try to consume spaces at the end of the text.
3732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
3742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LENGTH_FIXED_SPACES_AT_END = 2;
3762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
3802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If more room is necessary, then try to consume spaces at the end of the text.
3812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: LamAlef options
3822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This option is an alias to LENGTH_FIXED_SPACES_AT_END
3832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
3842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LAMALEF_END = 2;
3862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
3892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If more room is necessary, then try to consume spaces at the beginning of the text.
3902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
3912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LENGTH_FIXED_SPACES_AT_BEGINNING = 3;
3932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
3962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * If more room is necessary, then try to consume spaces at the beginning of the text.
3972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: LamAlef options
3982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This option is an alias to LENGTH_FIXED_SPACES_AT_BEGINNING
3992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
4002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LAMALEF_BEGIN = 3;
4022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Memory option: the result must have the same length as the source.
4052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Shaping Mode: For each LAMALEF character found, expand LAMALEF using space at end.
4062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               If there is no space at end, use spaces at beginning of the buffer. If there
4072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               is no space at beginning of the buffer, use spaces at the near (i.e. the space
4082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *               after the LAMALEF character).
4092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
4102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Deshaping Mode: Perform the same function as the flag equals LAMALEF_END.
4112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Affects: LamAlef options
4122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
4132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LAMALEF_AUTO  = 0x10000;
4152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bit mask for memory options.
4182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LENGTH_MASK = 0x10003;
4212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Bit mask for LamAlef memory options.
4232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
4242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LAMALEF_MASK  = 0x10003;
4272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Direction indicator: the source is in logical (keyboard) order.
4302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TEXT_DIRECTION_LOGICAL = 0;
4332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Direction indicator:the source is in visual RTL order,
4362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the rightmost displayed character stored first.
4372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This option is an alias to U_SHAPE_TEXT_DIRECTION_LOGICAL
4382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.2
4392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TEXT_DIRECTION_VISUAL_RTL = 0;
4412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Direction indicator: the source is in visual (display) order, that is,
4442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the leftmost displayed character is stored first.
4452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TEXT_DIRECTION_VISUAL_LTR = 4;
4482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bit mask for direction indicators.
4512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int TEXT_DIRECTION_MASK = 4;
4542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Letter shaping option: do not perform letter shaping.
4582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LETTERS_NOOP = 0;
4612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Letter shaping option: replace normative letter characters in the U+0600 (Arabic) block,
4642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * by shaped ones in the U+FE70 (Presentation Forms B) block. Performs Lam-Alef ligature
4652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * substitution.
4662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LETTERS_SHAPE = 8;
4692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Letter shaping option: replace shaped letter characters in the U+FE70 (Presentation Forms B) block
4722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * by normative ones in the U+0600 (Arabic) block.  Converts Lam-Alef ligatures to pairs of Lam and
4732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Alef characters, consuming spaces if required.
4742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LETTERS_UNSHAPE = 0x10;
4772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Letter shaping option: replace normative letter characters in the U+0600 (Arabic) block,
4802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * except for the TASHKEEL characters at U+064B...U+0652, by shaped ones in the U+Fe70
4812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * (Presentation Forms B) block.  The TASHKEEL characters will always be converted to
4822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the isolated forms rather than to their correct shape.
4832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LETTERS_SHAPE_TASHKEEL_ISOLATED = 0x18;
4862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bit mask for letter shaping options.
4892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int LETTERS_MASK = 0x18;
4922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit shaping option: do not perform digit shaping.
4962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
4972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGITS_NOOP = 0;
4992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
5022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGITS_EN2AN = 0x20;
5052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
5082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGITS_AN2EN = 0x40;
5112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit shaping option:
5142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
5152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * if the most recent strongly directional character
5162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
5172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The initial state at the start of the text is assumed to be not an Arabic,
5182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * letter, so European digits at the start of the text will not change.
5192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Compare to DIGITS_ALEN2AN_INIT_AL.
5202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGITS_EN2AN_INIT_LR = 0x60;
5232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit shaping option:
5262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
5272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * if the most recent strongly directional character
5282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
5292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The initial state at the start of the text is assumed to be an Arabic,
5302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * letter, so European digits at the start of the text will change.
5312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Compare to DIGITS_ALEN2AN_INT_LR.
5322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGITS_EN2AN_INIT_AL = 0x80;
5352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Not a valid option value. */
5372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //private static final int DIGITS_RESERVED = 0xa0;
5382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bit mask for digit shaping options.
5412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGITS_MASK = 0xe0;
5442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
5472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGIT_TYPE_AN = 0;
5502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
5532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGIT_TYPE_AN_EXTENDED = 0x100;
5562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bit mask for digit type options.
5592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int DIGIT_TYPE_MASK = 0x0100; // 0x3f00?
5622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * some constants
5652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char HAMZAFE_CHAR       = '\ufe80';
5672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char HAMZA06_CHAR       = '\u0621';
5682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char YEH_HAMZA_CHAR     = '\u0626';
5692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char YEH_HAMZAFE_CHAR   = '\uFE89';
5702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char LAMALEF_SPACE_SUB  = '\uffff';
5712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char TASHKEEL_SPACE_SUB = '\ufffe';
5722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char LAM_CHAR      = '\u0644';
5732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char SPACE_CHAR    = '\u0020';
5742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char SHADDA_CHAR   = '\uFE7C';
5752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char SHADDA06_CHAR = '\u0651';
5762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char TATWEEL_CHAR  = '\u0640';
5772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char SHADDA_TATWEEL_CHAR = '\uFE7D';
5782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char NEW_TAIL_CHAR = '\uFE73';
5792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char OLD_TAIL_CHAR = '\u200B';
5802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int SHAPE_MODE      = 0;
5812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int DESHAPE_MODE    = 1;
5822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean equals(Object rhs) {
5872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return rhs != null &&
5882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            rhs.getClass() == ArabicShaping.class &&
5892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            options == ((ArabicShaping)rhs).options;
5902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
5912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
5942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     ///CLOVER:OFF
5962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int hashCode() {
5972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return options;
5982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
5992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
6012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 2.0
6022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
6032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String toString() {
6042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        StringBuilder buf = new StringBuilder(super.toString());
6052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        buf.append('[');
6062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & LAMALEF_MASK) {
6082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LAMALEF_RESIZE: buf.append("LamAlef resize"); break;
6092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LAMALEF_NEAR: buf.append("LamAlef spaces at near"); break;
6102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LAMALEF_BEGIN: buf.append("LamAlef spaces at begin"); break;
6112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LAMALEF_END: buf.append("LamAlef spaces at end"); break;
6122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LAMALEF_AUTO: buf.append("lamAlef auto"); break;
6132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & TEXT_DIRECTION_MASK) {
6152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case TEXT_DIRECTION_LOGICAL: buf.append(", logical"); break;
6162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case TEXT_DIRECTION_VISUAL_LTR: buf.append(", visual"); break;
6172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & LETTERS_MASK) {
6192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_NOOP: buf.append(", no letter shaping"); break;
6202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_SHAPE: buf.append(", shape letters"); break;
6212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_SHAPE_TASHKEEL_ISOLATED: buf.append(", shape letters tashkeel isolated"); break;
6222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_UNSHAPE: buf.append(", unshape letters"); break;
6232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & SEEN_MASK) {
6252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case SEEN_TWOCELL_NEAR: buf.append(", Seen at near"); break;
6262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & YEHHAMZA_MASK) {
6282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case YEHHAMZA_TWOCELL_NEAR: buf.append(", Yeh Hamza at near"); break;
6292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & TASHKEEL_MASK) {
6312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case TASHKEEL_BEGIN: buf.append(", Tashkeel at begin"); break;
6322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case TASHKEEL_END: buf.append(", Tashkeel at end"); break;
6332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case TASHKEEL_REPLACE_BY_TATWEEL: buf.append(", Tashkeel replace with tatweel"); break;
6342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case TASHKEEL_RESIZE: buf.append(", Tashkeel resize"); break;
6352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & DIGITS_MASK) {
6382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGITS_NOOP: buf.append(", no digit shaping"); break;
6392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGITS_EN2AN: buf.append(", shape digits to AN"); break;
6402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGITS_AN2EN: buf.append(", shape digits to EN"); break;
6412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGITS_EN2AN_INIT_LR: buf.append(", shape digits to AN contextually: default EN"); break;
6422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGITS_EN2AN_INIT_AL: buf.append(", shape digits to AN contextually: default AL"); break;
6432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & DIGIT_TYPE_MASK) {
6452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGIT_TYPE_AN: buf.append(", standard Arabic-Indic digits"); break;
6462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case DIGIT_TYPE_AN_EXTENDED: buf.append(", extended Arabic-Indic digits"); break;
6472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        buf.append("]");
6492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return buf.toString();
6512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
6522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    ///CLOVER:ON
6532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //
6552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // ported api
6562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //
6572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int IRRELEVANT = 4;
6592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int LAMTYPE = 16;
6602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int ALEFTYPE = 32;
6612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int LINKR = 1;
6632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int LINKL = 2;
6642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int LINK_MASK = 3;
6652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int irrelevantPos[] = {
6672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0x0, 0x2, 0x4, 0x6, 0x8, 0xA, 0xC, 0xE
6682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
6692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
6712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char convertLamAlef[] =  {
6722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0622', // FEF5
6732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0622', // FEF6
6742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0623', // FEF7
6752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0623', // FEF8
6762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0625', // FEF9
6772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0625', // FEFA
6782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0627', // FEFB
6792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0627'  // FEFC
6802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
6812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*/
6822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int tailFamilyIsolatedFinal[] = {
6842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB1 */ 1,
6852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB2 */ 1,
6862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB3 */ 0,
6872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB4 */ 0,
6882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB5 */ 1,
6892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB6 */ 1,
6902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB7 */ 0,
6912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB8 */ 0,
6922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEB9 */ 1,
6932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEBA */ 1,
6942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEBB */ 0,
6952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEBC */ 0,
6962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEBD */ 1,
6972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FEBE */ 1
6982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
6992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
7002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int tashkeelMedial[] = {
7012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE70 */ 0,
7022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE71 */ 1,
7032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE72 */ 0,
7042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE73 */ 0,
7052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE74 */ 0,
7062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE75 */ 0,
7072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE76 */ 0,
7082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE77 */ 1,
7092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE78 */ 0,
7102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE79 */ 1,
7112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE7A */ 0,
7122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE7B */ 1,
7132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE7C */ 0,
7142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE7D */ 1,
7152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE7E */ 0,
7162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /* FE7F */ 1
7172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
7182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
7192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char yehHamzaToYeh[] =
7202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    {
7212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* isolated*/ 0xFEEF,
7222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* final   */ 0xFEF0
7232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
7242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
7252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final char convertNormalizedLamAlef[] = {
7262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0622', // 065C
7272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0623', // 065D
7282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0625', // 065E
7292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        '\u0627', // 065F
7302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
7312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
7322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int[] araLink = {
7332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32 + 256 * 0x11,  /*0x0622*/
7342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32 + 256 * 0x13,  /*0x0623*/
7352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x15,  /*0x0624*/
7362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32 + 256 * 0x17,  /*0x0625*/
7372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x19,  /*0x0626*/
7382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32 + 256 * 0x1D,  /*0x0627*/
7392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x1F,  /*0x0628*/
7402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x23,  /*0x0629*/
7412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x25,  /*0x062A*/
7422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x29,  /*0x062B*/
7432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x2D,  /*0x062C*/
7442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x31,  /*0x062D*/
7452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x35,  /*0x062E*/
7462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x39,  /*0x062F*/
7472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x3B,  /*0x0630*/
7482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x3D,  /*0x0631*/
7492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x3F,  /*0x0632*/
7502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x41,  /*0x0633*/
7512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x45,  /*0x0634*/
7522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x49,  /*0x0635*/
7532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x4D,  /*0x0636*/
7542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x51,  /*0x0637*/
7552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x55,  /*0x0638*/
7562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x59,  /*0x0639*/
7572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x5D,  /*0x063A*/
7582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0, 0, 0, 0, 0,                  /*0x063B-0x063F*/
7592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2,                          /*0x0640*/
7602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x61,  /*0x0641*/
7612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x65,  /*0x0642*/
7622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x69,  /*0x0643*/
7632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2       + 16 + 256 * 0x6D,  /*0x0644*/
7642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x71,  /*0x0645*/
7652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x75,  /*0x0646*/
7662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x79,  /*0x0647*/
7672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x7D,  /*0x0648*/
7682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x7F,  /*0x0649*/
7692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2            + 256 * 0x81,  /*0x064A*/
7702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        4, 4, 4, 4,                     /*0x064B-0x064E*/
7712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        4, 4, 4, 4,                     /*0x064F-0x0652*/
7722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        4, 4, 4, 0, 0,                  /*0x0653-0x0657*/
7732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0, 0, 0, 0,                     /*0x0658-0x065B*/
7742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x85,  /*0x065C*/
7752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x87,  /*0x065D*/
7762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x89,  /*0x065E*/
7772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1                + 256 * 0x8B,  /*0x065F*/
7782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0, 0, 0, 0, 0,                  /*0x0660-0x0664*/
7792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0, 0, 0, 0, 0,                  /*0x0665-0x0669*/
7802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0, 0, 0, 0, 0, 0,               /*0x066A-0x066F*/
7812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        4,                              /*0x0670*/
7822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0,                              /*0x0671*/
7832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32,               /*0x0672*/
7842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32,               /*0x0673*/
7852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0,                              /*0x0674*/
7862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1           + 32,               /*0x0675*/
7872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 1,                           /*0x0676-0x0677*/
7882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2, 1+2, 1+2,   /*0x0678-0x067D*/
7892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2, 1+2, 1+2,   /*0x067E-0x0683*/
7902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2,             /*0x0684-0x0687*/
7912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /*0x0688-0x0691*/
7922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 1, 1, 1, 1, 1, 1, 1,         /*0x0692-0x0699*/
7932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2, 1+2, 1+2,   /*0x069A-0x06A3*/
7942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2,             /*0x069A-0x06A3*/
7952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2, 1+2, 1+2,   /*0x06A4-0x06AD*/
7962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2,             /*0x06A4-0x06AD*/
7972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2, 1+2, 1+2,   /*0x06AE-0x06B7*/
7982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2,             /*0x06AE-0x06B7*/
7992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2, 1+2, 1+2,   /*0x06B8-0x06BF*/
8002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2,                       /*0x06B8-0x06BF*/
8012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1,                              /*0x06C0*/
8022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2,                            /*0x06C1*/
8032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /*0x06C2-0x06CB*/
8042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2,                            /*0x06CC*/
8052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1,                              /*0x06CD*/
8062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+2, 1+2, 1+2, 1+2,             /*0x06CE-0x06D1*/
8072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 1                            /*0x06D2-0x06D3*/
8082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
8092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
8102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int[] presLink = {
8112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2,                        /*0xFE70*/
8122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2,                        /*0xFE71*/
8132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2, 0, 1+ 2, 0, 1+ 2,      /*0xFE72-0xFE76*/
8142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 2,                        /*0xFE77*/
8152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+ 2, 1 + 2, 1+2, 1 + 2,      /*0xFE78-0xFE81*/
8162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1+ 2, 1 + 2, 1+2, 1 + 2,      /*0xFE82-0xFE85*/
8172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0, 0 + 32, 1 + 32, 0 + 32,    /*0xFE86-0xFE89*/
8182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 32, 0, 1,  0 + 32,        /*0xFE8A-0xFE8D*/
8192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 32, 0, 2,  1 + 2,         /*0xFE8E-0xFE91*/
8202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0 + 32, 1 + 32, 0,         /*0xFE92-0xFE95*/
8212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        2, 1 + 2, 1, 0,               /*0xFE96-0xFE99*/
8222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1 + 2,               /*0xFE9A-0xFE9D*/
8232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1 + 2,               /*0xFE9E-0xFEA1*/
8242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1 + 2,               /*0xFEA2-0xFEA5*/
8252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1 + 2,               /*0xFEA6-0xFEA9*/
8262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1 + 2,               /*0xFEAA-0xFEAD*/
8272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 1, 0,                   /*0xFEAE-0xFEB1*/
8282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 1, 0,                   /*0xFEB2-0xFEB5*/
8292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEB6-0xFEB9*/
8302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEBA-0xFEBD*/
8312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEBE-0xFEC1*/
8322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEC2-0xFEC5*/
8332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEC6-0xFEC9*/
8342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFECA-0xFECD*/
8352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFECE-0xFED1*/
8362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFED2-0xFED5*/
8372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFED6-0xFED9*/
8382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEDA-0xFEDD*/
8392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEDE-0xFEE1*/
8402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0 + 16, 2 + 16, 1 + 2 +16, /*0xFEE2-0xFEE5*/
8412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1 + 16, 0, 2, 1+2,            /*0xFEE6-0xFEE9*/
8422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEEA-0xFEED*/
8432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEEE-0xFEF1*/
8442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 1, 0,                   /*0xFEF2-0xFEF5*/
8452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 2, 1+2,                 /*0xFEF6-0xFEF9*/
8462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 1, 0,                   /*0xFEFA-0xFEFD*/
8472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1, 0, 1, 0,
8482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        1
8492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
8502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
8512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int[] convertFEto06 = {
8522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /***********0******1******2******3******4******5******6******7******8******9******A******B******C******D******E******F***/
8532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FE7*/   0x64B, 0x64B, 0x64C, 0x64C, 0x64D, 0x64D, 0x64E, 0x64E, 0x64F, 0x64F, 0x650, 0x650, 0x651, 0x651, 0x652, 0x652,
8542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FE8*/   0x621, 0x622, 0x622, 0x623, 0x623, 0x624, 0x624, 0x625, 0x625, 0x626, 0x626, 0x626, 0x626, 0x627, 0x627, 0x628,
8552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FE9*/   0x628, 0x628, 0x628, 0x629, 0x629, 0x62A, 0x62A, 0x62A, 0x62A, 0x62B, 0x62B, 0x62B, 0x62B, 0x62C, 0x62C, 0x62C,
8562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FEA*/   0x62C, 0x62D, 0x62D, 0x62D, 0x62D, 0x62E, 0x62E, 0x62E, 0x62E, 0x62F, 0x62F, 0x630, 0x630, 0x631, 0x631, 0x632,
8572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FEB*/   0x632, 0x633, 0x633, 0x633, 0x633, 0x634, 0x634, 0x634, 0x634, 0x635, 0x635, 0x635, 0x635, 0x636, 0x636, 0x636,
8582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FEC*/   0x636, 0x637, 0x637, 0x637, 0x637, 0x638, 0x638, 0x638, 0x638, 0x639, 0x639, 0x639, 0x639, 0x63A, 0x63A, 0x63A,
8592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FED*/   0x63A, 0x641, 0x641, 0x641, 0x641, 0x642, 0x642, 0x642, 0x642, 0x643, 0x643, 0x643, 0x643, 0x644, 0x644, 0x644,
8602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FEE*/   0x644, 0x645, 0x645, 0x645, 0x645, 0x646, 0x646, 0x646, 0x646, 0x647, 0x647, 0x647, 0x647, 0x648, 0x648, 0x649,
8612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*FEF*/   0x649, 0x64A, 0x64A, 0x64A, 0x64A, 0x65C, 0x65C, 0x65D, 0x65D, 0x65E, 0x65E, 0x65F, 0x65F
8622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
8632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
8642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int shapeTable[][][] = {
8652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        { {0,0,0,0}, {0,0,0,0}, {0,1,0,3}, {0,1,0,1} },
8662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        { {0,0,2,2}, {0,0,1,2}, {0,1,1,2}, {0,1,1,3} },
8672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        { {0,0,0,0}, {0,0,0,0}, {0,1,0,3}, {0,1,0,3} },
8682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        { {0,0,1,2}, {0,0,1,2}, {0,1,1,2}, {0,1,1,3} }
8692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
8702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
8712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
8722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This function shapes European digits to Arabic-Indic digits
8732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * in-place, writing over the input characters.  Data is in visual
8742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * order.
8752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
8762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private void shapeToArabicDigitsWithContext(char[] dest,
8772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                                int start,
8782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                                int length,
8792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                                char digitBase,
8802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                                boolean lastStrongWasAL) {
8812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        UBiDiProps bdp=UBiDiProps.INSTANCE;
8822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        digitBase -= '0'; // move common adjustment out of loop
8832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
8842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int i = start + length; --i >= start;) {
8852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            char ch = dest[i];
8862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            switch (bdp.getClass(ch)) {
8872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case UCharacterDirection.LEFT_TO_RIGHT:
8882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case UCharacterDirection.RIGHT_TO_LEFT:
8892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                lastStrongWasAL = false;
8902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
8912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case UCharacterDirection.RIGHT_TO_LEFT_ARABIC:
8922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                lastStrongWasAL = true;
8932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
8942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case UCharacterDirection.EUROPEAN_NUMBER:
8952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (lastStrongWasAL && ch <= '\u0039') {
8962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    dest[i] = (char)(ch + digitBase);
8972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
8982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
8992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            default:
9002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
9012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
9022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
9032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
9042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
9062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : invertBuffer
9072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: This function inverts the buffer, it's used
9082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           in case the user specifies the buffer to be
9092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           TEXT_DIRECTION_LOGICAL
9102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
9112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static void invertBuffer(char[] buffer,
9122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                     int start,
9132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                     int length) {
9142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(int i = start, j = start + length - 1; i < j; i++, --j) {
9162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            char temp = buffer[i];
9172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buffer[i] = buffer[j];
9182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buffer[j] = temp;
9192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
9202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
9212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
9232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : changeLamAlef
9242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Converts the Alef characters into an equivalent
9252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           LamAlef location in the 0x06xx Range, this is an
9262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           intermediate stage in the operation of the program
9272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           later it'll be converted into the 0xFExx LamAlefs
9282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           in the shaping function.
9292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
9302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static char changeLamAlef(char ch) {
9312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch(ch) {
9322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case '\u0622': return '\u065C';
9332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case '\u0623': return '\u065D';
9342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case '\u0625': return '\u065E';
9352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case '\u0627': return '\u065F';
9362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        default:  return '\u0000'; // not a lamalef
9372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
9382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
9392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
9412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : specialChar
9422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Special Arabic characters need special handling in the shapeUnicode
9432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           function, this function returns 1 or 2 for these special characters
9442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
9452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int specialChar(char ch) {
9462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((ch > '\u0621' && ch < '\u0626') ||
9472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            (ch == '\u0627') ||
9482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            (ch > '\u062E' && ch < '\u0633') ||
9492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            (ch > '\u0647' && ch < '\u064A') ||
9502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            (ch == '\u0629')) {
9512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 1;
9522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if (ch >= '\u064B' && ch<= '\u0652') {
9532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 2;
9542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if (ch >= 0x0653 && ch <= 0x0655 ||
9552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   ch == 0x0670 ||
9562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   ch >= 0xFE70 && ch <= 0xFE7F) {
9572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 3;
9582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
9592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;
9602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
9612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
9622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
9642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : getLink
9652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Resolves the link between the characters as
9662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           Arabic characters have four forms :
9672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           Isolated, Initial, Middle and Final Form
9682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
9692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int getLink(char ch) {
9702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (ch >= '\u0622' && ch <= '\u06D3') {
9712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return araLink[ch - '\u0622'];
9722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if (ch == '\u200D') {
9732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 3;
9742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if (ch >= '\u206D' && ch <= '\u206F') {
9752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 4;
9762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if (ch >= '\uFE70' && ch <= '\uFEFC') {
9772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return presLink[ch - '\uFE70'];
9782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
9792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;
9802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
9812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
9822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
9842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : countSpaces
9852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Counts the number of spaces
9862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           at each end of the logical buffer
9872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
9882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int countSpacesLeft(char[] dest,
9892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                       int start,
9902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                       int count) {
9912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (int i = start, e = start + count; i < e; ++i) {
9922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (dest[i] != SPACE_CHAR) {
9932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return i - start;
9942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
9952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
9962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return count;
9972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
9982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
9992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int countSpacesRight(char[] dest,
10002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                        int start,
10012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                        int count) {
10022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (int i = start + count; --i >= start;) {
10042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (dest[i] != SPACE_CHAR) {
10052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return start + count - 1 - i;
10062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
10072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
10082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return count;
10092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : isTashkeelChar
10132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Returns true for Tashkeel characters else return false
10142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isTashkeelChar(char ch) {
10162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ( ch >='\u064B' && ch <= '\u0652' );
10172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Name     : isSeenTailFamilyChar
10212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Function : returns 1 if the character is a seen family isolated character
10222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           in the FE range otherwise returns 0
10232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int isSeenTailFamilyChar(char ch) {
10262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (ch >= 0xfeb1 && ch < 0xfebf){
10272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             return tailFamilyIsolatedFinal [ch - 0xFEB1];
10282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
10292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             return 0;
10302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
10312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     /* Name     : isSeenFamilyChar
10342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      * Function : returns 1 if the character is a seen family character in the Unicode
10352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      *            06 range otherwise returns 0
10362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int isSeenFamilyChar(char  ch){
10392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (ch >= 0x633 && ch <= 0x636){
10402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 1;
10412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }else {
10422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;
10432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
10442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Name     : isTailChar
10482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Function : returns true if the character matches one of the tail characters
10492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           (0xfe73 or 0x200b) otherwise returns false
10502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isTailChar(char ch) {
10532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(ch == OLD_TAIL_CHAR || ch == NEW_TAIL_CHAR){
10542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return true;
10552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }else{
10562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return false;
10572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
10582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Name     : isAlefMaksouraChar
10622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Function : returns true if the character is a Alef Maksoura Final or isolated
10632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           otherwise returns false
10642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isAlefMaksouraChar(char ch) {
10662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ( (ch == 0xFEEF) || ( ch == 0xFEF0) || (ch == 0x0649));
10672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name     : isYehHamzaChar
10712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function : returns true if the character is a yehHamza isolated or yehhamza
10722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *            final is found otherwise returns false
10732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isYehHamzaChar(char ch) {
10752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if((ch==0xFE89)||(ch==0xFE8A)){
10762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return true;
10772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }else{
10782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
10792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
10802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Name     : isTashkeelCharFE
10842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Function : Returns true for Tashkeel characters in FE range else return false
10852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isTashkeelCharFE(char ch) {
10882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ( ch!=0xFE75 &&(ch>=0xFE70 && ch<= 0xFE7F) );
10892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
10902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
10912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
10922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name: isTashkeelOnTatweelChar
10932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Checks if the Tashkeel Character is on Tatweel or not,if the
10942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           Tashkeel on tatweel (FE range), it returns 1 else if the
10952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           Tashkeel with shadda on tatweel (FC range)return 2 otherwise
10962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           returns 0
10972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
10982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int isTashkeelOnTatweelChar(char ch){
10992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (ch >= 0xfe70 && ch <= 0xfe7f && ch != NEW_TAIL_CHAR && ch != 0xFE75 && ch != SHADDA_TATWEEL_CHAR)
11002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        {
11012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return tashkeelMedial [ch - 0xFE70];
11022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if( (ch >= 0xfcf2 && ch <= 0xfcf4) || (ch == SHADDA_TATWEEL_CHAR)) {
11032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 2;
11042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
11052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;
11062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
11072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
11082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
11102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name: isIsolatedTashkeelChar
11112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Checks if the Tashkeel Character is in the isolated form
11122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           (i.e. Unicode FE range) returns 1 else if the Tashkeel
11132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           with shadda is in the isolated form (i.e. Unicode FC range)
11142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           returns 1 otherwise returns 0
11152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
11162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int isIsolatedTashkeelChar(char ch){
11172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (ch >= 0xfe70 && ch <= 0xfe7f && ch != NEW_TAIL_CHAR && ch != 0xFE75){
11182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return (1 - tashkeelMedial [ch - 0xFE70]);
11192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if(ch >= 0xfc5e && ch <= 0xfc63){
11202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 1;
11212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else{
11222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;
11232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
11242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
11252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
11272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : isAlefChar
11282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Returns 1 for Alef characters else return 0
11292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
11302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isAlefChar(char ch) {
11312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ch == '\u0622' || ch == '\u0623' || ch == '\u0625' || ch == '\u0627';
11322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
11332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
11352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : isLamAlefChar
11362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Returns true for LamAlef characters else return false
11372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
11382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isLamAlefChar(char ch) {
11392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ch >= '\uFEF5' && ch <= '\uFEFC';
11402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
11412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isNormalizedLamAlefChar(char ch) {
11432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ch >= '\u065C' && ch <= '\u065F';
11442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
11452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
11472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : calculateSize
11482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: This function calculates the destSize to be used in preflighting
11492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           when the destSize is equal to 0
11502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
11512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int calculateSize(char[] source,
11522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int sourceStart,
11532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int sourceLength) {
11542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int destSize = sourceLength;
11562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & LETTERS_MASK) {
11582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_SHAPE:
11592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_SHAPE_TASHKEEL_ISOLATED:
11602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (isLogical) {
11612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for (int i = sourceStart, e = sourceStart + sourceLength - 1; i < e; ++i) {
11622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if ((source[i] == LAM_CHAR && isAlefChar(source[i+1])) || isTashkeelCharFE(source[i])){
11632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        --destSize;
11642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
11652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
11662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else { // visual
11672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for(int i = sourceStart + 1, e = sourceStart + sourceLength; i < e; ++i) {
11682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if ((source[i] == LAM_CHAR && isAlefChar(source[i-1])) || isTashkeelCharFE(source[i])) {
11692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        --destSize;
11702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
11712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
11722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
11732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
11742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_UNSHAPE:
11762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for(int i = sourceStart, e = sourceStart + sourceLength; i < e; ++i) {
11772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (isLamAlefChar(source[i])) {
11782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    destSize++;
11792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
11802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
11812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
11822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        default:
11842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
11852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
11862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return destSize;
11882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
11892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
11912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
11922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : countSpaceSub
11932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Counts number of times the subChar appears in the array
11942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
11952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int countSpaceSub(char [] dest,int length, char subChar){
11962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int i = 0;
11972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int count = 0;
11982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while (i < length) {
11992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (dest[i] == subChar) {
12002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              count++;
12012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }
12022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          i++;
12032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
12042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return count;
12052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
12062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
12072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
12082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : shiftArray
12092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Shifts characters to replace space sub characters
12102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
12112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static void shiftArray(char [] dest,int start, int e, char subChar){
12122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int w = e;
12132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int r = e;
12142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while (--r >= start) {
12152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          char ch = dest[r];
12162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (ch != subChar) {
12172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            --w;
12182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (w != r) {
12192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              dest[w] = ch;
12202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
12212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
12222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
12232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   }
12242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
12252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
12262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : flipArray
12272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: inverts array, so that start becomes end and vice versa
12282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
12292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      private static int flipArray(char [] dest, int start, int e, int w){
12302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int r;
12312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (w > start) {
12322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // shift, assume small buffer size so don't use arraycopy
12332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          r = w;
12342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          w = start;
12352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          while (r < e) {
12362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            dest[w++] = dest[r++];
12372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller           }
12382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         } else {
12392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             w = e;
12402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         }
12412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return w;
12422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      }
12432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
12442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
12452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name     : handleTashkeelWithTatweel
12462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function : Replaces Tashkeel as following:
12472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *            Case 1 :if the Tashkeel on tatweel, replace it with Tatweel.
12482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *            Case 2 :if the Tashkeel aggregated with Shadda on Tatweel, replace
12492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *                   it with Shadda on Tatweel.
12502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *            Case 3: if the Tashkeel is isolated replace it with Space.
12512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
12522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
12532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static int handleTashkeelWithTatweel(char[] dest, int sourceLength) {
12542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                     int i;
12552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                     for(i = 0; i < sourceLength; i++){
12562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                         if((isTashkeelOnTatweelChar(dest[i]) == 1)){
12572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             dest[i] = TATWEEL_CHAR;
12582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }else if((isTashkeelOnTatweelChar(dest[i]) == 2)){
12592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             dest[i] = SHADDA_TATWEEL_CHAR;
12602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }else if((isIsolatedTashkeelChar(dest[i])==1) && dest[i] != SHADDA_CHAR){
12612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             dest[i] = SPACE_CHAR;
12622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
12632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                     }
12642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                     return sourceLength;
12652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
12662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
12672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
12682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Name     : handleGeneratedSpaces
12692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *Function : The shapeUnicode function converts Lam + Alef into LamAlef + space,
12702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           and Tashkeel to space.
12712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           handleGeneratedSpaces function puts these generated spaces
12722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           according to the options the user specifies. LamAlef and Tashkeel
12732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           spaces can be replaced at begin, at end, at near or decrease the
12742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           buffer size.
12752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
12762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           There is also Auto option for LamAlef and tashkeel, which will put
12772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           the spaces at end of the buffer (or end of text if the user used
12782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           the option SPACES_RELATIVE_TO_TEXT_BEGIN_END).
12792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
12802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           If the text type was visual_LTR and the option
12812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           SPACES_RELATIVE_TO_TEXT_BEGIN_END was selected the END
12822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           option will place the space at the beginning of the buffer and
12832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           BEGIN will place the space at the end of the buffer.
12842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
12852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  private int handleGeneratedSpaces(char[] dest,
12862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int start,
12872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int length) {
12882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
12892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      int lenOptionsLamAlef = options & LAMALEF_MASK;
12902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      int lenOptionsTashkeel = options & TASHKEEL_MASK;
12912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      boolean lamAlefOn = false;
12922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      boolean tashkeelOn = false;
12932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
12942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      if (!isLogical & !spacesRelativeToTextBeginEnd) {
12952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          switch (lenOptionsLamAlef) {
12962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          case LAMALEF_BEGIN: lenOptionsLamAlef = LAMALEF_END; break;
12972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          case LAMALEF_END: lenOptionsLamAlef = LAMALEF_BEGIN; break;
12982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          default: break;
12992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         }
13002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          switch (lenOptionsTashkeel){
13012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          case TASHKEEL_BEGIN: lenOptionsTashkeel = TASHKEEL_END; break;
13022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          case TASHKEEL_END: lenOptionsTashkeel = TASHKEEL_BEGIN; break;
13032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          default: break;
13042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
13062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      if (lenOptionsLamAlef == LAMALEF_NEAR) {
13092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          for (int i = start, e = i + length; i < e; ++i) {
13102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              if (dest[i] == LAMALEF_SPACE_SUB) {
13112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  dest[i] = SPACE_CHAR;
13122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }
13132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      } else {
13162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          final int e = start + length;
13182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          int wL = countSpaceSub(dest, length, LAMALEF_SPACE_SUB);
13192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          int wT = countSpaceSub(dest, length, TASHKEEL_SPACE_SUB);
13202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lenOptionsLamAlef == LAMALEF_END){
13222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            lamAlefOn = true;
13232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lenOptionsTashkeel == TASHKEEL_END){
13252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            tashkeelOn = true;
13262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lamAlefOn && (lenOptionsLamAlef == LAMALEF_END)) {
13302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            shiftArray(dest, start, e, LAMALEF_SPACE_SUB);
13312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while (wL > start) {
13322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                dest[--wL] = SPACE_CHAR;
13332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
13342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (tashkeelOn && (lenOptionsTashkeel == TASHKEEL_END)){
13372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            shiftArray(dest, start, e, TASHKEEL_SPACE_SUB);
13382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while (wT > start) {
13392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                 dest[--wT] = SPACE_CHAR;
13402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
13412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          lamAlefOn = false;
13442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          tashkeelOn = false;
13452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lenOptionsLamAlef == LAMALEF_RESIZE){
13472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            lamAlefOn = true;
13482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lenOptionsTashkeel == TASHKEEL_RESIZE){
13502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            tashkeelOn = true;
13512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lamAlefOn && (lenOptionsLamAlef == LAMALEF_RESIZE)){
13542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              shiftArray(dest, start, e, LAMALEF_SPACE_SUB);
13552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              wL = flipArray(dest,start,e, wL);
13562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              length = wL - start;
13572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (tashkeelOn && (lenOptionsTashkeel == TASHKEEL_RESIZE)) {
13592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              shiftArray(dest, start, e, TASHKEEL_SPACE_SUB);
13602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              wT = flipArray(dest,start,e, wT);
13612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              length = wT - start;
13622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          lamAlefOn = false;
13652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          tashkeelOn = false;
13662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if ((lenOptionsLamAlef == LAMALEF_BEGIN) ||
13682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              (lenOptionsLamAlef == LAMALEF_AUTO)){
13692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                lamAlefOn = true;
13702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lenOptionsTashkeel == TASHKEEL_BEGIN){
13722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                tashkeelOn = true;
13732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
13742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lamAlefOn && ((lenOptionsLamAlef == LAMALEF_BEGIN)||
13762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            (lenOptionsLamAlef == LAMALEF_AUTO))) { // spaces at beginning
13772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              shiftArray(dest, start, e, LAMALEF_SPACE_SUB);
13782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               wL = flipArray(dest,start,e, wL);
13792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  while (wL < e) {
13802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                      dest[wL++] = SPACE_CHAR;
13812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  }
13822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }
13832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              if(tashkeelOn && (lenOptionsTashkeel == TASHKEEL_BEGIN)){
13842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               shiftArray(dest, start, e, TASHKEEL_SPACE_SUB);
13852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               wT = flipArray(dest,start,e, wT);
13862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  while (wT < e) {
13872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                      dest[wT++] = SPACE_CHAR;
13882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  }
13892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }
13902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller           }
13912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      return length;
13932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  }
13942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
13962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  /*
13972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *Name     :expandCompositCharAtBegin
13982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *Function :Expands the LamAlef character to Lam and Alef consuming the required
13992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *         space from beginning of the buffer. If the text type was visual_LTR
14002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *         and the option SPACES_RELATIVE_TO_TEXT_BEGIN_END was selected
14012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *         the spaces will be located at end of buffer.
14022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *         If there are no spaces to expand the LamAlef, an exception is thrown.
14032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*/
14042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private boolean expandCompositCharAtBegin(char[] dest,int start, int length,
14052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            int lacount) {
14062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     boolean spaceNotFound = false;
14072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     if (lacount > countSpacesRight(dest, start, length)) {
14092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         spaceNotFound = true;
14102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         return spaceNotFound;
14112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     }
14122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     for (int r = start + length - lacount, w = start + length; --r >= start;) {
14132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         char ch = dest[r];
14142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         if (isNormalizedLamAlefChar(ch)) {
14152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             dest[--w] = LAM_CHAR;
14162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             dest[--w] = convertNormalizedLamAlef[ch - '\u065C'];
14172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         } else {
14182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller             dest[--w] = ch;
14192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         }
14202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     }
14212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     return spaceNotFound;
14222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  }
14242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  /*
14262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *Name     : expandCompositCharAtEnd
14272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *Function : Expands the LamAlef character to Lam and Alef consuming the
14282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *           required space from end of the buffer. If the text type was
14292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *           Visual LTR and the option SPACES_RELATIVE_TO_TEXT_BEGIN_END
14302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *           was used, the spaces will be consumed from begin of buffer. If
14312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *           there are no spaces to expand the LamAlef, an exception is thrown.
14322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   */
14332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  private boolean  expandCompositCharAtEnd(char[] dest,int start, int length,
14352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                          int lacount){
14362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      boolean spaceNotFound = false;
14372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      if (lacount > countSpacesLeft(dest, start, length)) {
14392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          spaceNotFound = true;
14402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          return spaceNotFound;
14412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      }
14422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      for (int r = start + lacount, w = start, e = start + length; r < e; ++r) {
14432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          char ch = dest[r];
14442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (isNormalizedLamAlefChar(ch)) {
14452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              dest[w++] = convertNormalizedLamAlef[ch - '\u065C'];
14462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              dest[w++] = LAM_CHAR;
14472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          } else {
14482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              dest[w++] = ch;
14492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
14502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      }
14512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      return spaceNotFound;
14522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  }
14532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  /*
14552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *Name     : expandCompositCharAtNear
14562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *Function : Expands the LamAlef character into Lam + Alef, YehHamza character
14572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *           into Yeh + Hamza, SeenFamily character into SeenFamily character
14582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   *           + Tail, while consuming the space next to the character.
14592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller   */
14602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  private boolean expandCompositCharAtNear(char[] dest,int start, int length,
14622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                       int yehHamzaOption, int seenTailOption, int lamAlefOption){
14632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      boolean spaceNotFound = false;
14652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      if (isNormalizedLamAlefChar(dest[start])) {
14692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          spaceNotFound = true;
14702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          return spaceNotFound;
14712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      }
14722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      for (int i = start + length; --i >=start;) {
14732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          char ch = dest[i];
14742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          if (lamAlefOption == 1 && isNormalizedLamAlefChar(ch)) {
14752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              if (i>start &&dest[i-1] == SPACE_CHAR) {
14762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  dest[i] = LAM_CHAR;
14772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  dest[--i] = convertNormalizedLamAlef[ch - '\u065C'];
14782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              } else {
14792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  spaceNotFound = true;
14802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  return spaceNotFound;
14812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }
14822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }else if(seenTailOption == 1 && isSeenTailFamilyChar(ch) == 1){
14832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              if(i>start &&dest[i-1] == SPACE_CHAR){
14842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  dest[i-1] = tailChar;
14852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              } else{
14862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  spaceNotFound = true;
14872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  return spaceNotFound;
14882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }
14892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }else if(yehHamzaOption == 1 && isYehHamzaChar(ch)){
14902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               if(i>start &&dest[i-1] == SPACE_CHAR){
14922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  dest[i] = yehHamzaToYeh[ch - YEH_HAMZAFE_CHAR];
14932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  dest[i-1] = HAMZAFE_CHAR;
14942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller              }else{
14952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  spaceNotFound = true;
14962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                  return spaceNotFound;
14972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
14982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
14992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
15002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          }
15012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      }
15022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller      return false;
15032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
15042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller  }
15052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
15062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
15072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : expandCompositChar
15082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: LamAlef needs special handling as the LamAlef is
15092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           one character while expanding it will give two
15102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           characters Lam + Alef, so we need to expand the LamAlef
15112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           in near or far spaces according to the options the user
15122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           specifies or increase the buffer size.
15132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           Dest has enough room for the expansion if we are growing.
15142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           lamalef are normalized to the 'special characters'
15152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
15162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int expandCompositChar(char[] dest,
15172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int start,
15182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int length,
15192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int lacount,
15202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int shapingMode) throws ArabicShapingException {
15212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
15222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lenOptionsLamAlef = options & LAMALEF_MASK;
15232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lenOptionsSeen = options & SEEN_MASK;
15242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lenOptionsYehHamza = options & YEHHAMZA_MASK;
15252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean spaceNotFound = false;
15262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
15272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (!isLogical && !spacesRelativeToTextBeginEnd) {
15282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            switch (lenOptionsLamAlef) {
15292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case LAMALEF_BEGIN: lenOptionsLamAlef = LAMALEF_END; break;
15302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case LAMALEF_END: lenOptionsLamAlef = LAMALEF_BEGIN; break;
15312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            default: break;
15322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
15332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
15342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
15352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(shapingMode == 1){
15362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(lenOptionsLamAlef == LAMALEF_AUTO){
15372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(isLogical){
15382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    spaceNotFound = expandCompositCharAtEnd(dest, start, length, lacount);
15392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spaceNotFound){
15402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        spaceNotFound = expandCompositCharAtBegin(dest, start, length, lacount);
15412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spaceNotFound){
15432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        spaceNotFound = expandCompositCharAtNear(dest, start, length,0,0,1);
15442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spaceNotFound){
15462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        throw new ArabicShapingException("No spacefor lamalef");
15472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }else{
15492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    spaceNotFound = expandCompositCharAtBegin(dest, start, length, lacount);
15502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spaceNotFound){
15512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        spaceNotFound = expandCompositCharAtEnd(dest, start, length, lacount);
15522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spaceNotFound){
15542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        spaceNotFound = expandCompositCharAtNear(dest, start, length,0,0,1);
15552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(spaceNotFound){
15572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        throw new ArabicShapingException("No spacefor lamalef");
15582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
15602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }else if(lenOptionsLamAlef == LAMALEF_END){
15612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spaceNotFound = expandCompositCharAtEnd(dest, start, length, lacount);
15622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(spaceNotFound){
15632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    throw new ArabicShapingException("No spacefor lamalef");
15642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
15652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }else if(lenOptionsLamAlef == LAMALEF_BEGIN){
15662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spaceNotFound = expandCompositCharAtBegin(dest, start, length, lacount);
15672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(spaceNotFound){
15682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    throw new ArabicShapingException("No spacefor lamalef");
15692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
15702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }else if(lenOptionsLamAlef == LAMALEF_NEAR){
15712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spaceNotFound = expandCompositCharAtNear(dest, start, length,0,0,1);
15722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(spaceNotFound){
15732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    throw new ArabicShapingException("No spacefor lamalef");
15742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
15752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }else if(lenOptionsLamAlef == LAMALEF_RESIZE){
15762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for (int r = start + length, w = r + lacount; --r >= start;) {
15772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    char ch = dest[r];
15782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (isNormalizedLamAlefChar(ch)) {
15792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[--w] = '\u0644';
15802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[--w] = convertNormalizedLamAlef[ch - '\u065C'];
15812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else {
15822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[--w] = ch;
15832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
15842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
15852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                length += lacount;
15862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
15872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }else{
15882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(lenOptionsSeen == SEEN_TWOCELL_NEAR){
15892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spaceNotFound = expandCompositCharAtNear(dest, start, length,0,1,0);
15902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(spaceNotFound){
15912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    throw new ArabicShapingException("No space for Seen tail expansion");
15922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
15932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
15942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(lenOptionsYehHamza == YEHHAMZA_TWOCELL_NEAR){
15952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                spaceNotFound = expandCompositCharAtNear(dest, start, length,1,0,0);
15962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if(spaceNotFound){
15972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    throw new ArabicShapingException("No space for YehHamza expansion");
15982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
15992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
16002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
16012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return length;
16022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
16032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /* Convert the input buffer from FExx Range into 06xx Range
16062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * to put all characters into the 06xx range
16072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * even the lamalef is converted to the special region in
16082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the 06xx range.  Return the number of lamalef chars found.
16092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
16102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int normalize(char[] dest, int start, int length) {
16112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lacount = 0;
16122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (int i = start, e = i + length; i < e; ++i) {
16132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            char ch = dest[i];
16142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (ch >= '\uFE70' && ch <= '\uFEFC') {
16152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (isLamAlefChar(ch)) {
16162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ++lacount;
16172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
16182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                dest[i] = (char)convertFEto06[ch - '\uFE70'];
16192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
16202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
16212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return lacount;
16222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
16232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
16252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : deshapeNormalize
16262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Convert the input buffer from FExx Range into 06xx Range
16272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           even the lamalef is converted to the special region in the 06xx range.
16282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           According to the options the user enters, all seen family characters
16292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           followed by a tail character are merged to seen tail family character and
16302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           any yeh followed by a hamza character are merged to yehhamza character.
16312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           Method returns the number of lamalef chars found.
16322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
16332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int deshapeNormalize(char[] dest, int start, int length) {
16342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lacount = 0;
16352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int yehHamzaComposeEnabled = 0;
16362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int seenComposeEnabled = 0;
16372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        yehHamzaComposeEnabled = ((options&YEHHAMZA_MASK) == YEHHAMZA_TWOCELL_NEAR) ? 1 : 0;
16392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        seenComposeEnabled = ((options&SEEN_MASK) == SEEN_TWOCELL_NEAR)? 1 : 0;
16402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (int i = start, e = i + length; i < e; ++i) {
16422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            char ch = dest[i];
16432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if( (yehHamzaComposeEnabled == 1) && ((ch == HAMZA06_CHAR) || (ch == HAMZAFE_CHAR))
16452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               && (i < (length - 1)) && isAlefMaksouraChar(dest[i+1] )) {
16462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                dest[i] = SPACE_CHAR;
16472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                dest[i+1] = YEH_HAMZA_CHAR;
16482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       } else if ( (seenComposeEnabled == 1) && (isTailChar(ch)) && (i< (length - 1))
16492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                       && (isSeenTailFamilyChar(dest[i+1])==1) ) {
16502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               dest[i] = SPACE_CHAR;
16512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       }
16522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       else if (ch >= '\uFE70' && ch <= '\uFEFC') {
16532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (isLamAlefChar(ch)) {
16542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ++lacount;
16552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
16562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                dest[i] = (char)convertFEto06[ch - '\uFE70'];
16572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
16582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
16592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return lacount;
16602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
16612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
16632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : shapeUnicode
16642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Converts an Arabic Unicode buffer in 06xx Range into a shaped
16652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           arabic Unicode buffer in FExx Range
16662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
16672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int shapeUnicode(char[] dest,
16682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             int start,
16692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             int length,
16702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             int destSize,
16712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                             int tashkeelFlag)throws ArabicShapingException {
16722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lamalef_count = normalize(dest, start, length);
16742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // resolve the link between the characters.
16762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Arabic characters have four forms: Isolated, Initial, Medial and Final.
16772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Tashkeel characters have two, isolated or medial, and sometimes only isolated.
16782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // tashkeelFlag == 0: shape normally, 1: shape isolated, 2: don't shape
16792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean lamalef_found = false, seenfam_found = false;
16812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean yehhamza_found = false, tashkeel_found = false;
16822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int i = start + length - 1;
16832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int currLink = getLink(dest[i]);
16842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int nextLink = 0;
16852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int prevLink = 0;
16862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lastLink = 0;
16872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        //int prevPos = i;
16882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lastPos = i;
16892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int nx = -2;
16902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int nw = 0;
16912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
16922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while (i >= 0) {
16932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // If high byte of currLink > 0 then there might be more than one shape
16942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if ((currLink & '\uFF00') > 0 || isTashkeelChar(dest[i])) {
16952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                nw = i - 1;
16962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                nx = -2;
16972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                while (nx < 0) { // we need to know about next char
16982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (nw == -1) {
16992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        nextLink = 0;
17002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        nx = Integer.MAX_VALUE;
17012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else {
17022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        nextLink = getLink(dest[nw]);
17032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if ((nextLink & IRRELEVANT) == 0) {
17042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            nx = nw;
17052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        } else {
17062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            --nw;
17072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
17082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
17102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (((currLink & ALEFTYPE) > 0) && ((lastLink & LAMTYPE) > 0)) {
17122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    lamalef_found = true;
17132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    char wLamalef = changeLamAlef(dest[i]); // get from 0x065C-0x065f
17142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (wLamalef != '\u0000') {
17152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        // replace alef by marker, it will be removed later
17162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[i] = '\uffff';
17172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[lastPos] = wLamalef;
17182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        i = lastPos;
17192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    lastLink = prevLink;
17222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    currLink = getLink(wLamalef); // requires '\u0000', unfortunately
17232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
17242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if ((i > 0) && (dest[i-1] == SPACE_CHAR))
17252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                {
17262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if ( isSeenFamilyChar(dest[i]) == 1){
17272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        seenfam_found = true;
17282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else if (dest[i] == YEH_HAMZA_CHAR) {
17292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        yehhamza_found = true;
17302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
17322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                else if(i==0){
17332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if ( isSeenFamilyChar(dest[i]) == 1){
17342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        seenfam_found = true;
17352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else if (dest[i] == YEH_HAMZA_CHAR) {
17362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        yehhamza_found = true;
17372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
17392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // get the proper shape according to link ability of neighbors
17422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // and of character; depends on the order of the shapes
17432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // (isolated, initial, middle, final) in the compatibility area
17442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int flag = specialChar(dest[i]);
17462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int shape = shapeTable[nextLink & LINK_MASK]
17482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    [lastLink & LINK_MASK]
17492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    [currLink & LINK_MASK];
17502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (flag == 1) {
17522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    shape &= 0x1;
17532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else if (flag == 2) {
17542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (tashkeelFlag == 0 &&
17552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        ((lastLink & LINKL) != 0) &&
17562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        ((nextLink & LINKR) != 0) &&
17572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[i] != '\u064C' &&
17582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[i] != '\u064D' &&
17592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        !((nextLink & ALEFTYPE) == ALEFTYPE &&
17602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                          (lastLink & LAMTYPE) == LAMTYPE)) {
17612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        shape = 1;
17632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else if(tashkeelFlag == 2 && dest[i] == SHADDA06_CHAR){
17652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        shape = 1;
17662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else {
17682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        shape = 0;
17692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
17712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (flag == 2) {
17722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (tashkeelFlag == 2 && dest[i] != SHADDA06_CHAR) {
17732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[i] = TASHKEEL_SPACE_SUB;
17742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        tashkeel_found = true;
17752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    else{
17772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        dest[i] = (char)('\uFE70' + irrelevantPos[dest[i] - '\u064B'] + shape);
17782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
17792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // else leave tashkeel alone
17802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
17812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    dest[i] = (char)('\uFE70' + (currLink >> 8) + shape);
17822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
17832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
17842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // move one notch forward
17862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if ((currLink & IRRELEVANT) == 0) {
17872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                prevLink = lastLink;
17882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                lastLink = currLink;
17892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                //prevPos = lastPos;
17902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                lastPos = i;
17912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
17922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            --i;
17942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (i == nx) {
17952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                currLink = nextLink;
17962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                nx = -2;
17972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else if (i != -1) {
17982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                currLink = getLink(dest[i]);
17992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
18002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // If we found a lam/alef pair in the buffer
18032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // call handleGeneratedSpaces to remove the spaces that were added
18042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        destSize = length;
18062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (lamalef_found || tashkeel_found) {
18072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            destSize = handleGeneratedSpaces(dest, start, length);
18082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (seenfam_found || yehhamza_found){
18102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            destSize = expandCompositChar(dest, start, destSize, lamalef_count, SHAPE_MODE);
18112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return destSize;
18132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
18142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
18162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Name    : deShapeUnicode
18172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Function: Converts an Arabic Unicode buffer in FExx Range into unshaped
18182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *           arabic Unicode buffer in 06xx Range
18192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
18202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int deShapeUnicode(char[] dest,
18212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                               int start,
18222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                               int length,
18232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                               int destSize) throws ArabicShapingException {
18242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int lamalef_count = deshapeNormalize(dest, start, length);
18262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // If there was a lamalef in the buffer call expandLamAlef
18282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (lamalef_count != 0) {
18292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // need to adjust dest to fit expanded buffer... !!!
18302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            destSize = expandCompositChar(dest, start, length, lamalef_count,DESHAPE_MODE);
18312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
18322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            destSize = length;
18332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return destSize;
18362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
18372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int internalShape(char[] source,
18392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int sourceStart,
18402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int sourceLength,
18412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              char[] dest,
18422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int destStart,
18432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                              int destSize) throws ArabicShapingException {
18442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (sourceLength == 0) {
18462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return 0;
18472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (destSize == 0) {
18502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (((options & LETTERS_MASK) != LETTERS_NOOP) &&
18512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                ((options & LAMALEF_MASK) == LAMALEF_RESIZE)) {
18522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return calculateSize(source, sourceStart, sourceLength);
18542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
18552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return sourceLength; // by definition
18562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
18572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // always use temp buffer
18602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        char[] temp = new char[sourceLength * 2]; // all lamalefs requiring expansion
18612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        System.arraycopy(source, sourceStart, temp, 0, sourceLength);
18622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (isLogical) {
18642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            invertBuffer(temp, 0, sourceLength);
18652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int outputSize = sourceLength;
18682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        switch (options & LETTERS_MASK) {
18702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_SHAPE_TASHKEEL_ISOLATED:
18712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            outputSize = shapeUnicode(temp, 0, sourceLength, destSize, 1);
18722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
18732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_SHAPE:
18752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if( ((options&TASHKEEL_MASK)> 0) &&
18762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                ((options&TASHKEEL_MASK) !=TASHKEEL_REPLACE_BY_TATWEEL)) {
18772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   /* Call the shaping function with tashkeel flag == 2 for removal of tashkeel */
18782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                outputSize = shapeUnicode(temp, 0, sourceLength, destSize, 2);
18792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }else {
18802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   //default Call the shaping function with tashkeel flag == 1 */
18812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    outputSize = shapeUnicode(temp, 0, sourceLength, destSize, 0);
18822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   /*After shaping text check if user wants to remove tashkeel and replace it with tatweel*/
18842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   if( (options&TASHKEEL_MASK) == TASHKEEL_REPLACE_BY_TATWEEL){
18852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                       outputSize = handleTashkeelWithTatweel(temp,sourceLength);
18862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                   }
18872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller               }
18882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
18892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        case LETTERS_UNSHAPE:
18912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            outputSize = deShapeUnicode(temp, 0, sourceLength, destSize);
18922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
18932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        default:
18952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            break;
18962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
18972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
18982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (outputSize > destSize) {
18992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new ArabicShapingException("not enough room for result data");
19002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
19012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ((options & DIGITS_MASK) != DIGITS_NOOP) {
19032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            char digitBase = '\u0030'; // European digits
19042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            switch (options & DIGIT_TYPE_MASK) {
19052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case DIGIT_TYPE_AN:
19062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                digitBase = '\u0660';  // Arabic-Indic digits
19072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case DIGIT_TYPE_AN_EXTENDED:
19102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                digitBase = '\u06f0';  // Eastern Arabic-Indic digits (Persian and Urdu)
19112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            default:
19142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
19162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            switch (options & DIGITS_MASK) {
19182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case DIGITS_EN2AN:
19192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                {
19202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int digitDelta = digitBase - '\u0030';
19212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    for (int i = 0; i < outputSize; ++i) {
19222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        char ch = temp[i];
19232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if (ch <= '\u0039' && ch >= '\u0030') {
19242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            temp[i] += digitDelta;
19252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
19262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
19272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
19282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case DIGITS_AN2EN:
19312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                {
19322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    char digitTop = (char)(digitBase + 9);
19332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    int digitDelta = '\u0030' - digitBase;
19342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    for (int i = 0; i < outputSize; ++i) {
19352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        char ch = temp[i];
19362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if (ch <= digitTop && ch >= digitBase) {
19372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            temp[i] += digitDelta;
19382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
19392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
19402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
19412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case DIGITS_EN2AN_INIT_LR:
19442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                shapeToArabicDigitsWithContext(temp, 0, outputSize, digitBase, false);
19452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            case DIGITS_EN2AN_INIT_AL:
19482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                shapeToArabicDigitsWithContext(temp, 0, outputSize, digitBase, true);
19492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            default:
19522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                break;
19532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
19542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
19552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (isLogical) {
19572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            invertBuffer(temp, 0, outputSize);
19582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
19592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        System.arraycopy(temp, 0, dest, destStart, outputSize);
19612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
19622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return outputSize;
19632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
19642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
1965