18393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*
28393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius * (C) Copyright IBM Corp.  and others 1998-2013 - All Rights Reserved
48393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *
58393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius */
68393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
78393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "LETypes.h"
88393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "MorphTables.h"
98393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "StateTables.h"
108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "MorphStateTables.h"
118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "SubtableProcessor2.h"
128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "StateTableProcessor2.h"
138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "LEGlyphStorage.h"
148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "LESwaps.h"
158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "LookupTables.h"
168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include <stdio.h>
178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusU_NAMESPACE_BEGIN
198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusStateTableProcessor2::StateTableProcessor2()
218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius{
228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusStateTableProcessor2::StateTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  : SubtableProcessor2(morphSubtableHeader)
268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius{
278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    stateTableHeader = (const MorphStateTableHeader2 *) morphSubtableHeader;
288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    nClasses = SWAPL(stateTableHeader->stHeader.nClasses);
298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    classTableOffset = SWAPL(stateTableHeader->stHeader.classTableOffset);
308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    stateArrayOffset = SWAPL(stateTableHeader->stHeader.stateArrayOffset);
318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    entryTableOffset = SWAPL(stateTableHeader->stHeader.entryTableOffset);
328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    classTable = (LookupTable *) ((char *) &stateTableHeader->stHeader + classTableOffset);
348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    format = SWAPW(classTable->format);
358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    stateArray = (const EntryTableIndex2 *) ((char *) &stateTableHeader->stHeader + stateArrayOffset);
378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusStateTableProcessor2::~StateTableProcessor2()
408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius{
418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius{
458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Start at state 0
468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // XXX: How do we know when to start at state 1?
478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    le_uint16 currentState = 0;
488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    le_int32 glyphCount = glyphStorage.getGlyphCount();
498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    le_int32 currGlyph = 0;
518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if ((coverage & scfReverse2) != 0) {  // process glyphs in descending order
528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        currGlyph = glyphCount - 1;
538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        dir = -1;
548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    } else {
558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        dir = 1;
568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    beginStateTable();
598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    switch (format) {
608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        case ltfSimpleArray: {
618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#ifdef TEST_FORMAT
628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable;
638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                LookupValue classCode = classCodeOOB;
658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                if (currGlyph == glyphCount || currGlyph == -1) {
668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    // XXX: How do we handle EOT vs. EOL?
678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    classCode = classCodeEOT;
688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                } else {
698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    LEGlyphID gid = glyphStorage[currGlyph];
708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    if (glyphCode == 0xFFFF) {
738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        classCode = classCodeDEL;
748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else {
758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        classCode = SWAPW(lookupTable0->valueArray[gid]);
768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    }
778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset
808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#endif
828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            break;
838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        case ltfSegmentSingle: {
858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable;
868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                LookupValue classCode = classCodeOOB;
888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                if (currGlyph == glyphCount || currGlyph == -1) {
898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    // XXX: How do we handle EOT vs. EOL?
908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    classCode = classCodeEOT;
918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                } else {
928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    LEGlyphID gid = glyphStorage[currGlyph];
938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    if (glyphCode == 0xFFFF) {
968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        classCode = classCodeDEL;
978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else {
988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (segment != NULL) {
1008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            classCode = SWAPW(segment->value);
1018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
1028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    }
1038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
1048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
1058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
1068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            break;
1088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
1098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        case ltfSegmentArray: {
1108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            printf("Lookup Table Format4: specific interpretation needed!\n");
1118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            break;
1128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
1138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        case ltfSingleTable: {
1148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable;
1158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
1168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                LookupValue classCode = classCodeOOB;
1178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                if (currGlyph == glyphCount || currGlyph == -1) {
1188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    // XXX: How do we handle EOT vs. EOL?
1198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    classCode = classCodeEOT;
1208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                } else {
1218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    LEGlyphID gid = glyphStorage[currGlyph];
1228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
1238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    if (glyphCode == 0xFFFF) {
1258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        classCode = classCodeDEL;
1268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else {
1278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
1288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (segment != NULL) {
1298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            classCode = SWAPW(segment->value);
1308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    }
1328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
1338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
1348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
1358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            break;
1378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
1388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        case ltfTrimmedArray: {
1398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) classTable;
1408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
1418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            TTGlyphID lastGlyph  = firstGlyph + SWAPW(lookupTable8->glyphCount);
1428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
1448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                LookupValue classCode = classCodeOOB;
1458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                if (currGlyph == glyphCount || currGlyph == -1) {
1468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    // XXX: How do we handle EOT vs. EOL?
1478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    classCode = classCodeEOT;
1488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                } else {
1498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]);
1508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    if (glyphCode == 0xFFFF) {
1518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        classCode = classCodeDEL;
1528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
1538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
1548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    }
1558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
1568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
1578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
1588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            break;
1608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
1618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        default:
1628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            break;
1638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
1648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    endStateTable();
1668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
1678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusU_NAMESPACE_END
169