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 42U_NAMESPACE_BEGIN 43 44UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor2) 45 46IndicRearrangementProcessor2::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 53IndicRearrangementProcessor2::~IndicRearrangementProcessor2() 54{ 55} 56 57void IndicRearrangementProcessor2::beginStateTable() 58{ 59 firstGlyph = 0; 60 lastGlyph = 0; 61} 62 63le_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 93void IndicRearrangementProcessor2::endStateTable() 94{ 95} 96 97void 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 502U_NAMESPACE_END 503