Shaping Arabic Characters


In a previous post, I talked about converting Arabic digits. Today I’ll talk to you about shaping Arabic characters. Windows in general, performs the contextual shaping of Arabic characters as we type them. However some applications, especially graphic designer apps, such as Expression Design, perform their own shaping and layout. In this post I’m going to discuss ways you can implement character shaping and share with you the table of the different Arabic shapes or glyphs.

There are a couple of steps to shape Arabic characters correctly:

1- Determine the place of the character in the string, initial, beginning, middle, final forms. Remember that because the character is in the middle of a string, it doesn’t mean that it takes the middle form, since the character before it might only have final form. For example Ein after Alef, will have an initial form, instead of a middle form

2- You need to seek ahead to account for ligatures and if a character needs legating, specifically Lam Alef, and its variations.

3- Use this Arabic shaping table.

 I created my own implementation of the Arabic shaping and published it on vsarabic blog. The .exe for the tool is available and you can use it at Reshape Arabic letters for Designers - Developing Arabic applications should be easy! - Site Home - MSDN Blogs.

I hope you find this useful!

       int[,] GlyphMap = new int[41, 4] 


         // Isolated, Final, Initial, Middle Forms

            {0xFE80,0xFE80,0xFE80,0xFE80}, /* HAMZA 0x0621*/

            {0xFE81,0xFE82,0xFE81,0xFE82}, /* ALEF WITH MADDA ABOVE 0x622 */

            {0xFE83,0xFE84,0xFE83,0xFE84}, /* ALEF WITH HAMZA ABOVE 0x0623*/

            {0xFE85,0xFE86,0xFE85,0xFE86}, /* WAW WITH HAMZA ABOVE 0x0624 */

            {0xFE87,0xFE88,0xFE87,0xFE88}, /* ALEF WITH HAMZA BELOW 0x0625*/

            {0xFE89,0xFE8A,0xFE8B,0xFE8C}, /* YEH WITH HAMZA ABOVE 0x0626*/

            {0xFE8D,0xFE8E,0xFE8D,0xFE8E}, /* ALEF 0x0627*/

            {0xFE8F,0xFE90,0xFE91,0xFE92}, /* BEH 0x0628*/

            {0xFE93,0xFE94,0xFE93,0xFE94}, /* TEH MARBUTA 0x0629*/

            {0xFE95,0xFE96,0xFE97,0xFE98}, /* TEH 0x062A*/

            {0xFE99,0xFE9A,0xFE9B,0xFE9C}, /* THEH 0x062B*/

            {0xFE9D,0xFE9E,0xFE9F,0xFEA0}, /* JEEM 0x062C*/

            {0xFEA1,0xFEA2,0xFEA3,0xFEA4}, /* HAH 0x062D*/

            {0xFEA5,0xFEA6,0xFEA7,0xFEA8}, /* KHAH 0x062E*/

            {0xFEA9,0xFEAA,0xFEA9,0xFEAA}, /* DAL 0x062F*/

            {0xFEAB,0xFEAC,0xFEAB,0xFEAC}, /* THAL0x0630 */

            {0xFEAD,0xFEAE,0xFEAD,0xFEAE}, /* RAA 0x0631*/

            {0xFEAF,0xFEB0,0xFEAF,0xFEB0}, /* ZAIN 0x0632*/

            {0xFEB1,0xFEB2,0xFEB3,0xFEB4}, /* SEEN 0x0633*/

            {0xFEB5,0xFEB6,0xFEB7,0xFEB8}, /* SHEEN 0x0634*/

            {0xFEB9,0xFEBA,0xFEBB,0xFEBC}, /* SAD 0x0635*/

            {0xFEBD,0xFEBE,0xFEBF,0xFEC0}, /* DAD 0x0636*/

            {0xFEC1,0xFEC2,0xFEC3,0xFEC4}, /* TAH 0x0637*/

            {0xFEC5,0xFEC6,0xFEC7,0xFEC8}, /* ZAH 0x0638*/

            {0xFEC9,0xFECA,0xFECB,0xFECC}, /* AIN 0x0639*/

            {0xFECD,0xFECE,0xFECF,0xFED0}, /* GHAIN 0x063A*/

            {0x0640,0x0640,0x0640,0x0640}, /* TATWEEL 0x0640*/

            {0xFED1,0xFED2,0xFED3,0xFED4}, /* FAA 0x0641*/

            {0xFED5,0xFED6,0xFED7,0xFED8}, /* QAF 0x0642*/

            {0xFED9,0xFEDA,0xFEDB,0xFEDC}, /* KAF 0x0643*/

            {0xFEDD,0xFEDE,0xFEDF,0xFEE0}, /* LAM 0x0644*/

            {0xFEE1,0xFEE2,0xFEE3,0xFEE4}, /* MEEM 0x0645*/

            {0xFEE5,0xFEE6,0xFEE7,0xFEE8}, /* NOON 0x0646*/

            {0xFEE9,0xFEEA,0xFEEB,0xFEEC}, /* HEH 0x0647*/

            {0xFEED,0xFEEE,0xFEED,0xFEEE}, /* WAW 0x0648*/

            {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA 0x0649*/

            {0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH 0x064A*/

            {0xFEF5, 0xFEF6, 0xFEF5, 0xFEF6}, /* LAM ALEF MADD*/

            {0xFEF7, 0xFEF8, 0xFEF7, 0xFEF8}, /* LAM ALEF HAMZA ABOVE*/

            {0xFEF9, 0xFEFa, 0xFEF9, 0xFEFa}, /* LAM ALEF HAMZA BELOW*/

            {0xFEFb, 0xFEFc, 0xFEFb, 0xFEFc}, /* LAM ALEF */