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