2 **********************************************************************
3 * Copyright (C) 1998-2009, 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 LEInsertionCallback::~LEInsertionCallback()
21 LEGlyphStorage::LEGlyphStorage()
22 : fGlyphCount(0), fGlyphs(NULL
), fCharIndices(NULL
), fPositions(NULL
),
23 fAuxData(NULL
), fInsertionList(NULL
), fSrcIndex(0), fDestIndex(0)
25 // nothing else to do!
28 LEGlyphStorage::~LEGlyphStorage()
33 void LEGlyphStorage::reset()
37 if (fPositions
!= NULL
) {
38 LE_DELETE_ARRAY(fPositions
);
42 if (fAuxData
!= NULL
) {
43 LE_DELETE_ARRAY(fAuxData
);
47 if (fInsertionList
!= NULL
) {
48 delete fInsertionList
;
49 fInsertionList
= NULL
;
52 if (fCharIndices
!= NULL
) {
53 LE_DELETE_ARRAY(fCharIndices
);
57 if (fGlyphs
!= NULL
) {
58 LE_DELETE_ARRAY(fGlyphs
);
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
)
67 if (LE_FAILURE(success
)) {
71 if (initialGlyphCount
<= 0) {
72 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
76 if (fGlyphs
== NULL
) {
77 fGlyphCount
= initialGlyphCount
;
78 fGlyphs
= LE_NEW_ARRAY(LEGlyphID
, fGlyphCount
);
80 if (fGlyphs
== NULL
) {
81 success
= LE_MEMORY_ALLOCATION_ERROR
;
86 if (fCharIndices
== NULL
) {
87 fCharIndices
= LE_NEW_ARRAY(le_int32
, fGlyphCount
);
89 if (fCharIndices
== NULL
) {
90 LE_DELETE_ARRAY(fGlyphs
);
92 success
= LE_MEMORY_ALLOCATION_ERROR
;
96 // Initialize the charIndices array
97 le_int32 i
, count
= fGlyphCount
, dir
= 1, out
= 0;
100 out
= fGlyphCount
- 1;
104 for (i
= 0; i
< count
; i
+= 1, out
+= dir
) {
105 fCharIndices
[out
] = i
;
109 if (fInsertionList
== NULL
) {
110 // FIXME: check this for failure?
111 fInsertionList
= new LEInsertionList(rightToLeft
);
112 if (fInsertionList
== NULL
) {
113 LE_DELETE_ARRAY(fCharIndices
);
116 LE_DELETE_ARRAY(fGlyphs
);
119 success
= LE_MEMORY_ALLOCATION_ERROR
;
125 // FIXME: do we want to initialize the positions to [0, 0]?
126 le_int32
LEGlyphStorage::allocatePositions(LEErrorCode
&success
)
128 if (LE_FAILURE(success
)) {
132 if (fPositions
!= NULL
) {
133 success
= LE_INTERNAL_ERROR
;
137 fPositions
= LE_NEW_ARRAY(float, 2 * (fGlyphCount
+ 1));
139 if (fPositions
== NULL
) {
140 success
= LE_MEMORY_ALLOCATION_ERROR
;
147 // FIXME: do we want to initialize the aux data to NULL?
148 le_int32
LEGlyphStorage::allocateAuxData(LEErrorCode
&success
)
150 if (LE_FAILURE(success
)) {
154 if (fAuxData
!= NULL
) {
155 success
= LE_INTERNAL_ERROR
;
159 fAuxData
= LE_NEW_ARRAY(le_uint32
, fGlyphCount
);
161 if (fAuxData
== NULL
) {
162 success
= LE_MEMORY_ALLOCATION_ERROR
;
169 void LEGlyphStorage::getCharIndices(le_int32 charIndices
[], le_int32 indexBase
, LEErrorCode
&success
) const
173 if (LE_FAILURE(success
)) {
177 if (charIndices
== NULL
) {
178 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
182 if (fCharIndices
== NULL
) {
183 success
= LE_NO_LAYOUT_ERROR
;
187 for (i
= 0; i
< fGlyphCount
; i
+= 1) {
188 charIndices
[i
] = fCharIndices
[i
] + indexBase
;
192 void LEGlyphStorage::getCharIndices(le_int32 charIndices
[], LEErrorCode
&success
) const
194 if (LE_FAILURE(success
)) {
198 if (charIndices
== NULL
) {
199 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
203 if (fCharIndices
== NULL
) {
204 success
= LE_NO_LAYOUT_ERROR
;
208 LE_ARRAY_COPY(charIndices
, fCharIndices
, fGlyphCount
);
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
216 if (LE_FAILURE(success
)) {
220 if (glyphs
== NULL
) {
221 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
225 if (fGlyphs
== NULL
) {
226 success
= LE_NO_LAYOUT_ERROR
;
230 for (i
= 0; i
< fGlyphCount
; i
+= 1) {
231 glyphs
[i
] = fGlyphs
[i
] | extraBits
;
235 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs
[], LEErrorCode
&success
) const
237 if (LE_FAILURE(success
)) {
241 if (glyphs
== NULL
) {
242 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
246 if (fGlyphs
== NULL
) {
247 success
= LE_NO_LAYOUT_ERROR
;
251 LE_ARRAY_COPY(glyphs
, fGlyphs
, fGlyphCount
);
254 LEGlyphID
LEGlyphStorage::getGlyphID(le_int32 glyphIndex
, LEErrorCode
&success
) const
256 if (LE_FAILURE(success
)) {
260 if (fGlyphs
== NULL
) {
261 success
= LE_NO_LAYOUT_ERROR
;
265 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
266 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
270 return fGlyphs
[glyphIndex
];
273 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex
, LEGlyphID glyphID
, LEErrorCode
&success
)
275 if (LE_FAILURE(success
)) {
279 if (fGlyphs
== NULL
) {
280 success
= LE_NO_LAYOUT_ERROR
;
284 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
285 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
289 fGlyphs
[glyphIndex
] = glyphID
;
292 le_int32
LEGlyphStorage::getCharIndex(le_int32 glyphIndex
, LEErrorCode
&success
) const
294 if (LE_FAILURE(success
)) {
298 if (fCharIndices
== NULL
) {
299 success
= LE_NO_LAYOUT_ERROR
;
303 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
304 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
308 return fCharIndices
[glyphIndex
];
311 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex
, le_int32 charIndex
, LEErrorCode
&success
)
313 if (LE_FAILURE(success
)) {
317 if (fCharIndices
== NULL
) {
318 success
= LE_NO_LAYOUT_ERROR
;
322 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
323 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
327 fCharIndices
[glyphIndex
] = charIndex
;
330 void LEGlyphStorage::getAuxData(le_uint32 auxData
[], LEErrorCode
&success
) const
332 if (LE_FAILURE(success
)) {
336 if (auxData
== NULL
) {
337 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
341 if (fAuxData
== NULL
) {
342 success
= LE_NO_LAYOUT_ERROR
;
346 LE_ARRAY_COPY(auxData
, fAuxData
, fGlyphCount
);
349 le_uint32
LEGlyphStorage::getAuxData(le_int32 glyphIndex
, LEErrorCode
&success
) const
351 if (LE_FAILURE(success
)) {
355 if (fAuxData
== NULL
) {
356 success
= LE_NO_LAYOUT_ERROR
;
360 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
361 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
365 return fAuxData
[glyphIndex
];
368 void LEGlyphStorage::setAuxData(le_int32 glyphIndex
, le_uint32 auxData
, LEErrorCode
&success
)
370 if (LE_FAILURE(success
)) {
374 if (fAuxData
== NULL
) {
375 success
= LE_NO_LAYOUT_ERROR
;
379 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
380 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
384 fAuxData
[glyphIndex
] = auxData
;
387 void LEGlyphStorage::getGlyphPositions(float positions
[], LEErrorCode
&success
) const
389 if (LE_FAILURE(success
)) {
393 if (positions
== NULL
) {
394 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
398 if (fPositions
== NULL
) {
399 success
= LE_NO_LAYOUT_ERROR
;
403 LE_ARRAY_COPY(positions
, fPositions
, fGlyphCount
* 2 + 2);
406 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex
, float &x
, float &y
, LEErrorCode
&success
) const
408 if (LE_FAILURE(success
)) {
412 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
413 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
417 if (fPositions
== NULL
) {
418 success
= LE_NO_LAYOUT_ERROR
;
422 x
= fPositions
[glyphIndex
* 2];
423 y
= fPositions
[glyphIndex
* 2 + 1];
426 void LEGlyphStorage::setPosition(le_int32 glyphIndex
, float x
, float y
, LEErrorCode
&success
)
428 if (LE_FAILURE(success
)) {
432 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
433 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
437 fPositions
[glyphIndex
* 2] = x
;
438 fPositions
[glyphIndex
* 2 + 1] = y
;
441 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex
, float xAdjust
, float yAdjust
, LEErrorCode
&success
)
443 if (LE_FAILURE(success
)) {
447 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
448 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
452 fPositions
[glyphIndex
* 2] += xAdjust
;
453 fPositions
[glyphIndex
* 2 + 1] += yAdjust
;
456 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage
&from
)
458 if (fGlyphs
!= NULL
) {
459 LE_DELETE_ARRAY(fGlyphs
);
462 fGlyphs
= from
.fGlyphs
;
465 if (fInsertionList
!= NULL
) {
466 delete fInsertionList
;
469 fInsertionList
= from
.fInsertionList
;
470 from
.fInsertionList
= NULL
;
473 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage
&from
)
475 if (fCharIndices
!= NULL
) {
476 LE_DELETE_ARRAY(fCharIndices
);
479 fCharIndices
= from
.fCharIndices
;
480 from
.fCharIndices
= NULL
;
483 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage
&from
)
485 if (fPositions
!= NULL
) {
486 LE_DELETE_ARRAY(fPositions
);
489 fPositions
= from
.fPositions
;
490 from
.fPositions
= NULL
;
493 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage
&from
)
495 if (fAuxData
!= NULL
) {
496 LE_DELETE_ARRAY(fAuxData
);
499 fAuxData
= from
.fAuxData
;
500 from
.fAuxData
= NULL
;
503 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage
&from
)
505 fGlyphCount
= from
.fGlyphCount
;
508 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount
)
510 fGlyphCount
= newGlyphCount
;
513 // Move a glyph to a different position in the LEGlyphStorage ( used for Indic v2 processing )
515 void LEGlyphStorage::moveGlyph(le_int32 fromPosition
, le_int32 toPosition
, le_uint32 marker
)
518 LEErrorCode success
= LE_NO_ERROR
;
520 LEGlyphID holdGlyph
= getGlyphID(fromPosition
,success
);
521 le_int32 holdCharIndex
= getCharIndex(fromPosition
,success
);
522 le_uint32 holdAuxData
= getAuxData(fromPosition
,success
);
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
);
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
);
539 setGlyphID(toPosition
,holdGlyph
,success
);
540 setCharIndex(toPosition
,holdCharIndex
,success
);
541 setAuxData(toPosition
,holdAuxData
| marker
,success
);
545 // Glue code for existing stable API
546 LEGlyphID
*LEGlyphStorage::insertGlyphs(le_int32 atIndex
, le_int32 insertCount
)
548 LEErrorCode ignored
= LE_NO_LAYOUT_ERROR
;
549 return insertGlyphs(atIndex
, insertCount
, ignored
);
552 // FIXME: add error checking?
553 LEGlyphID
*LEGlyphStorage::insertGlyphs(le_int32 atIndex
, le_int32 insertCount
, LEErrorCode
& success
)
555 return fInsertionList
->insert(atIndex
, insertCount
, success
);
558 le_int32
LEGlyphStorage::applyInsertions()
560 le_int32 growAmount
= fInsertionList
->getGrowAmount();
562 if (growAmount
== 0) {
566 le_int32 newGlyphCount
= fGlyphCount
+ growAmount
;
568 LEGlyphID
*newGlyphs
= (LEGlyphID
*) LE_GROW_ARRAY(fGlyphs
, newGlyphCount
);
569 if (newGlyphs
== NULL
) {
570 // Could not grow the glyph array
575 le_int32
*newCharIndices
= (le_int32
*) LE_GROW_ARRAY(fCharIndices
, newGlyphCount
);
576 if (newCharIndices
== NULL
) {
577 // Could not grow the glyph array
580 fCharIndices
= newCharIndices
;
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
588 fAuxData
= (le_uint32
*)newAuxData
;
591 fSrcIndex
= fGlyphCount
- 1;
592 fDestIndex
= newGlyphCount
- 1;
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
;
608 fInsertionList
->applyInsertions(this);
610 fInsertionList
->reset();
612 return fGlyphCount
= newGlyphCount
;
615 le_bool
LEGlyphStorage::applyInsertion(le_int32 atPosition
, le_int32 count
, LEGlyphID newGlyphs
[])
618 // if the current position is within the block we're shifting
619 // it needs to be updated to the current glyph's
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
;
631 if (fAuxData
!= NULL
) {
632 le_int32 src
= fSrcIndex
, dest
= fDestIndex
;
634 while (src
> atPosition
) {
635 fAuxData
[dest
--] = fAuxData
[src
--];
638 for (le_int32 i
= count
- 1; i
>= 0; i
-= 1) {
639 fAuxData
[dest
--] = fAuxData
[atPosition
];
643 while (fSrcIndex
> atPosition
) {
644 fGlyphs
[fDestIndex
] = fGlyphs
[fSrcIndex
];
645 fCharIndices
[fDestIndex
] = fCharIndices
[fSrcIndex
];
651 for (le_int32 i
= count
- 1; i
>= 0; i
-= 1) {
652 fGlyphs
[fDestIndex
] = newGlyphs
[i
];
653 fCharIndices
[fDestIndex
] = fCharIndices
[atPosition
];
658 // the source glyph we're pointing at
659 // just got replaced by the insertion