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 "LEGlyphStorage.h" 14 #include "LESwaps.h" 15 #include "LookupTables.h" 16 17 U_NAMESPACE_BEGIN 18 19 StateTableProcessor2::StateTableProcessor2() 20 { 21 } 22 23 StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success) 24 : SubtableProcessor2(morphSubtableHeader, success), 25 dir(1), 26 format(0), 27 nClasses(0), 28 classTableOffset(0), 29 stateArrayOffset(0), 30 entryTableOffset(0), 31 classTable(), 32 stateArray(), 33 stateTableHeader(morphSubtableHeader, success), 34 stHeader(stateTableHeader, success, (const StateTableHeader2*)&stateTableHeader->stHeader) 35 { 36 if (LE_FAILURE(success)) { 37 return; 38 } 39 nClasses = SWAPL(stHeader->nClasses); 40 classTableOffset = SWAPL(stHeader->classTableOffset); 41 stateArrayOffset = SWAPL(stHeader->stateArrayOffset); 42 entryTableOffset = SWAPL(stHeader->entryTableOffset); 43 44 classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset); 45 format = SWAPW(classTable->format); 46 47 stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY); 48 } 49 50 StateTableProcessor2::~StateTableProcessor2() 51 { 52 } 53 54 void StateTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success) 55 { 56 if (LE_FAILURE(success)) return; 57 // Start at state 0 58 // XXX: How do we know when to start at state 1? 59 le_uint16 currentState = 0; 60 le_int32 glyphCount = glyphStorage.getGlyphCount(); 61 62 LE_STATE_PATIENCE_INIT(); 63 64 le_int32 currGlyph = 0; 65 if ((coverage & scfReverse2) != 0) { // process glyphs in descending order 66 currGlyph = glyphCount - 1; 67 dir = -1; 68 } else { 69 dir = 1; 70 } 71 72 beginStateTable(); 73 switch (format) { 74 case ltfSimpleArray: { 75 #ifdef TEST_FORMAT 76 LEReferenceTo<SimpleArrayLookupTable> lookupTable0(classTable, success); 77 if(LE_FAILURE(success)) break; 78 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 79 if (LE_FAILURE(success)) break; 80 if (LE_STATE_PATIENCE_DECR()) { 81 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 82 break; // patience exceeded. 83 } 84 LookupValue classCode = classCodeOOB; 85 if (currGlyph == glyphCount || currGlyph == -1) { 86 // XXX: How do we handle EOT vs. EOL? 87 classCode = classCodeEOT; 88 } else { 89 LEGlyphID gid = glyphStorage[currGlyph]; 90 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); 91 92 if (glyphCode == 0xFFFF) { 93 classCode = classCodeDEL; 94 } else { 95 classCode = SWAPW(lookupTable0->valueArray[gid]); 96 } 97 } 98 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); 99 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 100 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset 101 LE_STATE_PATIENCE_INCR(currGlyph); 102 } 103 #endif 104 break; 105 } 106 case ltfSegmentSingle: { 107 LEReferenceTo<SegmentSingleLookupTable> lookupTable2(classTable, success); 108 if(LE_FAILURE(success)) break; 109 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 110 if (LE_FAILURE(success)) break; 111 if (LE_STATE_PATIENCE_DECR()) { 112 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 113 break; // patience exceeded. 114 } 115 LookupValue classCode = classCodeOOB; 116 if (currGlyph == glyphCount || currGlyph == -1) { 117 // XXX: How do we handle EOT vs. EOL? 118 classCode = classCodeEOT; 119 } else { 120 LEGlyphID gid = glyphStorage[currGlyph]; 121 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); 122 123 if (glyphCode == 0xFFFF) { 124 classCode = classCodeDEL; 125 } else { 126 const LookupSegment *segment = 127 lookupTable2->lookupSegment(lookupTable2, lookupTable2->segments, gid, success); 128 if (segment != NULL && LE_SUCCESS(success)) { 129 classCode = SWAPW(segment->value); 130 } 131 } 132 } 133 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses,success)); 134 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 135 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 136 LE_STATE_PATIENCE_INCR(currGlyph); 137 } 138 break; 139 } 140 case ltfSegmentArray: { 141 //printf("Lookup Table Format4: specific interpretation needed!\n"); 142 break; 143 } 144 case ltfSingleTable: { 145 LEReferenceTo<SingleTableLookupTable> lookupTable6(classTable, success); 146 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 147 if (LE_FAILURE(success)) break; 148 if (LE_STATE_PATIENCE_DECR()) { 149 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 150 break; // patience exceeded. 151 } 152 LookupValue classCode = classCodeOOB; 153 if (currGlyph == glyphCount || currGlyph == -1) { 154 // XXX: How do we handle EOT vs. EOL? 155 classCode = classCodeEOT; 156 } else if(currGlyph > glyphCount) { 157 // note if > glyphCount, we've run off the end (bad font) 158 currGlyph = glyphCount; 159 classCode = classCodeEOT; 160 } else { 161 LEGlyphID gid = glyphStorage[currGlyph]; 162 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); 163 164 if (glyphCode == 0xFFFF) { 165 classCode = classCodeDEL; 166 } else { 167 const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6, lookupTable6->entries, gid, success); 168 if (segment != NULL) { 169 classCode = SWAPW(segment->value); 170 } 171 } 172 } 173 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); 174 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 175 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 176 LE_STATE_PATIENCE_INCR(currGlyph); 177 } 178 break; 179 } 180 case ltfTrimmedArray: { 181 LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(classTable, success); 182 if (LE_FAILURE(success)) break; 183 TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph); 184 TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount); 185 186 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 187 if(LE_STATE_PATIENCE_DECR()) { 188 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 189 break; // patience exceeded. 190 } 191 192 LookupValue classCode = classCodeOOB; 193 if (currGlyph == glyphCount || currGlyph == -1) { 194 // XXX: How do we handle EOT vs. EOL? 195 classCode = classCodeEOT; 196 } else { 197 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]); 198 if (glyphCode == 0xFFFF) { 199 classCode = classCodeDEL; 200 } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { 201 classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]); 202 } 203 } 204 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); 205 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 206 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 207 LE_STATE_PATIENCE_INCR(currGlyph); 208 } 209 break; 210 } 211 default: 212 break; 213 } 214 215 endStateTable(); 216 } 217 218 U_NAMESPACE_END 219