Remove packaging direcotry
[platform/upstream/icu.git] / source / layout / IndicRearrangementProcessor.cpp
1 /*
2  *
3  * (C) Copyright IBM Corp. 1998-2015 - 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
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
31 IndicRearrangementProcessor::~IndicRearrangementProcessor()
32 {
33 }
34
35 void IndicRearrangementProcessor::beginStateTable()
36 {
37     firstGlyph = 0;
38     lastGlyph = 0;
39 }
40
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 = (le_uint32)currGlyph;
50     }
51
52     if (flags & irfMarkLast) {
53         lastGlyph = (le_uint32)currGlyph;
54     }
55
56     doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success);
57
58     if (!(flags & irfDontAdvance)) {
59         // XXX: Should handle reverse too...
60         currGlyph += 1;
61     }
62
63     return newState;
64 }
65
66 void IndicRearrangementProcessor::endStateTable()
67 {
68 }
69
70 void IndicRearrangementProcessor::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const
71 {
72     LEGlyphID a, b, c, d;
73     le_int32 ia, ib, ic, id, ix, x;
74
75     if (LE_FAILURE(success)) return;
76
77     if (verb == irvNoAction) {
78         return;
79     }
80     if (firstGlyph > lastGlyph) {
81         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
82         return;
83     }
84
85     switch(verb)
86     {
87     case irvxA:
88         if (firstGlyph == lastGlyph) break;
89         if (firstGlyph + 1 < firstGlyph) {
90             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
91         break;
92         }
93         a = glyphStorage[firstGlyph];
94         ia = glyphStorage.getCharIndex(firstGlyph, success);
95         x = firstGlyph + 1;
96
97         while (x <= lastGlyph) {
98             glyphStorage[x - 1] = glyphStorage[x];
99             ix = glyphStorage.getCharIndex(x, success);
100             glyphStorage.setCharIndex(x - 1, ix, success);
101             x += 1;
102         }
103
104         glyphStorage[lastGlyph] = a;
105         glyphStorage.setCharIndex(lastGlyph, ia, success);
106         break;
107
108     case irvDx:
109         if (firstGlyph == lastGlyph) break;
110         if (lastGlyph - 1 > lastGlyph) {
111             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
112             break;
113         }
114         d = glyphStorage[lastGlyph];
115         id = glyphStorage.getCharIndex(lastGlyph, success);
116         x = lastGlyph - 1;
117
118         while (x >= firstGlyph) {
119             glyphStorage[x + 1] = glyphStorage[x];
120             ix = glyphStorage.getCharIndex(x, success);
121             glyphStorage.setCharIndex(x + 1, ix, success);
122             x -= 1;
123         }
124
125         glyphStorage[firstGlyph] = d;
126         glyphStorage.setCharIndex(firstGlyph, id, success);
127         break;
128
129     case irvDxA:
130         a = glyphStorage[firstGlyph];
131         ia = glyphStorage.getCharIndex(firstGlyph, success);
132         id = glyphStorage.getCharIndex(lastGlyph,  success);
133
134         glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
135         glyphStorage[lastGlyph] = a;
136
137         glyphStorage.setCharIndex(firstGlyph, id, success);
138         glyphStorage.setCharIndex(lastGlyph,  ia, success);
139         break;
140         
141     case irvxAB:
142         if ((firstGlyph + 2 < firstGlyph) ||
143             (lastGlyph - firstGlyph < 1)) { // difference == 1 is a no-op, < 1 is an error.
144             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
145             break;
146         }
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] = a;
161         glyphStorage[lastGlyph] = b;
162
163         glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
164         glyphStorage.setCharIndex(lastGlyph, ib, success);
165         break;
166
167     case irvxBA:
168         if ((firstGlyph + 2 < firstGlyph) ||
169             (lastGlyph - firstGlyph < 1)) {
170             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
171             break;
172         }
173         a = glyphStorage[firstGlyph];
174         b = glyphStorage[firstGlyph + 1];
175         ia = glyphStorage.getCharIndex(firstGlyph, success);
176         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
177         x = firstGlyph + 2;
178
179         while (x <= lastGlyph) {
180             glyphStorage[x - 2] = glyphStorage[x];
181             ix = glyphStorage.getCharIndex(x, success);
182             glyphStorage.setCharIndex(x - 2, ix, success);
183             x += 1;
184         }
185
186         glyphStorage[lastGlyph - 1] = b;
187         glyphStorage[lastGlyph] = a;
188
189         glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
190         glyphStorage.setCharIndex(lastGlyph, ia, success);
191         break;
192
193     case irvCDx:
194         if ((lastGlyph - 2 > lastGlyph) ||
195             (lastGlyph - firstGlyph < 1)) {
196             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
197             break;
198         }
199         c = glyphStorage[lastGlyph - 1];
200         d = glyphStorage[lastGlyph];
201         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
202         id = glyphStorage.getCharIndex(lastGlyph, success);
203         x = lastGlyph - 2;
204
205         while (x >= firstGlyph) {
206             glyphStorage[x + 2] = glyphStorage[x];
207             ix = glyphStorage.getCharIndex(x, success);
208             glyphStorage.setCharIndex(x + 2, ix, success);
209             x -= 1;
210         }
211         
212         glyphStorage[firstGlyph] = c;
213         glyphStorage[firstGlyph + 1] = d;
214
215         glyphStorage.setCharIndex(firstGlyph, ic, success);
216         glyphStorage.setCharIndex(firstGlyph + 1, id, success);
217         break; 
218
219     case irvDCx:
220         if ((lastGlyph - 2 > lastGlyph) ||
221             (lastGlyph - firstGlyph < 1)) {
222             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
223             break;
224         }
225         c = glyphStorage[lastGlyph - 1];
226         d = glyphStorage[lastGlyph];
227         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
228         id = glyphStorage.getCharIndex(lastGlyph, success);
229         x = lastGlyph - 2;
230
231         while (x >= firstGlyph) {
232             glyphStorage[x + 2] = glyphStorage[x];
233             ix = glyphStorage.getCharIndex(x, success);
234             glyphStorage.setCharIndex(x + 2, ix, success);
235             x -= 1;
236         }
237         
238         glyphStorage[firstGlyph] = d;
239         glyphStorage[firstGlyph + 1] = c;
240
241         glyphStorage.setCharIndex(firstGlyph, id, success);
242         glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
243         break; 
244
245     case irvCDxA:
246         if ((lastGlyph - 2 > lastGlyph) ||
247             (lastGlyph - firstGlyph < 2)) {
248             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
249             break;
250         }
251         a = glyphStorage[firstGlyph];
252         c = glyphStorage[lastGlyph - 1];
253         d = glyphStorage[lastGlyph];
254         ia = glyphStorage.getCharIndex(firstGlyph, success);
255         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
256         id = glyphStorage.getCharIndex(lastGlyph, success);
257         x = lastGlyph - 2;
258
259         while (x > firstGlyph) {
260             glyphStorage[x + 1] = glyphStorage[x];
261             ix = glyphStorage.getCharIndex(x, success);
262             glyphStorage.setCharIndex(x + 1, ix, success);
263             x -= 1;
264         }
265         
266         glyphStorage[firstGlyph] = c;
267         glyphStorage[firstGlyph + 1] = d;
268         glyphStorage[lastGlyph] = a;
269
270         glyphStorage.setCharIndex(firstGlyph, ic, success);
271         glyphStorage.setCharIndex(firstGlyph + 1, id, success);
272         glyphStorage.setCharIndex(lastGlyph, ia, success);
273         break; 
274
275     case irvDCxA:
276         if ((lastGlyph - 2 > lastGlyph) ||
277             (lastGlyph - firstGlyph < 2)) {
278             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
279             break;
280         }
281         a = glyphStorage[firstGlyph];
282         c = glyphStorage[lastGlyph - 1];
283         d = glyphStorage[lastGlyph];
284         ia = glyphStorage.getCharIndex(firstGlyph, success);
285         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
286         id = glyphStorage.getCharIndex(lastGlyph, success);
287         x = lastGlyph - 2;
288
289         while (x > firstGlyph) {
290             glyphStorage[x + 1] = glyphStorage[x];
291             ix = glyphStorage.getCharIndex(x, success);
292             glyphStorage.setCharIndex(x + 1, ix, success);
293             x -= 1;
294         }
295         
296         glyphStorage[firstGlyph] = d;
297         glyphStorage[firstGlyph + 1] = c;
298         glyphStorage[lastGlyph] = a;
299
300         glyphStorage.setCharIndex(firstGlyph, id, success);
301         glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
302         glyphStorage.setCharIndex(lastGlyph, ia, success);
303         break; 
304
305     case irvDxAB:
306         if ((firstGlyph + 2 < firstGlyph) ||
307             (lastGlyph - firstGlyph < 2)) {
308             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
309             break;
310         }
311         a = glyphStorage[firstGlyph];
312         b = glyphStorage[firstGlyph + 1];
313         d = glyphStorage[lastGlyph];
314         ia = glyphStorage.getCharIndex(firstGlyph, success);
315         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
316         id = glyphStorage.getCharIndex(lastGlyph, success);
317         x = firstGlyph + 2;
318
319         while (x < lastGlyph) {
320             glyphStorage[x - 2] = glyphStorage[x];
321             ix = glyphStorage.getCharIndex(x, success);
322             glyphStorage.setCharIndex(x - 2, ix, success);
323             x += 1;
324         }
325
326         glyphStorage[firstGlyph] = d;
327         glyphStorage[lastGlyph - 1] = a;
328         glyphStorage[lastGlyph] = b;
329
330         glyphStorage.setCharIndex(firstGlyph, id, success);
331         glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
332         glyphStorage.setCharIndex(lastGlyph, ib, success);
333         break;
334
335     case irvDxBA:
336         if ((firstGlyph + 2 < firstGlyph) ||
337             (lastGlyph - firstGlyph < 2)) {
338             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
339             break;
340         }
341         a = glyphStorage[firstGlyph];
342         b = glyphStorage[firstGlyph + 1];
343         d = glyphStorage[lastGlyph];
344         ia = glyphStorage.getCharIndex(firstGlyph, success);
345         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
346         id = glyphStorage.getCharIndex(lastGlyph, success);
347         x = firstGlyph + 2;
348
349         while (x < lastGlyph) {
350             glyphStorage[x - 2] = glyphStorage[x];
351             ix = glyphStorage.getCharIndex(x, success);
352             glyphStorage.setCharIndex(x - 2, ix, success);
353             x += 1;
354         }
355
356         glyphStorage[firstGlyph] = d;
357         glyphStorage[lastGlyph - 1] = b;
358         glyphStorage[lastGlyph] = a;
359
360         glyphStorage.setCharIndex(firstGlyph, id, success);
361         glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
362         glyphStorage.setCharIndex(lastGlyph, ia, success);
363         break;
364
365     case irvCDxAB:
366         if (lastGlyph - firstGlyph < 3) {
367             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
368             break;
369         }
370         a = glyphStorage[firstGlyph];
371         b = glyphStorage[firstGlyph + 1];
372
373         glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
374         glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
375
376         glyphStorage[lastGlyph - 1] = a;
377         glyphStorage[lastGlyph] = b;
378
379         ia = glyphStorage.getCharIndex(firstGlyph, success);
380         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
381         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
382         id = glyphStorage.getCharIndex(lastGlyph, success);
383
384         glyphStorage.setCharIndex(firstGlyph, ic, success);
385         glyphStorage.setCharIndex(firstGlyph + 1, id, success);
386
387         glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
388         glyphStorage.setCharIndex(lastGlyph, ib, success);
389         break;
390
391     case irvCDxBA:
392         if (lastGlyph - firstGlyph < 3) {
393             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
394             break;
395         }
396         a = glyphStorage[firstGlyph];
397         b = glyphStorage[firstGlyph + 1];
398
399         glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
400         glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
401
402         glyphStorage[lastGlyph - 1] = b;
403         glyphStorage[lastGlyph] = a;
404
405         ia = glyphStorage.getCharIndex(firstGlyph, success);
406         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
407         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
408         id = glyphStorage.getCharIndex(lastGlyph, success);
409
410         glyphStorage.setCharIndex(firstGlyph, ic, success);
411         glyphStorage.setCharIndex(firstGlyph + 1, id, success);
412
413         glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
414         glyphStorage.setCharIndex(lastGlyph, ia, success);
415         break;
416
417     case irvDCxAB:
418         if (lastGlyph - firstGlyph < 3) {
419             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
420             break;
421         }
422         a = glyphStorage[firstGlyph];
423         b = glyphStorage[firstGlyph + 1];
424
425         glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
426         glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
427
428         glyphStorage[lastGlyph - 1] = a;
429         glyphStorage[lastGlyph] = b;
430
431         ia = glyphStorage.getCharIndex(firstGlyph, success);
432         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
433         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
434         id = glyphStorage.getCharIndex(lastGlyph, success);
435
436         glyphStorage.setCharIndex(firstGlyph, id, success);
437         glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
438
439         glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
440         glyphStorage.setCharIndex(lastGlyph, ib, success);
441         break;
442
443     case irvDCxBA:
444         if (lastGlyph - firstGlyph < 3) {
445             success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
446             break;
447         }
448         a = glyphStorage[firstGlyph];
449         b = glyphStorage[firstGlyph + 1];
450
451         glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
452         glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
453
454         glyphStorage[lastGlyph - 1] = b;
455         glyphStorage[lastGlyph] = a;
456
457         ia = glyphStorage.getCharIndex(firstGlyph, success);
458         ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
459         ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
460         id = glyphStorage.getCharIndex(lastGlyph, success);
461
462         glyphStorage.setCharIndex(firstGlyph, id, success);
463         glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
464
465         glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
466         glyphStorage.setCharIndex(lastGlyph, ia, success);
467         break;
468     
469     default:
470         break;
471     }
472 }
473
474 U_NAMESPACE_END