1 /* 2 * 3 * (C) Copyright IBM Corp. 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 "SubtableProcessor.h" 12 #include "StateTableProcessor.h" 13 #include "LigatureSubstProc.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(LigatureSubstitutionProcessor) 24 25 LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success) 26 : StateTableProcessor(morphSubtableHeader, success), ligatureSubstitutionHeader(morphSubtableHeader, success) 27 { 28 if(LE_FAILURE(success)) return; 29 ligatureActionTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureActionTableOffset); 30 componentTableOffset = SWAPW(ligatureSubstitutionHeader->componentTableOffset); 31 ligatureTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureTableOffset); 32 33 entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY); 34 } 35 36 LigatureSubstitutionProcessor::~LigatureSubstitutionProcessor() 37 { 38 } 39 40 void LigatureSubstitutionProcessor::beginStateTable() 41 { 42 m = -1; 43 } 44 45 ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) 46 { 47 LEErrorCode success = LE_NO_ERROR; 48 const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success); 49 50 ByteOffset newState = SWAPW(entry->newStateOffset); 51 le_int16 flags = SWAPW(entry->flags); 52 53 if (flags & lsfSetComponent) { 54 if (++m >= nComponents) { 55 m = 0; 56 } 57 58 componentStack[m] = currGlyph; 59 } else if ( m == -1) { 60 // bad font- skip this glyph. 61 currGlyph++; 62 return newState; 63 } 64 65 ByteOffset actionOffset = flags & lsfActionOffsetMask; 66 67 if (actionOffset != 0) { 68 LEReferenceTo<LigatureActionEntry> ap(stHeader, success, actionOffset); 69 LigatureActionEntry action; 70 le_int32 offset, i = 0; 71 le_int32 stack[nComponents]; 72 le_int16 mm = -1; 73 74 do { 75 le_uint32 componentGlyph = componentStack[m--]; 76 77 action = SWAPL(*ap.getAlias()); 78 ap.addObject(success); // ap++ 79 80 if (m < 0) { 81 m = nComponents - 1; 82 } 83 84 offset = action & lafComponentOffsetMask; 85 if (offset != 0) { 86 LEReferenceToArrayOf<le_int16> offsetTable(stHeader, success, 2 * SignExtend(offset, lafComponentOffsetMask), LE_UNBOUNDED_ARRAY); 87 88 if(LE_FAILURE(success)) { 89 currGlyph++; 90 LE_DEBUG_BAD_FONT("off end of ligature substitution header"); 91 return newState; // get out! bad font 92 } 93 if(componentGlyph > (le_uint32)glyphStorage.getGlyphCount()) { 94 LE_DEBUG_BAD_FONT("preposterous componentGlyph"); 95 currGlyph++; 96 return newState; // get out! bad font 97 } 98 i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success)); 99 100 if (action & (lafLast | lafStore)) { 101 LEReferenceTo<TTGlyphID> ligatureOffset(stHeader, success, i); 102 TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias()); 103 104 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); 105 if(mm==nComponents) { 106 LE_DEBUG_BAD_FONT("exceeded nComponents"); 107 mm--; // don't overrun the stack. 108 } 109 stack[++mm] = componentGlyph; 110 i = 0; 111 } else { 112 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF); 113 } 114 } 115 #if LE_ASSERT_BAD_FONT 116 if(m<0) { 117 LE_DEBUG_BAD_FONT("m<0") 118 } 119 #endif 120 } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items 121 122 while (mm >= 0) { 123 if (++m >= nComponents) { 124 m = 0; 125 } 126 127 componentStack[m] = stack[mm--]; 128 } 129 } 130 131 if (!(flags & lsfDontAdvance)) { 132 // should handle reverse too! 133 currGlyph += 1; 134 } 135 136 return newState; 137 } 138 139 void LigatureSubstitutionProcessor::endStateTable() 140 { 141 } 142 143 U_NAMESPACE_END 144