1 /* 2 ********************************************************************** 3 * Copyright (C) 1998-2009, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 */ 7 8 #include "LETypes.h" 9 #include "LEInsertionList.h" 10 #include "LEGlyphStorage.h" 11 12 U_NAMESPACE_BEGIN 13 14 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage) 15 16 LEInsertionCallback::~LEInsertionCallback() 17 { 18 // nothing to do... 19 } 20 21 LEGlyphStorage::LEGlyphStorage() 22 : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL), 23 fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0) 24 { 25 // nothing else to do! 26 } 27 28 LEGlyphStorage::~LEGlyphStorage() 29 { 30 reset(); 31 } 32 33 void LEGlyphStorage::reset() 34 { 35 fGlyphCount = 0; 36 37 if (fPositions != NULL) { 38 LE_DELETE_ARRAY(fPositions); 39 fPositions = NULL; 40 } 41 42 if (fAuxData != NULL) { 43 LE_DELETE_ARRAY(fAuxData); 44 fAuxData = NULL; 45 } 46 47 if (fInsertionList != NULL) { 48 delete fInsertionList; 49 fInsertionList = NULL; 50 } 51 52 if (fCharIndices != NULL) { 53 LE_DELETE_ARRAY(fCharIndices); 54 fCharIndices = NULL; 55 } 56 57 if (fGlyphs != NULL) { 58 LE_DELETE_ARRAY(fGlyphs); 59 fGlyphs = NULL; 60 } 61 } 62 63 // FIXME: This might get called more than once, for various reasons. Is 64 // testing for pre-existing glyph and charIndices arrays good enough? 65 void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success) 66 { 67 if (LE_FAILURE(success)) { 68 return; 69 } 70 71 if (initialGlyphCount <= 0) { 72 success = LE_ILLEGAL_ARGUMENT_ERROR; 73 return; 74 } 75 76 if (fGlyphs == NULL) { 77 fGlyphCount = initialGlyphCount; 78 fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount); 79 80 if (fGlyphs == NULL) { 81 success = LE_MEMORY_ALLOCATION_ERROR; 82 return; 83 } 84 } 85 86 if (fCharIndices == NULL) { 87 fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount); 88 89 if (fCharIndices == NULL) { 90 LE_DELETE_ARRAY(fGlyphs); 91 fGlyphs = NULL; 92 success = LE_MEMORY_ALLOCATION_ERROR; 93 return; 94 } 95 96 // Initialize the charIndices array 97 le_int32 i, count = fGlyphCount, dir = 1, out = 0; 98 99 if (rightToLeft) { 100 out = fGlyphCount - 1; 101 dir = -1; 102 } 103 104 for (i = 0; i < count; i += 1, out += dir) { 105 fCharIndices[out] = i; 106 } 107 } 108 109 if (fInsertionList == NULL) { 110 // FIXME: check this for failure? 111 fInsertionList = new LEInsertionList(rightToLeft); 112 if (fInsertionList == NULL) { 113 LE_DELETE_ARRAY(fCharIndices); 114 fCharIndices = NULL; 115 116 LE_DELETE_ARRAY(fGlyphs); 117 fGlyphs = NULL; 118 119 success = LE_MEMORY_ALLOCATION_ERROR; 120 return; 121 } 122 } 123 } 124 125 // FIXME: do we want to initialize the positions to [0, 0]? 126 le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success) 127 { 128 if (LE_FAILURE(success)) { 129 return -1; 130 } 131 132 if (fPositions != NULL) { 133 success = LE_INTERNAL_ERROR; 134 return -1; 135 } 136 137 fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1)); 138 139 if (fPositions == NULL) { 140 success = LE_MEMORY_ALLOCATION_ERROR; 141 return -1; 142 } 143 144 return fGlyphCount; 145 } 146 147 // FIXME: do we want to initialize the aux data to NULL? 148 le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success) 149 { 150 if (LE_FAILURE(success)) { 151 return -1; 152 } 153 154 if (fAuxData != NULL) { 155 success = LE_INTERNAL_ERROR; 156 return -1; 157 } 158 159 fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount); 160 161 if (fAuxData == NULL) { 162 success = LE_MEMORY_ALLOCATION_ERROR; 163 return -1; 164 } 165 166 return fGlyphCount; 167 } 168 169 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const 170 { 171 le_int32 i; 172 173 if (LE_FAILURE(success)) { 174 return; 175 } 176 177 if (charIndices == NULL) { 178 success = LE_ILLEGAL_ARGUMENT_ERROR; 179 return; 180 } 181 182 if (fCharIndices == NULL) { 183 success = LE_NO_LAYOUT_ERROR; 184 return; 185 } 186 187 for (i = 0; i < fGlyphCount; i += 1) { 188 charIndices[i] = fCharIndices[i] + indexBase; 189 } 190 } 191 192 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const 193 { 194 if (LE_FAILURE(success)) { 195 return; 196 } 197 198 if (charIndices == NULL) { 199 success = LE_ILLEGAL_ARGUMENT_ERROR; 200 return; 201 } 202 203 if (fCharIndices == NULL) { 204 success = LE_NO_LAYOUT_ERROR; 205 return; 206 } 207 208 LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount); 209 } 210 211 // Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits 212 void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const 213 { 214 le_int32 i; 215 216 if (LE_FAILURE(success)) { 217 return; 218 } 219 220 if (glyphs == NULL) { 221 success = LE_ILLEGAL_ARGUMENT_ERROR; 222 return; 223 } 224 225 if (fGlyphs == NULL) { 226 success = LE_NO_LAYOUT_ERROR; 227 return; 228 } 229 230 for (i = 0; i < fGlyphCount; i += 1) { 231 glyphs[i] = fGlyphs[i] | extraBits; 232 } 233 } 234 235 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const 236 { 237 if (LE_FAILURE(success)) { 238 return; 239 } 240 241 if (glyphs == NULL) { 242 success = LE_ILLEGAL_ARGUMENT_ERROR; 243 return; 244 } 245 246 if (fGlyphs == NULL) { 247 success = LE_NO_LAYOUT_ERROR; 248 return; 249 } 250 251 LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount); 252 } 253 254 LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const 255 { 256 if (LE_FAILURE(success)) { 257 return 0xFFFF; 258 } 259 260 if (fGlyphs == NULL) { 261 success = LE_NO_LAYOUT_ERROR; 262 return 0xFFFF; 263 } 264 265 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { 266 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 267 return 0xFFFF; 268 } 269 270 return fGlyphs[glyphIndex]; 271 } 272 273 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success) 274 { 275 if (LE_FAILURE(success)) { 276 return; 277 } 278 279 if (fGlyphs == NULL) { 280 success = LE_NO_LAYOUT_ERROR; 281 return; 282 } 283 284 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { 285 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 286 return; 287 } 288 289 fGlyphs[glyphIndex] = glyphID; 290 } 291 292 le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const 293 { 294 if (LE_FAILURE(success)) { 295 return -1; 296 } 297 298 if (fCharIndices == NULL) { 299 success = LE_NO_LAYOUT_ERROR; 300 return -1; 301 } 302 303 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { 304 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 305 return -1; 306 } 307 308 return fCharIndices[glyphIndex]; 309 } 310 311 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success) 312 { 313 if (LE_FAILURE(success)) { 314 return; 315 } 316 317 if (fCharIndices == NULL) { 318 success = LE_NO_LAYOUT_ERROR; 319 return; 320 } 321 322 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { 323 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 324 return; 325 } 326 327 fCharIndices[glyphIndex] = charIndex; 328 } 329 330 void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const 331 { 332 if (LE_FAILURE(success)) { 333 return; 334 } 335 336 if (auxData == NULL) { 337 success = LE_ILLEGAL_ARGUMENT_ERROR; 338 return; 339 } 340 341 if (fAuxData == NULL) { 342 success = LE_NO_LAYOUT_ERROR; 343 return; 344 } 345 346 LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount); 347 } 348 349 le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const 350 { 351 if (LE_FAILURE(success)) { 352 return 0; 353 } 354 355 if (fAuxData == NULL) { 356 success = LE_NO_LAYOUT_ERROR; 357 return 0; 358 } 359 360 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { 361 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 362 return 0; 363 } 364 365 return fAuxData[glyphIndex]; 366 } 367 368 void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success) 369 { 370 if (LE_FAILURE(success)) { 371 return; 372 } 373 374 if (fAuxData == NULL) { 375 success = LE_NO_LAYOUT_ERROR; 376 return; 377 } 378 379 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { 380 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 381 return; 382 } 383 384 fAuxData[glyphIndex] = auxData; 385 } 386 387 void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const 388 { 389 if (LE_FAILURE(success)) { 390 return; 391 } 392 393 if (positions == NULL) { 394 success = LE_ILLEGAL_ARGUMENT_ERROR; 395 return; 396 } 397 398 if (fPositions == NULL) { 399 success = LE_NO_LAYOUT_ERROR; 400 return; 401 } 402 403 LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2); 404 } 405 406 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const 407 { 408 if (LE_FAILURE(success)) { 409 return; 410 } 411 412 if (glyphIndex < 0 || glyphIndex > fGlyphCount) { 413 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 414 return; 415 } 416 417 if (fPositions == NULL) { 418 success = LE_NO_LAYOUT_ERROR; 419 return; 420 } 421 422 x = fPositions[glyphIndex * 2]; 423 y = fPositions[glyphIndex * 2 + 1]; 424 } 425 426 void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success) 427 { 428 if (LE_FAILURE(success)) { 429 return; 430 } 431 432 if (glyphIndex < 0 || glyphIndex > fGlyphCount) { 433 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 434 return; 435 } 436 437 fPositions[glyphIndex * 2] = x; 438 fPositions[glyphIndex * 2 + 1] = y; 439 } 440 441 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success) 442 { 443 if (LE_FAILURE(success)) { 444 return; 445 } 446 447 if (glyphIndex < 0 || glyphIndex > fGlyphCount) { 448 success = LE_INDEX_OUT_OF_BOUNDS_ERROR; 449 return; 450 } 451 452 fPositions[glyphIndex * 2] += xAdjust; 453 fPositions[glyphIndex * 2 + 1] += yAdjust; 454 } 455 456 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from) 457 { 458 if (fGlyphs != NULL) { 459 LE_DELETE_ARRAY(fGlyphs); 460 } 461 462 fGlyphs = from.fGlyphs; 463 from.fGlyphs = NULL; 464 465 if (fInsertionList != NULL) { 466 delete fInsertionList; 467 } 468 469 fInsertionList = from.fInsertionList; 470 from.fInsertionList = NULL; 471 } 472 473 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from) 474 { 475 if (fCharIndices != NULL) { 476 LE_DELETE_ARRAY(fCharIndices); 477 } 478 479 fCharIndices = from.fCharIndices; 480 from.fCharIndices = NULL; 481 } 482 483 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from) 484 { 485 if (fPositions != NULL) { 486 LE_DELETE_ARRAY(fPositions); 487 } 488 489 fPositions = from.fPositions; 490 from.fPositions = NULL; 491 } 492 493 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from) 494 { 495 if (fAuxData != NULL) { 496 LE_DELETE_ARRAY(fAuxData); 497 } 498 499 fAuxData = from.fAuxData; 500 from.fAuxData = NULL; 501 } 502 503 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from) 504 { 505 fGlyphCount = from.fGlyphCount; 506 } 507 508 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount) 509 { 510 fGlyphCount = newGlyphCount; 511 } 512 513 // Move a glyph to a different position in the LEGlyphStorage ( used for Indic v2 processing ) 514 515 void LEGlyphStorage::moveGlyph(le_int32 fromPosition, le_int32 toPosition, le_uint32 marker ) 516 { 517 518 LEErrorCode success = LE_NO_ERROR; 519 520 LEGlyphID holdGlyph = getGlyphID(fromPosition,success); 521 le_int32 holdCharIndex = getCharIndex(fromPosition,success); 522 le_uint32 holdAuxData = getAuxData(fromPosition,success); 523 524 if ( fromPosition < toPosition ) { 525 for ( le_int32 i = fromPosition ; i < toPosition ; i++ ) { 526 setGlyphID(i,getGlyphID(i+1,success),success); 527 setCharIndex(i,getCharIndex(i+1,success),success); 528 setAuxData(i,getAuxData(i+1,success),success); 529 } 530 } else { 531 for ( le_int32 i = toPosition ; i > fromPosition ; i-- ) { 532 setGlyphID(i,getGlyphID(i-1,success),success); 533 setCharIndex(i,getCharIndex(i-1,success),success); 534 setAuxData(i,getAuxData(i-1,success),success); 535 536 } 537 } 538 539 setGlyphID(toPosition,holdGlyph,success); 540 setCharIndex(toPosition,holdCharIndex,success); 541 setAuxData(toPosition,holdAuxData | marker,success); 542 543 } 544 545 // Glue code for existing stable API 546 LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount) 547 { 548 LEErrorCode ignored = LE_NO_LAYOUT_ERROR; 549 return insertGlyphs(atIndex, insertCount, ignored); 550 } 551 552 // FIXME: add error checking? 553 LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount, LEErrorCode& success) 554 { 555 return fInsertionList->insert(atIndex, insertCount, success); 556 } 557 558 le_int32 LEGlyphStorage::applyInsertions() 559 { 560 le_int32 growAmount = fInsertionList->getGrowAmount(); 561 562 if (growAmount == 0) { 563 return fGlyphCount; 564 } 565 566 le_int32 newGlyphCount = fGlyphCount + growAmount; 567 568 LEGlyphID *newGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount); 569 if (newGlyphs == NULL) { 570 // Could not grow the glyph array 571 return fGlyphCount; 572 } 573 fGlyphs = newGlyphs; 574 575 le_int32 *newCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount); 576 if (newCharIndices == NULL) { 577 // Could not grow the glyph array 578 return fGlyphCount; 579 } 580 fCharIndices = newCharIndices; 581 582 if (fAuxData != NULL) { 583 le_uint32 *newAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData, newGlyphCount); 584 if (newAuxData == NULL) { 585 // could not grow the aux data array 586 return fGlyphCount; 587 } 588 fAuxData = (le_uint32 *)newAuxData; 589 } 590 591 fSrcIndex = fGlyphCount - 1; 592 fDestIndex = newGlyphCount - 1; 593 594 #if 0 595 // If the current position is at the end of the array 596 // update it to point to the end of the new array. The 597 // insertion callback will handle all other cases. 598 // FIXME: this is left over from GlyphIterator, but there's no easy 599 // way to implement this here... it seems that GlyphIterator doesn't 600 // really need it 'cause the insertions don't get applied until after a 601 // complete pass over the glyphs, after which the iterator gets reset anyhow... 602 // probably better to just document that for LEGlyphStorage and GlyphIterator... 603 if (position == glyphCount) { 604 position = newGlyphCount; 605 } 606 #endif 607 608 fInsertionList->applyInsertions(this); 609 610 fInsertionList->reset(); 611 612 return fGlyphCount = newGlyphCount; 613 } 614 615 le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]) 616 { 617 #if 0 618 // if the current position is within the block we're shifting 619 // it needs to be updated to the current glyph's 620 // new location. 621 // FIXME: this is left over from GlyphIterator, but there's no easy 622 // way to implement this here... it seems that GlyphIterator doesn't 623 // really need it 'cause the insertions don't get applied until after a 624 // complete pass over the glyphs, after which the iterator gets reset anyhow... 625 // probably better to just document that for LEGlyphStorage and GlyphIterator... 626 if (position >= atPosition && position <= fSrcIndex) { 627 position += fDestIndex - fSrcIndex; 628 } 629 #endif 630 631 if (fAuxData != NULL) { 632 le_int32 src = fSrcIndex, dest = fDestIndex; 633 634 while (src > atPosition) { 635 fAuxData[dest--] = fAuxData[src--]; 636 } 637 638 for (le_int32 i = count - 1; i >= 0; i -= 1) { 639 fAuxData[dest--] = fAuxData[atPosition]; 640 } 641 } 642 643 while (fSrcIndex > atPosition) { 644 fGlyphs[fDestIndex] = fGlyphs[fSrcIndex]; 645 fCharIndices[fDestIndex] = fCharIndices[fSrcIndex]; 646 647 fDestIndex -= 1; 648 fSrcIndex -= 1; 649 } 650 651 for (le_int32 i = count - 1; i >= 0; i -= 1) { 652 fGlyphs[fDestIndex] = newGlyphs[i]; 653 fCharIndices[fDestIndex] = fCharIndices[atPosition]; 654 655 fDestIndex -= 1; 656 } 657 658 // the source glyph we're pointing at 659 // just got replaced by the insertion 660 fSrcIndex -= 1; 661 662 return FALSE; 663 } 664 665 U_NAMESPACE_END 666 667