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 17U_NAMESPACE_BEGIN 18 19StateTableProcessor2::StateTableProcessor2() 20{ 21} 22 23StateTableProcessor2::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 50StateTableProcessor2::~StateTableProcessor2() 51{ 52} 53 54void 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 218U_NAMESPACE_END 219