1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 /*
27 *
28 * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
29 *
30 */
31
32 #include "LETypes.h"
33 #include "MorphTables.h"
34 #include "StateTables.h"
35 #include "MorphStateTables.h"
36 #include "SubtableProcessor2.h"
37 #include "StateTableProcessor2.h"
38 #include "IndicRearrangementProcessor2.h"
39 #include "LEGlyphStorage.h"
40 #include "LESwaps.h"
41
42 U_NAMESPACE_BEGIN
43
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor2)44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor2)
45
46 IndicRearrangementProcessor2::IndicRearrangementProcessor2(
47 const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
48 : StateTableProcessor2(morphSubtableHeader, success), indicRearrangementSubtableHeader(morphSubtableHeader, success),
49 entryTable(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY)
50 {
51 }
52
~IndicRearrangementProcessor2()53 IndicRearrangementProcessor2::~IndicRearrangementProcessor2()
54 {
55 }
56
beginStateTable()57 void IndicRearrangementProcessor2::beginStateTable()
58 {
59 firstGlyph = 0;
60 lastGlyph = 0;
61 }
62
processStateEntry(LEGlyphStorage & glyphStorage,le_int32 & currGlyph,EntryTableIndex2 index,LEErrorCode & success)63 le_uint16 IndicRearrangementProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
64 EntryTableIndex2 index, LEErrorCode &success)
65 {
66 const IndicRearrangementStateEntry2 *entry = entryTable.getAlias(index, success);
67 if (LE_FAILURE(success)) return 0; // TODO - what to return in bad state?
68 le_uint16 newState = SWAPW(entry->newStateIndex); // index to the new state
69 IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
70
71 if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) {
72 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
73 return 0;
74 }
75
76 if (flags & irfMarkFirst) {
77 firstGlyph = currGlyph;
78 }
79
80 if (flags & irfMarkLast) {
81 lastGlyph = currGlyph;
82 }
83
84 doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success);
85
86 if (!(flags & irfDontAdvance)) {
87 currGlyph += dir;
88 }
89
90 return newState; // index to new state
91 }
92
endStateTable()93 void IndicRearrangementProcessor2::endStateTable()
94 {
95 }
96
doRearrangementAction(LEGlyphStorage & glyphStorage,IndicRearrangementVerb verb,LEErrorCode & success) const97 void IndicRearrangementProcessor2::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const
98 {
99 LEGlyphID a, b, c, d;
100 le_int32 ia, ib, ic, id, ix, x;
101
102 if (LE_FAILURE(success)) return;
103
104 if (verb == irvNoAction) {
105 return;
106 }
107 if (firstGlyph > lastGlyph) {
108 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
109 return;
110 }
111
112 switch(verb)
113 {
114 case irvxA:
115 if (firstGlyph == lastGlyph) break;
116 if (firstGlyph + 1 < firstGlyph) {
117 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
118 break;
119 }
120 a = glyphStorage[firstGlyph];
121 ia = glyphStorage.getCharIndex(firstGlyph, success);
122 x = firstGlyph + 1;
123
124 while (x <= lastGlyph) {
125 glyphStorage[x - 1] = glyphStorage[x];
126 ix = glyphStorage.getCharIndex(x, success);
127 glyphStorage.setCharIndex(x - 1, ix, success);
128 x += 1;
129 }
130
131 glyphStorage[lastGlyph] = a;
132 glyphStorage.setCharIndex(lastGlyph, ia, success);
133 break;
134
135 case irvDx:
136 if (firstGlyph == lastGlyph) break;
137 if (lastGlyph - 1 > lastGlyph) {
138 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
139 break;
140 }
141 d = glyphStorage[lastGlyph];
142 id = glyphStorage.getCharIndex(lastGlyph, success);
143 x = lastGlyph - 1;
144
145 while (x >= firstGlyph) {
146 glyphStorage[x + 1] = glyphStorage[x];
147 ix = glyphStorage.getCharIndex(x, success);
148 glyphStorage.setCharIndex(x + 1, ix, success);
149 x -= 1;
150 }
151
152 glyphStorage[firstGlyph] = d;
153 glyphStorage.setCharIndex(firstGlyph, id, success);
154 break;
155
156 case irvDxA:
157 a = glyphStorage[firstGlyph];
158 ia = glyphStorage.getCharIndex(firstGlyph, success);
159 id = glyphStorage.getCharIndex(lastGlyph, success);
160
161 glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
162 glyphStorage[lastGlyph] = a;
163
164 glyphStorage.setCharIndex(firstGlyph, id, success);
165 glyphStorage.setCharIndex(lastGlyph, ia, success);
166 break;
167
168 case irvxAB:
169 if ((firstGlyph + 2 < firstGlyph) ||
170 (lastGlyph - firstGlyph < 1)) { // difference == 1 is a no-op, < 1 is an error.
171 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
172 break;
173 }
174 a = glyphStorage[firstGlyph];
175 b = glyphStorage[firstGlyph + 1];
176 ia = glyphStorage.getCharIndex(firstGlyph, success);
177 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
178 x = firstGlyph + 2;
179
180 while (x <= lastGlyph) {
181 glyphStorage[x - 2] = glyphStorage[x];
182 ix = glyphStorage.getCharIndex(x, success);
183 glyphStorage.setCharIndex(x - 2, ix, success);
184 x += 1;
185 }
186
187 glyphStorage[lastGlyph - 1] = a;
188 glyphStorage[lastGlyph] = b;
189
190 glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
191 glyphStorage.setCharIndex(lastGlyph, ib, success);
192 break;
193
194 case irvxBA:
195 if ((firstGlyph + 2 < firstGlyph) ||
196 (lastGlyph - firstGlyph < 1)) {
197 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
198 break;
199 }
200 a = glyphStorage[firstGlyph];
201 b = glyphStorage[firstGlyph + 1];
202 ia = glyphStorage.getCharIndex(firstGlyph, success);
203 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
204 x = firstGlyph + 2;
205
206 while (x <= lastGlyph) {
207 glyphStorage[x - 2] = glyphStorage[x];
208 ix = glyphStorage.getCharIndex(x, success);
209 glyphStorage.setCharIndex(x - 2, ix, success);
210 x += 1;
211 }
212
213 glyphStorage[lastGlyph - 1] = b;
214 glyphStorage[lastGlyph] = a;
215
216 glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
217 glyphStorage.setCharIndex(lastGlyph, ia, success);
218 break;
219
220 case irvCDx:
221 if ((lastGlyph - 2 > lastGlyph) ||
222 (lastGlyph - firstGlyph < 1)) {
223 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
224 break;
225 }
226 c = glyphStorage[lastGlyph - 1];
227 d = glyphStorage[lastGlyph];
228 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
229 id = glyphStorage.getCharIndex(lastGlyph, success);
230 x = lastGlyph - 2;
231
232 while (x >= firstGlyph) {
233 glyphStorage[x + 2] = glyphStorage[x];
234 ix = glyphStorage.getCharIndex(x, success);
235 glyphStorage.setCharIndex(x + 2, ix, success);
236 x -= 1;
237 }
238
239 glyphStorage[firstGlyph] = c;
240 glyphStorage[firstGlyph + 1] = d;
241
242 glyphStorage.setCharIndex(firstGlyph, ic, success);
243 glyphStorage.setCharIndex(firstGlyph + 1, id, success);
244 break;
245
246 case irvDCx:
247 if ((lastGlyph - 2 > lastGlyph) ||
248 (lastGlyph - firstGlyph < 1)) {
249 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
250 break;
251 }
252 c = glyphStorage[lastGlyph - 1];
253 d = glyphStorage[lastGlyph];
254 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
255 id = glyphStorage.getCharIndex(lastGlyph, success);
256 x = lastGlyph - 2;
257
258 while (x >= firstGlyph) {
259 glyphStorage[x + 2] = glyphStorage[x];
260 ix = glyphStorage.getCharIndex(x, success);
261 glyphStorage.setCharIndex(x + 2, ix, success);
262 x -= 1;
263 }
264
265 glyphStorage[firstGlyph] = d;
266 glyphStorage[firstGlyph + 1] = c;
267
268 glyphStorage.setCharIndex(firstGlyph, id, success);
269 glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
270 break;
271
272 case irvCDxA:
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] = c;
294 glyphStorage[firstGlyph + 1] = d;
295 glyphStorage[lastGlyph] = a;
296
297 glyphStorage.setCharIndex(firstGlyph, ic, success);
298 glyphStorage.setCharIndex(firstGlyph + 1, id, success);
299 glyphStorage.setCharIndex(lastGlyph, ia, success);
300 break;
301
302 case irvDCxA:
303 if ((lastGlyph - 2 > lastGlyph) ||
304 (lastGlyph - firstGlyph < 2)) {
305 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
306 break;
307 }
308 a = glyphStorage[firstGlyph];
309 c = glyphStorage[lastGlyph - 1];
310 d = glyphStorage[lastGlyph];
311 ia = glyphStorage.getCharIndex(firstGlyph, success);
312 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
313 id = glyphStorage.getCharIndex(lastGlyph, success);
314 x = lastGlyph - 2;
315
316 while (x > firstGlyph) {
317 glyphStorage[x + 1] = glyphStorage[x];
318 ix = glyphStorage.getCharIndex(x, success);
319 glyphStorage.setCharIndex(x + 1, ix, success);
320 x -= 1;
321 }
322
323 glyphStorage[firstGlyph] = d;
324 glyphStorage[firstGlyph + 1] = c;
325 glyphStorage[lastGlyph] = a;
326
327 glyphStorage.setCharIndex(firstGlyph, id, success);
328 glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
329 glyphStorage.setCharIndex(lastGlyph, ia, success);
330 break;
331
332 case irvDxAB:
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] = a;
355 glyphStorage[lastGlyph] = b;
356
357 glyphStorage.setCharIndex(firstGlyph, id, success);
358 glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
359 glyphStorage.setCharIndex(lastGlyph, ib, success);
360 break;
361
362 case irvDxBA:
363 if ((firstGlyph + 2 < firstGlyph) ||
364 (lastGlyph - firstGlyph < 2)) {
365 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
366 break;
367 }
368 a = glyphStorage[firstGlyph];
369 b = glyphStorage[firstGlyph + 1];
370 d = glyphStorage[lastGlyph];
371 ia = glyphStorage.getCharIndex(firstGlyph, success);
372 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
373 id = glyphStorage.getCharIndex(lastGlyph, success);
374 x = firstGlyph + 2;
375
376 while (x < lastGlyph) {
377 glyphStorage[x - 2] = glyphStorage[x];
378 ix = glyphStorage.getCharIndex(x, success);
379 glyphStorage.setCharIndex(x - 2, ix, success);
380 x += 1;
381 }
382
383 glyphStorage[firstGlyph] = d;
384 glyphStorage[lastGlyph - 1] = b;
385 glyphStorage[lastGlyph] = a;
386
387 glyphStorage.setCharIndex(firstGlyph, id, success);
388 glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
389 glyphStorage.setCharIndex(lastGlyph, ia, success);
390 break;
391
392 case irvCDxAB:
393 if (lastGlyph - firstGlyph < 3) {
394 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
395 break;
396 }
397 a = glyphStorage[firstGlyph];
398 b = glyphStorage[firstGlyph + 1];
399
400 glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
401 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
402
403 glyphStorage[lastGlyph - 1] = a;
404 glyphStorage[lastGlyph] = b;
405
406 ia = glyphStorage.getCharIndex(firstGlyph, success);
407 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
408 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
409 id = glyphStorage.getCharIndex(lastGlyph, success);
410
411 glyphStorage.setCharIndex(firstGlyph, ic, success);
412 glyphStorage.setCharIndex(firstGlyph + 1, id, success);
413
414 glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
415 glyphStorage.setCharIndex(lastGlyph, ib, success);
416 break;
417
418 case irvCDxBA:
419 if (lastGlyph - firstGlyph < 3) {
420 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
421 break;
422 }
423 a = glyphStorage[firstGlyph];
424 b = glyphStorage[firstGlyph + 1];
425
426 glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
427 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
428
429 glyphStorage[lastGlyph - 1] = b;
430 glyphStorage[lastGlyph] = a;
431
432 ia = glyphStorage.getCharIndex(firstGlyph, success);
433 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
434 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
435 id = glyphStorage.getCharIndex(lastGlyph, success);
436
437 glyphStorage.setCharIndex(firstGlyph, ic, success);
438 glyphStorage.setCharIndex(firstGlyph + 1, id, success);
439
440 glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
441 glyphStorage.setCharIndex(lastGlyph, ia, success);
442 break;
443
444 case irvDCxAB:
445 if (lastGlyph - firstGlyph < 3) {
446 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
447 break;
448 }
449 a = glyphStorage[firstGlyph];
450 b = glyphStorage[firstGlyph + 1];
451
452 glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
453 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
454
455 glyphStorage[lastGlyph - 1] = a;
456 glyphStorage[lastGlyph] = b;
457
458 ia = glyphStorage.getCharIndex(firstGlyph, success);
459 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
460 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
461 id = glyphStorage.getCharIndex(lastGlyph, success);
462
463 glyphStorage.setCharIndex(firstGlyph, id, success);
464 glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
465
466 glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
467 glyphStorage.setCharIndex(lastGlyph, ib, success);
468 break;
469
470 case irvDCxBA:
471 if (lastGlyph - firstGlyph < 3) {
472 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
473 break;
474 }
475 a = glyphStorage[firstGlyph];
476 b = glyphStorage[firstGlyph + 1];
477
478 glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
479 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
480
481 glyphStorage[lastGlyph - 1] = b;
482 glyphStorage[lastGlyph] = a;
483
484 ia = glyphStorage.getCharIndex(firstGlyph, success);
485 ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
486 ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
487 id = glyphStorage.getCharIndex(lastGlyph, success);
488
489 glyphStorage.setCharIndex(firstGlyph, id, success);
490 glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
491
492 glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
493 glyphStorage.setCharIndex(lastGlyph, ia, success);
494 break;
495
496 default:
497 break;
498 }
499
500 }
501
502 U_NAMESPACE_END
503