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