1 /* 2 * 3 * (C) Copyright IBM Corp and Others. 1998-2014 - 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 "LigatureSubstProc2.h" 14 #include "LEGlyphStorage.h" 15 #include "LESwaps.h" 16 17 U_NAMESPACE_BEGIN 18 19 #define ExtendedComplement(m) ((le_int32) (~((le_uint32) (m)))) 20 #define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m)) 21 #define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v)) 22 23 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2) 24 25 LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success) 26 : StateTableProcessor2(morphSubtableHeader, success), 27 ligActionOffset(0), 28 componentOffset(0), ligatureOffset(0), entryTable(), ligatureSubstitutionHeader(morphSubtableHeader, success) 29 { 30 if (LE_FAILURE(success)) return; 31 32 ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset); 33 componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset); 34 ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset); 35 36 entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY); 37 } 38 39 LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2() 40 { 41 } 42 43 void LigatureSubstitutionProcessor2::beginStateTable() 44 { 45 m = -1; 46 } 47 48 le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success) 49 { 50 const LigatureSubstitutionStateEntry2 *entry = entryTable.getAlias(index, success); 51 if(LE_FAILURE(success)) return 0; 52 53 le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex); 54 le_uint16 flags = SWAPW(entry->entryFlags); 55 le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex); 56 57 if (flags & lsfSetComponent) { 58 if (++m >= nComponents) { 59 m = 0; 60 } 61 componentStack[m] = currGlyph; 62 } else if ( m == -1) { 63 // bad font- skip this glyph. 64 //LE_DEBUG_BAD_FONT("m==-1 (componentCount went negative)") 65 currGlyph+= dir; 66 return nextStateIndex; 67 } 68 69 ByteOffset actionOffset = flags & lsfPerformAction; 70 71 if (actionOffset != 0) { 72 LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset 73 ap.addObject(ligActionIndex - 1, success); // index offset ( one before the actual start, because we will pre-increment) 74 LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY); 75 LigatureActionEntry action; 76 le_int32 offset, i = 0; 77 le_int32 stack[nComponents]; 78 le_int16 mm = -1; 79 80 LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY); 81 if(LE_FAILURE(success)) { 82 currGlyph+= dir; 83 return nextStateIndex; // get out! bad font 84 } 85 86 do { 87 le_int32 componentGlyph = componentStack[m--]; // pop off 88 89 ap.addObject(success); 90 action = SWAPL(*ap.getAlias()); 91 92 if (m < 0) { 93 m = nComponents - 1; 94 } 95 96 offset = action & lafComponentOffsetMask; 97 if (offset != 0) { 98 if(componentGlyph > glyphStorage.getGlyphCount() || componentGlyph < 0) { 99 LE_DEBUG_BAD_FONT("preposterous componentGlyph"); 100 currGlyph+= dir; 101 return nextStateIndex; // get out! bad font 102 } 103 i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success)); 104 105 if (action & (lafLast | lafStore)) { 106 TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success)); 107 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); 108 if(mm==nComponents) { 109 LE_DEBUG_BAD_FONT("exceeded nComponents"); 110 mm--; // don't overrun the stack. 111 } 112 stack[++mm] = componentGlyph; 113 i = 0; 114 } else { 115 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF); 116 } 117 } 118 #if LE_ASSERT_BAD_FONT 119 if(m<0) { 120 LE_DEBUG_BAD_FONT("m<0") 121 } 122 #endif 123 } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items 124 125 while (mm >= 0) { 126 if (++m >= nComponents) { 127 m = 0; 128 } 129 130 componentStack[m] = stack[mm--]; 131 } 132 } 133 134 if (!(flags & lsfDontAdvance)) { 135 currGlyph += dir; 136 } 137 138 return nextStateIndex; 139 } 140 141 void LigatureSubstitutionProcessor2::endStateTable() 142 { 143 } 144 145 U_NAMESPACE_END 146