]>
Commit | Line | Data |
---|---|---|
51004dcb A |
1 | /* |
2 | * | |
2ca993e8 | 3 | * (C) Copyright IBM Corp. and others 1998-2015 - All Rights Reserved |
51004dcb A |
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 | ||
57a6839d A |
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) | |
51004dcb | 25 | { |
51004dcb A |
26 | } |
27 | ||
28 | IndicRearrangementProcessor2::~IndicRearrangementProcessor2() | |
29 | { | |
30 | } | |
31 | ||
32 | void IndicRearrangementProcessor2::beginStateTable() | |
33 | { | |
34 | firstGlyph = 0; | |
35 | lastGlyph = 0; | |
36 | } | |
37 | ||
57a6839d A |
38 | le_uint16 IndicRearrangementProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, |
39 | EntryTableIndex2 index, LEErrorCode &success) | |
51004dcb | 40 | { |
57a6839d A |
41 | const IndicRearrangementStateEntry2 *entry = entryTable.getAlias(index, success); |
42 | if (LE_FAILURE(success)) return 0; // TODO - what to return in bad state? | |
51004dcb A |
43 | le_uint16 newState = SWAPW(entry->newStateIndex); // index to the new state |
44 | IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags); | |
45 | ||
46 | if (flags & irfMarkFirst) { | |
2ca993e8 | 47 | firstGlyph = (le_uint32)currGlyph; |
51004dcb A |
48 | } |
49 | ||
50 | if (flags & irfMarkLast) { | |
2ca993e8 | 51 | lastGlyph = (le_uint32)currGlyph; |
51004dcb A |
52 | } |
53 | ||
2ca993e8 | 54 | doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success); |
51004dcb A |
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 | ||
2ca993e8 | 67 | void IndicRearrangementProcessor2::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const |
51004dcb A |
68 | { |
69 | LEGlyphID a, b, c, d; | |
70 | le_int32 ia, ib, ic, id, ix, x; | |
2ca993e8 A |
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 | } | |
51004dcb A |
81 | |
82 | switch(verb) | |
83 | { | |
51004dcb | 84 | case irvxA: |
2ca993e8 A |
85 | if (firstGlyph == lastGlyph) break; |
86 | if (firstGlyph + 1 < firstGlyph) { | |
87 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
88 | break; | |
89 | } | |
51004dcb A |
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: | |
2ca993e8 A |
106 | if (firstGlyph == lastGlyph) break; |
107 | if (lastGlyph - 1 > lastGlyph) { | |
108 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
109 | break; | |
110 | } | |
51004dcb A |
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: | |
2ca993e8 A |
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 | } | |
51004dcb A |
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: | |
2ca993e8 A |
165 | if ((firstGlyph + 2 < firstGlyph) || |
166 | (lastGlyph - firstGlyph < 1)) { | |
167 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
168 | break; | |
169 | } | |
51004dcb A |
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: | |
2ca993e8 A |
191 | if ((lastGlyph - 2 > lastGlyph) || |
192 | (lastGlyph - firstGlyph < 1)) { | |
193 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
194 | break; | |
195 | } | |
51004dcb A |
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: | |
2ca993e8 A |
217 | if ((lastGlyph - 2 > lastGlyph) || |
218 | (lastGlyph - firstGlyph < 1)) { | |
219 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
220 | break; | |
221 | } | |
51004dcb A |
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: | |
2ca993e8 A |
243 | if ((lastGlyph - 2 > lastGlyph) || |
244 | (lastGlyph - firstGlyph < 2)) { | |
245 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
246 | break; | |
247 | } | |
51004dcb A |
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: | |
2ca993e8 A |
273 | if ((lastGlyph - 2 > lastGlyph) || |
274 | (lastGlyph - firstGlyph < 2)) { | |
275 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
276 | break; | |
277 | } | |
51004dcb A |
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: | |
2ca993e8 A |
303 | if ((firstGlyph + 2 < firstGlyph) || |
304 | (lastGlyph - firstGlyph < 2)) { | |
305 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
306 | break; | |
307 | } | |
51004dcb A |
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: | |
2ca993e8 A |
333 | if ((firstGlyph + 2 < firstGlyph) || |
334 | (lastGlyph - firstGlyph < 2)) { | |
335 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
336 | break; | |
337 | } | |
51004dcb A |
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: | |
2ca993e8 A |
363 | if (lastGlyph - firstGlyph < 3) { |
364 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
365 | break; | |
366 | } | |
51004dcb A |
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: | |
2ca993e8 A |
389 | if (lastGlyph - firstGlyph < 3) { |
390 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
391 | break; | |
392 | } | |
51004dcb A |
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: | |
2ca993e8 A |
415 | if (lastGlyph - firstGlyph < 3) { |
416 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
417 | break; | |
418 | } | |
51004dcb A |
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: | |
2ca993e8 A |
441 | if (lastGlyph - firstGlyph < 3) { |
442 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
443 | break; | |
444 | } | |
51004dcb A |
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 |