src.com.ibm.as400.access.BidiShape Maven / Gradle / Ivy
Show all versions of jt400-jdk8 Show documentation
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: BidiShape.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2005 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
/**
* Multi-threading considerations: This class is thread-safe,
* since its only public method is synchronized, and there are no instance
* variables. However, to avoid delays, each thread should use its own
* instances of this class.
**/
class BidiShape {
/* replaces Arabic base letters by the appropriate
* presentation forms.
*/
/* Link attribute are unsigned 16 bit integer with the following format: */
/* bit 0: links to the right */
/* bit 1: links to the left */
/* bit 2: is irrelevant to linking */
/* bit 4: Lam type UNI Code */
/* bit 5: Alef type UNI Code */
/* bit 8-15: offset to presentation shapes starting at U+FE70 */
static final char Tail = 0x200B ;
private static final short shapeTable[][][]=
{
/* lastLink = 0 | lastLink = 1 | lastLink = 2 | lastLink = 3 */
/* nextLink = 0 */ { {0,0,0,0}, {0,0,0,0}, {0,1,0,3}, {0,1,0,1} },
/* nextLink = 1 */ { {0,0,2,2}, {0,0,1,2}, {0,1,1,2}, {0,1,1,3} },
/* nextLink = 2 */ { {0,0,0,0}, {0,0,0,0}, {0,1,0,3}, {0,1,0,3} },
/* nextLink = 3 */ { {0,0,1,2}, {0,0,1,2}, {0,1,1,2}, {0,1,1,3} } };
private static final int convertFEto06[] =
{
0x64B, 0x64B,
0x64C, 0x64C,
0x64D, 0x64D,
0x64E, 0x64E,
0x64F, 0x64F,
0x650, 0x650,
0x651, 0x651,
0x652, 0x652,
0x621,
0x622, 0x622,
0x623,0x623,
0x624,0x624,
0x625,0x625,
0x626,0x626,0x626,0x626,
0x627,0x627,
0x628,0x628,0x628,0x628,
0x629,0x629,
0x62A,0x62A,0x62A,0x62A,
0x62B,0x62B,0x62B,0x62B,
0x62C,0x62C,0x62C,0x62C,
0x62D,0x62D,0x62D,0x62D,
0x62E,0x62E,0x62E,0x62E,
0x62F,0x62F,
0x630,0x630,
0x631,0x631,
0x632,0x632,
0x633,0x633, 0x633,0x633,
0x634, 0x634,0x634,0x634,
0x635,0x635,0x635,0x635,
0x636,0x636,0x636,0x636,
0x637,0x637,0x637,0x637,
0x638,0x638,0x638,0x638,
0x639,0x639,0x639,0x639,
0x63A,0x63A,0x63A,0x63A,
0x641,0x641,0x641,0x641,
0x642,0x642,0x642,0x642,
0x643,0x643,0x643,0x643,
0x644,0x644,0x644,0x644,
0x645,0x645,0x645,0x645,
0x646,0x646,0x646,0x646,
0x647,0x647,0x647,0x647,
0x648, 0x648,
0x649,0x649,
0x64A,0x64A,0x64A,0x64A,
0x65C, 0x65C,
0x65D,0x65D,
0x65E,0x65E,
0x65F,0x65F
};
private static final int convert06toFE[] =
{
0x10,
0x11,
0x13,
0x15,
0x17,
0x19,
0x1D,
0x1F,
0x23,
0x25,
0x29,
0x2D,
0x31,
0x35,
0x39,
0x3B,
0x3D,
0x3F,
0x41,
0x45,
0x49,
0x4D,
0x51,
0x55,
0x59,
0x5D,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x61,
0x65,
0x69,
0x6D,
0x71,
0x75,
0x79,
0x7D,
0x7F,
0x81,
0x0,
0x2,
0x4,
0x6,
0x8,
0xA,
0xC,
0xE
};
/*****************************************************************************/
private static final int Link06[]=
{
1 + 32 + 256 * 0x11,
1 + 32 + 256 * 0x13,
1 + 256 * 0x15,
1 + 32 + 256 * 0x17,
1 + 2 + 256 * 0x19,
1 + 32 + 256 * 0x1D,
1 + 2 + 256 * 0x1F,
1 + 256 * 0x23,
1 + 2 + 256 * 0x25,
1 + 2 + 256 * 0x29,
1 + 2 + 256 * 0x2D,
1 + 2 + 256 * 0x31,
1 + 2 + 256 * 0x35,
1 + 256 * 0x39,
1 + 256 * 0x3B,
1 + 256 * 0x3D,
1 + 256 * 0x3F,
1 + 2 + 256 * 0x41,
1 + 2 + 256 * 0x45,
1 + 2 + 256 * 0x49,
1 + 2 + 256 * 0x4D,
1 + 2 + 256 * 0x51,
1 + 2 + 256 * 0x55,
1 + 2 + 256 * 0x59,
1 + 2 + 256 * 0x5D,
0, 0, 0, 0, 0, /* 0x63B - 0x63F */
1 + 2,
1 + 2 + 256 * 0x61,
1 + 2 + 256 * 0x65,
1 + 2 + 256 * 0x69,
1 + 2 + 16 + 256 * 0x6D,
1 + 2 + 256 * 0x71,
1 + 2 + 256 * 0x75,
1 + 2 + 256 * 0x79,
1 + 256 * 0x7D,
1 + 256 * 0x7F,
1 + 2 + 256 * 0x81,
4, 4, 4, 4,
4, 4, 4, 4, /* 0x64B - 0x652 */
0, 0, 0, 0, 0,
0, 0, 0, 0, /* 0x653 - 0x65B */
1 + 256 * 0x85,
1 + 256 * 0x87,
1 + 256 * 0x89,
1 + 256 * 0x8B,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, /* 0x660 - 0x66F */
4,
0,
1 + 32,
1 + 32,
0,
1 + 32,
1, 1,
1+2, 1+2, 1+2, 1+2, 1+2, 1+2,
1+2, 1+2, 1+2, 1+2, 1+2, 1+2,
1+2, 1+2, 1+2, 1+2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2,
1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2,
1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2,
1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2, 1+2,
1,
1+2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1+2,
1,
1+2, 1+2, 1+2, 1+2,
1, 1
};
/*****************************************************************************/
private static final short LinkFE[]=
{
1 + 2,
1 + 2,
1 + 2, 0, 1+ 2, 0, 1+ 2,
1 + 2,
1+ 2, 1 + 2, 1+2, 1 + 2,
1+ 2, 1 + 2, 1+2, 1 + 2,
0, 0 + 32, 1 + 32, 0 + 32,
1 + 32, 0, 1, 0 + 32,
1 + 32, 0, 2, 1 + 2,
1, 0 + 32, 1 + 32, 0,
2, 1 + 2, 1, 0,
1, 0, 2, 1 + 2,
1, 0, 2, 1 + 2,
1, 0, 2, 1 + 2,
1, 0, 2, 1 + 2,
1, 0, 2, 1 + 2,
1, 0, 1, 0,
1, 0, 1, 0,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0 + 16, 2 + 16, 1 + 2 +16,
1 + 16, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 2, 1+2,
1, 0, 1, 0,
1, 0, 2, 1+2,
1, 0, 1, 0,
1, 0, 1, 0,
1
};
/*****************************************************************************/
private static final short IrreleventPos[]=
{
0x0,
0x2,
0x4,
0x6,
0x8,
0xA,
0xC,
0xE,
} ;
//Used by Lam-Alef methods
static char AlefType[] = {
'\u0622',
'\u0622',
'\u0623',
'\u0623',
'\u0625',
'\u0625',
'\u0627',
'\u0627',
};
//Used by Tashkeel handeling methods
static char Tashkeel[] = {
'\ufe70', //Tanween Fath
'\ufe72', //Tanween Dam
'\ufe74', //Tanween Kasr
'\ufe76', //Fatha
'\ufe78', //Dama
'\ufe7A', //Kassra
'\ufe7c', //Shadda
'\ufe7e', //Sekooun
};
//Used by Tashkeel handeling methods
static char Tashkeel_Tatweel[] = {
'\ufe71', //Tanween Fath with tatweel
'\ufe72', //Tanween Dam -- No Ttween Dam with Tashkeel in the FE Range
'\ufe74', //Tanween Kasr -- No Ttween Dam with Tashkeel in the FE Range
'\ufe77', //Fatha with tatweel
'\ufe79', //Dama with tatweel
'\ufe7b', //Kassra with tatweel
'\ufe7d', //Shadda with tatweel
'\ufe7f', //Sekooun with tatweel
};
private static final int LINKR = 1;
private static final int LINKL = 2;
private static final int IRRELEVANT = 4;
private static final int LAMTYPE = 16;
private static final int ALEFTYPE = 32;
private static final int LINKFIELD = 3;
/**
* Method shapingRoutine
* This method represents the shaping routine.
* @param inAttr The input Bidi Attributes (TextType, TextShape, ...etc.)
* @param outAttr The output Bidi Attributes (TextType, TextShape, ...etc.)
* @param str The buffer to be shaped.
* @param rtl The buffer orientation.
*/
synchronized void shapingRoutine(BidiFlagSet inAttr, BidiFlagSet outAttr, char str[], boolean rtl)
{
int currLink; /* link attributes of current character at position Ix */
int lastLink=0; /* link attributes of the last character which was not irrelevant to linking */
int nextLink=0; /* link attributes of the next character which is not irrelevant to linking */
int prevLink=0; /* link attributes of the character before the last which is not irrelevant to linking */
int lastPos; /* position of the last character which was not irrelevant */
int Nx; /* position of the next character which is not irrelevant */
int prevPos; /* position of the character before the last which was not irr*/
int iEnd, Nw, step, Shape, Ix;
char wLamalef;
int flag;
BidiFlag inTextType, outTextType, /*inTextShape,*/ outTextShape;
int bufLen = str.length;
if ( bufLen == 0)
return;
//Initialize variables
inTextType = inAttr.getType();
outTextType = outAttr.getType();
//inTextShape = inAttr.getText();
outTextShape = outAttr.getText();
if(inTextType == BidiFlag.TYPE_VISUAL && outTextType == BidiFlag.TYPE_IMPLICIT) //Visual to Implicit
{ //We must test if this check is the best check for shapping Shaped -> Nominal
for (int idx = 0; idx < bufLen ; idx++)
{
//Convert the characters from FE to 06 range
if ( (str[idx] >= 0xFE70) && (str[idx] <= 0xFEF4 ) )
{
//This change fix NULL pointer exception with IBMJDK 1.4
//IBMJDK1.4 cann't resolve casting correctly
int newCharValue = str[idx] - 0xFE70;
str[idx] = (char)(convertFEto06 [ newCharValue ] ) ;
}
}
}//end if Visual to Implicit
else if(outTextType == BidiFlag.TYPE_VISUAL)
{ //We must test if this check is the best check for shapping -> Nominal
/* This pass is done so that Arabic characters are processed in language */
/* order. If outAttr is RTL , this means start processing from the begining of*/
/* the str (source) till its end; if outAttr is LTR , this means start */
/* processing from the end of the str (source) till its beginning */
if (rtl)
{
Ix = 0; /* Setting the low boundary of the processing */
iEnd = str.length ; /* Setting the high boundary of the processing */
step = +1;
}
else {
Ix = str.length - 1; /* Setting the low boundary of the processing */
iEnd = -1; /* Setting the high boundary of the processing */
step = -1;
}
prevLink = 0;
lastLink = 0;
currLink = uba_getLink ( str[Ix] );
prevPos = Ix;
lastPos = Ix;
Nx = -2;
while ( Ix != iEnd )
{
if ((currLink & 0xFF00) > 0 ) /* If there are more than one shape */
{
Nw = Ix + step;
while ( Nx < 0 ) { /* we need to know about next char */
if (Nw == iEnd) {
nextLink = 0;
Nx = 30000; /* will stay so until end of pass*/
}
else {
nextLink = uba_getLink(str[Nw]);
if ((nextLink & IRRELEVANT) == 0)
Nx = Nw;
else Nw += step;
}
}
if ( ((currLink & ALEFTYPE) > 0) && ((lastLink & LAMTYPE) > 0))
{
wLamalef = Lamalef( str[Ix] ); //get from 0x065C-0x065f
if ( wLamalef != 0)
{
if (rtl)
{
str[lastPos] = wLamalef ;
for(int h=Ix;h0; h--)
{str[h] =str[h-1];}
str[0] =(char) 0x0020;
Ix=lastPos;
} //LTR
}//(wLamalef != 0)
lastLink = prevLink;
currLink = uba_getLink(wLamalef);
Nx = -2; //force recompute of nextLink
}
/* get the proper shape according to link ability of
neighbors and of character; depends on the order of
the shapes (isolated, initial, middle, final) in the
compatibility area */
flag=specialChar (str[Ix]);
if (outTextShape == BidiFlag.TEXT_INITIAL)
{
if(flag==0)
Shape = 2;
else
Shape = 0;
}
else if (outTextShape == BidiFlag.TEXT_MIDDLE)
{
if(flag == 0)
Shape = 3;
else
Shape = 1;
}
else if (outTextShape == BidiFlag.TEXT_FINAL)
{
if(flag == 0)
Shape = 1;
else
Shape = 1;
}
else if (outTextShape == BidiFlag.TEXT_ISOLATED)
{
Shape = 0;
}
else
{
Shape = shapeTable[nextLink & (LINKR + LINKL)]
[lastLink & (LINKR + LINKL)]
[currLink & (LINKR + LINKL)];
}
str[Ix] = (char)(0xFE70 + ( currLink >> 8 ) + Shape) ;
}
/* move one notch forward */
if ((currLink & IRRELEVANT) == 0) {
prevLink = lastLink;
lastLink = currLink;
prevPos = lastPos;
lastPos = Ix;
}
//Tashkil characters
if ( ((currLink & IRRELEVANT) > 0) && (0 <= (str[Ix] - 0x064B)) && ((str[Ix] - 0x064B) < IrreleventPos.length ) ) {
int charidx = str[Ix] - 0x064B;
int MyShape =0;
int next = (int) (nextLink & (LINKR + LINKL));
int last =lastLink & (LINKR + LINKL);
if ( ( (last==3)&& (next==1) )
|| ( (last==3) && (next==3) ) )
MyShape= 1;
if ( ((nextLink & ALEFTYPE) > 0) && ((lastLink & LAMTYPE) > 0) )
MyShape=0;
if ( (str[Ix]==0x064C) //Wawdoma
|| (str[Ix]==0x064D) ) //kasrten
MyShape=0;
str[Ix] = (char)(0xFE70 + IrreleventPos[charidx]+ MyShape) ;
}
Ix += step;
if ( Ix == Nx ) {
currLink = nextLink;
Nx = -2;
}
else
{
if (Ix != iEnd)
currLink = uba_getLink ( str[Ix]) ;
}
} //end while
}// end of else to visual
}
/**
* Method shape.
* In this method, the shaping process (Arabic options handling and shaping routine) is performed.
*
* @param inAttr The input Bidi Attributes (TextType, TextShape, ...etc.)
* @param outAttr The output Bidi Attributes (TextType, TextShape, ...etc.)
* @param str The buffer to be shaped.
* @param optionSet The Arabic options used in shaping process.
*/
synchronized char[] shape(BidiFlagSet inAttr, BidiFlagSet outAttr, char str[], ArabicOptionSet optionSet)
{
boolean rtl = true;
BidiFlag inTextType, outTextType, /*inTextShape,*/ outTextShape;
ArabicOption lamAlefOpt, seenOpt, yehHamzaOpt, tashkeelOpt;
int bufLen = str.length;
if ( bufLen == 0)
return str;
if(optionSet == null) //Set Arabic options to the default values in case user did not specify them.
{
optionSet = new ArabicOptionSet();
}
//Initialize variables
inTextType = inAttr.getType();
outTextType = outAttr.getType();
rtl = outAttr.getOrientation() == BidiFlag.ORIENTATION_RTL;
//inTextShape = inAttr.getText();
outTextShape = outAttr.getText();
lamAlefOpt = optionSet.getLamAlefMode();
seenOpt = optionSet.getSeenMode();
yehHamzaOpt = optionSet.getYehHamzaMode();
tashkeelOpt = optionSet.getTashkeelMode();
if(inTextType == BidiFlag.TYPE_VISUAL && outTextType == BidiFlag.TYPE_IMPLICIT) //Visual to Implicit
{
//Seen Deshaping
if( (seenOpt == ArabicOption.SEEN_NEAR) || (seenOpt == ArabicOption.SEEN_AUTO) )
deshapeSeenNear(str,bufLen);
/*Yeh Hamza DeShapping*/
if (( yehHamzaOpt == ArabicOption.YEHHAMZA_TWO_CELL_NEAR ) || ( yehHamzaOpt == ArabicOption.YEHHAMZA_AUTO))
{
deshapeYehHamzaTwoCellNear(str, bufLen);
}
/*Tashkeel DeShapping*/
if((tashkeelOpt == ArabicOption.TASHKEEL_KEEP) || ( tashkeelOpt == ArabicOption.TASHKEEL_AUTO))
{
//No processing is done
}
else if (tashkeelOpt == ArabicOption.TASHKEEL_CUSTOMIZED_ATBEGIN)
{
customizeTashkeelAtBegin( str, bufLen);
}
else if (tashkeelOpt == ArabicOption.TASHKEEL_CUSTOMIZED_ATEND)
{
customizeTashkeelAtEnd( str, bufLen);
}
/*LamAlef DeShapping*/
if( lamAlefOpt == ArabicOption.LAMALEF_RESIZE_BUFFER ){
str=deshapeLamAlefWithResizeBuffer(str, bufLen);
bufLen= str.length;
}
else if (lamAlefOpt == ArabicOption.LAMALEF_NEAR)
{
deshapeLamAlefNear(str, bufLen);
}
else if (lamAlefOpt == ArabicOption.LAMALEF_ATBEGIN)
{
deshapeLamAlefAtBegin(str, bufLen);
}
else if (lamAlefOpt == ArabicOption.LAMALEF_ATEND)
{
deshapeLamAlefAtEnd(str, bufLen);
}
else if(lamAlefOpt == ArabicOption.LAMALEF_AUTO ){
deshapeLamAlefAuto(str, bufLen,rtl);
}
shapingRoutine(inAttr, outAttr, str, rtl);
}//end if Visual to Implicit
else if(outTextType == BidiFlag.TYPE_VISUAL)
{
shapingRoutine(inAttr, outAttr, str, rtl);
/* Seen Shapping*/
if( (seenOpt == ArabicOption.SEEN_NEAR) || (seenOpt == ArabicOption.SEEN_AUTO) )
shapeSeenNear(str,bufLen, rtl);
/* Yeh Hamza Shapping*/
if( (yehHamzaOpt == ArabicOption.YEHHAMZA_TWO_CELL_NEAR) || ( yehHamzaOpt == ArabicOption.YEHHAMZA_AUTO)){
shapeYehHamzaTwoCellNear(str, bufLen, rtl);
}
/*Tashkeel Shapping*/
if((tashkeelOpt == ArabicOption.TASHKEEL_KEEP) || ( tashkeelOpt == ArabicOption.TASHKEEL_AUTO))
{
//No processing is done
}
else if (tashkeelOpt == ArabicOption.TASHKEEL_CUSTOMIZED_ATBEGIN)
{
customizeTashkeelAtBegin( str, bufLen);
}
else if (tashkeelOpt == ArabicOption.TASHKEEL_CUSTOMIZED_ATEND)
{
customizeTashkeelAtEnd( str, bufLen);
}
/* LamAlef Handling*/
if( lamAlefOpt == ArabicOption.LAMALEF_RESIZE_BUFFER ){
str=handleLamAlefWithResizeBuffer(str, bufLen, rtl);
bufLen=str.length;
}
else if (lamAlefOpt == ArabicOption.LAMALEF_NEAR){
handleLamAlefNear(str, bufLen, rtl);
}
else if (lamAlefOpt == ArabicOption.LAMALEF_ATBEGIN)
{
// In case of LTR spaces are already in the absolute begining of buffer
if (rtl)
handleLamAlefAtBegin(str, bufLen);
}
else if (lamAlefOpt == ArabicOption.LAMALEF_ATEND)
{
// In case of RTL spaces are already in the absolute end of buffer
if (!rtl)
handleLamAlefAtEnd(str, bufLen);
}
else if(lamAlefOpt == ArabicOption.LAMALEF_AUTO )
{
//No processing is done
}
}// end of else if to shaped
return str;
}
/**
* Method uba_getLink.
*
* @param x the character to be checked
* @return int
*/
private static int uba_getLink(char x)
{
if(x >= 0x0622 && x <= 0x06D3) //06 Range
return(Link06[x-0x0622]);
else if(x == 0x200D) //(ZWJ)
return(3);
else if(x >= 0x206D && x <= 0x206F) //Alternate Formating
return(4);
else if(x >= 0xFE70 && x <= 0xFEFC) //FE range
return(LinkFE[x-0xFE70]);
else
return(0);
}
/**
* Method Lamalef.
*
* @param x the character to be checked
* @return char
*/
private static char Lamalef(char x)
{
switch(x)
{
case 0x0622: return (0x065C);
case 0x0623: return (0x065D);
case 0x0625: return (0x065E);
case 0x0627: return (0x065F);
}
return (0);
}
/**
* Method specialChar.
*
* @param ch the character to be checked
* @return int
*/
private static int specialChar(char ch)
{
// hamza ,
if((ch >= 0x0621 && ch < 0x0626)|| (ch == 0x0627 )||
(ch > 0x062e && ch < 0x0633) ||
(ch > 0x0647 && ch < 0x064a) || ch == 0x0629)
return(1);
else
return(0);
}
/**
* Method SeenChar.
* This method checks if the passed chracter is one of the Seen family characters.
* Seen family characters are Seen, Sheen, Sad and Dad. For each character of them there are
* two shapes.
*
* @param ch The character to be checked.
* @return boolean true, if the character belongs to Seen family.
* false, otherwise
*/
private static boolean SeenChar(char ch)
{
if ( (ch==0xFEB1) ||
(ch==0xFEB2) ||
(ch==0xFEB5) ||
(ch==0xFEB6) ||
(ch==0xFEB9) ||
(ch==0xFEBA) ||
(ch==0xFEBD) ||
(ch==0xFEBE)
)
return(true);
else
return(false);
}
//The following methods are responsible for handling Arabic Options
/* ******************************** */
/* */
/* Methods for Lam Alef handling */
/* */
/* ******************************** */
/**
* Method handleLamAlefWithResizeBuffer.
* This method shrink the input buffer by the number of Lam-Alef occurences.
* The buffer is supposed to come with LamAlef shaped with a space at end/begin
* of the buffer depending on wherther the output is rtl or ltr.
* And the method role is to remove this space and shrink the buffer
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
* @param rtl The buffer orientation.
* @return int The new size of the buffer.
*
*/
private char[] handleLamAlefWithResizeBuffer(char[] buffer, int length, boolean rtl){
int counter =0 ;
int lamAlefCount=0;
char compressedBuffer[];
for (counter=0;counter= 0xFEF5) && (buffer[counter] <= 0xFEFC ))
lamAlefCount++;
}
if(lamAlefCount == 0) return buffer;
compressedBuffer = new char[length-lamAlefCount];
if(rtl){//Remove the sapces at the end of the buffer
System.arraycopy(buffer,0, compressedBuffer, 0, buffer.length-lamAlefCount);
}
else {//Remove the sapces in the begining of the buffer
System.arraycopy(buffer, lamAlefCount, compressedBuffer, 0, buffer.length-lamAlefCount);
}
return compressedBuffer;
}
/**
* Method deshapeLamAlefWithResizeBuffer.
* This method enlarge the input buffer by the number of Lam-Alef occurences.
* All Lam-Alef characters are expanded to Lam + Alef characters .
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
* @param rtl The buffer orientation.
* @return int The new size of the buffer.
*
*/
private char[] deshapeLamAlefWithResizeBuffer(char[] buffer, int length){
char ChAlefType;
int oldBufferCounter =0 ;
int newBufferCounter =0 ;
int lamAlefCount=0;
char expandedBuffer[];
for (oldBufferCounter=0;oldBufferCounter= 0xFEF5) && (buffer[oldBufferCounter] <= 0xFEFC ))
lamAlefCount++;
}
if(lamAlefCount == 0) return buffer;
expandedBuffer = new char[length+lamAlefCount];
oldBufferCounter =0;
while (oldBufferCounter < length)
{
if ( ( buffer[oldBufferCounter] >= 0xFEF5) && (buffer[oldBufferCounter] <= 0xFEFC ))
{
ChAlefType = (char)AlefType[buffer[oldBufferCounter]-0xFEF5];
expandedBuffer[newBufferCounter] = '\u0644';
newBufferCounter++;
expandedBuffer[newBufferCounter] = ChAlefType;
}
else
{
expandedBuffer[newBufferCounter] = buffer[oldBufferCounter];
}
newBufferCounter++;
oldBufferCounter ++;
}
return expandedBuffer;
}
/**
* Method handleLamAlefNear
* This method moves the spaces located in the begining of buffer with respect to
* orientation (buffer[0] in LTR and buffer[length -1] in RTL) to the position near
* to each of Lam-Alef characters.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
* @param rtl The buffer orientation.
*
*/
private void handleLamAlefNear(char[] buffer, int length, boolean rtl)
{
int count = 0;
int tempIdx;
while (count < length)
{
if ((buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) && buffer[length - 1] == 0x0020 && rtl)
{
for (tempIdx = length -1; tempIdx > count + 1; tempIdx--)
buffer [tempIdx] = buffer [tempIdx - 1];
if(count < length - 1)
buffer[count + 1] = 0x0020;
}
else if ((buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) && buffer[0] == 0x0020 && !rtl)
{
for (tempIdx = 0; tempIdx < count - 1; tempIdx++)
buffer [tempIdx] = buffer [tempIdx + 1];
if (count != 0)
buffer[count - 1] = 0x0020;
}
count ++;
}
}
/**
* Method deshapeLamAlefNear
* This method expands Lam-Alef character to Lam and Alef using the space near to
* Lam-Alef character. In case no spaces occurs near this character no processing
* will be done and the output buffer will contain the Lam-Alef character in its
* FE hexadecimal value.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void deshapeLamAlefNear(char[] buffer, int length)
{
char ChAlefType;
int count = 1;
while (count < length)
{
if ( (buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) &&
( (count!= length - 1) && ( buffer[count + 1] == 0x0020) )
)
{
ChAlefType = (char)AlefType[buffer[count]-0xFEF5];
buffer[count + 1] = ChAlefType;
buffer[count] = '\u0644';
}
count ++;
}
}
/**
* Method handleLamAlefAtBegin
* This method moves the space located in the absolute end of buffer to the absolute begin of buffer so these
* spaces can be used in Lam-Alef deshaping in the other way back.
* character.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void handleLamAlefAtBegin(char[] buffer, int length)
{
int count = 0;
int tempIdx, lamAlefOccurences = 0;
while (count < length)
{
if ((buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) && buffer[length - 1] == 0x0020)
{
for (tempIdx = length - 1; tempIdx >lamAlefOccurences; tempIdx--)
buffer [tempIdx] = buffer [tempIdx - 1];
buffer[lamAlefOccurences] = 0x0020;
lamAlefOccurences++;
count++;
}
count ++;
}
}
/**
* Method deshapeLamAlefAtBegin
* This method expands Lam-Alef character to Lam and Alef using the spaces in the absolute begin of buffer.
* In case no spaces occurs near this character no processing will be done and the output buffer will contain
* the Lam-Alef character in its FE hexadecimal value.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void deshapeLamAlefAtBegin(char[] buffer, int length)
{
char ChAlefType;
int count = 0 ;
int tempIdx;
while (count < length)
{
if ( (buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) && buffer[0] == 0x0020)
{
ChAlefType = (char)AlefType[buffer[count]-0xFEF5];
for (tempIdx = 0; tempIdx < count - 1; tempIdx++)
buffer [tempIdx] = buffer [tempIdx + 1];
buffer[count - 1] = '\u0644';
buffer[count] = ChAlefType;
}
count ++;
}
}
/**
* Method handleLamAlefAtEnd
* This method moves the space located in the absolute begin of buffer to the absolute end of buffer so these
* spaces can be used in Lam-Alef deshaping in the other way back.
* character.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void handleLamAlefAtEnd(char[] buffer, int length)
{
int count = 0;
int tempIdx, lamAlefOccurences = 0;
while (count < length)
{
if ((buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) && buffer[0] == 0x0020)
{
for (tempIdx = 0; tempIdx < length - lamAlefOccurences - 1; tempIdx++)
buffer [tempIdx] = buffer [tempIdx + 1];
buffer[length - lamAlefOccurences - 1] = 0x0020;
lamAlefOccurences++;
}
count ++;
}
}
/**
* Method deshapeLamAlefAtEnd
* This method expands Lam-Alef character to Lam and Alef using the spaces in the absolute end of buffer.
* In case no spaces occurs near this character no processing will be done and the output buffer will contain
* the Lam-Alef character in its FE hexadecimal value.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void deshapeLamAlefAtEnd(char[] buffer, int length)
{
char ChAlefType;
int count = 0 ;
int tempIdx;
while (count < length)
{
if ( (buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC ) && buffer[length - 1] == 0x0020)
{
ChAlefType = (char)AlefType[buffer[count]-0xFEF5];
for (tempIdx = length - 1; tempIdx > count + 1; tempIdx--)
buffer [tempIdx] = buffer [tempIdx - 1];
buffer[count] = '\u0644';
buffer[count + 1] = ChAlefType;
}
count ++;
}
}
/**
* Method handleLamAlefAuto.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
* @param rtl The buffer orientation.
*
*/
private void handleLamAlefAuto(char[] buffer, int length, boolean rtl)
{}
/**
* Method deshapeLamAlefAuto.
*
* This method expands LamAlef character to Lam and Alef characters consuming the space
* located in the in the begining of buffer with respect to orientation (buffer[0] in LTR
* and buffer[length -1] in RTL)
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
* @param rtl The buffer orientation.
*/
private void deshapeLamAlefAuto(char[] buffer, int length, boolean rtl){
char ChAlefType;
int count =0 ;
while (count < length)
{
if ( ( buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC )&&buffer[length-1]==0x0020&&rtl)
{
ChAlefType = (char)AlefType[buffer[count]-0xFEF5];
for(int h=length-1;h>count;h--)
buffer[h] = buffer[h-1];
buffer[count+1] = ChAlefType;
buffer[count] = '\u0644';
}
else if ( ( buffer[count] >= 0xFEF5) && (buffer[count] <= 0xFEFC )&&buffer[0]==0x0020&&!rtl)
{
ChAlefType = (char)AlefType[buffer[count]-0xFEF5];
for(int h=0;h= 0) && ( buffer[idx-1] == 0x0020) ) )
buffer[idx-1] = BidiShape.Tail;
}
}
}
/**
* This method replaces Seen Tail by a space near to the Seen character.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void deshapeSeenNear(char[] buffer, int length)
{
for (int idx = 0; idx < length ; idx++)
{
if (buffer[idx] == BidiShape.Tail)
buffer[idx]= (char)0x0020;
}
}
/**
* Method shapeSeenAtBegin.
*
* @param buffer
* @param length
* @param rtl
*/
private void shapeSeenAtBegin(char[] buffer, int length, boolean rtl){}
/**
* Method deshapeSeenAtBegin.
*
* @param buffer
* @param length
* @param rtl
*/
private void deshapeSeenAtBegin(char[] buffer, int length, boolean rtl){}
/**
* Method shapeSeenAtEnd.
*
* @param buffer
* @param length
* @param rtl
*/
private void shapeSeenAtEnd(char[] buffer, int length, boolean rtl){}
/**
* Method deshapeSeenAtEnd.
*
* @param buffer
* @param length
* @param rtl
*/
private void deshapeSeenAtEnd(char[] buffer, int length, boolean rtl){}
/**
* Method handleSeenAuto.
*
* @param buffer
* @param length
* @param rtl
*/
private void handleSeenAuto(char[] buffer, int length, boolean rtl){}
/**
* Method deshapeSeenAuto.
* @param buffer
* @param length
* @param rtl
*/
private void deshapeSeenAuto(char[] buffer, int length, boolean rtl){}
/* ******************************** */
/* */
/* Methods for Yeh Hamza handling */
/* */
/* ******************************** */
/**
* Method shapeYehHamzaTwoCellNear.
* This method convert every YehHamza to Yeh + Hamza depending on whether the output
* buffer is rtl or ltr using the space near the YeahHamza
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
* @param rtl The buffer orientation.
*
*/
private void shapeYehHamzaTwoCellNear(char[] buffer, int length, boolean rtl){
int counter=0;
for (counter =0; counter < length ; counter++)
{
if(rtl)
{
if ( buffer[counter] == 0xfe8a )
{
buffer[counter]= 0xfef0;//Yeh
if ( (counter+1 < length) && ( buffer[counter+1] == 0x0020) )
buffer[counter+1] = 0xfe80; //hamza
}
if ( buffer[counter] == 0xfe89 )
{
buffer[counter] = 0xfeef ;//Yeh
if ( (counter+1 < length) && ( buffer[counter+1] == 0x0020) )
buffer[counter+1] = 0xfe80 ;//hamza
}
}
else
{
if ( buffer[counter] == 0xfe8a )
{
buffer[counter]= 0xfef0;//Yeh
if ( (counter-1 >= 0) && ( buffer[counter-1] == 0x0020) )
buffer[counter-1] = 0xfe80; //hamza
}
if ( buffer[counter] == 0xfe89 )
{
buffer[counter] = 0xfeef;//Yeh
if ( (counter-1 >= 0) && ( buffer[counter-1] == 0x0020) )
buffer[counter-1] = 0xfe80 ;//hamza
}
}
}
}
/**
* Method deshapeYehHamzaTwoCellNear.
* This method convert every Yeh follwed by a Hamza to YehHamza character
* and put the spaces near the character
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void deshapeYehHamzaTwoCellNear(char[] buffer, int length){
int counter=0;
for (counter =0; counter < length ; counter++)
{
if ((counter+1 = 0xFE70) && (buffer[count] <= 0xFE72) ) ||
(buffer[count] == 0xFE74) ||
( (buffer[count] >= 0xFE76) && (buffer[count] <= 0xFE7B) ) ||
( (buffer[count] >= 0xFE7E) && (buffer[count] <= 0xFE7F) ) )
{
for(int idx = count; idx > tashkeelOcuurences; idx--)
buffer[idx] = buffer[idx - 1];
buffer[tashkeelOcuurences] = 0x0020;
tashkeelOcuurences++;
}
count ++;
}
}
/**
* Method customizeTashkeelAtEnd.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void customizeTashkeelAtEnd(char[] buffer, int length)
{
int count =0 ;
int tashkeelOcuurences = 0;
while (count < length)
{
if ( ( (buffer[count] >= 0xFE70) && (buffer[count] <= 0xFE72) ) ||
(buffer[count] == 0xFE74) ||
( (buffer[count] >= 0xFE76) && (buffer[count] <= 0xFE7B) ) ||
( (buffer[count] >= 0xFE7E) && (buffer[count] <= 0xFE7F) ) )
{
for(int idx = count; idx < length - tashkeelOcuurences - 1; idx++)
buffer[idx] = buffer[idx + 1];
buffer[length - tashkeelOcuurences - 1] = 0x0020;
tashkeelOcuurences++;
}
count ++;
}
}
/**
* Method handleTashkeelAuto.
*
* @param buffer The buffer containing the data to be processed.
* @param length The buffer length.
*
*/
private void handleTashkeelAuto(char[] buffer, int length){}
}