1/*
2 *
3 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
4 *
5 */
6
7#include "LETypes.h"
8#include "MorphTables.h"
9#include "StateTables.h"
10#include "MorphStateTables.h"
11#include "SubtableProcessor.h"
12#include "StateTableProcessor.h"
13#include "IndicRearrangementProcessor.h"
14#include "LEGlyphStorage.h"
15#include "LESwaps.h"
16
17U_NAMESPACE_BEGIN
18
19UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor)
20
21IndicRearrangementProcessor::IndicRearrangementProcessor(const MorphSubtableHeader *morphSubtableHeader)
22  : StateTableProcessor(morphSubtableHeader)
23{
24    indicRearrangementSubtableHeader = (const IndicRearrangementSubtableHeader *) morphSubtableHeader;
25    entryTable = (const IndicRearrangementStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
26}
27
28IndicRearrangementProcessor::~IndicRearrangementProcessor()
29{
30}
31
32void IndicRearrangementProcessor::beginStateTable()
33{
34    firstGlyph = 0;
35    lastGlyph = 0;
36}
37
38ByteOffset IndicRearrangementProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
39{
40    const IndicRearrangementStateEntry *entry = &entryTable[index];
41    ByteOffset newState = SWAPW(entry->newStateOffset);
42    IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
43
44    if (flags & irfMarkFirst) {
45        firstGlyph = currGlyph;
46    }
47
48    if (flags & irfMarkLast) {
49        lastGlyph = currGlyph;
50    }
51
52    doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask));
53
54    if (!(flags & irfDontAdvance)) {
55        // XXX: Should handle reverse too...
56        currGlyph += 1;
57    }
58
59    return newState;
60}
61
62void IndicRearrangementProcessor::endStateTable()
63{
64}
65
66void IndicRearrangementProcessor::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const
67{
68    LEGlyphID a, b, c, d;
69    le_int32 ia, ib, ic, id, ix, x;
70    LEErrorCode success = LE_NO_ERROR;
71
72    switch(verb)
73    {
74    case irvNoAction:
75        break;
76
77    case irvxA:
78        a = glyphStorage[firstGlyph];
79        ia = glyphStorage.getCharIndex(firstGlyph, success);
80        x = firstGlyph + 1;
81
82        while (x <= lastGlyph) {
83            glyphStorage[x - 1] = glyphStorage[x];
84            ix = glyphStorage.getCharIndex(x, success);
85            glyphStorage.setCharIndex(x - 1, ix, success);
86            x += 1;
87        }
88
89        glyphStorage[lastGlyph] = a;
90        glyphStorage.setCharIndex(lastGlyph, ia, success);
91        break;
92
93    case irvDx:
94        d = glyphStorage[lastGlyph];
95        id = glyphStorage.getCharIndex(lastGlyph, success);
96        x = lastGlyph - 1;
97
98        while (x >= firstGlyph) {
99            glyphStorage[x + 1] = glyphStorage[x];
100            ix = glyphStorage.getCharIndex(x, success);
101            glyphStorage.setCharIndex(x + 1, ix, success);
102            x -= 1;
103        }
104
105        glyphStorage[firstGlyph] = d;
106        glyphStorage.setCharIndex(firstGlyph, id, success);
107        break;
108
109    case irvDxA:
110        a = glyphStorage[firstGlyph];
111        ia = glyphStorage.getCharIndex(firstGlyph, success);
112        id = glyphStorage.getCharIndex(lastGlyph,  success);
113
114        glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
115        glyphStorage[lastGlyph] = a;
116
117        glyphStorage.setCharIndex(firstGlyph, id, success);
118        glyphStorage.setCharIndex(lastGlyph,  ia, success);
119        break;
120
121    case irvxAB:
122        a = glyphStorage[firstGlyph];
123        b = glyphStorage[firstGlyph + 1];
124        ia = glyphStorage.getCharIndex(firstGlyph, success);
125        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
126        x = firstGlyph + 2;
127
128        while (x <= lastGlyph) {
129            glyphStorage[x - 2] = glyphStorage[x];
130            ix = glyphStorage.getCharIndex(x, success);
131            glyphStorage.setCharIndex(x - 2, ix, success);
132            x += 1;
133        }
134
135        glyphStorage[lastGlyph - 1] = a;
136        glyphStorage[lastGlyph] = b;
137
138        glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
139        glyphStorage.setCharIndex(lastGlyph, ib, success);
140        break;
141
142    case irvxBA:
143        a = glyphStorage[firstGlyph];
144        b = glyphStorage[firstGlyph + 1];
145        ia = glyphStorage.getCharIndex(firstGlyph, success);
146        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
147        x = firstGlyph + 2;
148
149        while (x <= lastGlyph) {
150            glyphStorage[x - 2] = glyphStorage[x];
151            ix = glyphStorage.getCharIndex(x, success);
152            glyphStorage.setCharIndex(x - 2, ix, success);
153            x += 1;
154        }
155
156        glyphStorage[lastGlyph - 1] = b;
157        glyphStorage[lastGlyph] = a;
158
159        glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
160        glyphStorage.setCharIndex(lastGlyph, ia, success);
161        break;
162
163    case irvCDx:
164        c = glyphStorage[lastGlyph - 1];
165        d = glyphStorage[lastGlyph];
166        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
167        id = glyphStorage.getCharIndex(lastGlyph, success);
168        x = lastGlyph - 2;
169
170        while (x >= firstGlyph) {
171            glyphStorage[x + 2] = glyphStorage[x];
172            ix = glyphStorage.getCharIndex(x, success);
173            glyphStorage.setCharIndex(x + 2, ix, success);
174            x -= 1;
175        }
176
177        glyphStorage[firstGlyph] = c;
178        glyphStorage[firstGlyph + 1] = d;
179
180        glyphStorage.setCharIndex(firstGlyph, ic, success);
181        glyphStorage.setCharIndex(firstGlyph + 1, id, success);
182        break;
183
184    case irvDCx:
185        c = glyphStorage[lastGlyph - 1];
186        d = glyphStorage[lastGlyph];
187        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
188        id = glyphStorage.getCharIndex(lastGlyph, success);
189        x = lastGlyph - 2;
190
191        while (x >= firstGlyph) {
192            glyphStorage[x + 2] = glyphStorage[x];
193            ix = glyphStorage.getCharIndex(x, success);
194            glyphStorage.setCharIndex(x + 2, ix, success);
195            x -= 1;
196        }
197
198        glyphStorage[firstGlyph] = d;
199        glyphStorage[firstGlyph + 1] = c;
200
201        glyphStorage.setCharIndex(firstGlyph, id, success);
202        glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
203        break;
204
205    case irvCDxA:
206        a = glyphStorage[firstGlyph];
207        c = glyphStorage[lastGlyph - 1];
208        d = glyphStorage[lastGlyph];
209        ia = glyphStorage.getCharIndex(firstGlyph, success);
210        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
211        id = glyphStorage.getCharIndex(lastGlyph, success);
212        x = lastGlyph - 2;
213
214        while (x > firstGlyph) {
215            glyphStorage[x + 1] = glyphStorage[x];
216            ix = glyphStorage.getCharIndex(x, success);
217            glyphStorage.setCharIndex(x + 1, ix, success);
218            x -= 1;
219        }
220
221        glyphStorage[firstGlyph] = c;
222        glyphStorage[firstGlyph + 1] = d;
223        glyphStorage[lastGlyph] = a;
224
225        glyphStorage.setCharIndex(firstGlyph, ic, success);
226        glyphStorage.setCharIndex(firstGlyph + 1, id, success);
227        glyphStorage.setCharIndex(lastGlyph, ia, success);
228        break;
229
230    case irvDCxA:
231        a = glyphStorage[firstGlyph];
232        c = glyphStorage[lastGlyph - 1];
233        d = glyphStorage[lastGlyph];
234        ia = glyphStorage.getCharIndex(firstGlyph, success);
235        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
236        id = glyphStorage.getCharIndex(lastGlyph, success);
237        x = lastGlyph - 2;
238
239        while (x > firstGlyph) {
240            glyphStorage[x + 1] = glyphStorage[x];
241            ix = glyphStorage.getCharIndex(x, success);
242            glyphStorage.setCharIndex(x + 1, ix, success);
243            x -= 1;
244        }
245
246        glyphStorage[firstGlyph] = d;
247        glyphStorage[firstGlyph + 1] = c;
248        glyphStorage[lastGlyph] = a;
249
250        glyphStorage.setCharIndex(firstGlyph, id, success);
251        glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
252        glyphStorage.setCharIndex(lastGlyph, ia, success);
253        break;
254
255    case irvDxAB:
256        a = glyphStorage[firstGlyph];
257        b = glyphStorage[firstGlyph + 1];
258        d = glyphStorage[lastGlyph];
259        ia = glyphStorage.getCharIndex(firstGlyph, success);
260        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
261        id = glyphStorage.getCharIndex(lastGlyph, success);
262        x = firstGlyph + 2;
263
264        while (x < lastGlyph) {
265            glyphStorage[x - 2] = glyphStorage[x];
266            ix = glyphStorage.getCharIndex(x, success);
267            glyphStorage.setCharIndex(x - 2, ix, success);
268            x += 1;
269        }
270
271        glyphStorage[firstGlyph] = d;
272        glyphStorage[lastGlyph - 1] = a;
273        glyphStorage[lastGlyph] = b;
274
275        glyphStorage.setCharIndex(firstGlyph, id, success);
276        glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
277        glyphStorage.setCharIndex(lastGlyph, ib, success);
278        break;
279
280    case irvDxBA:
281        a = glyphStorage[firstGlyph];
282        b = glyphStorage[firstGlyph + 1];
283        d = glyphStorage[lastGlyph];
284        ia = glyphStorage.getCharIndex(firstGlyph, success);
285        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
286        id = glyphStorage.getCharIndex(lastGlyph, success);
287        x = firstGlyph + 2;
288
289        while (x < lastGlyph) {
290            glyphStorage[x - 2] = glyphStorage[x];
291            ix = glyphStorage.getCharIndex(x, success);
292            glyphStorage.setCharIndex(x - 2, ix, success);
293            x += 1;
294        }
295
296        glyphStorage[firstGlyph] = d;
297        glyphStorage[lastGlyph - 1] = b;
298        glyphStorage[lastGlyph] = a;
299
300        glyphStorage.setCharIndex(firstGlyph, id, success);
301        glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
302        glyphStorage.setCharIndex(lastGlyph, ia, success);
303        break;
304
305    case irvCDxAB:
306        a = glyphStorage[firstGlyph];
307        b = glyphStorage[firstGlyph + 1];
308
309        glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
310        glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
311
312        glyphStorage[lastGlyph - 1] = a;
313        glyphStorage[lastGlyph] = b;
314
315        ia = glyphStorage.getCharIndex(firstGlyph, success);
316        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
317        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
318        id = glyphStorage.getCharIndex(lastGlyph, success);
319
320        glyphStorage.setCharIndex(firstGlyph, ic, success);
321        glyphStorage.setCharIndex(firstGlyph + 1, id, success);
322
323        glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
324        glyphStorage.setCharIndex(lastGlyph, ib, success);
325        break;
326
327    case irvCDxBA:
328        a = glyphStorage[firstGlyph];
329        b = glyphStorage[firstGlyph + 1];
330
331        glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
332        glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
333
334        glyphStorage[lastGlyph - 1] = b;
335        glyphStorage[lastGlyph] = a;
336
337        ia = glyphStorage.getCharIndex(firstGlyph, success);
338        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
339        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
340        id = glyphStorage.getCharIndex(lastGlyph, success);
341
342        glyphStorage.setCharIndex(firstGlyph, ic, success);
343        glyphStorage.setCharIndex(firstGlyph + 1, id, success);
344
345        glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
346        glyphStorage.setCharIndex(lastGlyph, ia, success);
347        break;
348
349    case irvDCxAB:
350        a = glyphStorage[firstGlyph];
351        b = glyphStorage[firstGlyph + 1];
352
353        glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
354        glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
355
356        glyphStorage[lastGlyph - 1] = a;
357        glyphStorage[lastGlyph] = b;
358
359        ia = glyphStorage.getCharIndex(firstGlyph, success);
360        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
361        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
362        id = glyphStorage.getCharIndex(lastGlyph, success);
363
364        glyphStorage.setCharIndex(firstGlyph, id, success);
365        glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
366
367        glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
368        glyphStorage.setCharIndex(lastGlyph, ib, success);
369        break;
370
371    case irvDCxBA:
372        a = glyphStorage[firstGlyph];
373        b = glyphStorage[firstGlyph + 1];
374
375        glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
376        glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
377
378        glyphStorage[lastGlyph - 1] = b;
379        glyphStorage[lastGlyph] = a;
380
381        ia = glyphStorage.getCharIndex(firstGlyph, success);
382        ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
383        ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
384        id = glyphStorage.getCharIndex(lastGlyph, success);
385
386        glyphStorage.setCharIndex(firstGlyph, id, success);
387        glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
388
389        glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
390        glyphStorage.setCharIndex(lastGlyph, ia, success);
391        break;
392
393    default:
394        break;
395    }
396}
397
398U_NAMESPACE_END
399