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