]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/IndicRearrangementProcessor.cpp
ICU-59180.0.1.tar.gz
[apple/icu.git] / icuSources / 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