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