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. and others 1998-2013 - All Rights Reserved 29 * 30 */ 31 32#include "LETypes.h" 33#include "MorphTables.h" 34#include "StateTables.h" 35#include "MorphStateTables.h" 36#include "SubtableProcessor2.h" 37#include "StateTableProcessor2.h" 38#include "LEGlyphStorage.h" 39#include "LESwaps.h" 40#include "LookupTables.h" 41 42U_NAMESPACE_BEGIN 43 44StateTableProcessor2::StateTableProcessor2() 45{ 46} 47 48StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success) 49 : SubtableProcessor2(morphSubtableHeader, success), stateTableHeader(morphSubtableHeader, success), 50 stHeader(stateTableHeader, success, (const StateTableHeader2*)&stateTableHeader->stHeader), 51 nClasses(0), classTableOffset(0), stateArrayOffset(0), entryTableOffset(0), classTable(), format(0), 52 stateArray() 53{ 54 if (LE_FAILURE(success)) { 55 return; 56 } 57 nClasses = SWAPL(stHeader->nClasses); 58 classTableOffset = SWAPL(stHeader->classTableOffset); 59 stateArrayOffset = SWAPL(stHeader->stateArrayOffset); 60 entryTableOffset = SWAPL(stHeader->entryTableOffset); 61 62 classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset); 63 if (LE_FAILURE(success)) return; 64 format = SWAPW(classTable->format); 65 66 stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY); 67} 68 69StateTableProcessor2::~StateTableProcessor2() 70{ 71} 72 73void StateTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success) 74{ 75 if (LE_FAILURE(success)) return; 76 // Start at state 0 77 // XXX: How do we know when to start at state 1? 78 le_uint16 currentState = 0; 79 le_int32 glyphCount = glyphStorage.getGlyphCount(); 80 81 LE_STATE_PATIENCE_INIT(); 82 83 le_int32 currGlyph = 0; 84 if ((coverage & scfReverse2) != 0) { // process glyphs in descending order 85 currGlyph = glyphCount - 1; 86 dir = -1; 87 } else { 88 dir = 1; 89 } 90 91 beginStateTable(); 92 switch (format) { 93 case ltfSimpleArray: { 94#ifdef TEST_FORMAT 95 LEReferenceTo<SimpleArrayLookupTable> lookupTable0(classTable, success); 96 if(LE_FAILURE(success)) break; 97 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 98 if (LE_FAILURE(success)) break; 99 if (LE_STATE_PATIENCE_DECR()) { 100 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 101 break; // patience exceeded. 102 } 103 LookupValue classCode = classCodeOOB; 104 if (currGlyph == glyphCount || currGlyph == -1) { 105 // XXX: How do we handle EOT vs. EOL? 106 classCode = classCodeEOT; 107 break; 108 } else { 109 LEGlyphID gid = glyphStorage[currGlyph]; 110 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); 111 112 if (glyphCode == 0xFFFF) { 113 classCode = classCodeDEL; 114 } else { 115 classCode = SWAPW(lookupTable0->valueArray[gid]); 116 } 117 } 118 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); 119 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 120 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset 121 LE_STATE_PATIENCE_INCR(currGlyph); 122 } 123#endif 124 break; 125 } 126 case ltfSegmentSingle: { 127 LEReferenceTo<SegmentSingleLookupTable> lookupTable2(classTable, success); 128 if(LE_FAILURE(success)) break; 129 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 130 if (LE_FAILURE(success)) break; 131 if (LE_STATE_PATIENCE_DECR()) { 132 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 133 break; // patience exceeded. 134 } 135 LookupValue classCode = classCodeOOB; 136 if (currGlyph == glyphCount || currGlyph == -1) { 137 // XXX: How do we handle EOT vs. EOL? 138 classCode = classCodeEOT; 139 break; 140 } else { 141 LEGlyphID gid = glyphStorage[currGlyph]; 142 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); 143 144 if (glyphCode == 0xFFFF) { 145 classCode = classCodeDEL; 146 } else { 147 const LookupSegment *segment = 148 lookupTable2->lookupSegment(lookupTable2, lookupTable2->segments, gid, success); 149 if (segment != NULL && LE_SUCCESS(success)) { 150 classCode = SWAPW(segment->value); 151 } 152 } 153 } 154 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses,success)); 155 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 156 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 157 LE_STATE_PATIENCE_INCR(currGlyph); 158 } 159 break; 160 } 161 case ltfSegmentArray: { 162 //printf("Lookup Table Format4: specific interpretation needed!\n"); 163 break; 164 } 165 case ltfSingleTable: { 166 LEReferenceTo<SingleTableLookupTable> lookupTable6(classTable, success); 167 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 168 if (LE_FAILURE(success)) break; 169 if (LE_STATE_PATIENCE_DECR()) { 170 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 171 break; // patience exceeded. 172 } 173 LookupValue classCode = classCodeOOB; 174 if (currGlyph == glyphCount || currGlyph == -1) { 175 // XXX: How do we handle EOT vs. EOL? 176 classCode = classCodeEOT; 177 break; 178 } else if(currGlyph > glyphCount) { 179 // note if > glyphCount, we've run off the end (bad font) 180 currGlyph = glyphCount; 181 classCode = classCodeEOT; 182 } else { 183 LEGlyphID gid = glyphStorage[currGlyph]; 184 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); 185 186 if (glyphCode == 0xFFFF) { 187 classCode = classCodeDEL; 188 } else { 189 const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6, lookupTable6->entries, gid, success); 190 if (segment != NULL) { 191 classCode = SWAPW(segment->value); 192 } 193 } 194 } 195 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); 196 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 197 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 198 LE_STATE_PATIENCE_INCR(currGlyph); 199 } 200 break; 201 } 202 case ltfTrimmedArray: { 203 LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(classTable, success); 204 if (LE_FAILURE(success)) break; 205 TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph); 206 TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount); 207 208 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { 209 if(LE_STATE_PATIENCE_DECR()) { 210 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") 211 break; // patience exceeded. 212 } 213 214 LookupValue classCode = classCodeOOB; 215 if (currGlyph == glyphCount || currGlyph == -1) { 216 // XXX: How do we handle EOT vs. EOL? 217 classCode = classCodeEOT; 218 break; 219 } else { 220 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]); 221 if (glyphCode == 0xFFFF) { 222 classCode = classCodeDEL; 223 } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { 224 classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]); 225 } 226 } 227 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); 228 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); 229 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); 230 LE_STATE_PATIENCE_INCR(currGlyph); 231 } 232 break; 233 } 234 default: 235 break; 236 } 237 238 endStateTable(); 239} 240 241U_NAMESPACE_END 242