2023-06-21 12:46:23 -04:00

773 lines
34 KiB
C#

using System;
using System.Text;
/*
* Copyright 2003 by Paulo Soares.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
namespace iTextSharp.text.pdf {
/**
* Shape arabic characters. This code was inspired by an LGPL'ed C library:
* Pango ( see http://www.pango.com/ ). Note that the code of this is the
* original work of Paulo Soares. Hence it is perfectly justifiable to distribute
* it under the MPL.
*
* @author Paulo Soares (psoares@consiste.pt)
*/
public class ArabicLigaturizer {
static bool IsVowel(char s) {
return ((s >= '\u064B') && (s <= '\u0655')) || (s == '\u0670');
}
static char Charshape(char s, int which)
/* which 0=isolated 1=final 2=initial 3=medial */
{
int l, r, m;
if ((s >= '\u0621') && (s <= '\u06D3')) {
l = 0;
r = chartable.Length - 1;
while (l <= r) {
m = (l + r) / 2;
if (s == chartable[m][0]) {
return chartable[m][which + 1];
}
else if (s < chartable[m][0]) {
r = m - 1;
}
else {
l = m + 1;
}
}
}
else if (s >= '\ufef5' && s <= '\ufefb')
return (char)(s + which);
return s;
}
static int Shapecount(char s) {
int l, r, m;
if ((s >= '\u0621') && (s <= '\u06D3') && !IsVowel(s)) {
l = 0;
r = chartable.Length - 1;
while (l <= r) {
m = (l + r) / 2;
if (s == chartable[m][0]) {
return chartable[m].Length - 1;
}
else if (s < chartable[m][0]) {
r = m - 1;
}
else {
l = m + 1;
}
}
}
else if (s == ZWJ) {
return 4;
}
return 1;
}
static int Ligature(char newchar, Charstruct oldchar) {
/* 0 == no ligature possible; 1 == vowel; 2 == two chars; 3 == Lam+Alef */
int retval = 0;
if (oldchar.basechar == 0)
return 0;
if (IsVowel(newchar)) {
retval = 1;
if ((oldchar.vowel != 0) && (newchar != SHADDA)) {
retval = 2; /* we eliminate the old vowel .. */
}
switch (newchar) {
case SHADDA:
if (oldchar.mark1 == 0) {
oldchar.mark1 = SHADDA;
}
else {
return 0; /* no ligature possible */
}
break;
case HAMZABELOW:
switch (oldchar.basechar) {
case ALEF:
oldchar.basechar = ALEFHAMZABELOW;
retval = 2;
break;
case LAM_ALEF:
oldchar.basechar = LAM_ALEFHAMZABELOW;
retval = 2;
break;
default:
oldchar.mark1 = HAMZABELOW;
break;
}
break;
case HAMZAABOVE:
switch (oldchar.basechar) {
case ALEF:
oldchar.basechar = ALEFHAMZA;
retval = 2;
break;
case LAM_ALEF:
oldchar.basechar = LAM_ALEFHAMZA;
retval = 2;
break;
case WAW:
oldchar.basechar = WAWHAMZA;
retval = 2;
break;
case YEH:
case ALEFMAKSURA:
case FARSIYEH:
oldchar.basechar = YEHHAMZA;
retval = 2;
break;
default: /* whatever sense this may make .. */
oldchar.mark1 = HAMZAABOVE;
break;
}
break;
case MADDA:
switch (oldchar.basechar) {
case ALEF:
oldchar.basechar = ALEFMADDA;
retval = 2;
break;
}
break;
default:
oldchar.vowel = newchar;
break;
}
if (retval == 1) {
oldchar.lignum++;
}
return retval;
}
if (oldchar.vowel != 0) { /* if we already joined a vowel, we can't join a Hamza */
return 0;
}
switch (oldchar.basechar) {
case LAM:
switch (newchar) {
case ALEF:
oldchar.basechar = LAM_ALEF;
oldchar.numshapes = 2;
retval = 3;
break;
case ALEFHAMZA:
oldchar.basechar = LAM_ALEFHAMZA;
oldchar.numshapes = 2;
retval = 3;
break;
case ALEFHAMZABELOW:
oldchar.basechar = LAM_ALEFHAMZABELOW;
oldchar.numshapes = 2;
retval = 3;
break;
case ALEFMADDA:
oldchar.basechar = LAM_ALEFMADDA;
oldchar.numshapes = 2;
retval = 3;
break;
}
break;
case (char)0:
oldchar.basechar = newchar;
oldchar.numshapes = Shapecount(newchar);
retval = 1;
break;
}
return retval;
}
static void Copycstostring(StringBuilder str, Charstruct s, int level) {
/* s is a shaped charstruct; i is the index into the string */
if (s.basechar == 0)
return;
str.Append(s.basechar);
s.lignum--;
if (s.mark1 != 0) {
if ((level & ar_novowel) == 0) {
str.Append(s.mark1);
s.lignum--;
}
else {
s.lignum--;
}
}
if (s.vowel != 0) {
if ((level & ar_novowel) == 0) {
str.Append(s.vowel);
s.lignum--;
}
else { /* vowel elimination */
s.lignum--;
}
}
}
// return len
internal static void Doublelig(StringBuilder str, int level)
/* Ok. We have presentation ligatures in our font. */
{
int len;
int olen = len = str.Length;
int j = 0, si = 1;
char lapresult;
while (si < olen) {
lapresult = (char)0;
if ((level & ar_composedtashkeel) != 0) {
switch (str[j]) {
case SHADDA:
switch (str[si]) {
case KASRA:
lapresult = '\uFC62';
break;
case FATHA:
lapresult = '\uFC60';
break;
case DAMMA:
lapresult = '\uFC61';
break;
case '\u064C':
lapresult = '\uFC5E';
break;
case '\u064D':
lapresult = '\uFC5F';
break;
}
break;
case KASRA:
if (str[si] == SHADDA)
lapresult = '\uFC62';
break;
case FATHA:
if (str[si] == SHADDA)
lapresult = '\uFC60';
break;
case DAMMA:
if (str[si] == SHADDA)
lapresult = '\uFC61';
break;
}
}
if ((level & ar_lig) != 0) {
switch (str[j]) {
case '\uFEDF': /* LAM initial */
switch (str[si]) {
case '\uFE9E':
lapresult = '\uFC3F';
break; /* JEEM final */
case '\uFEA0':
lapresult = '\uFCC9';
break; /* JEEM medial */
case '\uFEA2':
lapresult = '\uFC40';
break; /* HAH final */
case '\uFEA4':
lapresult = '\uFCCA';
break; /* HAH medial */
case '\uFEA6':
lapresult = '\uFC41';
break; /* KHAH final */
case '\uFEA8':
lapresult = '\uFCCB';
break; /* KHAH medial */
case '\uFEE2':
lapresult = '\uFC42';
break; /* MEEM final */
case '\uFEE4':
lapresult = '\uFCCC';
break; /* MEEM medial */
}
break;
case '\uFE97': /* TEH inital */
switch (str[si]) {
case '\uFEA0':
lapresult = '\uFCA1';
break; /* JEEM medial */
case '\uFEA4':
lapresult = '\uFCA2';
break; /* HAH medial */
case '\uFEA8':
lapresult = '\uFCA3';
break; /* KHAH medial */
}
break;
case '\uFE91': /* BEH inital */
switch (str[si]) {
case '\uFEA0':
lapresult = '\uFC9C';
break; /* JEEM medial */
case '\uFEA4':
lapresult = '\uFC9D';
break; /* HAH medial */
case '\uFEA8':
lapresult = '\uFC9E';
break; /* KHAH medial */
}
break;
case '\uFEE7': /* NOON inital */
switch (str[si]) {
case '\uFEA0':
lapresult = '\uFCD2';
break; /* JEEM initial */
case '\uFEA4':
lapresult = '\uFCD3';
break; /* HAH medial */
case '\uFEA8':
lapresult = '\uFCD4';
break; /* KHAH medial */
}
break;
case '\uFEE8': /* NOON medial */
switch (str[si]) {
case '\uFEAE':
lapresult = '\uFC8A';
break; /* REH final */
case '\uFEB0':
lapresult = '\uFC8B';
break; /* ZAIN final */
}
break;
case '\uFEE3': /* MEEM initial */
switch (str[si]) {
case '\uFEA0':
lapresult = '\uFCCE';
break; /* JEEM medial */
case '\uFEA4':
lapresult = '\uFCCF';
break; /* HAH medial */
case '\uFEA8':
lapresult = '\uFCD0';
break; /* KHAH medial */
case '\uFEE4':
lapresult = '\uFCD1';
break; /* MEEM medial */
}
break;
case '\uFED3': /* FEH initial */
switch (str[si]) {
case '\uFEF2':
lapresult = '\uFC32';
break; /* YEH final */
}
break;
default:
break;
} /* end switch string[si] */
}
if (lapresult != 0) {
str[j] = lapresult;
len--;
si++; /* jump over one character */
/* we'll have to change this, too. */
}
else {
j++;
str[j] = str[si];
si++;
}
}
str.Length = len;
}
static bool Connects_to_left(Charstruct a) {
return a.numshapes > 2;
}
internal static void Shape(char[] text, StringBuilder str, int level) {
/* string is assumed to be empty and big enough.
* text is the original text.
* This routine does the basic arabic reshaping.
* *len the number of non-null characters.
*
* Note: We have to unshape each character first!
*/
int join;
int which;
char nextletter;
int p = 0; /* initialize for output */
Charstruct oldchar = new Charstruct();
Charstruct curchar = new Charstruct();
while (p < text.Length) {
nextletter = text[p++];
//nextletter = unshape (nextletter);
join = Ligature(nextletter, curchar);
if (join == 0) { /* shape curchar */
int nc = Shapecount(nextletter);
//(*len)++;
if (nc == 1) {
which = 0; /* final or isolated */
}
else {
which = 2; /* medial or initial */
}
if (Connects_to_left(oldchar)) {
which++;
}
which = which % (curchar.numshapes);
curchar.basechar = Charshape(curchar.basechar, which);
/* get rid of oldchar */
Copycstostring(str, oldchar, level);
oldchar = curchar; /* new values in oldchar */
/* init new curchar */
curchar = new Charstruct();
curchar.basechar = nextletter;
curchar.numshapes = nc;
curchar.lignum++;
// (*len) += unligature (&curchar, level);
}
else if (join == 1) {
}
// else
// {
// (*len) += unligature (&curchar, level);
// }
// p = g_utf8_next_char (p);
}
/* Handle last char */
if (Connects_to_left(oldchar))
which = 1;
else
which = 0;
which = which % (curchar.numshapes);
curchar.basechar = Charshape(curchar.basechar, which);
/* get rid of oldchar */
Copycstostring(str, oldchar, level);
Copycstostring(str, curchar, level);
}
internal static int Arabic_shape(char[] src, int srcoffset, int srclength, char[] dest, int destoffset, int destlength, int level) {
char[] str = new char[srclength];
for (int k = srclength + srcoffset - 1; k >= srcoffset; --k)
str[k - srcoffset] = src[k];
StringBuilder str2 = new StringBuilder(srclength);
Shape(str, str2, level);
if ((level & (ar_composedtashkeel | ar_lig)) != 0)
Doublelig(str2, level);
// string.Reverse();
System.Array.Copy(str2.ToString().ToCharArray(), 0, dest, destoffset, str2.Length);
return str2.Length;
}
internal static void ProcessNumbers(char[] text, int offset, int length, int options) {
int limit = offset + length;
if ((options & DIGITS_MASK) != 0) {
char digitBase = '\u0030'; // European digits
switch (options & DIGIT_TYPE_MASK) {
case DIGIT_TYPE_AN:
digitBase = '\u0660'; // Arabic-Indic digits
break;
case DIGIT_TYPE_AN_EXTENDED:
digitBase = '\u06f0'; // Eastern Arabic-Indic digits (Persian and Urdu)
break;
default:
break;
}
switch (options & DIGITS_MASK) {
case DIGITS_EN2AN: {
int digitDelta = digitBase - '\u0030';
for (int i = offset; i < limit; ++i) {
char ch = text[i];
if (ch <= '\u0039' && ch >= '\u0030') {
text[i] += (char)digitDelta;
}
}
}
break;
case DIGITS_AN2EN: {
char digitTop = (char)(digitBase + 9);
int digitDelta = '\u0030' - digitBase;
for (int i = offset; i < limit; ++i) {
char ch = text[i];
if (ch <= digitTop && ch >= digitBase) {
text[i] += (char)digitDelta;
}
}
}
break;
case DIGITS_EN2AN_INIT_LR:
ShapeToArabicDigitsWithContext(text, 0, length, digitBase, false);
break;
case DIGITS_EN2AN_INIT_AL:
ShapeToArabicDigitsWithContext(text, 0, length, digitBase, true);
break;
default:
break;
}
}
}
internal static void ShapeToArabicDigitsWithContext(char[] dest, int start, int length, char digitBase, bool lastStrongWasAL) {
digitBase -= '0'; // move common adjustment out of loop
int limit = start + length;
for (int i = start; i < limit; ++i) {
char ch = dest[i];
switch (BidiOrder.GetDirection(ch)) {
case BidiOrder.L:
case BidiOrder.R:
lastStrongWasAL = false;
break;
case BidiOrder.AL:
lastStrongWasAL = true;
break;
case BidiOrder.EN:
if (lastStrongWasAL && ch <= '\u0039') {
dest[i] = (char)(ch + digitBase);
}
break;
default:
break;
}
}
}
private const char ALEF = '\u0627';
private const char ALEFHAMZA = '\u0623';
private const char ALEFHAMZABELOW = '\u0625';
private const char ALEFMADDA = '\u0622';
private const char LAM = '\u0644';
private const char HAMZA = '\u0621';
private const char TATWEEL = '\u0640';
private const char ZWJ = '\u200D';
private const char HAMZAABOVE = '\u0654';
private const char HAMZABELOW = '\u0655';
private const char WAWHAMZA = '\u0624';
private const char YEHHAMZA = '\u0626';
private const char WAW = '\u0648';
private const char ALEFMAKSURA = '\u0649';
private const char YEH = '\u064A';
private const char FARSIYEH = '\u06CC';
private const char SHADDA = '\u0651';
private const char KASRA = '\u0650';
private const char FATHA = '\u064E';
private const char DAMMA = '\u064F';
private const char MADDA = '\u0653';
private const char LAM_ALEF = '\uFEFB';
private const char LAM_ALEFHAMZA = '\uFEF7';
private const char LAM_ALEFHAMZABELOW = '\uFEF9';
private const char LAM_ALEFMADDA = '\uFEF5';
private static char[][] chartable = {
new char[]{'\u0621', '\uFE80'}, /* HAMZA */
new char[]{'\u0622', '\uFE81', '\uFE82'}, /* ALEF WITH MADDA ABOVE */
new char[]{'\u0623', '\uFE83', '\uFE84'}, /* ALEF WITH HAMZA ABOVE */
new char[]{'\u0624', '\uFE85', '\uFE86'}, /* WAW WITH HAMZA ABOVE */
new char[]{'\u0625', '\uFE87', '\uFE88'}, /* ALEF WITH HAMZA BELOW */
new char[]{'\u0626', '\uFE89', '\uFE8A', '\uFE8B', '\uFE8C'}, /* YEH WITH HAMZA ABOVE */
new char[]{'\u0627', '\uFE8D', '\uFE8E'}, /* ALEF */
new char[]{'\u0628', '\uFE8F', '\uFE90', '\uFE91', '\uFE92'}, /* BEH */
new char[]{'\u0629', '\uFE93', '\uFE94'}, /* TEH MARBUTA */
new char[]{'\u062A', '\uFE95', '\uFE96', '\uFE97', '\uFE98'}, /* TEH */
new char[]{'\u062B', '\uFE99', '\uFE9A', '\uFE9B', '\uFE9C'}, /* THEH */
new char[]{'\u062C', '\uFE9D', '\uFE9E', '\uFE9F', '\uFEA0'}, /* JEEM */
new char[]{'\u062D', '\uFEA1', '\uFEA2', '\uFEA3', '\uFEA4'}, /* HAH */
new char[]{'\u062E', '\uFEA5', '\uFEA6', '\uFEA7', '\uFEA8'}, /* KHAH */
new char[]{'\u062F', '\uFEA9', '\uFEAA'}, /* DAL */
new char[]{'\u0630', '\uFEAB', '\uFEAC'}, /* THAL */
new char[]{'\u0631', '\uFEAD', '\uFEAE'}, /* REH */
new char[]{'\u0632', '\uFEAF', '\uFEB0'}, /* ZAIN */
new char[]{'\u0633', '\uFEB1', '\uFEB2', '\uFEB3', '\uFEB4'}, /* SEEN */
new char[]{'\u0634', '\uFEB5', '\uFEB6', '\uFEB7', '\uFEB8'}, /* SHEEN */
new char[]{'\u0635', '\uFEB9', '\uFEBA', '\uFEBB', '\uFEBC'}, /* SAD */
new char[]{'\u0636', '\uFEBD', '\uFEBE', '\uFEBF', '\uFEC0'}, /* DAD */
new char[]{'\u0637', '\uFEC1', '\uFEC2', '\uFEC3', '\uFEC4'}, /* TAH */
new char[]{'\u0638', '\uFEC5', '\uFEC6', '\uFEC7', '\uFEC8'}, /* ZAH */
new char[]{'\u0639', '\uFEC9', '\uFECA', '\uFECB', '\uFECC'}, /* AIN */
new char[]{'\u063A', '\uFECD', '\uFECE', '\uFECF', '\uFED0'}, /* GHAIN */
new char[]{'\u0640', '\u0640', '\u0640', '\u0640', '\u0640'}, /* TATWEEL */
new char[]{'\u0641', '\uFED1', '\uFED2', '\uFED3', '\uFED4'}, /* FEH */
new char[]{'\u0642', '\uFED5', '\uFED6', '\uFED7', '\uFED8'}, /* QAF */
new char[]{'\u0643', '\uFED9', '\uFEDA', '\uFEDB', '\uFEDC'}, /* KAF */
new char[]{'\u0644', '\uFEDD', '\uFEDE', '\uFEDF', '\uFEE0'}, /* LAM */
new char[]{'\u0645', '\uFEE1', '\uFEE2', '\uFEE3', '\uFEE4'}, /* MEEM */
new char[]{'\u0646', '\uFEE5', '\uFEE6', '\uFEE7', '\uFEE8'}, /* NOON */
new char[]{'\u0647', '\uFEE9', '\uFEEA', '\uFEEB', '\uFEEC'}, /* HEH */
new char[]{'\u0648', '\uFEED', '\uFEEE'}, /* WAW */
new char[]{'\u0649', '\uFEEF', '\uFEF0', '\uFBE8', '\uFBE9'}, /* ALEF MAKSURA */
new char[]{'\u064A', '\uFEF1', '\uFEF2', '\uFEF3', '\uFEF4'}, /* YEH */
new char[]{'\u0671', '\uFB50', '\uFB51'}, /* ALEF WASLA */
new char[]{'\u0679', '\uFB66', '\uFB67', '\uFB68', '\uFB69'}, /* TTEH */
new char[]{'\u067A', '\uFB5E', '\uFB5F', '\uFB60', '\uFB61'}, /* TTEHEH */
new char[]{'\u067B', '\uFB52', '\uFB53', '\uFB54', '\uFB55'}, /* BEEH */
new char[]{'\u067E', '\uFB56', '\uFB57', '\uFB58', '\uFB59'}, /* PEH */
new char[]{'\u067F', '\uFB62', '\uFB63', '\uFB64', '\uFB65'}, /* TEHEH */
new char[]{'\u0680', '\uFB5A', '\uFB5B', '\uFB5C', '\uFB5D'}, /* BEHEH */
new char[]{'\u0683', '\uFB76', '\uFB77', '\uFB78', '\uFB79'}, /* NYEH */
new char[]{'\u0684', '\uFB72', '\uFB73', '\uFB74', '\uFB75'}, /* DYEH */
new char[]{'\u0686', '\uFB7A', '\uFB7B', '\uFB7C', '\uFB7D'}, /* TCHEH */
new char[]{'\u0687', '\uFB7E', '\uFB7F', '\uFB80', '\uFB81'}, /* TCHEHEH */
new char[]{'\u0688', '\uFB88', '\uFB89'}, /* DDAL */
new char[]{'\u068C', '\uFB84', '\uFB85'}, /* DAHAL */
new char[]{'\u068D', '\uFB82', '\uFB83'}, /* DDAHAL */
new char[]{'\u068E', '\uFB86', '\uFB87'}, /* DUL */
new char[]{'\u0691', '\uFB8C', '\uFB8D'}, /* RREH */
new char[]{'\u0698', '\uFB8A', '\uFB8B'}, /* JEH */
new char[]{'\u06A4', '\uFB6A', '\uFB6B', '\uFB6C', '\uFB6D'}, /* VEH */
new char[]{'\u06A6', '\uFB6E', '\uFB6F', '\uFB70', '\uFB71'}, /* PEHEH */
new char[]{'\u06A9', '\uFB8E', '\uFB8F', '\uFB90', '\uFB91'}, /* KEHEH */
new char[]{'\u06AD', '\uFBD3', '\uFBD4', '\uFBD5', '\uFBD6'}, /* NG */
new char[]{'\u06AF', '\uFB92', '\uFB93', '\uFB94', '\uFB95'}, /* GAF */
new char[]{'\u06B1', '\uFB9A', '\uFB9B', '\uFB9C', '\uFB9D'}, /* NGOEH */
new char[]{'\u06B3', '\uFB96', '\uFB97', '\uFB98', '\uFB99'}, /* GUEH */
new char[]{'\u06BA', '\uFB9E', '\uFB9F'}, /* NOON GHUNNA */
new char[]{'\u06BB', '\uFBA0', '\uFBA1', '\uFBA2', '\uFBA3'}, /* RNOON */
new char[]{'\u06BE', '\uFBAA', '\uFBAB', '\uFBAC', '\uFBAD'}, /* HEH DOACHASHMEE */
new char[]{'\u06C0', '\uFBA4', '\uFBA5'}, /* HEH WITH YEH ABOVE */
new char[]{'\u06C1', '\uFBA6', '\uFBA7', '\uFBA8', '\uFBA9'}, /* HEH GOAL */
new char[]{'\u06C5', '\uFBE0', '\uFBE1'}, /* KIRGHIZ OE */
new char[]{'\u06C6', '\uFBD9', '\uFBDA'}, /* OE */
new char[]{'\u06C7', '\uFBD7', '\uFBD8'}, /* U */
new char[]{'\u06C8', '\uFBDB', '\uFBDC'}, /* YU */
new char[]{'\u06C9', '\uFBE2', '\uFBE3'}, /* KIRGHIZ YU */
new char[]{'\u06CB', '\uFBDE', '\uFBDF'}, /* VE */
new char[]{'\u06CC', '\uFBFC', '\uFBFD', '\uFBFE', '\uFBFF'}, /* FARSI YEH */
new char[]{'\u06D0', '\uFBE4', '\uFBE5', '\uFBE6', '\uFBE7'}, /* E */
new char[]{'\u06D2', '\uFBAE', '\uFBAF'}, /* YEH BARREE */
new char[]{'\u06D3', '\uFBB0', '\uFBB1'} /* YEH BARREE WITH HAMZA ABOVE */
};
public const int ar_nothing = 0x0;
public const int ar_novowel = 0x1;
public const int ar_composedtashkeel = 0x4;
public const int ar_lig = 0x8;
/**
* Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
*/
public const int DIGITS_EN2AN = 0x20;
/**
* Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
*/
public const int DIGITS_AN2EN = 0x40;
/**
* Digit shaping option:
* Replace European digits (U+0030...U+0039) by Arabic-Indic digits
* if the most recent strongly directional character
* is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
* The initial state at the start of the text is assumed to be not an Arabic,
* letter, so European digits at the start of the text will not change.
* Compare to DIGITS_ALEN2AN_INIT_AL.
*/
public const int DIGITS_EN2AN_INIT_LR = 0x60;
/**
* Digit shaping option:
* Replace European digits (U+0030...U+0039) by Arabic-Indic digits
* if the most recent strongly directional character
* is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
* The initial state at the start of the text is assumed to be an Arabic,
* letter, so European digits at the start of the text will change.
* Compare to DIGITS_ALEN2AN_INT_LR.
*/
public const int DIGITS_EN2AN_INIT_AL = 0x80;
/** Not a valid option value. */
private const int DIGITS_RESERVED = 0xa0;
/**
* Bit mask for digit shaping options.
*/
public const int DIGITS_MASK = 0xe0;
/**
* Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
*/
public const int DIGIT_TYPE_AN = 0;
/**
* Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
*/
public const int DIGIT_TYPE_AN_EXTENDED = 0x100;
/**
* Bit mask for digit type options.
*/
public const int DIGIT_TYPE_MASK = '\u0100'; // '\u3f00'?
private class Charstruct {
internal char basechar;
internal char mark1; /* has to be initialized to zero */
internal char vowel;
internal int lignum; /* is a ligature with lignum aditional characters */
internal int numshapes = 1;
};
}
}