Home | History | Annotate | Download | only in layout
      1 /*
      2  *
      3  * (C) Copyright IBM Corp.  and others 1998-2013 - All Rights Reserved
      4  *
      5  */
      6 
      7 #include "LETypes.h"
      8 #include "MorphTables.h"
      9 #include "StateTables.h"
     10 #include "MorphStateTables.h"
     11 #include "SubtableProcessor2.h"
     12 #include "StateTableProcessor2.h"
     13 #include "ContextualGlyphInsertionProc2.h"
     14 #include "LEGlyphStorage.h"
     15 #include "LESwaps.h"
     16 
     17 U_NAMESPACE_BEGIN
     18 
     19 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
     20 
     21 ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
     22   : StateTableProcessor2(morphSubtableHeader)
     23 {
     24     contextualGlyphHeader = (const ContextualGlyphInsertionHeader2 *) morphSubtableHeader;
     25     le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
     26     insertionTable = ((le_uint16 *) ((char *)&stateTableHeader->stHeader + insertionTableOffset));
     27     entryTable = (const ContextualGlyphInsertionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
     28 }
     29 
     30 ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
     31 {
     32 }
     33 
     34 void ContextualGlyphInsertionProcessor2::beginStateTable()
     35 {
     36     markGlyph = 0;
     37 }
     38 
     39 le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
     40 {
     41     const ContextualGlyphInsertionStateEntry2 *entry = &entryTable[index];
     42     le_uint16 newState = SWAPW(entry->newStateIndex);
     43     le_uint16 flags = SWAPW(entry->flags);
     44     le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
     45     le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
     46     int i = 0;
     47 
     48     if (markIndex > 0) {
     49         le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
     50         if (!(flags & cgiMarkedIsKashidaLike)) {
     51             // extra glyph(s) will be added directly before/after the specified marked glyph
     52             if (!(flags & cgiMarkInsertBefore)) {
     53                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
     54                 for (i = 0; i < count; i++, markIndex++) {
     55                     insertGlyphs[i] = insertionTable[markIndex];
     56                 }
     57                 insertGlyphs[i] = glyphStorage[markGlyph];
     58                 glyphStorage.applyInsertions();
     59             } else {
     60                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
     61                 insertGlyphs[0] = glyphStorage[markGlyph];
     62                 for (i = 1; i < count + 1; i++, markIndex++) {
     63                     insertGlyphs[i] = insertionTable[markIndex];
     64                 }
     65                 glyphStorage.applyInsertions();
     66             }
     67         } else {
     68             // inserted as a split-vowel-like insertion
     69             // extra glyph(s) will be inserted some distance away from the marked glyph
     70             if (!(flags & cgiMarkInsertBefore)) {
     71                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
     72                 for (i = 0; i < count; i++, markIndex++) {
     73                     insertGlyphs[i] = insertionTable[markIndex];
     74                 }
     75                 insertGlyphs[i] = glyphStorage[markGlyph];
     76                 glyphStorage.applyInsertions();
     77             } else {
     78                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
     79                 insertGlyphs[0] = glyphStorage[markGlyph];
     80                 for (i = 1; i < count + 1; i++, markIndex++) {
     81                     insertGlyphs[i] = insertionTable[markIndex];
     82                 }
     83                 glyphStorage.applyInsertions();
     84             }
     85         }
     86     }
     87 
     88     if (currIndex > 0) {
     89         le_int16 count = flags & cgiCurrentInsertCountMask;
     90         if (!(flags & cgiCurrentIsKashidaLike)) {
     91             // extra glyph(s) will be added directly before/after the specified current glyph
     92             if (!(flags & cgiCurrentInsertBefore)) {
     93                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
     94                 for (i = 0; i < count; i++, currIndex++) {
     95                     insertGlyphs[i] = insertionTable[currIndex];
     96                 }
     97                 insertGlyphs[i] = glyphStorage[currGlyph];
     98                 glyphStorage.applyInsertions();
     99             } else {
    100                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
    101                 insertGlyphs[0] = glyphStorage[currGlyph];
    102                 for (i = 1; i < count + 1; i++, currIndex++) {
    103                     insertGlyphs[i] = insertionTable[currIndex];
    104                 }
    105                 glyphStorage.applyInsertions();
    106             }
    107         } else {
    108             // inserted as a split-vowel-like insertion
    109             // extra glyph(s) will be inserted some distance away from the current glyph
    110             if (!(flags & cgiCurrentInsertBefore)) {
    111                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
    112                 for (i = 0; i < count; i++, currIndex++) {
    113                     insertGlyphs[i] = insertionTable[currIndex];
    114                 }
    115                 insertGlyphs[i] = glyphStorage[currGlyph];
    116                 glyphStorage.applyInsertions();
    117             } else {
    118                 LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
    119                 insertGlyphs[0] = glyphStorage[currGlyph];
    120                 for (i = 1; i < count + 1; i++, currIndex++) {
    121                     insertGlyphs[i] = insertionTable[currIndex];
    122                 }
    123                 glyphStorage.applyInsertions();
    124             }
    125         }
    126     }
    127 
    128     if (flags & cgiSetMark) {
    129         markGlyph = currGlyph;
    130     }
    131 
    132     if (!(flags & cgiDontAdvance)) {
    133         currGlyph += dir;
    134     }
    135 
    136     return newState;
    137 }
    138 
    139 void ContextualGlyphInsertionProcessor2::endStateTable()
    140 {
    141 }
    142 
    143 U_NAMESPACE_END
    144