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