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 17U_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 23UOBJECT_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 36LigatureSubstitutionProcessor::~LigatureSubstitutionProcessor() 37{ 38} 39 40void LigatureSubstitutionProcessor::beginStateTable() 41{ 42 m = -1; 43} 44 45ByteOffset 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 139void LigatureSubstitutionProcessor::endStateTable() 140{ 141} 142 143U_NAMESPACE_END 144