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. 1998-2004 - All Rights Reserved 29 * 30 */ 31 32 #include "LETypes.h" 33 #include "MorphTables.h" 34 #include "StateTables.h" 35 #include "MorphStateTables.h" 36 #include "SubtableProcessor.h" 37 #include "StateTableProcessor.h" 38 #include "IndicRearrangementProcessor.h" 39 #include "LEGlyphStorage.h" 40 #include "LESwaps.h" 41 42 U_NAMESPACE_BEGIN 43 44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor) 45 46 IndicRearrangementProcessor::IndicRearrangementProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success) 47 : StateTableProcessor(morphSubtableHeader, success), 48 indicRearrangementSubtableHeader(morphSubtableHeader, success), 49 entryTable(stateTableHeader, success, (const IndicRearrangementStateEntry*)(&stateTableHeader->stHeader), 50 entryTableOffset, LE_UNBOUNDED_ARRAY), 51 int16Table(stateTableHeader, success, (const le_int16*)entryTable.getAlias(), 0, LE_UNBOUNDED_ARRAY) 52 53 { 54 } 55 56 IndicRearrangementProcessor::~IndicRearrangementProcessor() 57 { 58 } 59 60 void IndicRearrangementProcessor::beginStateTable() 61 { 62 firstGlyph = 0; 63 lastGlyph = 0; 64 } 65 66 ByteOffset IndicRearrangementProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) 67 { 68 LEErrorCode success = LE_NO_ERROR; // todo- make a param? 69 const IndicRearrangementStateEntry *entry = entryTable.getAlias(index,success); 70 ByteOffset newState = SWAPW(entry->newStateOffset); 71 IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags); 72 73 if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) { 74 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 75 return 0; 76 } 77 78 if (flags & irfMarkFirst) { 79 firstGlyph = currGlyph; 80 } 81 82 if (flags & irfMarkLast) { 83 lastGlyph = currGlyph; 84 } 85 86 doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success); 87 88 if (!(flags & irfDontAdvance)) { 89 // XXX: Should handle reverse too... 90 currGlyph += 1; 91 } 92 93 return newState; 94 } 95 96 void IndicRearrangementProcessor::endStateTable() 97 { 98 } 99 100 void IndicRearrangementProcessor::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const 101 { 102 LEGlyphID a, b, c, d; 103 le_int32 ia, ib, ic, id, ix, x; 104 105 if (LE_FAILURE(success)) return; 106 107 if (verb == irvNoAction) { 108 return; 109 } 110 if (firstGlyph > lastGlyph) { 111 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 112 return; 113 } 114 115 switch(verb) 116 { 117 case irvxA: 118 if (firstGlyph == lastGlyph) break; 119 if (firstGlyph + 1 < firstGlyph) { 120 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 121 break; 122 } 123 a = glyphStorage[firstGlyph]; 124 ia = glyphStorage.getCharIndex(firstGlyph, success); 125 x = firstGlyph + 1; 126 127 while (x <= lastGlyph) { 128 glyphStorage[x - 1] = glyphStorage[x]; 129 ix = glyphStorage.getCharIndex(x, success); 130 glyphStorage.setCharIndex(x - 1, ix, success); 131 x += 1; 132 } 133 134 glyphStorage[lastGlyph] = a; 135 glyphStorage.setCharIndex(lastGlyph, ia, success); 136 break; 137 138 case irvDx: 139 if (firstGlyph == lastGlyph) break; 140 if (lastGlyph - 1 > lastGlyph) { 141 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 142 break; 143 } 144 d = glyphStorage[lastGlyph]; 145 id = glyphStorage.getCharIndex(lastGlyph, success); 146 x = lastGlyph - 1; 147 148 while (x >= firstGlyph) { 149 glyphStorage[x + 1] = glyphStorage[x]; 150 ix = glyphStorage.getCharIndex(x, success); 151 glyphStorage.setCharIndex(x + 1, ix, success); 152 x -= 1; 153 } 154 155 glyphStorage[firstGlyph] = d; 156 glyphStorage.setCharIndex(firstGlyph, id, success); 157 break; 158 159 case irvDxA: 160 a = glyphStorage[firstGlyph]; 161 ia = glyphStorage.getCharIndex(firstGlyph, success); 162 id = glyphStorage.getCharIndex(lastGlyph, success); 163 164 glyphStorage[firstGlyph] = glyphStorage[lastGlyph]; 165 glyphStorage[lastGlyph] = a; 166 167 glyphStorage.setCharIndex(firstGlyph, id, success); 168 glyphStorage.setCharIndex(lastGlyph, ia, success); 169 break; 170 171 case irvxAB: 172 if ((firstGlyph + 2 < firstGlyph) || 173 (lastGlyph - firstGlyph < 1)) { // difference == 1 is a no-op, < 1 is an error. 174 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 175 break; 176 } 177 a = glyphStorage[firstGlyph]; 178 b = glyphStorage[firstGlyph + 1]; 179 ia = glyphStorage.getCharIndex(firstGlyph, success); 180 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 181 x = firstGlyph + 2; 182 183 while (x <= lastGlyph) { 184 glyphStorage[x - 2] = glyphStorage[x]; 185 ix = glyphStorage.getCharIndex(x, success); 186 glyphStorage.setCharIndex(x - 2, ix, success); 187 x += 1; 188 } 189 190 glyphStorage[lastGlyph - 1] = a; 191 glyphStorage[lastGlyph] = b; 192 193 glyphStorage.setCharIndex(lastGlyph - 1, ia, success); 194 glyphStorage.setCharIndex(lastGlyph, ib, success); 195 break; 196 197 case irvxBA: 198 if ((firstGlyph + 2 < firstGlyph) || 199 (lastGlyph - firstGlyph < 1)) { 200 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 201 break; 202 } 203 a = glyphStorage[firstGlyph]; 204 b = glyphStorage[firstGlyph + 1]; 205 ia = glyphStorage.getCharIndex(firstGlyph, success); 206 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 207 x = firstGlyph + 2; 208 209 while (x <= lastGlyph) { 210 glyphStorage[x - 2] = glyphStorage[x]; 211 ix = glyphStorage.getCharIndex(x, success); 212 glyphStorage.setCharIndex(x - 2, ix, success); 213 x += 1; 214 } 215 216 glyphStorage[lastGlyph - 1] = b; 217 glyphStorage[lastGlyph] = a; 218 219 glyphStorage.setCharIndex(lastGlyph - 1, ib, success); 220 glyphStorage.setCharIndex(lastGlyph, ia, success); 221 break; 222 223 case irvCDx: 224 if ((lastGlyph - 2 > lastGlyph) || 225 (lastGlyph - firstGlyph < 1)) { 226 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 227 break; 228 } 229 c = glyphStorage[lastGlyph - 1]; 230 d = glyphStorage[lastGlyph]; 231 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 232 id = glyphStorage.getCharIndex(lastGlyph, success); 233 x = lastGlyph - 2; 234 235 while (x >= firstGlyph) { 236 glyphStorage[x + 2] = glyphStorage[x]; 237 ix = glyphStorage.getCharIndex(x, success); 238 glyphStorage.setCharIndex(x + 2, ix, success); 239 x -= 1; 240 } 241 242 glyphStorage[firstGlyph] = c; 243 glyphStorage[firstGlyph + 1] = d; 244 245 glyphStorage.setCharIndex(firstGlyph, ic, success); 246 glyphStorage.setCharIndex(firstGlyph + 1, id, success); 247 break; 248 249 case irvDCx: 250 if ((lastGlyph - 2 > lastGlyph) || 251 (lastGlyph - firstGlyph < 1)) { 252 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 253 break; 254 } 255 c = glyphStorage[lastGlyph - 1]; 256 d = glyphStorage[lastGlyph]; 257 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 258 id = glyphStorage.getCharIndex(lastGlyph, success); 259 x = lastGlyph - 2; 260 261 while (x >= firstGlyph) { 262 glyphStorage[x + 2] = glyphStorage[x]; 263 ix = glyphStorage.getCharIndex(x, success); 264 glyphStorage.setCharIndex(x + 2, ix, success); 265 x -= 1; 266 } 267 268 glyphStorage[firstGlyph] = d; 269 glyphStorage[firstGlyph + 1] = c; 270 271 glyphStorage.setCharIndex(firstGlyph, id, success); 272 glyphStorage.setCharIndex(firstGlyph + 1, ic, success); 273 break; 274 275 case irvCDxA: 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] = c; 297 glyphStorage[firstGlyph + 1] = d; 298 glyphStorage[lastGlyph] = a; 299 300 glyphStorage.setCharIndex(firstGlyph, ic, success); 301 glyphStorage.setCharIndex(firstGlyph + 1, id, success); 302 glyphStorage.setCharIndex(lastGlyph, ia, success); 303 break; 304 305 case irvDCxA: 306 if ((lastGlyph - 2 > lastGlyph) || 307 (lastGlyph - firstGlyph < 2)) { 308 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 309 break; 310 } 311 a = glyphStorage[firstGlyph]; 312 c = glyphStorage[lastGlyph - 1]; 313 d = glyphStorage[lastGlyph]; 314 ia = glyphStorage.getCharIndex(firstGlyph, success); 315 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 316 id = glyphStorage.getCharIndex(lastGlyph, success); 317 x = lastGlyph - 2; 318 319 while (x > firstGlyph) { 320 glyphStorage[x + 1] = glyphStorage[x]; 321 ix = glyphStorage.getCharIndex(x, success); 322 glyphStorage.setCharIndex(x + 1, ix, success); 323 x -= 1; 324 } 325 326 glyphStorage[firstGlyph] = d; 327 glyphStorage[firstGlyph + 1] = c; 328 glyphStorage[lastGlyph] = a; 329 330 glyphStorage.setCharIndex(firstGlyph, id, success); 331 glyphStorage.setCharIndex(firstGlyph + 1, ic, success); 332 glyphStorage.setCharIndex(lastGlyph, ia, success); 333 break; 334 335 case irvDxAB: 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] = a; 358 glyphStorage[lastGlyph] = b; 359 360 glyphStorage.setCharIndex(firstGlyph, id, success); 361 glyphStorage.setCharIndex(lastGlyph - 1, ia, success); 362 glyphStorage.setCharIndex(lastGlyph, ib, success); 363 break; 364 365 case irvDxBA: 366 if ((firstGlyph + 2 < firstGlyph) || 367 (lastGlyph - firstGlyph < 2)) { 368 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 369 break; 370 } 371 a = glyphStorage[firstGlyph]; 372 b = glyphStorage[firstGlyph + 1]; 373 d = glyphStorage[lastGlyph]; 374 ia = glyphStorage.getCharIndex(firstGlyph, success); 375 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 376 id = glyphStorage.getCharIndex(lastGlyph, success); 377 x = firstGlyph + 2; 378 379 while (x < lastGlyph) { 380 glyphStorage[x - 2] = glyphStorage[x]; 381 ix = glyphStorage.getCharIndex(x, success); 382 glyphStorage.setCharIndex(x - 2, ix, success); 383 x += 1; 384 } 385 386 glyphStorage[firstGlyph] = d; 387 glyphStorage[lastGlyph - 1] = b; 388 glyphStorage[lastGlyph] = a; 389 390 glyphStorage.setCharIndex(firstGlyph, id, success); 391 glyphStorage.setCharIndex(lastGlyph - 1, ib, success); 392 glyphStorage.setCharIndex(lastGlyph, ia, success); 393 break; 394 395 case irvCDxAB: 396 if (lastGlyph - firstGlyph < 3) { 397 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 398 break; 399 } 400 a = glyphStorage[firstGlyph]; 401 b = glyphStorage[firstGlyph + 1]; 402 403 glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1]; 404 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph]; 405 406 glyphStorage[lastGlyph - 1] = a; 407 glyphStorage[lastGlyph] = b; 408 409 ia = glyphStorage.getCharIndex(firstGlyph, success); 410 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 411 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 412 id = glyphStorage.getCharIndex(lastGlyph, success); 413 414 glyphStorage.setCharIndex(firstGlyph, ic, success); 415 glyphStorage.setCharIndex(firstGlyph + 1, id, success); 416 417 glyphStorage.setCharIndex(lastGlyph - 1, ia, success); 418 glyphStorage.setCharIndex(lastGlyph, ib, success); 419 break; 420 421 case irvCDxBA: 422 if (lastGlyph - firstGlyph < 3) { 423 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 424 break; 425 } 426 a = glyphStorage[firstGlyph]; 427 b = glyphStorage[firstGlyph + 1]; 428 429 glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1]; 430 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph]; 431 432 glyphStorage[lastGlyph - 1] = b; 433 glyphStorage[lastGlyph] = a; 434 435 ia = glyphStorage.getCharIndex(firstGlyph, success); 436 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 437 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 438 id = glyphStorage.getCharIndex(lastGlyph, success); 439 440 glyphStorage.setCharIndex(firstGlyph, ic, success); 441 glyphStorage.setCharIndex(firstGlyph + 1, id, success); 442 443 glyphStorage.setCharIndex(lastGlyph - 1, ib, success); 444 glyphStorage.setCharIndex(lastGlyph, ia, success); 445 break; 446 447 case irvDCxAB: 448 if (lastGlyph - firstGlyph < 3) { 449 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 450 break; 451 } 452 a = glyphStorage[firstGlyph]; 453 b = glyphStorage[firstGlyph + 1]; 454 455 glyphStorage[firstGlyph] = glyphStorage[lastGlyph]; 456 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1]; 457 458 glyphStorage[lastGlyph - 1] = a; 459 glyphStorage[lastGlyph] = b; 460 461 ia = glyphStorage.getCharIndex(firstGlyph, success); 462 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 463 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 464 id = glyphStorage.getCharIndex(lastGlyph, success); 465 466 glyphStorage.setCharIndex(firstGlyph, id, success); 467 glyphStorage.setCharIndex(firstGlyph + 1, ic, success); 468 469 glyphStorage.setCharIndex(lastGlyph - 1, ia, success); 470 glyphStorage.setCharIndex(lastGlyph, ib, success); 471 break; 472 473 case irvDCxBA: 474 if (lastGlyph - firstGlyph < 3) { 475 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 476 break; 477 } 478 a = glyphStorage[firstGlyph]; 479 b = glyphStorage[firstGlyph + 1]; 480 481 glyphStorage[firstGlyph] = glyphStorage[lastGlyph]; 482 glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1]; 483 484 glyphStorage[lastGlyph - 1] = b; 485 glyphStorage[lastGlyph] = a; 486 487 ia = glyphStorage.getCharIndex(firstGlyph, success); 488 ib = glyphStorage.getCharIndex(firstGlyph + 1, success); 489 ic = glyphStorage.getCharIndex(lastGlyph - 1, success); 490 id = glyphStorage.getCharIndex(lastGlyph, success); 491 492 glyphStorage.setCharIndex(firstGlyph, id, success); 493 glyphStorage.setCharIndex(firstGlyph + 1, ic, success); 494 495 glyphStorage.setCharIndex(lastGlyph - 1, ib, success); 496 glyphStorage.setCharIndex(lastGlyph, ia, success); 497 break; 498 499 default: 500 break; 501 } 502 } 503 504 U_NAMESPACE_END