Back to index

lightning-sunbird  0.9+nobinonly
dvng-x.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  * Pangolite
00003  * dvng-x.c:
00004  * 
00005  * ***** BEGIN LICENSE BLOCK *****
00006  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00007  *
00008  * The contents of this file are subject to the Mozilla Public License Version
00009  * 1.1 (the "License"); you may not use this file except in compliance with
00010  * the License. You may obtain a copy of the License at
00011  * http://www.mozilla.org/MPL/
00012  *
00013  * Software distributed under the License is distributed on an "AS IS" basis,
00014  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00015  * for the specific language governing rights and limitations under the
00016  * License.
00017  *
00018  * The Original Code is mozilla.org code. The Initial Developer of the Original Code is Sun Microsystems, Inc.  Portions created by SUN are Copyright (C) 2002 SUN Microsystems, Inc. All Rights Reserved.
00019  *
00020  * The Initial Developer of the Original Code is
00021  * Sun Microsystems, Inc.
00022  * Portions created by the Initial Developer are Copyright (C) 2002
00023  * the Initial Developer. All Rights Reserved.
00024  *
00025  * Contributor(s):
00026  *   Prabhat Hegde (prabhat.hegde@sun.com)
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either of the GNU General Public License Version 2 or later (the "GPL"),
00030  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include <glib.h>
00043 #include <string.h>
00044 
00045 #include "pango-engine.h"
00046 #include "pango-coverage.h"
00047 
00048 #define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
00049 #define MAX_CLUSTER_CHRS 256
00050 #define MAX_GLYPHS       256
00051 #define GLYPH_COMBINING  256
00052 
00053 /*************************************************************************
00054  *         CHARACTER TYPE CONSTANTS - What they represent                *
00055  *         ----------------------------------------------                *
00056  *                                                                       *
00057  * _NP : Vowel-Modifier Visarg(U+0903) (Displayed to the right).         *
00058  * _UP : Vowel-Modifer Chandrabindu(U+0901) and Anuswar (U+0902).        *
00059  *       Displayed above the Consonant/Vowel                             *
00060  * _IV : Independant Vowels                                              *
00061  * _CN : All consonants except _CK and _RC below                         *
00062  * _CK : Consonants that can be followed by a Nukta(U+093C). Characters  *
00063  *       (U+0958-U+095F). No clue why Unicode imposed it on Devanagari.  *
00064  * _RC : Consonant Ra - Needs to handle 'Reph'                           *
00065  * _NM : Handle special case of Matras when followed by a Chandrabindu/  *
00066  *       Anuswar.                                                        *
00067  * _IM : Choti I Matra (U+093F). Needs to handle re-ordering.            *
00068  * _HL : Halant (U+094D)                                                 *
00069  * _NK : Nukta (U+093C)                                                  *
00070  * _VD : For Vedic extension characters (U+0951 - U+0954)                *
00071  * _HD : Hindu Numerals written in Devanagari                            *
00072  * _MS : For Matras such U+0941, U+0942 which need to be attached to the *
00073  *       holding consonant at the Stem.                                  *
00074  * _RM : A cluster of Ra+Halant at the begining would be represented by  *
00075  *       a Reph (placed in sun.unicode.india-0 at 0xF812). Reph is       *
00076  *       typically attached on top of the last consonant.                *
00077  * _II_M, _EY_M, _AI_M, _OW1_M, _OW2_M, _AYE_M, _EE_M, _AWE_M, _O_M,     * 
00078  *     : Separate glyphs are provided which combine matra with a reph.   *
00079  *       Matras which need to use this are represented by the above.     *
00080  *************************************************************************/
00081  
00082 /*************************************************************************
00083  *                          CLUSTERING LOGIC                             *
00084  *                          ----------------                             *
00085  *                                                                       *
00086  * Notations used to describe Devanagari Script Generic Info:            *
00087  * D : Vowel-Modifiers (U+0901 - U+0903)                                 *
00088  * V : Vowels (U+0905 - U+0913) & (U+0960, U+0961)                       *
00089  * C : Consonants (U+0915 - U+0939)                                      *
00090  * M : Matras (U+093E - U+094C) & (U+0962, U+0963)                       *
00091  * H : Halant (U+094D)                                                   *
00092  * N : Nukta (U+093C)                                                    *
00093  *                                                                       *
00094  * RULES:-                                                               *
00095  * -------                                                               *
00096  * Syllable/Cluster types                                                *
00097  *                                                                       *
00098  * 1] Vowel Syllable ::- V[D]                                            *
00099  * 2] Cons - Vowel Syllable ::- [Cons-Syllable] Full- Cons [M] [D]       *
00100  * 3] Cons-Syllable  ::- [Pure-Cons][Pure-Cons] Pure-Cons                *
00101  * 4] Pure-Cons  ::- Full-Cons H                                         *
00102  * 5] Full-Cons  ::- C[N]                                                *
00103  *                                                                       *
00104  * Notes:                                                                *
00105  * 1] Nukta (N) can come after only those consonants with which it can   *
00106  *    combine, ie U+0915-U+0917, U+091C, U+0921, U+0922, U+092B & U+092F *
00107  * 2] Worst case Vowel cluster - V D                                     *
00108  * 3] A worst case Consonant cluster: C N H C N H C N H C N M D          *
00109  *************************************************************************/
00110 
00111 /*
00112  * Devanagari character classes
00113  */
00114 #define _NP    1L
00115 #define _UP    (1L<<1)
00116 #define _IV    (1L<<2)
00117 #define _CN    (1L<<3)
00118 #define _CK    (1L<<4)
00119 #define _RC    (1L<<5)
00120 #define _NM    (1L<<6)
00121 #define _IM    (1L<<7)
00122 #define _HL    (1L<<8)
00123 #define _NK    (1L<<9)
00124 #define _VD    (1L<<10)
00125 #define _HD    (1L<<11)
00126 #define _II_M  (1L<<12)
00127 #define _EY_M  (1L<<13)
00128 #define _AI_M  (1L<<14)
00129 #define _OW1_M (1L<<15)
00130 #define _OW2_M (1L<<16)
00131 #define _MS    (1L<<17)
00132 #define _AYE_M (1L<<18)
00133 #define _EE_M  (1L<<19)
00134 #define _AWE_M (1L<<20)
00135 #define _O_M   (1L<<21)
00136 #define _RM    (_II_M|_EY_M|_AI_M|_OW1_M|_OW2_M|_AYE_M|_EE_M|_AWE_M|_O_M)
00137 
00138 /* Common Non-defined type */
00139 #define __ND 0
00140 
00141 /*
00142  * Devanagari character types
00143  */
00144 #define __UP     1
00145 #define __NP     2
00146 #define __IV     3
00147 #define __CN     4
00148 #define __CK     5
00149 #define __RC     6
00150 #define __NM     7
00151 #define __RM     8
00152 #define __IM     9
00153 #define __HL    10
00154 #define __NK    11
00155 #define __VD    12
00156 #define __HD    13
00157 
00158 /*
00159  * Devanagari Glyph Type State
00160  */
00161 #define St0      0
00162 #define St1      1
00163 #define St2      2
00164 #define St3      3
00165 #define St4      4
00166 #define St5      5
00167 #define St6      6
00168 #define St7      7
00169 #define St8      8
00170 #define St9      9
00171 #define St10    10
00172 #define St11    11
00173 #define St12    12
00174 #define St13    13
00175 #define St14    14
00176 #define St15    15
00177 #define St16    16
00178 #define St17    17
00179 #define St18    18
00180 #define St19    19
00181 #define St20    20
00182 
00183 #define _ND     0
00184 #define _NC     1
00185 #define _UC     (1<<1)
00186 #define _BC     (1<<2)
00187 #define _SC     (1<<3)
00188 #define _AV     (1<<4)
00189 #define _BV     (1<<5)
00190 #define _TN     (1<<6)
00191 #define _AD     (1<<7)
00192 #define _BD     (1<<8)
00193 #define _AM     (1<<9)
00194 
00195 #define MAP_SIZE     243
00196 #define MAX_STATE     21
00197 #define MAX_DEVA_TYPE 14
00198 #define MAX_CORE_CONS  6
00199 
00200 #define SCRIPT_ENGINE_NAME  "DvngScriptEngineX"
00201 #define PANGO_RENDER_TYPE_X "PangoliteRenderX"
00202 
00203 #define ucs2dvng(ch) (gunichar2)((gunichar2)(ch) - 0x0900)
00204 
00205 typedef guint16 PangoliteXSubfont;
00206 #define PANGO_MOZ_MAKE_GLYPH(index) ((guint32)0 | (index))
00207 
00208 /* We handle the following ranges between U+0901 to U+0970 exactly
00209  */
00210 static PangoliteEngineRange dvng_ranges[] = {
00211   { 0x0901, 0x0903, "*" },
00212   { 0x0905, 0x0939, "*" },
00213   { 0x093c, 0x094d, "*" },
00214   { 0x0950, 0x0954, "*" },
00215   { 0x0958, 0x0970, "*" }, /* Hindi Ranges */
00216 };
00217 
00218 static PangoliteEngineInfo script_engines[] = {
00219   {
00220     SCRIPT_ENGINE_NAME,
00221     PANGO_ENGINE_TYPE_SHAPE,
00222     PANGO_RENDER_TYPE_X,
00223     dvng_ranges, 
00224     G_N_ELEMENTS(dvng_ranges)
00225   }
00226 };
00227 
00228 /* X window system script engine portion
00229  */
00230 typedef struct _DvngFontInfo DvngFontInfo;
00231 
00232 /* The type of encoding that we will use
00233  */
00234 typedef enum {
00235   DVNG_FONT_NONE,
00236   DVNG_FONT_SUN
00237 } DvngFontType;
00238 
00239 /*
00240  */
00241 typedef struct {
00242   const gunichar       ISCII[MAX_CORE_CONS];
00243   const unsigned short ISFOC[MAX_CORE_CONS];
00244 } DvngGlyphEntry;
00245 
00246 /*
00247  */
00248 struct _DvngFontInfo
00249 {
00250   DvngFontType  type;
00251   PangoliteXSubfont subfont;
00252 };
00253 
00254 typedef long DvngCls;
00255 typedef int  StateType;
00256 
00257 /*
00258  * Devanagari character class table
00259  */
00260 static const DvngCls DvngChrClsTbl[128] = {
00261 /*            0,       1,      2,        3,      4,       5,    6,   7,
00262               8,       9,      A,        B,      C,       D,    E,   F, */
00263 /* 0 */     _ND,     _UP,     _UP,     _NP,    _ND,     _IV,   _IV, _IV,
00264             _IV,     _IV,     _IV,     _IV,    _IV,     _IV,   _IV, _IV,
00265 /* 1 */     _IV,     _IV,     _IV,     _IV,    _IV, _CK|_MS,   _CK, _CK,
00266             _CN,     _CN,     _CN,     _CN,    _CK,     _CN,   _CN,_CN|_MS,
00267 /* 2 */ _CN|_MS, _CK|_MS, _CK|_MS,     _CN,    _CN,     _CN,   _CN, _CN,
00268             _CN,     _CN,     _CN, _CK|_MS,    _CN,     _CN,   _CN, _CN,
00269 /* 3 */     _RC,     _CN,     _CN,     _CN,    _CN,     _CN,   _CN, _CN,
00270             _CN, _CN|_MS,     _ND,     _ND,    _NK,     _VD,   _NM, _IM,
00271 /* 4 */   _II_M,     _NM,     _NM,     _NM,    _NM,  _AYE_M, _EE_M, _EY_M,
00272           _AI_M,  _AWE_M,    _O_M,  _OW1_M, _OW2_M,     _HL,   _ND, _ND,
00273 /* 5 */     _ND,     _VD,     _VD,     _VD,    _VD,     _ND,   _ND, _ND,
00274             _CN,     _CN,     _CN,     _CN,    _CN,     _CN,   _CN, _CN,
00275 /* 6 */     _IV,     _IV,     _NM,     _NM,    _ND,     _ND,   _HD, _HD,
00276             _HD,     _HD,     _HD,     _HD,    _HD,     _HD,   _HD, _HD,
00277 /* 7 */     _ND,     _ND,     _ND,     _ND,    _ND,     _ND,   _ND, _ND,
00278             _ND,     _ND,     _ND,     _ND,    _ND,     _ND,   _ND, _ND,
00279 };
00280 
00281 /*
00282  * Devanagari character type table
00283  */
00284 static const gint DvngChrTypeTbl[128] = {
00285 /*         0,    1,    2,    3,    4,    5,    6,    7,
00286            8,    9,    A,    B,    C,    D,    E,    F, */
00287 /* 0 */ __ND, __UP, __UP, __NP, __ND, __IV, __IV, __IV,
00288         __IV, __IV, __IV, __IV, __IV, __IV, __IV, __IV,
00289 /* 1 */ __IV, __IV, __IV, __IV, __IV, __CK, __CK, __CK,
00290         __CN, __CN, __CN, __CN, __CK, __CN, __CN, __CN,
00291 /* 2 */ __CN, __CK, __CK, __CN, __CN, __CN, __CN, __CN,
00292         __CN, __CN, __CN, __CK, __CN, __CN, __CN, __CN,
00293 /* 3 */ __RC, __CN, __CN, __CN, __CN, __CN, __CN, __CN,
00294         __CN, __CN, __ND, __ND, __NK, __VD, __NM, __IM,
00295 /* 4 */ __RM, __NM, __NM, __NM, __NM, __RM, __RM, __RM,
00296         __RM, __RM, __RM, __RM, __RM, __HL, __ND, __ND,
00297 /* 5 */ __ND, __VD, __VD, __VD, __VD, __ND, __ND, __ND,
00298         __CN, __CN, __CN, __CN, __CN, __CN, __CN, __CN,
00299 /* 6 */ __IV, __IV, __NM, __NM, __ND, __ND, __HD, __HD,
00300         __HD, __HD, __HD, __HD, __HD, __HD, __HD, __HD,
00301 /* 7 */ __ND, __ND, __ND, __ND, __ND, __ND, __ND, __ND,
00302         __ND, __ND, __ND, __ND, __ND, __ND, __ND, __ND,
00303 };
00304 
00305 /*
00306  * Devanagari character composible table
00307  */
00308 static const gint DvngComposeTbl[14][14] = {
00309   /*        ND, UP, NP, IV, CN, CK, RC, NM, RM, IM, HL, NK, VD, HD,  */
00310   /* 0  */ { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* ND */
00311   /* 1  */ { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* UP */
00312   /* 2  */ { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* NP */
00313   /* 3  */ { 0,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* IV */
00314   /* 4  */ { 0,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,}, /* CN */
00315   /* 5  */ { 0,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,}, /* CK */
00316   /* 6  */ { 0,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,}, /* RC */
00317   /* 7  */ { 0,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* NM */
00318   /* 8  */ { 0,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* RM */
00319   /* 9  */ { 0,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* IM */
00320   /* 10 */ { 0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,}, /* HL */
00321   /* 11 */ { 0,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,}, /* NK */
00322   /* 12 */ { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* VD */
00323   /* 13 */ { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,}, /* HD */
00324 };
00325 
00326 StateType DvngStateTbl[MAX_STATE][MAX_DEVA_TYPE] = {
00327 
00328   /* ND,   UP,   NP,   IV,   CN,   CK,   RC,   NM,   RM,
00329      IM,   HL,   NK,   VD,   HD */
00330                                            /* State 0 */
00331  {  St11, St1, St1,  St2,  St4,  St4, St12,  St1,  St1,
00332     St1,  St1, St1,  St1, St11, },
00333                                            /* State 1 */
00334  {  St1,  St1,  St1,  St1,  St1,  St1,  St1,  St1,  St1,
00335     St1,  St1,  St1,  St1,  St1, },
00336                                            /* State 2 */
00337  {  St2,  St3,  St3,  St2,  St2,  St2,  St2,  St2,  St2,
00338     St2,  St2,  St2,  St2,  St2, },
00339                                            /* State 3 */
00340  {  St3,  St3,  St3,  St3,  St3,  St3,  St3,  St3,  St3,
00341     St3,  St3,  St3,  St3,  St3, },
00342                                            /* State 4 */
00343  {  St4,  St8,  St8,  St4,  St4,  St4,  St4,  St6,  St6,
00344     St9,  St5,  St4,  St4,  St4, },
00345                                            /* State 5 */
00346  {  St5,  St5,  St5,  St5,  St4,  St4,  St4,  St5,  St5,
00347     St5,  St5,  St5,  St5,  St5, },
00348                                            /* State 6 */
00349  {  St6,  St7,  St7,  St6,  St6,  St6,  St6,  St6,  St6,
00350     St6,  St6,  St6,  St6,  St6, },
00351                                            /* State 7 */
00352  {  St7,  St7,  St7,  St7,  St7,  St7,  St7,  St7,  St7,
00353     St7,  St7,  St7,  St7,  St7, },
00354                                            /* State 8 */
00355  {  St8,  St8,  St8,  St8,  St8,  St8,  St8,  St8,  St8,
00356     St8,  St8,  St8,  St8,  St8, },
00357                                            /* State 9 */
00358  {  St9, St10, St10,  St9,  St9,  St9,  St9,  St9,  St9,
00359     St9,  St9,  St9,  St9,  St9, },
00360                                           /* State 10 */
00361  { St10, St10, St10, St10, St10, St10, St10, St10, St10,
00362    St10, St10, St10, St10, St10, },
00363                                           /* State 11 */
00364  { St11, St11, St11, St11, St11, St11, St11, St11, St11,
00365    St11, St11, St11, St11, St11, },
00366                                           /* State 12 */
00367  { St12,  St8,  St8, St12, St12, St12, St12,  St6,  St6,
00368     St9, St13, St12, St12, St12, },
00369                                           /* State 13 */
00370  { St13, St13, St13, St13, St14, St14, St14, St13, St13,
00371    St13, St13, St13, St13, St13, },
00372                                            /* State 14 */
00373  { St14, St18, St18, St14, St14, St14, St14, St16, St16,
00374    St19, St15, St14, St14, St14, },
00375                                            /* State 15 */
00376  { St15, St15, St15, St15, St14, St14, St14, St15, St15,
00377    St15, St15, St15, St15, St15, },
00378                                            /* State 16 */
00379  { St16, St17, St17, St16, St16, St16, St16, St16, St16,
00380    St16, St16, St16, St16, St16, },
00381                                            /* State 17 */
00382  { St17, St17, St17, St17, St17, St17, St17, St17, St17,
00383    St17, St17, St17, St17, St17, },
00384                                            /* State 18 */
00385  { St18, St18, St18, St18, St18, St18, St18, St18, St18,
00386    St18, St18, St18, St18, St18, },
00387                                            /* State 19 */
00388  { St19, St20, St20, St19, St19, St19, St19, St19, St19,
00389    St19, St19, St19, St19, St19, },
00390                                            /* State 20 */
00391  { St20, St20, St20, St20, St20, St20, St20, St20, St20,
00392    St20, St20, St20, St20, St20, },
00393 };
00394 
00395 int DvngRuleTbl[128] = {
00396 /*       0,  1,  2,  3,  4,  5,  6,  7,
00397          8,  9,  A,  B,  C,  D,  E,  F, */
00398 
00399 /* 0 */  0,  1,  1,  1,  0,  1,  1,  1,
00400          1,  1,  1,  1,  1,  1,  1,  1,
00401 /* 1 */  1,  1,  1,  1,  1,  4,  4,  4,
00402          4,  2,  4,  1,  4,  4,  3,  3,
00403 /* 2 */  3,  3,  3,  2,  4,  4,  4,  4,
00404          4,  1,  4,  4,  4,  4,  4,  4,
00405 /* 3 */  2,  2,  2,  2,  1,  4,  4,  3,
00406          5,  4,  0,  0,  2,  1,  1,  1,
00407 /* 4 */  1,  1,  1,  1,  1,  1,  1,  1,
00408          1,  1,  1,  1,  1,  3,  0,  0,
00409 /* 5 */  1,  1,  1,  1,  1,  0,  0,  0,
00410          1,  1,  1,  1,  1,  1,  1,  1,
00411 /* 6 */  1,  1,  1,  1,  1,  1,  1,  1,
00412          1,  1,  1,  1,  1,  1,  1,  1,
00413 /* 7 */  1,  0,  0,  0,  0,  0,  0,  0,
00414          0,  0,  0,  0,  0,  0,  0,  0,
00415 };
00416 
00417 #define IsDvngCharCls(ch, mask) (DvngChrClsTbl[ucs2dvng((ch))] & (mask))
00418 
00419 #define IsComposible(ch1, ch2) (DvngComposeTbl[DvngChrTypeTbl[ucs2dvng((ch1))]][DvngChrTypeTbl[ucs2dvng((ch2))]])
00420 
00421 #define GetDvngRuleCt(ch) (DvngRuleTbl[ucs2dvng((ch))])
00422 
00423 #define IsKern(gid) ((gid >= 0xF830 && gid <= 0xF83E) ? TRUE : FALSE)
00424 
00425 #define IsMatraAtStem(gid) (((gid >= 0xF811 && gid <= 0xF813) || \
00426                              (gid >= 0xF81E && gid <= 0xF82F) || \
00427                              (gid >= 0x0962 && gid <= 0x0963) || \
00428                              (gid >= 0x0941 && gid <= 0x0948) || \
00429                              (gid == 0x093C) || (gid == 0x094D)) ? TRUE : FALSE)
00430 
00431 #define SetClusterState(st, ch) DvngStateTbl[(st)][DvngChrTypeTbl[ucs2dvng((ch))]]
00432 
00433 #define MAP_SIZE 243
00434 
00435 /*
00436  * Devanagari Glyph Tables
00437  */
00438 static const DvngGlyphEntry sunGlyphTbl[MAP_SIZE] = {
00439   /* Vowel Modifiers - Ct 3 */
00440   { {0x0901,0x0},                       {0x0901,0x0} },
00441   { {0x0902,0x0},                       {0x0902,0x0} },
00442   { {0x0903,0x0},                       {0x0903,0x0} },
00443 
00444   /* vowels 13 - Ct 18 */
00445   { {0x0905,0x0},                       {0x0905,0x0} },
00446   { {0x0906,0x0},                       {0x0906,0x0} },
00447   { {0x0907,0x0},                       {0x0907,0x0} },
00448   { {0x0908,0x0},                       {0x0908,0x0} },
00449   { {0x0909,0x0},                       {0x0909,0x0} },
00450   { {0x090a,0x0},                       {0x090a,0xF830,0x0} },
00451   { {0x090b,0x0},                       {0x090b,0xF831,0x0} },
00452   { {0x0960,0x0},                       {0x0960,0xF831,0x0} },
00453   { {0x090c,0x0},                       {0x090c,0xF83D,0x0} },
00454   { {0x0961,0x0},                       {0x0961,0xF83D,0x0} },
00455   { {0x090d,0x0},                       {0x090d,0x0} },
00456   { {0x090e,0x0},                       {0x090e,0x0} },
00457   { {0x090f,0x0},                       {0x090f,0x0} },
00458   { {0x0910,0x0},                       {0x0910,0x0} },
00459   { {0x0911,0x0},                       {0x0911,0x0} },
00460   { {0x0912,0x0},                       {0x0912,0x0} },
00461   { {0x0913,0x0},                       {0x0913,0x0} },
00462   { {0x0914,0x0},                       {0x0914,0x0} },
00463 
00464   /* Vowel signs - Ct 17 */
00465   { {0x093e,0x0},                       {0x093e,0x0} },
00466   { {0x093f,0x0},                       {0x093f,0x0} },
00467   { {0x0940,0x0},                       {0x0940,0x0} },
00468   { {0x0941,0x0},                       {0x0941,0x0} },
00469   { {0x0942,0x0},                       {0x0942,0x0} },
00470   { {0x0943,0x0},                       {0x0943,0x0} },
00471   { {0x0944,0x0},                       {0x0944,0x0} },
00472   { {0x0945,0x0},                       {0x0945,0x0} },
00473   { {0x0946,0x0},                       {0x0946,0x0} },
00474   { {0x0947,0x0},                       {0x0947,0x0} },
00475   { {0x0948,0x0},                       {0x0948,0x0} },
00476   { {0x0949,0x0},                       {0x0949,0x0} },
00477   { {0x094a,0x0},                       {0x094a,0x0} },
00478   { {0x094b,0x0},                       {0x094b,0x0} },
00479   { {0x094c,0x0},                       {0x094c,0x0} },
00480   { {0x0962,0x0},                       {0x0962,0x0} },
00481   { {0x0963,0x0},                       {0x0963,0x0} },
00482 
00483   /* Consonants */
00484   /* ka -> ka + kern space */
00485   { {0x0915,0x0},                       {0x0915,0xF832,0x0} },
00486   /* ka nukta  -> ka nukta + kern space */
00487   { {0x0915,0x093c,0x0},                {0x0958,0xF832,0x0} },
00488   /* ka + halant  -> half ka */
00489   { {0x0915,0x094d,0x0},                {0xF7C1,0x0} },
00490   /* ka nukta + halant-> half ka nukta */
00491   { {0x0915,0x093c,0x094d,0x0},         {0xF7C2,0x0} },
00492 
00493   { {0x0915,0x094d,0x0915,0x0},         {0xF845,0xF832,0x0} },
00494 
00495   /* ka + halant + ta -> kta + kern space */
00496   { {0x0915,0x094d,0x0924,0x0},         {0xF7C4,0xF832,0x0} },
00497   /* ka + halant + ra -> kra + kern space */
00498   { {0x0915,0x094d,0x0930,0x0},         {0xF7C3,0xF832,0x0} },
00499   { {0x0915,0x094d,0x0930,0x094d,0x0},  {0xF7C3,0x094d,0xF832,0x0} },
00500   /* ka + halant + SHa -> kSHa */
00501   { {0x0915,0x094d,0x0937,0x0},         {0xF7C5,0x093E,0x0} }, 
00502   /* ka + halant + SHa + halant -> half kSHa */
00503   { {0x0915,0x094d,0x0937,0x094d,0x0},  {0xF7C5,0x0} },
00504 
00505   /* kha 6 */
00506   { {0x0916,0x0},                       {0x0916,0x0} },
00507   { {0x0916,0x094d,0x0},                {0xF7C6,0x0} },
00508   { {0x0916,0x093c,0x0},                {0x0959,0x0} },
00509   { {0x0916,0x093c,0x094d,0x0},         {0xF7C7,0x0} },
00510   { {0x0916,0x094d,0x0930,0x0},         {0xF7C8,0x093E,0x0} },
00511   { {0x0916,0x094d,0x0930,0x094d,0x0},  {0xF7C8,0x0} },
00512 
00513   /* ga 6 */
00514   { {0x0917,0x0},                       {0x0917,0x0} },
00515   { {0x0917,0x094d,0x0},                {0xF7C9,0x0} },
00516   { {0x0917,0x093c,0x0},                {0x095a,0x0} },
00517   { {0x0917,0x093c,0x094d,0x0},         {0xF7CA,0x0} },
00518   { {0x0917,0x094d,0x0930,0x0},         {0xF7CB,0x093E,0x0} },
00519   { {0x0917,0x094d,0x0930,0x094d,0x0},  {0xF7CB,0x0} },
00520 
00521   /* gha 4 */
00522   { {0x0918,0x0},                       {0x0918,0x0} },
00523   { {0x0918,0x094d,0x0},                {0xF7CC,0x0} },
00524   { {0x0918,0x094d,0x0930,0x0},         {0xF7CD,0x093E,0x0} },
00525   { {0x0918,0x094d,0x0930,0x094d,0x0},  {0xF7CD,0x0} },
00526 
00527   /* nga 1 */
00528   { {0x0919,0x0},                       {0x0919,0xF833,0x0} },
00529 
00530   /* { {0x0919,0x094d,0x0},             {0x0919,0x094d,0xF833,0x0} }, */
00531 
00532   /* cha 4 */
00533   { {0x091a,0x0},                       {0x091a,0x0} },
00534   /* cha  + halant -> half cha   */
00535   { {0x091a,0x094d,0x0},                {0xF7CE,0x0} },
00536   /* cha + halant ra -> chra  */
00537   { {0x091a,0x094d,0x0930,0x0},         {0xF7CF,0x093E,0x0} },
00538   /* cha  + halant ra + halant  */
00539   { {0x091a,0x094d,0x0930,0x094d,0x0},  {0xF7CF,0x0} },
00540 
00541   /* chha 1 */
00542   { {0x091b,0x0},                       {0x091b,0xF834,0x0} },
00543 
00544   /* chha + halant -> chha+ halant */
00545   /*  { {0x091b,0x094d,0x0 },           {0x091b,0x094d,0xF834,0x0} }, */
00546 
00547   /* ja 6 */
00548   /* ja  */
00549   { {0x091c,0x0},                       {0x091c,0x0} },
00550   /* ja + halant -> half ja  */
00551   { {0x091c,0x094d,0x0},                {0xF7D0,0x0} },
00552   /* ja + nukta -> za */
00553   { {0x091c,0x093c,0x0},                {0xF7D1,0x093E,0x0} },
00554   /* ja + nukta + halant -> half za */
00555   { {0x091c,0x093c,0x094d,0x0 },        {0xF7D1,0x0} },
00556   /* ja + halant + ra -> jra  */
00557   { {0x091c,0x094d,0x0930,0x0},         {0xF7D2,0x093E,0x0} },
00558   /* ja + halant + ra + halant -> */
00559   { {0x091c,0x094d,0x0930,0x094d,0x0},  {0xF7D2,0x0} },
00560 
00561   /* dna 2 */
00562   /* ja + halant + jna -> dna  */
00563   { {0x091c,0x094d,0x091e,0x0},         {0xF7D3,0x093E,0x0} },
00564   /* ja + halant + jna -> half dna  */
00565   { {0x091c,0x094d,0x091e,0x094d,0x0},  {0xF7D3,0x0} },
00566 
00567   /* jha 4 */
00568   /* jha  */
00569   { {0x091d,0x0},                       {0x091d,0x0} },
00570   /* jha + halant -> half jha  */
00571   { {0x091d,0x094d,0x0},                {0xF7D4,0x0} },
00572   /* jha + halant -> jhra */
00573   { {0x091d,0x094d,0x0930,0x0},         {0xF7D5,0x093E,0x0} },
00574   /*  jha + halant -> half jhra */
00575   { {0x091d,0x094d,0x0930,0x094d,0x0},  {0xF7D5,0x0} },
00576 
00577   /* nya 2 */
00578   /* nya */
00579   { {0x091e,0x0},                       {0x091e,0x0} },
00580   /* nya + halant -> half nya */
00581   { {0x091e,0x094d,0x0},                {0xF7D6,0x0} },
00582 
00583   { {0x091e,0x094d,0x091c,0x0},         {0xF846,0x0} },
00584 
00585   /* Ta 3 */
00586   /* Ta -> Ta + kern space */
00587   { {0x091f,0x0},                       {0x091F,0xF835,0x0} },
00588 
00589   { {0x091f,0x094d,0x0},                {0x091f,0x094d,0xF835,0x0} },
00590 
00591   /* Ta + halant + Ta -> TaTa + kern space */
00592   { {0x091f,0x094d,0x091f,0x0},         {0xF7D7,0xF835,0x0} },
00593   /* Ta + halant + Tha -> TaTha + kern space */
00594   { {0x091f,0x094d,0x0920,0x0},         {0xF7D8,0xF835,0x0} },
00595 
00596   /* Tha 2 */
00597   /* Tha -> Tha + kern space */
00598   { {0x0920,0x0},                       {0x0920,0xF836,0x0} },
00599 
00600   { {0x0920,0x094d,0x0},                {0x0920,0x094d,0xF836,0x0} },
00601 
00602   /* Tha + halant + Tha -> + kern space */
00603   { {0x0920,0x094d,0x0920,0x0},         {0xF7D9,0xF836,0x0} },
00604 
00605   /* Da 1 */
00606   /* Da  -> Da  + kern space */
00607   { {0x0921,0x0},                       {0x0921,0xF837,0x0} },
00608 
00609   { {0x0921,0x094d,0x0},                {0x0921,0x094d,0xF837,0x0} },
00610  
00611   /* Da nukta 1 */
00612   /* Da + nukta -> + kern space */
00613   { {0x0921,0x093c,0x0},                {0x095c,0xF837,0x0} },
00614 
00615   /* Da + nukta+ halant */
00616   { {0x0921,0x093c,0x094d,0x0},         {0x095c,0x094d,0xF837,0x0} },
00617 
00618   { {0x0921,0x094d,0x0917,0x0},         {0xF847,0xF837,0x0} },
00619 
00620   /* Da halant Da 1 */
00621   /* Da + halant + Da - > + kern space */
00622   { {0x0921,0x094d,0x0921,0x0},         {0xF7DA,0xF837,0x0} },
00623 
00624   /* Da halant Dha 1 */
00625   /* Da + halant + Dha -> + kern space */
00626   { {0x0921,0x094d,0x0922,0x0},         {0xF7DB,0xF837,0x0} },
00627 
00628   /* Dha 1 */
00629   /* Dha  + kern space */
00630   { {0x0922,0x0},                       {0x0922,0xF838,0x0} },
00631 
00632   /* Dha nukta 1 */
00633   /* Dha + nukta -> + kern space */
00634   { {0x0922,0x093c,0x0},                {0x095d,0xF838,0x0} },
00635   { {0x0922,0x093c,0x094d,0x0},         {0x095d,0x094d,0xF838,0x0} },
00636 
00637   { {0x0922,0x094d,0x0},                {0x0922,0x094d,0xF838,0x0} },
00638 
00639   /* Nna 2 */
00640   /* Nna */
00641   { {0x0923,0x0},                       {0x0923,0x0} },
00642   /* Nna + halant -> half Nna */
00643   { {0x0923,0x094d,0x0},                {0xF7DC,0x0} },
00644 
00645   /* ta 6 */
00646   /* ta */
00647   { {0x0924,0x0},                       {0x0924,0x0} },
00648   /* ta + halant -> half ta */
00649   { {0x0924,0x094d,0x0},                {0xF7DD,0x0} },
00650   /* ta + halant + ra -> half tra */
00651   { {0x0924,0x094d,0x0930,0x0},         {0xF7DE,0x093E,0x0} },
00652   /* ta + halant + ra + halant -> half tra  */
00653   { {0x0924,0x094d,0x0930,0x094d,0x0},  {0xF7DE,0x0} },
00654   /* ta + halant + ta -> */
00655   { {0x0924,0x094d,0x0924,0x0},         {0xF7DF,0x093E,0x0} },
00656   /* ta + halant + ta + halant -> */
00657   { {0x0924,0x094d,0x0924,0x094d,0x0},  {0xF7DF,0x0} },
00658 
00659   /* tha 4 */
00660   /* tha */
00661   { {0x0925,0x0},                       {0x0925,0x0} },
00662   /* tha + halant -> half tha */
00663   { {0x0925,0x094d,0x0},                {0xF7E0,0x0} },
00664   /* tha + halant + ra ->  */
00665   { {0x0925,0x094d,0x0930,0x0},         {0xF7E1,0x093E,0x0} },
00666   /* tha + halant + ra + halant -> */
00667   { {0x0925,0x094d,0x0930,0x094d,0x0},  {0xF7E1,0x0} },
00668 
00669   /* da 1 */
00670   /* da -> da + kern space */
00671   { {0x0926,0x0},                       {0x0926,0xF839,0x0} },
00672   /* da + halant -> half da + kern space */
00673   { {0x0926,0x094d,0x0},                {0x0926,0x094d,0xF839,0x0} },
00674 
00675   /* da ri 1 */
00676   /* da + ru -> da + ru + kern space */
00677   { {0x0926,0x0943,0x0},                {0xF7E2,0xF839,0x0} },
00678 
00679   /* da halant ra 1 */
00680   /* da + halant + ra -> dra + kern space  */
00681   { {0x0926,0x094d,0x0930,0x0},         {0xF7E3,0xF839,0x0} },
00682   { {0x0926,0x094d,0x0930,0x094d,0x0},  {0xF7E3,0x094d,0xF839,0x0} },
00683 
00684   { {0x0926,0x094d,0x0918,0x0},         {0xF848,0xF839,0x0} },
00685 
00686   /* da halant da 1 */
00687   /* da + halant + da  -> + kern space */
00688   { {0x0926,0x094d,0x0926,0x0},         {0xF7E4,0xF839,0x0} },
00689 
00690   /* da halant dha 1 */
00691   /* da + halant + dha -> + kern space  */
00692   { {0x0926,0x094d,0x0927,0x0},         {0xF7E5,0xF839,0x0} },
00693 
00694   { {0x0926,0x094d,0x092c,0x0},         {0xF849,0xF839,0x0} },
00695 
00696   { {0x0926,0x094d,0x092d,0x0},         {0xF844,0xF839,0x0} },
00697 
00698   /* da halant ma 1 */
00699   /* da + halant + ma -> + kern space */
00700   { {0x0926,0x094d,0x092e,0x0},         {0xF7E6,0xF839,0x0} },
00701 
00702   /* da halant ya 1 */
00703   /* da + halant + ya -> + kern space */
00704   { {0x0926,0x094d,0x092f,0x0},         {0xF7E7,0xF839,0x0} },
00705 
00706   /* da halant va 1 */
00707   /* da + halant + va -> + kern space  */
00708   { {0x0926,0x094d,0x0935,0x0},         {0xF7E8,0xF839,0x0} },
00709 
00710   /* dha 4 */
00711   /* Dha  */
00712   { {0x0927,0x0},                       {0x0927,0x0} },
00713   /* Dha + halant - > half Dha */
00714   { {0x0927,0x094d,0x0},                {0xF7E9,0x0} },
00715   /* Dha + halant + ra -> half Dhra */
00716   { {0x0927,0x094d,0x0930,0x0},         {0xF7EA,0x093E,0x0} },
00717   /* Dha + halant + ra + halant ->  */
00718   { {0x0927,0x094d,0x0930,0x094d,0x0},  {0xF7EA,0x0} },
00719 
00720   /* na 6 */
00721   /* na */
00722   { {0x0928,0x0},                       {0x0928,0x0} },
00723   /* na + halant  ->  half na */
00724   { {0x0928,0x094d,0x0},                {0xF7EB,0x0} },
00725   /* na + halant + ra  -> */
00726   { {0x0928,0x094d,0x0930,0x0},         {0xF7EC,0x093E,0x0} },
00727   /* na + halant + ra + halant -> */
00728   { {0x0928,0x094d,0x0930,0x094d,0x0},  {0xF7EC,0x0} },
00729   /* na + halant + na -> */
00730   { {0x0928,0x094d,0x0928,0x0},         {0xF7ED,0x093E,0x0} },
00731   /* na + halant + na + halant -> */
00732   { {0x0928,0x094d,0x0928,0x094d,0x0},  {0xF7ED,0x0} },
00733 
00734   { {0x0929,0x0},                       {0x0929,0x0} },
00735 
00736   /* pa 4 */
00737   /* pa */
00738   { {0x092a,0x0},                       {0x092a,0x0} },
00739   /* pa + halant -> half pa */
00740   { {0x092a,0x094d,0x0},                {0xF7EE,0x0} },
00741   /* pa + halant +ra -> pra */
00742   { {0x092a,0x094d,0x0930,0x0},         {0xF7EF,0x093E,0x0} },
00743   /* pa + halant + ra + halant -> half pra */
00744   { {0x092a,0x094d,0x0930,0x094d,0x0},  {0xF7EF,0x0} },
00745 
00746   /* pha 5 */
00747   /* pha -> pha + kern space */
00748   { {0x092b,0x0 },                      {0x092b,0xF832,0x0} },
00749   /* pha + halant -> half pha */
00750   { {0x092b,0x094d,0x0},                {0xF7F0,0x0} },
00751   /* pha nukta -> pha nukta + kern space */
00752   { {0x092b,0x093c,0x0},                {0x095e,0xF832,0x0} },
00753   /* pha nukta + halant-> half pha nukta */
00754   { {0x092b,0x093c,0x094d,0x0},         {0xF7F1,0x0} },
00755   /* pha + halant + ra -> fra + kern space */
00756   { {0x092b,0x094d,0x0930,0x0},         {0xF7F5,0xF832,0x0} },
00757   /* pha + halant + ra -> fra + kern space */
00758   { {0x092b,0x094d,0x0930,0x094d,0x0},  {0xF7F5,0xF832,0x094d,0x0} },
00759 
00760   /* ba 4 */
00761   /* ba */
00762   { {0x092c,0x0},                       {0x092c,0x0} },
00763   /* ba + halant -> half ba */
00764   { {0x092c,0x094d,0x0},                {0xF7F6,0x0} },
00765   /* ba + halant + ra -> */
00766   { {0x092c,0x094d,0x0930,0x0},         {0xF7F7,0x093E,0x0} },
00767   /* ba + halant ra + halant -> */
00768   { {0x092c,0x094d,0x0930,0x094d,0x0},  {0xF7F7,0x0} },
00769 
00770   /* bha 4 */
00771   /* bha  */
00772   { {0x092d,0x0},                       {0x092d,0x0} },
00773   /* bha + halant -> half halant  */
00774   { {0x092d,0x094d,0x0},                {0xF7F8,0x0} },
00775   /* bha + halant + ra ->  */
00776   { {0x092d,0x094d,0x0930,0x0},         {0xF7F9,0x093E,0x0} },
00777   /* bha + halant + ra + halant ->  */
00778   { {0x092d,0x094d,0x0930,0x094d,0x0},  {0xF7F9,0x0} },
00779   /* ma 4 */
00780   /* ma  */
00781   { {0x092e,0x0},                       {0x092e,0x0} },
00782   /* ma + halant -> half ma */
00783   { {0x092e,0x094d,0x0},                {0xF7FA,0x0} },
00784   /* ma + halant + ra -> */
00785   { {0x092e,0x094d,0x0930,0x0},         {0xF7FB,0x093E,0x0} },
00786   /* ma + halant + ra + halant ->  */
00787   { {0x092e,0x094d,0x0930,0x094d,0x0},  {0xF7FB,0x0} },
00788 
00789   /* ya 4 */
00790   /* ya */
00791   { {0x092f,0x0},                       {0x092f,0x0} },
00792   /* ya + halant -> half ya */
00793   { {0x092f,0x094d,0x0},                {0xF7FC,0x0} },
00794   /* ya + halant + ra -> */
00795   { {0x092f,0x094d,0x0930,0x0},         {0xF7FD,0x093E,0x0} },
00796   /* ya + halant + ra + halant -> */
00797   { {0x092f,0x094d,0x0930,0x094d,0x0},  {0xF7FD,0x0} },
00798 
00799   /* ra 3 */
00800   /* ra  */
00801   { {0x0930,0x0 },                      {0x0930,0xF83A,0x0} },
00802   /*  { {0x0930,0x094d,0x0},                 {0xF812,0x0} }, */
00803   /* ra + u -> Ru + kern space */
00804   { {0x0930,0x0941,0x0},                {0xF800,0xF83B,0x0} },
00805   /* ra + U -> RU + kern space */
00806   { {0x0930,0x0942,0x0},                {0xF801,0xF83C,0x0} },
00807 
00808   { {0x0931,0x0},                       {0x0931,0x0} },
00809   { {0x0931,0x094d,0x0},                {0xF7FF,0x0} },
00810 
00811   /* la 2 */
00812   /* la  */
00813   { {0x0932,0x0},                       {0x0932,0x0} },
00814   /* la + halant -> */
00815   { {0x0932,0x094d,0x0},                {0xF802,0x0} },
00816   /* La 2 */
00817   /* La */
00818   { {0x0933,0x0},                       {0x0933,0x0} },
00819   /* La + halant -> half La */
00820   { {0x0933,0x094d,0x0},                {0xF803,0x0} },
00821 
00822   { {0x0934,0x0} ,                      {0x0934,0x0} },
00823   /* va 4 */
00824   /* va */
00825   { {0x0935,0x0},                       {0x0935,0x0} },
00826   /* va + halant -> half va */
00827   { {0x0935,0x094d,0x0},                {0xF804,0x0} },
00828   /* va + halant + ra ->  */
00829   { {0x0935,0x094d,0x0930,0x0},         {0xF805,0x093E,0x0} },
00830   /* va + halant + ra + halant ->   */
00831   { {0x0935,0x094d,0x0930,0x094d,0x0},  {0xF805,0x0} },
00832 
00833   /* sha 6 */
00834   /* sha */
00835   { {0x0936,0x0},                       {0x0936,0x0} },
00836   /* sha + halant -> half sha */
00837   { {0x0936,0x094d,0x0},                {0xF806,0x0} },
00838 
00839   { {0x0936,0x094d,0x091a,0x0},         {0xF83F,0x0} },
00840   { {0x0936,0x094d,0x0928,0x0},         {0xF840,0x0} },
00841 
00842   /* sha + halant + va -> shwa */
00843   { {0x0936,0x094d,0x0935,0x0},         {0xF807,0x093E,0x0} },
00844   /* sha + halant + va + halant -> half shwa */
00845   { {0x0936,0x094d,0x0935,0x094d,0x0},  {0xF807,0x0} },
00846   /* sha + halant + ra -> shra */
00847   { {0x0936,0x094d,0x0930,0x0},         {0xF808,0x093E,0x0} },
00848   /* sha + halant + ra + halant -> half shra */
00849   { {0x0936,0x094d,0x0930,0x094d,0x0},  {0xF808,0x0} },
00850   /* SHa 2 */
00851   /* SHa */
00852   { {0x0937,0x0},                       {0x0937,0x0} },
00853   /* SHa + halant -> half SHa  */
00854   { {0x0937,0x094d,0x0},                {0xF809,0x0} },
00855 
00856   { {0x0937,0x094d,0x091f,0x0},         {0xF841,0xF835,0x0} },
00857   { {0x0937,0x094d,0x0920,0x0},         {0xF842,0xF836,0x0} },
00858 
00859   /* sa 4 */
00860   /* sa */
00861   { {0x0938,0x0},                       {0x0938,0x0} },
00862   /* sa + halant -> half sa */
00863   { {0x0938,0x094d,0x0},                {0xF80A,0x0} },
00864   /* sa + halant + ra ->  */
00865   { {0x0938,0x094d,0x0930,0x0},         {0xF80B,0x093E,0x0} },
00866   /* sa + halan + ra + halant -> */
00867   { {0x0938,0x094d,0x0930,0x094d,0x0},  {0xF80B,0x0} },
00868 
00869   { {0x0938,0x094d,0x0924,0x094d,0x0930,0x0}, {0xF843,0x0} },
00870 
00871   /* ha 2 */
00872   /* ha + kern space  */
00873   { {0x0939,0x0},                       {0x0939,0xF83E,0x0} },
00874   /* ha + halant  -> half ha */
00875   { {0x0939,0x094d,0x0},                {0xF80C,0xF83E,0x0} },
00876   /* ha + Rii + matra -> */
00877   { {0x0939,0x0943,0x0},                {0xF80D,0xF83E,0x0} },
00878   /* ha + halant + ra -> */
00879   { {0x0939,0x094d,0x0930,0x0},         {0xF80E,0xF83E,0x0} },
00880   /* ha + halant + ra + halant -> */
00881   { {0x0939,0x094d,0x0930,0x094d,0x0},  {0xF80E,0x094d,0xF83E,0x0} },
00882 
00883   { {0x0939,0x094d,0x0923,0x0},         {0xF84D,0xF83E,0x0} },
00884   { {0x0939,0x094d,0x0928,0x0},         {0xF84C,0xF83E,0x0} },
00885 
00886   /* ha + halant + ma -> */
00887   { {0x0939,0x094d,0x092e,0x0},         {0xF80F,0xF83E,0x0} },
00888   /* ha + halant + ya -> */
00889   { {0x0939,0x094d,0x092f,0x0},         {0xF810,0xF83E,0x0} },
00890 
00891   { {0x0939,0x094d,0x0932,0x0},         {0xF84A,0xF83E,0x0} },
00892   { {0x0939,0x094d,0x0935,0x0},         {0xF84B,0xF83E,0x0} },
00893 
00894   { {0x0958,0x0},                       {0x0958,0xF832,0x0} },
00895   { {0x0959,0x0},                       {0x0959,0x0} },
00896   { {0x095a,0x0},                       {0x095a,0x0} },
00897   { {0x095b,0x0},                       {0x095b,0x0} },
00898   { {0x095c,0x0},                       {0x095c,0xF837,0x0} },
00899   { {0x095d,0x0},                       {0x095d,0xF838,0x0} },
00900   { {0x095e,0x0},                       {0x095e,0xF832,0x0} },
00901   { {0x095f,0x0},                       {0x095f,0x0} },
00902 
00903   /*"\xd8\x", "", */
00904 
00905   /* misc 5 */
00906 
00907   /* nukta */
00908   { {0x093c,0x0},                       {0x093c,0x0} },
00909   /* nukta + u matra */
00910   { {0x093c,0x0941,0x0},                {0xF81E,0x0} },
00911   /* nukta + Uu matra -> */
00912   { {0x093c,0x0942,0x0},                {0xF821,0x0} },
00913 
00914   /* halant */
00915   { {0x094d,0x0},                       {0x094d,0x0} },
00916   /* halant + ya -> */
00917   { {0x094d,0x092f,0x0},                {0xF7FE,0x0} },
00918   /* halant + ra  */
00919   { {0x094d,0x0930,0x0},                {0xF811,0x0} },
00920   /* halant + ra + halant */
00921   { {0x094d,0x0930,0x094d,0x0},         {0x094d,0x0930,0x0930,0x0} },
00922   /* halant + ra + u matra -> */
00923   { {0x094d,0x0930,0x0941,0x0},         {0xF81F,0x0} },
00924   /* halant + ra + Uu matra ->  */
00925   { {0x094d,0x0930,0x0942,0x0},         {0xF822,0x0} },
00926 
00927   /* Vedic Characters */
00928   { {0x093d,0x0},                       {0x093d,0x0} },
00929   { {0x0950,0x0},                       {0x0950,0x0} },
00930   { {0x0951,0x0},                       {0x0951,0x0} },
00931   { {0x0952,0x0},                       {0x0952,0x0} },
00932   { {0x0953,0x0},                       {0x0953,0x0} },
00933   { {0x0954,0x0},                       {0x0954,0x0} },
00934   { {0x0964,0x0},                       {0x0964,0x0} },
00935   { {0x0965,0x0},                       {0x0965,0x0} },
00936   { {0x0970,0x0},                       {0x0970,0x0} },
00937 
00938   /* Dig09its */
00939   { {0x0966,0x0},                       {0x0966,0x0} },
00940   { {0x0967,0x0},                       {0x0967,0x0} },
00941   { {0x0968,0x0},                       {0x0968,0x0} },
00942   { {0x0969,0x0},                       {0x0969,0x0} },
00943   { {0x096a,0x0},                       {0x096a,0x0} },
00944   { {0x096b,0x0},                       {0x096b,0x0} },
00945   { {0x096c,0x0},                       {0x096c,0x0} },
00946   { {0x096d,0x0},                       {0x096d,0x0} },
00947   { {0x096e,0x0},                       {0x096e,0x0} },
00948   { {0x096f,0x0},                       {0x096f,0x0} }
00949 };
00950 
00951 /* Returns a structure with information we will use to render given the
00952  * #PangoliteFont. This is computed once per font and cached for retrieval.
00953  */
00954 static DvngFontInfo *
00955 get_font_info(const char *fontCharset)
00956 {
00957   static const char *charsets[] = {
00958     "sun.unicode.india-0",
00959   };
00960 
00961   static const int charset_types[] = {
00962     DVNG_FONT_SUN
00963   };
00964   
00965   DvngFontInfo *font_info = g_new(DvngFontInfo, 1);
00966   guint        i; 
00967 
00968   font_info->type = DVNG_FONT_NONE;
00969   for (i = 0; i < G_N_ELEMENTS(charsets); i++) {
00970     if (strcmp(fontCharset, charsets[i]) == 0) {    
00971       font_info->type = (DvngFontType)charset_types[i];
00972       font_info->subfont = (PangoliteXSubfont)i;
00973       break;
00974     }
00975   }
00976   
00977   return font_info;
00978 }
00979 
00980 static void
00981 add_glyph(PangoliteGlyphString *glyphs,
00982           gint                 clusterStart,
00983           PangoliteGlyph       glyph,
00984           gint                 combining)
00985 {
00986   gint index = glyphs->num_glyphs;
00987 
00988   if ((clusterStart == 0) && (index != 0))
00989     clusterStart++;
00990 
00991   pangolite_glyph_string_set_size (glyphs, index + 1);  
00992   glyphs->glyphs[index].glyph = glyph;
00993   glyphs->glyphs[index].is_cluster_start = combining;
00994   glyphs->log_clusters[index] = clusterStart;
00995 }
00996 
00997 static void
00998 GetBaseConsGlyphs(gunichar2  *cluster,
00999                   gint       numCoreCons,
01000                   PangoliteGlyph *glyphList,
01001                   gint       *nGlyphs)
01002 {
01003   int i, j, delta, nMin, nMaxRuleCt, ruleIdx;
01004   gboolean  StillMatching;
01005   gunichar2 temp_out;
01006   gint      tmpCt = *nGlyphs;
01007 
01008   i = 0;
01009   while (i < numCoreCons) {
01010     
01011     nMaxRuleCt = GetDvngRuleCt(cluster[i]);    
01012     while (nMaxRuleCt) {
01013       nMin = MIN(nMaxRuleCt, numCoreCons);      
01014       ruleIdx = 0;
01015 
01016 NotFound:
01017       j = delta = 0;
01018       StillMatching = FALSE;
01019       while (((delta < nMin) || sunGlyphTbl[ruleIdx].ISCII[j]) &&
01020              (ruleIdx < MAP_SIZE) ) {
01021         StillMatching = TRUE;
01022         if ((delta < nMin) && (j < MAX_CORE_CONS) &&
01023             (cluster[i + delta] != sunGlyphTbl[ruleIdx].ISCII[j])) {
01024           ruleIdx++;
01025           goto NotFound;
01026         }
01027         delta++;
01028         j++;
01029       }
01030       
01031       if (StillMatching) /* Found */
01032         break;
01033       else
01034         nMaxRuleCt--;
01035     }
01036     
01037     i += nMin;
01038     
01039     /* Can't find entry in the table */
01040     if ((StillMatching == FALSE) || (ruleIdx >= MAP_SIZE)) {
01041       for (j = 0; j < numCoreCons; j++)
01042         glyphList[tmpCt++] = PANGO_MOZ_MAKE_GLYPH(cluster[j]);
01043     }
01044     else if (((tmpCt > 0) && IsKern(glyphList[tmpCt - 1])) &&
01045              IsMatraAtStem(sunGlyphTbl[ruleIdx].ISFOC[0])) {
01046       temp_out = glyphList[tmpCt - 1];
01047       
01048       for (j=0; sunGlyphTbl[ruleIdx].ISFOC[j]; j++)
01049         glyphList[tmpCt - 1] = PANGO_MOZ_MAKE_GLYPH(sunGlyphTbl[ruleIdx].ISFOC[j]);
01050         
01051       glyphList[tmpCt++] = PANGO_MOZ_MAKE_GLYPH(temp_out);
01052     }
01053     else {
01054       for (j=0; sunGlyphTbl[ruleIdx].ISFOC[j]; j++)
01055         glyphList[tmpCt++] = PANGO_MOZ_MAKE_GLYPH(sunGlyphTbl[ruleIdx].ISFOC[j]);
01056     }
01057   }
01058   *nGlyphs = tmpCt;
01059 }
01060 
01061 static gint
01062 get_adjusted_glyphs_list(DvngFontInfo *fontInfo,
01063                          gunichar2    *cluster,
01064                          gint         nChars,
01065                          PangoliteGlyph   *gLst,
01066                          StateType    *DvngClusterState)
01067 {
01068   int i, k, len;
01069   gint      nGlyphs = 0;
01070   gunichar2 dummy;
01071   
01072   switch (*DvngClusterState) {
01073   case St1:
01074     if (IsDvngCharCls(cluster[0], _IM)) {
01075       GetBaseConsGlyphs(cluster, nChars, gLst, &nGlyphs);
01076       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF7C0);
01077     }
01078     else {
01079       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF7C0);
01080       GetBaseConsGlyphs(cluster, nChars, gLst, &nGlyphs);
01081     }
01082     break;
01083 
01084     case St2:
01085     case St3:
01086     case St4:
01087     case St5:
01088     case St6:
01089       GetBaseConsGlyphs(cluster, nChars, gLst, &nGlyphs);
01090       break;
01091       
01092     case St7:
01093       if (IsDvngCharCls(cluster[nChars - 1], _UP)) {
01094 
01095         if (IsDvngCharCls(cluster[nChars - 2], _RM))
01096           GetBaseConsGlyphs(cluster, nChars - 2, gLst, &nGlyphs);
01097         else
01098           GetBaseConsGlyphs(cluster, nChars, gLst, &nGlyphs);
01099 
01100         if (IsDvngCharCls(cluster[nChars - 2], _RM)) {
01101 
01102           if (IsDvngCharCls(cluster[nChars - 2], _II_M))
01103             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF81B);
01104 
01105           else if (IsDvngCharCls(cluster[nChars - 2], _AYE_M)) {
01106             dummy = gLst[nGlyphs - 1];
01107             gLst[nGlyphs - 1] = PANGO_MOZ_MAKE_GLYPH(0xF82D);
01108             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01109           }
01110 
01111           else if (IsDvngCharCls(cluster[nChars - 2], _EE_M))
01112             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF824);
01113           
01114           else if (IsDvngCharCls(cluster[nChars - 2], _EY_M))
01115             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF827);
01116 
01117           else if (IsDvngCharCls(cluster[nChars - 2], _AI_M))
01118             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82A);
01119 
01120           else if (IsDvngCharCls(cluster[nChars - 2], _AWE_M)) {
01121             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01122             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82D);
01123           }
01124 
01125           else if (IsDvngCharCls(cluster[nChars - 2], _O_M)) {
01126             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01127             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF824);
01128           }
01129 
01130           else if (IsDvngCharCls(cluster[nChars - 2], _OW1_M)) {
01131             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01132             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF827);
01133           }
01134 
01135           else if (IsDvngCharCls(cluster[nChars - 2], _OW2_M)) {
01136             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01137             gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82A);
01138           }
01139         }
01140       }
01141       else {
01142         GetBaseConsGlyphs(cluster, nChars, gLst, &nGlyphs);
01143       }
01144       break;
01145 
01146     case St8:
01147       GetBaseConsGlyphs(cluster, nChars - 1, gLst, &nGlyphs);
01148       if (IsKern(gLst[nGlyphs - 1])) {
01149         dummy = gLst[nGlyphs - 1];
01150         gLst[nGlyphs - 1] = PANGO_MOZ_MAKE_GLYPH(cluster[nChars - 1]);
01151         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01152       }
01153       else
01154         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(cluster[nChars - 1]);
01155       break;
01156       
01157     case St9:
01158       if (IsDvngCharCls(cluster[0], _MS))
01159         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093F);
01160       else
01161         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF817);        
01162 
01163       GetBaseConsGlyphs(cluster, nChars - 1, gLst, &nGlyphs);
01164       break;
01165 
01166   case St10:
01167     if (IsDvngCharCls(cluster[0], _MS))
01168       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF814);
01169     else
01170       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF818);
01171 
01172     GetBaseConsGlyphs(cluster, nChars - 2, gLst, &nGlyphs);
01173     break;
01174     
01175   case St11:
01176     GetBaseConsGlyphs(cluster, nChars, gLst, &nGlyphs);
01177     break;
01178     
01179   case St12:
01180     gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x0930);
01181     gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF83A);
01182     break;
01183     
01184   case St13:
01185     gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x0930);
01186     gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x094D);
01187     gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF83A);
01188     break;
01189     
01190   case St14:    
01191     GetBaseConsGlyphs(cluster+2, nChars - 2, gLst, &nGlyphs);
01192     if (IsKern(gLst[nGlyphs - 1])) {
01193       dummy = gLst[nGlyphs - 1];
01194       gLst[nGlyphs - 1] = PANGO_MOZ_MAKE_GLYPH(0xF812);
01195       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01196     }
01197     else
01198       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF812);
01199     break;
01200     
01201   case St15:    
01202     GetBaseConsGlyphs(cluster+2, nChars - 3, gLst, &nGlyphs);
01203     if (IsKern(gLst[nGlyphs - 1])) {      
01204       dummy = gLst[nGlyphs - 2];
01205       gLst[nGlyphs - 2] = PANGO_MOZ_MAKE_GLYPH(0xF812);
01206       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x094D);
01207       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01208     }
01209     else {
01210       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF812);
01211       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x094D);
01212     }
01213     break;
01214     
01215   case St16:
01216     if (IsDvngCharCls(cluster[nChars - 1], _RM))
01217       GetBaseConsGlyphs(cluster+2, nChars - 3, gLst, &nGlyphs);
01218     else
01219       GetBaseConsGlyphs(cluster+2, nChars - 2, gLst, &nGlyphs);
01220 
01221     if (IsDvngCharCls(cluster[nChars - 1], ~(_RM))){
01222 
01223       if (IsKern(gLst[nGlyphs - 1])) {
01224         dummy = gLst[nGlyphs - 1];
01225         gLst[nGlyphs - 1] = PANGO_MOZ_MAKE_GLYPH(0xF812);
01226         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01227       }
01228       else
01229         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF812);
01230     }
01231     else {
01232 
01233       if (IsDvngCharCls(cluster[nChars - 1], _II_M))
01234         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF81C);
01235 
01236       else if (IsDvngCharCls(cluster[nChars - 1], _EY_M))
01237         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF828);
01238 
01239       else if (IsDvngCharCls(cluster[nChars -1], _AI_M))
01240         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82B);
01241 
01242       else if (IsDvngCharCls(cluster[nChars - 1], _OW1_M)) {
01243         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01244         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF828);
01245       }
01246 
01247       else if (IsDvngCharCls(cluster[nChars - 1], _OW2_M)) {
01248         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01249         gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82B);
01250       }
01251     }
01252     break;
01253     
01254   case St17:
01255     if (IsDvngCharCls(cluster[nChars - 1], _UP)) {
01256 
01257       if (IsDvngCharCls(cluster[nChars - 2], _RM))
01258         GetBaseConsGlyphs(cluster+2, nChars - 4, gLst, &nGlyphs);
01259       else
01260         GetBaseConsGlyphs(cluster+2, nChars - 3, gLst, &nGlyphs);
01261 
01262       if (IsDvngCharCls(cluster[nChars - 2], ~(_RM))) {
01263 
01264         if (IsKern(gLst[nGlyphs - 1])) {
01265           dummy = gLst[nGlyphs - 1];
01266           gLst[nGlyphs - 1] = PANGO_MOZ_MAKE_GLYPH(0xF813);
01267           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01268         }
01269         else
01270           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF813);
01271       }
01272       else {
01273         if (IsDvngCharCls(cluster[nChars - 2], _II_M))
01274           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF81D);
01275 
01276         else if (IsDvngCharCls(cluster[nChars - 2], _EY_M))
01277           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF829);
01278 
01279         else if (IsDvngCharCls(cluster[nChars - 2], _AI_M))
01280           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82C);
01281 
01282         else if (IsDvngCharCls(cluster[nChars - 2], _OW1_M)) {
01283           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01284           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF829);
01285         }
01286         else if (IsDvngCharCls(cluster[nChars - 2], _OW2_M)) {
01287           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0x093E);
01288           gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF82C);
01289         }
01290       } /* ? else GetBaseConsGlyphs(); */
01291     break;
01292     
01293   case St18:
01294     GetBaseConsGlyphs(cluster-2, nChars-3, gLst, &nGlyphs);
01295     if (IsKern(gLst[nGlyphs - 1])) {
01296       dummy = gLst[nGlyphs - 1];
01297       gLst[nGlyphs - 1] = PANGO_MOZ_MAKE_GLYPH(0xF813);
01298       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(dummy);
01299     }
01300     else
01301       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF813);
01302     break;
01303     
01304   case St19:
01305     if (IsDvngCharCls(cluster[0], _MS))
01306       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF815);
01307     else
01308       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF819);
01309 
01310     GetBaseConsGlyphs(cluster+2, nChars-3, gLst, &nGlyphs);
01311     break;
01312     
01313   case St20:
01314     if (IsDvngCharCls(cluster[0], _MS))
01315       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF816);
01316     else
01317       gLst[nGlyphs++] = PANGO_MOZ_MAKE_GLYPH(0xF81A);
01318 
01319     GetBaseConsGlyphs(cluster+2, nChars - 4, gLst, &nGlyphs);
01320     break;
01321     }
01322   }
01323 
01324   return nGlyphs;
01325 }
01326 
01327 static gint
01328 get_glyphs_list(DvngFontInfo *fontInfo,
01329                 gunichar2    *cluster,
01330                 gint          numChars,
01331                 PangoliteGlyph   *glyphLst,
01332                 StateType    *clustState)
01333 {
01334   PangoliteGlyph glyph;
01335   gint       i;
01336 
01337   switch (fontInfo->type) {
01338   case DVNG_FONT_NONE:
01339     for (i = 0; i < numChars; i++)
01340       glyphLst[i] = 0; /*pangolite_x_get_unknown_glyph(fontInfo->font);*/
01341     return numChars;
01342     
01343   case DVNG_FONT_SUN:
01344     return get_adjusted_glyphs_list(fontInfo, cluster, numChars, glyphLst, clustState);
01345   }
01346   
01347   return 0; /* Quiet GCC */
01348 }
01349 
01350 static void
01351 add_cluster(DvngFontInfo     *fontInfo,
01352             PangoliteGlyphString *glyphs,
01353             gint              clusterBeg,
01354             gunichar2        *cluster,
01355             gint              numChars,
01356             StateType        *clustState)
01357 {
01358   PangoliteGlyph glyphsList[MAX_GLYPHS];
01359   gint           i, numGlyphs, ClusterStart=0;
01360   
01361   numGlyphs = get_glyphs_list(fontInfo, cluster, numChars, glyphsList, clustState);
01362   for (i = 0; i < numGlyphs; i++) {
01363 
01364     ClusterStart = (gint)GLYPH_COMBINING;
01365     if (i == 0)
01366       ClusterStart = numChars;
01367     add_glyph(glyphs, clusterBeg, glyphsList[i], ClusterStart);
01368   }
01369 }
01370 
01371 static const gunichar2 *
01372 get_next_cluster(const gunichar2 *text,
01373                  gint             length,
01374                  gunichar2       *cluster,
01375                  gint            *numChars,
01376                  StateType       *clustState)
01377 {
01378   const gunichar2 *p;
01379   gint            n_chars = 0;
01380   StateType       aSt = *clustState;
01381 
01382   p = text;
01383   while (p < text + length) {
01384     gunichar2 cur = *p;
01385     
01386     if ((n_chars == 0) ||
01387         ((n_chars > 0) && IsComposible(cluster[n_chars - 1], cur))) {
01388       cluster[n_chars++] = cur;
01389       aSt = SetClusterState(aSt, cur);
01390       p++;
01391     }
01392     else
01393       break;
01394   }
01395   
01396   *numChars = n_chars;
01397   *clustState = aSt;
01398   return p;
01399 }
01400 
01401 static void 
01402 dvng_engine_shape(const char       *fontCharset,
01403                   const gunichar2  *text,
01404                   gint             length,
01405                   PangoliteAnalysis    *analysis,
01406                   PangoliteGlyphString *glyphs)
01407 {
01408   DvngFontInfo    *fontInfo;
01409   const gunichar2 *p, *log_cluster;
01410   gunichar2       cluster[MAX_CLUSTER_CHRS];
01411   gint            num_chrs;
01412   StateType       aSt = St0;
01413 
01414   fontInfo = get_font_info(fontCharset);
01415 
01416   p = text;
01417   while (p < text + length) {
01418     log_cluster = p;
01419     aSt = St0;
01420     p = get_next_cluster(p, text + length - p, cluster, &num_chrs, &aSt);
01421     add_cluster(fontInfo, glyphs, log_cluster-text, cluster, num_chrs, &aSt);
01422   }
01423 }
01424 
01425 static PangoliteCoverage *
01426 dvng_engine_get_coverage(const char *fontCharset,
01427                          const char *lang)
01428 {
01429   PangoliteCoverage *result = pangolite_coverage_new ();  
01430   DvngFontInfo  *fontInfo = get_font_info (fontCharset);
01431   
01432   if (fontInfo->type != DVNG_FONT_NONE) {
01433     gunichar2 wc;
01434  
01435     for (wc = 0x901; wc <= 0x903; wc++)
01436       pangolite_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
01437     for (wc = 0x905; wc <= 0x939; wc++)
01438       pangolite_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
01439     for (wc = 0x93c; wc <= 0x94d; wc++)
01440       pangolite_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
01441     for (wc = 0x950; wc <= 0x954; wc++)
01442       pangolite_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
01443     for (wc = 0x958; wc <= 0x970; wc++)
01444       pangolite_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
01445     /*    pangolite_coverage_set (result, ZWJ, PANGO_COVERAGE_EXACT); */
01446   }
01447   
01448   return result;
01449 }
01450 
01451 static PangoliteEngine *
01452 dvng_engine_x_new ()
01453 {
01454   PangoliteEngineShape *result;
01455   
01456   result = g_new (PangoliteEngineShape, 1);
01457   result->engine.id = SCRIPT_ENGINE_NAME;
01458   result->engine.type = PANGO_ENGINE_TYPE_SHAPE;
01459   result->engine.length = sizeof (result);
01460   result->script_shape = dvng_engine_shape;
01461   result->get_coverage = dvng_engine_get_coverage;
01462   return (PangoliteEngine *)result;
01463 }
01464 
01465 /* The following three functions provide the public module API for
01466  * Pangolite. If we are compiling it is a module, then we name the
01467  * entry points script_engine_list, etc. But if we are compiling
01468  * it for inclusion directly in Pangolite, then we need them to
01469  * to have distinct names for this module, so we prepend
01470  * _pangolite_thai_x_
01471  */
01472 #ifdef X_MODULE_PREFIX
01473 #define MODULE_ENTRY(func) _pangolite_dvng_x_##func
01474 #else
01475 #define MODULE_ENTRY(func) func
01476 #endif
01477 
01478 /* List the engines contained within this module
01479  */
01480 void 
01481 MODULE_ENTRY(script_engine_list) (PangoliteEngineInfo **engines, gint *n_engines)
01482 {
01483   *engines = script_engines;
01484   *n_engines = G_N_ELEMENTS (script_engines);
01485 }
01486 
01487 /* Load a particular engine given the ID for the engine
01488  */
01489 PangoliteEngine *
01490 MODULE_ENTRY(script_engine_load) (const char *id)
01491 {
01492   if (!strcmp (id, SCRIPT_ENGINE_NAME))
01493     return dvng_engine_x_new ();
01494   else
01495     return NULL;
01496 }
01497 
01498 void 
01499 MODULE_ENTRY(script_engine_unload) (PangoliteEngine *engine)
01500 {
01501 }
01502