1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 /* 27 * 28 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved 29 * 30 */ 31 32 #include "LETypes.h" 33 #include "MorphTables.h" 34 #include "StateTables.h" 35 #include "MorphStateTables.h" 36 #include "SubtableProcessor.h" 37 #include "StateTableProcessor.h" 38 #include "LEGlyphStorage.h" 39 #include "LESwaps.h" 40 41 U_NAMESPACE_BEGIN 42 43 StateTableProcessor::StateTableProcessor() 44 { 45 } 46 47 StateTableProcessor::StateTableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success) 48 : SubtableProcessor(morphSubtableHeader, success), stateTableHeader(morphSubtableHeader, success), 49 stHeader(stateTableHeader, success, (const StateTableHeader*)&stateTableHeader->stHeader) 50 { 51 if(LE_FAILURE(success)) return; 52 stateSize = SWAPW(stateTableHeader->stHeader.stateSize); 53 classTableOffset = SWAPW(stateTableHeader->stHeader.classTableOffset); 54 stateArrayOffset = SWAPW(stateTableHeader->stHeader.stateArrayOffset); 55 entryTableOffset = SWAPW(stateTableHeader->stHeader.entryTableOffset); 56 57 classTable = LEReferenceTo<ClassTable>(stateTableHeader, success, ((char *) &stateTableHeader->stHeader + classTableOffset)); 58 if(LE_FAILURE(success)) return; 59 firstGlyph = SWAPW(classTable->firstGlyph); 60 lastGlyph = firstGlyph + SWAPW(classTable->nGlyphs); 61 } 62 63 StateTableProcessor::~StateTableProcessor() 64 { 65 } 66 67 void StateTableProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success) 68 { 69 if (LE_FAILURE(success)) return; 70 LE_STATE_PATIENCE_INIT(); 71 72 // Start at state 0 73 // XXX: How do we know when to start at state 1? 74 ByteOffset currentState = stateArrayOffset; 75 76 // XXX: reverse? 77 le_int32 currGlyph = 0; 78 le_int32 glyphCount = glyphStorage.getGlyphCount(); 79 80 beginStateTable(); 81 82 while (currGlyph <= glyphCount) { 83 if(LE_STATE_PATIENCE_DECR()) break; // patience exceeded. 84 if (LE_FAILURE(success)) break; 85 ClassCode classCode = classCodeOOB; 86 if (currGlyph == glyphCount) { 87 // XXX: How do we handle EOT vs. EOL? 88 classCode = classCodeEOT; 89 break; 90 } else { 91 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]); 92 93 if (glyphCode == 0xFFFF) { 94 classCode = classCodeDEL; 95 } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { 96 classCode = classTable->classArray[glyphCode - firstGlyph]; 97 } 98 } 99 100 LEReferenceToArrayOf<EntryTableIndex> stateArray(stHeader, success, currentState, LE_UNBOUNDED_ARRAY); 101 EntryTableIndex entryTableIndex = stateArray.getObject((le_uint8)classCode, success); 102 if (LE_FAILURE(success)) { break; } 103 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 104 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 105 LE_STATE_PATIENCE_INCR(currGlyph); 106 } 107 108 endStateTable(); 109 } 110 111 U_NAMESPACE_END