First public contribution.
2 **********************************************************************
3 * Copyright (C) 1998-2004, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
9 #include "LEInsertionList.h"
10 #include "LEGlyphStorage.h"
14 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage)
16 LEGlyphStorage::LEGlyphStorage()
17 : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
18 fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0)
20 // nothing else to do!
23 LEGlyphStorage::~LEGlyphStorage()
28 void LEGlyphStorage::reset()
32 if (fPositions != NULL) {
33 LE_DELETE_ARRAY(fPositions);
37 if (fAuxData != NULL) {
38 LE_DELETE_ARRAY(fAuxData);
42 if (fInsertionList != NULL) {
43 delete fInsertionList;
44 fInsertionList = NULL;
47 if (fCharIndices != NULL) {
48 LE_DELETE_ARRAY(fCharIndices);
52 if (fGlyphs != NULL) {
53 LE_DELETE_ARRAY(fGlyphs);
58 // FIXME: This might get called more than once, for various reasons. Is
59 // testing for pre-existing glyph and charIndices arrays good enough?
60 void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success)
62 if (LE_FAILURE(success)) {
66 if (initialGlyphCount <= 0) {
67 success = LE_ILLEGAL_ARGUMENT_ERROR;
71 if (fGlyphs == NULL) {
72 fGlyphCount = initialGlyphCount;
73 fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount);
75 if (fGlyphs == NULL) {
76 success = LE_MEMORY_ALLOCATION_ERROR;
81 if (fCharIndices == NULL) {
82 fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount);
84 if (fCharIndices == NULL) {
85 LE_DELETE_ARRAY(fGlyphs);
87 success = LE_MEMORY_ALLOCATION_ERROR;
91 // Initialize the charIndices array
92 le_int32 i, count = fGlyphCount, dir = 1, out = 0;
95 out = fGlyphCount - 1;
99 for (i = 0; i < count; i += 1, out += dir) {
100 fCharIndices[out] = i;
104 if (fInsertionList == NULL) {
105 fInsertionList = new LEInsertionList(rightToLeft);
106 if (fInsertionList == NULL) {
107 LE_DELETE_ARRAY(fCharIndices);
109 LE_DELETE_ARRAY(fGlyphs);
111 success = LE_MEMORY_ALLOCATION_ERROR;
117 // FIXME: do we want to initialize the positions to [0, 0]?
118 le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
120 if (LE_FAILURE(success)) {
124 if (fPositions != NULL) {
125 LE_DELETE_ARRAY(fPositions);
128 fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1));
130 if (fPositions == NULL) {
131 success = LE_MEMORY_ALLOCATION_ERROR;
138 // FIXME: do we want to initialize the aux data to NULL?
139 le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
141 if (LE_FAILURE(success)) {
145 fAuxData = LE_NEW_ARRAY(void *, fGlyphCount);
147 if (fAuxData == NULL) {
148 success = LE_MEMORY_ALLOCATION_ERROR;
155 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
159 if (LE_FAILURE(success)) {
163 if (charIndices == NULL) {
164 success = LE_ILLEGAL_ARGUMENT_ERROR;
168 if (fCharIndices == NULL) {
169 success = LE_NO_LAYOUT_ERROR;
173 for (i = 0; i < fGlyphCount; i += 1) {
174 charIndices[i] = fCharIndices[i] + indexBase;
178 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
180 if (LE_FAILURE(success)) {
184 if (charIndices == NULL) {
185 success = LE_ILLEGAL_ARGUMENT_ERROR;
189 if (fCharIndices == NULL) {
190 success = LE_NO_LAYOUT_ERROR;
194 LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount);
197 // Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
198 void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
202 if (LE_FAILURE(success)) {
206 if (glyphs == NULL) {
207 success = LE_ILLEGAL_ARGUMENT_ERROR;
211 if (fGlyphs == NULL) {
212 success = LE_NO_LAYOUT_ERROR;
216 for (i = 0; i < fGlyphCount; i += 1) {
217 glyphs[i] = fGlyphs[i] | extraBits;
221 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
223 if (LE_FAILURE(success)) {
227 if (glyphs == NULL) {
228 success = LE_ILLEGAL_ARGUMENT_ERROR;
232 if (fGlyphs == NULL) {
233 success = LE_NO_LAYOUT_ERROR;
237 LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
240 LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const
242 if (LE_FAILURE(success)) {
246 if (fGlyphs == NULL) {
247 success = LE_NO_LAYOUT_ERROR;
251 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
252 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
256 return fGlyphs[glyphIndex];
259 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success)
261 if (LE_FAILURE(success)) {
265 if (fGlyphs == NULL) {
266 success = LE_NO_LAYOUT_ERROR;
270 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
271 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
275 fGlyphs[glyphIndex] = glyphID;
278 le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const
280 if (LE_FAILURE(success)) {
284 if (fCharIndices == NULL) {
285 success = LE_NO_LAYOUT_ERROR;
289 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
290 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
294 return fCharIndices[glyphIndex];
297 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success)
299 if (LE_FAILURE(success)) {
303 if (fCharIndices == NULL) {
304 success = LE_NO_LAYOUT_ERROR;
308 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
309 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
313 fCharIndices[glyphIndex] = charIndex;
316 void LEGlyphStorage::getAuxData(void *auxData[], LEErrorCode &success) const
318 if (LE_FAILURE(success)) {
322 if (auxData == NULL) {
323 success = LE_ILLEGAL_ARGUMENT_ERROR;
327 if (fAuxData == NULL) {
328 success = LE_NO_LAYOUT_ERROR;
332 LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount);
335 void *LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
337 if (LE_FAILURE(success)) {
341 if (fAuxData == NULL) {
342 success = LE_NO_LAYOUT_ERROR;
346 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
347 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
351 return fAuxData[glyphIndex];
354 void LEGlyphStorage::setAuxData(le_int32 glyphIndex, void *auxData, LEErrorCode &success)
356 if (LE_FAILURE(success)) {
360 if (fAuxData == NULL) {
361 success = LE_NO_LAYOUT_ERROR;
365 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
366 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
370 fAuxData[glyphIndex] = auxData;
373 void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const
375 if (LE_FAILURE(success)) {
379 if (positions == NULL) {
380 success = LE_ILLEGAL_ARGUMENT_ERROR;
384 if (fPositions == NULL) {
385 success = LE_NO_LAYOUT_ERROR;
389 LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2);
392 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
394 if (LE_FAILURE(success)) {
398 if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
399 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
403 if (fPositions == NULL) {
404 success = LE_NO_LAYOUT_ERROR;
408 x = fPositions[glyphIndex * 2];
409 y = fPositions[glyphIndex * 2 + 1];
412 void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success)
414 if (LE_FAILURE(success)) {
418 if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
419 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
423 fPositions[glyphIndex * 2] = x;
424 fPositions[glyphIndex * 2 + 1] = y;
427 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success)
429 if (LE_FAILURE(success)) {
433 if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
434 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
438 fPositions[glyphIndex * 2] += xAdjust;
439 fPositions[glyphIndex * 2 + 1] += yAdjust;
442 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from)
444 if (fGlyphs != NULL) {
445 LE_DELETE_ARRAY(fGlyphs);
448 fGlyphs = from.fGlyphs;
451 if (fInsertionList != NULL) {
452 delete fInsertionList;
455 fInsertionList = from.fInsertionList;
456 from.fInsertionList = NULL;
459 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from)
461 if (fCharIndices != NULL) {
462 LE_DELETE_ARRAY(fCharIndices);
465 fCharIndices = from.fCharIndices;
466 from.fCharIndices = NULL;
469 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from)
471 if (fPositions != NULL) {
472 LE_DELETE_ARRAY(fPositions);
475 fPositions = from.fPositions;
476 from.fPositions = NULL;
479 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from)
481 if (fAuxData != NULL) {
482 LE_DELETE_ARRAY(fAuxData);
485 fAuxData = from.fAuxData;
486 from.fAuxData = NULL;
489 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
491 fGlyphCount = from.fGlyphCount;
494 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
496 fGlyphCount = newGlyphCount;
499 LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount,
500 LEErrorCode& success)
502 return fInsertionList->insert(atIndex, insertCount, success);
505 le_int32 LEGlyphStorage::applyInsertions()
507 le_int32 growAmount = fInsertionList->getGrowAmount();
509 if (growAmount == 0) {
513 le_int32 newGlyphCount = fGlyphCount + growAmount;
515 LEGlyphID *newGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount);
517 // Could not grow the glyph array
522 le_int32 *newCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount);
523 if (!newCharIndices) {
524 // Could not grow the glyph array
527 fCharIndices = newCharIndices;
529 if (fAuxData != NULL) {
530 void **newAuxData = (void **) LE_GROW_ARRAY(fAuxData, newGlyphCount);
532 // could not grow the aux data array
535 fAuxData = newAuxData;
538 fSrcIndex = fGlyphCount - 1;
539 fDestIndex = newGlyphCount - 1;
542 // If the current position is at the end of the array
543 // update it to point to the end of the new array. The
544 // insertion callback will handle all other cases.
545 // FIXME: this is left over from GlyphIterator, but there's no easy
546 // way to implement this here... it seems that GlyphIterator doesn't
547 // really need it 'cause the insertions don't get applied until after a
548 // complete pass over the glyphs, after which the iterator gets reset anyhow...
549 // probably better to just document that for LEGlyphStorage and GlyphIterator...
550 if (position == glyphCount) {
551 position = newGlyphCount;
555 fInsertionList->applyInsertions(this);
557 fInsertionList->reset();
559 return fGlyphCount = newGlyphCount;
562 le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
565 // if the current position is within the block we're shifting
566 // it needs to be updated to the current glyph's
568 // FIXME: this is left over from GlyphIterator, but there's no easy
569 // way to implement this here... it seems that GlyphIterator doesn't
570 // really need it 'cause the insertions don't get applied until after a
571 // complete pass over the glyphs, after which the iterator gets reset anyhow...
572 // probably better to just document that for LEGlyphStorage and GlyphIterator...
573 if (position >= atPosition && position <= fSrcIndex) {
574 position += fDestIndex - fSrcIndex;
578 if (fAuxData != NULL) {
579 le_int32 src = fSrcIndex, dest = fDestIndex;
581 while (src > atPosition) {
582 fAuxData[dest--] = fAuxData[src--];
585 for (le_int32 i = count - 1; i >= 0; i -= 1) {
586 fAuxData[dest--] = fAuxData[atPosition];
590 while (fSrcIndex > atPosition) {
591 fGlyphs[fDestIndex] = fGlyphs[fSrcIndex];
592 fCharIndices[fDestIndex] = fCharIndices[fSrcIndex];
598 for (le_int32 i = count - 1; i >= 0; i -= 1) {
599 fGlyphs[fDestIndex] = newGlyphs[i];
600 fCharIndices[fDestIndex] = fCharIndices[atPosition];
605 // the source glyph we're pointing at
606 // just got replaced by the insertion
612 void LEGlyphStorage::forMlylRakar(LEGlyphID aGlyphID)
616 if (fGlyphs == NULL) {
620 for (i = 0; i < fGlyphCount; i++) {
621 if (fGlyphs[i] == aGlyphID) {
623 while (j>=0 && fGlyphs[j] == 0xFFFF) {
627 if (j>=0 && fGlyphs[j] != 0xFFFF && fGlyphs[j] != aGlyphID) {
628 fGlyphs[i] = fGlyphs[j];
629 fGlyphs[j] = aGlyphID;
631 le_int32 tempCharIndex = fCharIndices[j];
632 fCharIndices[j] = fCharIndices[i];
633 fCharIndices[i] = tempCharIndex;
635 void * tempAuxData = fAuxData[j];
636 fAuxData[j] = fAuxData[i];
637 fAuxData[i] = fAuxData[j];