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