fontservices/textshaperplugin/IcuSource/layout/ThaiShaping.cpp
changeset 0 1fb32624e06b
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2  *
       
     3  * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
       
     4  *
       
     5  */
       
     6 
       
     7 #include "LETypes.h"
       
     8 #include "LEGlyphFilter.h"
       
     9 #include "OpenTypeTables.h"
       
    10 #include "LEGlyphStorage.h"
       
    11 #include "ThaiShaping.h"
       
    12 
       
    13 U_NAMESPACE_BEGIN
       
    14 
       
    15 enum {
       
    16     CH_SPACE        = 0x0020,
       
    17     CH_YAMAKKAN     = 0x0E4E,
       
    18     CH_MAI_HANAKAT  = 0x0E31,
       
    19     CH_SARA_AA      = 0x0E32,
       
    20     CH_SARA_AM      = 0x0E33,
       
    21     CH_SARA_UEE     = 0x0E37,
       
    22     CH_MAITAIKHU    = 0x0E47,
       
    23     CH_NIKHAHIT     = 0x0E4D,
       
    24     CH_SARA_U       = 0x0E38,
       
    25     CH_PHINTHU      = 0x0E3A,
       
    26     CH_YO_YING      = 0x0E0D,
       
    27     CH_THO_THAN     = 0x0E10,
       
    28     CH_DOTTED_CIRCLE = 0x25CC
       
    29 };
       
    30 
       
    31     le_uint8 ThaiShaping::getCharClass(LEUnicode ch)
       
    32 {
       
    33     le_uint8 charClass = NON;
       
    34     
       
    35     if (ch >= 0x0E00 && ch <= 0x0E5B) {
       
    36         charClass = classTable[ch - 0x0E00];
       
    37     }
       
    38     
       
    39     return charClass;
       
    40 }
       
    41 
       
    42 
       
    43 LEUnicode ThaiShaping::leftAboveVowel(LEUnicode vowel, le_uint8 glyphSet)
       
    44 {
       
    45     static const LEUnicode leftAboveVowels[][7] = {
       
    46         {0x0E61, 0x0E32, 0x0E33, 0x0E64, 0x0E65, 0x0E66, 0x0E67},
       
    47         {0xF710, 0x0E32, 0x0E33, 0xF701, 0xF702, 0xF703, 0xF704},
       
    48         {0xF884, 0x0E32, 0x0E33, 0xF885, 0xF886, 0xF887, 0xF788},
       
    49         {0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37}
       
    50     };
       
    51    
       
    52     if (vowel >= CH_MAI_HANAKAT && vowel <= CH_SARA_UEE) {
       
    53         return leftAboveVowels[glyphSet][vowel - CH_MAI_HANAKAT];
       
    54     }
       
    55     
       
    56     if (vowel == CH_YAMAKKAN && glyphSet == 0) {
       
    57         return 0x0E7E;
       
    58     }
       
    59     
       
    60     return vowel;
       
    61 }
       
    62 
       
    63 LEUnicode ThaiShaping::lowerRightTone(LEUnicode tone, le_uint8 glyphSet)
       
    64 {
       
    65     static const LEUnicode lowerRightTones[][7] = {
       
    66         {0x0E68, 0x0E69, 0x0E6A, 0x0E6B, 0x0E6C, 0x0E6D, 0x0E6E},
       
    67         {0x0E47, 0xF70A, 0xF70B, 0xF70C, 0xF70D, 0xF70E, 0x0E4D},
       
    68         {0x0E47, 0xF88B, 0xF88E, 0xF891, 0xF894, 0xF897, 0x0E4D},
       
    69         {0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
       
    70     };
       
    71 
       
    72     if (tone >= CH_MAITAIKHU && tone <= CH_NIKHAHIT) {
       
    73         return lowerRightTones[glyphSet][tone - CH_MAITAIKHU];
       
    74     }
       
    75     
       
    76     return tone;
       
    77 }
       
    78 
       
    79 LEUnicode ThaiShaping::lowerLeftTone(LEUnicode tone, le_uint8 glyphSet)
       
    80 {
       
    81     static const LEUnicode lowerLeftTones[][7] = {
       
    82         {0x0E76, 0x0E77, 0x0E78, 0x0E79, 0x0E7A, 0x0E7B, 0x0E7C},
       
    83         {0xF712, 0xF705, 0xF706, 0xF707, 0xF708, 0xF709, 0xF711},
       
    84         {0xF889, 0xF88C, 0xF88F, 0xF892, 0xF895, 0xF898, 0xF899},
       
    85         {0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
       
    86     };
       
    87 
       
    88     if (tone >= CH_MAITAIKHU && tone <= CH_NIKHAHIT) {
       
    89         return lowerLeftTones[glyphSet][tone - CH_MAITAIKHU];
       
    90     }
       
    91     
       
    92     return tone;
       
    93 }
       
    94 
       
    95 LEUnicode ThaiShaping::upperLeftTone(LEUnicode tone, le_uint8 glyphSet)
       
    96 {
       
    97     static const LEUnicode upperLeftTones[][7] = {
       
    98         {0x0E6F, 0x0E70, 0x0E71, 0x0E72, 0x0E73, 0x0E74, 0x0E75},
       
    99         {0xF712, 0xF713, 0xF714, 0xF715, 0xF716, 0xF717, 0xF711},
       
   100         {0xF889, 0xF88A, 0xF88D, 0xF890, 0xF893, 0xF896, 0xF899},
       
   101         {0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
       
   102     };
       
   103 
       
   104     if (tone >= CH_MAITAIKHU && tone <= CH_NIKHAHIT) {
       
   105         return upperLeftTones[glyphSet][tone - CH_MAITAIKHU];
       
   106     }
       
   107     
       
   108     return tone;
       
   109 }
       
   110 
       
   111 LEUnicode ThaiShaping::lowerBelowVowel(LEUnicode vowel, le_uint8 glyphSet)
       
   112 {
       
   113     static const LEUnicode lowerBelowVowels[][3] = {
       
   114         {0x0E3C, 0x0E3D, 0x0E3E},
       
   115         {0xF718, 0xF719, 0xF71A},
       
   116         {0x0E38, 0x0E39, 0x0E3A},
       
   117         {0x0E38, 0x0E39, 0x0E3A}
       
   118 
       
   119     };
       
   120 
       
   121     if (vowel >= CH_SARA_U && vowel <= CH_PHINTHU) {
       
   122         return lowerBelowVowels[glyphSet][vowel - CH_SARA_U];
       
   123     }
       
   124     
       
   125     return vowel;
       
   126 }
       
   127 
       
   128 LEUnicode ThaiShaping::noDescenderCOD(LEUnicode cod, le_uint8 glyphSet)
       
   129 {
       
   130     static const LEUnicode noDescenderCODs[][4] = {
       
   131         {0x0E60, 0x0E0E, 0x0E0F, 0x0E63},
       
   132         {0xF70F, 0x0E0E, 0x0E0F, 0xF700},
       
   133         {0x0E0D, 0x0E0E, 0x0E0F, 0x0E10},
       
   134         {0x0E0D, 0x0E0E, 0x0E0F, 0x0E10}
       
   135 
       
   136     };
       
   137 
       
   138     if (cod >= CH_YO_YING && cod <= CH_THO_THAN) {
       
   139         return noDescenderCODs[glyphSet][cod - CH_YO_YING];
       
   140     }
       
   141     
       
   142     return cod;
       
   143 }
       
   144 
       
   145 le_uint8 ThaiShaping::doTransition (StateTransition transition, LEUnicode currChar, le_int32 inputIndex, le_uint8 glyphSet,
       
   146         LEUnicode errorChar, LEUnicode *outputBuffer, LEGlyphStorage &glyphStorage, le_int32 &outputIndex)
       
   147 {
       
   148     LEErrorCode success = LE_NO_ERROR;
       
   149 
       
   150     switch (transition.action) {
       
   151     case tA:
       
   152         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   153         outputBuffer[outputIndex++] = currChar;
       
   154         break;
       
   155         
       
   156     case tC:
       
   157         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   158         outputBuffer[outputIndex++] = currChar;
       
   159         break;
       
   160         
       
   161     case tD:
       
   162         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   163         outputBuffer[outputIndex++] = leftAboveVowel(currChar, glyphSet);
       
   164         break;
       
   165         
       
   166     case tE:
       
   167         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   168         outputBuffer[outputIndex++] = lowerRightTone(currChar, glyphSet);
       
   169         break;
       
   170         
       
   171     case tF:
       
   172         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   173         outputBuffer[outputIndex++] = lowerLeftTone(currChar, glyphSet);
       
   174         break;
       
   175     
       
   176     case tG:
       
   177         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   178         outputBuffer[outputIndex++] = upperLeftTone(currChar, glyphSet);
       
   179         break;
       
   180         
       
   181     case tH:
       
   182     {
       
   183         LEUnicode cod = outputBuffer[outputIndex - 1];
       
   184         LEUnicode coa = noDescenderCOD(cod, glyphSet);
       
   185 
       
   186         if (cod != coa) {
       
   187             outputBuffer[outputIndex - 1] = coa;
       
   188             
       
   189             glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   190             outputBuffer[outputIndex++] = currChar;
       
   191             break;
       
   192         }
       
   193 
       
   194         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   195         outputBuffer[outputIndex++] = lowerBelowVowel(currChar, glyphSet);
       
   196         break;
       
   197     }
       
   198         
       
   199     case tR:
       
   200         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   201         outputBuffer[outputIndex++] = errorChar;
       
   202 
       
   203         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   204         outputBuffer[outputIndex++] = currChar;
       
   205         break;
       
   206         
       
   207     case tS:
       
   208         if (currChar == CH_SARA_AM) {
       
   209             glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   210             outputBuffer[outputIndex++] = errorChar;
       
   211         }
       
   212 
       
   213         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   214         outputBuffer[outputIndex++] = currChar;
       
   215         break;
       
   216         
       
   217     default:
       
   218         // FIXME: if we get here, there's an error
       
   219         // in the state table!
       
   220         glyphStorage.setCharIndex(outputIndex, inputIndex, success);
       
   221         outputBuffer[outputIndex++] = currChar;
       
   222         break;
       
   223      }
       
   224      
       
   225      return transition.nextState;
       
   226 }
       
   227 
       
   228 le_uint8 ThaiShaping::getNextState(LEUnicode ch, le_uint8 prevState, le_int32 inputIndex, le_uint8 glyphSet, LEUnicode errorChar,
       
   229                               le_uint8 &charClass, LEUnicode *output, LEGlyphStorage &glyphStorage, le_int32 &outputIndex)
       
   230 {
       
   231     StateTransition transition;
       
   232 
       
   233     charClass = getCharClass(ch);
       
   234     transition = getTransition(prevState, charClass);
       
   235     
       
   236     return doTransition(transition, ch, inputIndex, glyphSet, errorChar, output, glyphStorage, outputIndex);
       
   237 }
       
   238 
       
   239 le_bool ThaiShaping::isLegalHere(LEUnicode ch, le_uint8 prevState)
       
   240 {
       
   241     le_uint8 charClass = getCharClass(ch);
       
   242     StateTransition transition = getTransition(prevState, charClass);
       
   243 
       
   244     switch (transition.action) {
       
   245     case tA:
       
   246     case tC:
       
   247     case tD:
       
   248     case tE:
       
   249     case tF:
       
   250     case tG:
       
   251     case tH:
       
   252         return TRUE;
       
   253             
       
   254     case tR:
       
   255     case tS:
       
   256         return FALSE;
       
   257             
       
   258     default:
       
   259         // FIXME: if we get here, there's an error
       
   260         // in the state table!
       
   261         return FALSE;
       
   262     }
       
   263 }
       
   264     
       
   265 le_int32 ThaiShaping::compose(const LEUnicode *input, le_int32 offset, le_int32 charCount, le_uint8 glyphSet,
       
   266                           LEUnicode errorChar, LEUnicode *output, LEGlyphStorage &glyphStorage)
       
   267 {
       
   268     le_uint8 state = 0;
       
   269     le_int32 inputIndex;
       
   270     le_int32 outputIndex = 0;
       
   271     le_uint8 conState = 0xFF;
       
   272     le_int32 conInput = -1;
       
   273     le_int32 conOutput = -1;
       
   274     
       
   275     for (inputIndex = 0; inputIndex < charCount; inputIndex += 1) {
       
   276         LEUnicode ch = input[inputIndex + offset];
       
   277         le_uint8 charClass;
       
   278         
       
   279         // Decompose SARA AM into NIKHAHIT + SARA AA
       
   280         if (ch == CH_SARA_AM && isLegalHere(ch, state)) {
       
   281             outputIndex = conOutput;
       
   282             state = getNextState(CH_NIKHAHIT, conState, inputIndex, glyphSet, errorChar, charClass,
       
   283                 output, glyphStorage, outputIndex);
       
   284             
       
   285             for (int j = conInput + 1; j < inputIndex; j += 1) {
       
   286                 ch = input[j + offset];
       
   287                 state = getNextState(ch, state, j, glyphSet, errorChar, charClass,
       
   288                     output, glyphStorage, outputIndex);
       
   289             }
       
   290             
       
   291             ch = CH_SARA_AA;
       
   292         }
       
   293         
       
   294         state = getNextState(ch, state, inputIndex, glyphSet, errorChar, charClass,
       
   295             output, glyphStorage, outputIndex);
       
   296         
       
   297         if (charClass >= CON && charClass <= COD) {
       
   298             conState = state;
       
   299             conInput = inputIndex;
       
   300             conOutput = outputIndex;
       
   301         }
       
   302     }
       
   303     
       
   304     return outputIndex;
       
   305 }
       
   306 
       
   307 U_NAMESPACE_END