| /* |
| * |
| * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved |
| * |
| */ |
| |
| #include "LETypes.h" |
| #include "MorphTables.h" |
| #include "StateTables.h" |
| #include "MorphStateTables.h" |
| #include "SubtableProcessor2.h" |
| #include "StateTableProcessor2.h" |
| #include "LEGlyphStorage.h" |
| #include "LESwaps.h" |
| #include "LookupTables.h" |
| #include <stdio.h> |
| |
| U_NAMESPACE_BEGIN |
| |
| StateTableProcessor2::StateTableProcessor2() |
| { |
| } |
| |
| StateTableProcessor2::StateTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader) |
| : SubtableProcessor2(morphSubtableHeader) |
| { |
| stateTableHeader = (const MorphStateTableHeader2 *) morphSubtableHeader; |
| nClasses = SWAPL(stateTableHeader->stHeader.nClasses); |
| classTableOffset = SWAPL(stateTableHeader->stHeader.classTableOffset); |
| stateArrayOffset = SWAPL(stateTableHeader->stHeader.stateArrayOffset); |
| entryTableOffset = SWAPL(stateTableHeader->stHeader.entryTableOffset); |
| |
| classTable = (LookupTable *) ((char *) &stateTableHeader->stHeader + classTableOffset); |
| format = SWAPW(classTable->format); |
| |
| stateArray = (const EntryTableIndex2 *) ((char *) &stateTableHeader->stHeader + stateArrayOffset); |
| } |
| |
| StateTableProcessor2::~StateTableProcessor2() |
| { |
| } |
| |
| void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) |
| { |
| // Start at state 0 |
| // XXX: How do we know when to start at state 1? |
| le_uint16 currentState = 0; |
| le_int32 glyphCount = glyphStorage.getGlyphCount(); |
| |
| le_int32 currGlyph = 0; |
| if ((coverage & scfReverse2) != 0) { // process glyphs in descending order |
| currGlyph = glyphCount - 1; |
| dir = -1; |
| } else { |
| dir = 1; |
| } |
| |
| beginStateTable(); |
| switch (format) { |
| case ltfSimpleArray: { |
| #ifdef TEST_FORMAT |
| SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable; |
| while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
| LookupValue classCode = classCodeOOB; |
| if (currGlyph == glyphCount || currGlyph == -1) { |
| // XXX: How do we handle EOT vs. EOL? |
| classCode = classCodeEOT; |
| } else { |
| LEGlyphID gid = glyphStorage[currGlyph]; |
| TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
| |
| if (glyphCode == 0xFFFF) { |
| classCode = classCodeDEL; |
| } else { |
| classCode = SWAPW(lookupTable0->valueArray[gid]); |
| } |
| } |
| EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
| currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset |
| } |
| #endif |
| break; |
| } |
| case ltfSegmentSingle: { |
| SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable; |
| while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
| LookupValue classCode = classCodeOOB; |
| if (currGlyph == glyphCount || currGlyph == -1) { |
| // XXX: How do we handle EOT vs. EOL? |
| classCode = classCodeEOT; |
| } else { |
| LEGlyphID gid = glyphStorage[currGlyph]; |
| TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
| |
| if (glyphCode == 0xFFFF) { |
| classCode = classCodeDEL; |
| } else { |
| const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid); |
| if (segment != NULL) { |
| classCode = SWAPW(segment->value); |
| } |
| } |
| } |
| EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
| currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); |
| } |
| break; |
| } |
| case ltfSegmentArray: { |
| printf("Lookup Table Format4: specific interpretation needed!\n"); |
| break; |
| } |
| case ltfSingleTable: { |
| SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable; |
| while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
| LookupValue classCode = classCodeOOB; |
| if (currGlyph == glyphCount || currGlyph == -1) { |
| // XXX: How do we handle EOT vs. EOL? |
| classCode = classCodeEOT; |
| } else { |
| LEGlyphID gid = glyphStorage[currGlyph]; |
| TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
| |
| if (glyphCode == 0xFFFF) { |
| classCode = classCodeDEL; |
| } else { |
| const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid); |
| if (segment != NULL) { |
| classCode = SWAPW(segment->value); |
| } |
| } |
| } |
| EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
| currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); |
| } |
| break; |
| } |
| case ltfTrimmedArray: { |
| TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) classTable; |
| TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph); |
| TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount); |
| |
| while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
| LookupValue classCode = classCodeOOB; |
| if (currGlyph == glyphCount || currGlyph == -1) { |
| // XXX: How do we handle EOT vs. EOL? |
| classCode = classCodeEOT; |
| } else { |
| TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]); |
| if (glyphCode == 0xFFFF) { |
| classCode = classCodeDEL; |
| } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { |
| classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]); |
| } |
| } |
| EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
| currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| |
| endStateTable(); |
| } |
| |
| U_NAMESPACE_END |