2 **********************************************************************
3 * Copyright (C) 1998-2006, 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
);
115 // FIXME: do we want to initialize the positions to [0, 0]?
116 le_int32
LEGlyphStorage::allocatePositions(LEErrorCode
&success
)
118 if (LE_FAILURE(success
)) {
122 if (fPositions
!= NULL
) {
123 success
= LE_INTERNAL_ERROR
;
127 fPositions
= LE_NEW_ARRAY(float, 2 * (fGlyphCount
+ 1));
129 if (fPositions
== NULL
) {
130 success
= LE_MEMORY_ALLOCATION_ERROR
;
137 // FIXME: do we want to initialize the aux data to NULL?
138 le_int32
LEGlyphStorage::allocateAuxData(LEErrorCode
&success
)
140 if (LE_FAILURE(success
)) {
144 if (fAuxData
!= NULL
) {
145 success
= LE_INTERNAL_ERROR
;
149 fAuxData
= LE_NEW_ARRAY(le_uint32
, fGlyphCount
);
151 if (fAuxData
== NULL
) {
152 success
= LE_MEMORY_ALLOCATION_ERROR
;
159 void LEGlyphStorage::getCharIndices(le_int32 charIndices
[], le_int32 indexBase
, LEErrorCode
&success
) const
163 if (LE_FAILURE(success
)) {
167 if (charIndices
== NULL
) {
168 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
172 if (fCharIndices
== NULL
) {
173 success
= LE_NO_LAYOUT_ERROR
;
177 for (i
= 0; i
< fGlyphCount
; i
+= 1) {
178 charIndices
[i
] = fCharIndices
[i
] + indexBase
;
182 void LEGlyphStorage::getCharIndices(le_int32 charIndices
[], LEErrorCode
&success
) const
184 if (LE_FAILURE(success
)) {
188 if (charIndices
== NULL
) {
189 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
193 if (fCharIndices
== NULL
) {
194 success
= LE_NO_LAYOUT_ERROR
;
198 LE_ARRAY_COPY(charIndices
, fCharIndices
, fGlyphCount
);
201 // Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
202 void LEGlyphStorage::getGlyphs(le_uint32 glyphs
[], le_uint32 extraBits
, LEErrorCode
&success
) const
206 if (LE_FAILURE(success
)) {
210 if (glyphs
== NULL
) {
211 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
215 if (fGlyphs
== NULL
) {
216 success
= LE_NO_LAYOUT_ERROR
;
220 for (i
= 0; i
< fGlyphCount
; i
+= 1) {
221 glyphs
[i
] = fGlyphs
[i
] | extraBits
;
225 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs
[], LEErrorCode
&success
) const
227 if (LE_FAILURE(success
)) {
231 if (glyphs
== NULL
) {
232 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
236 if (fGlyphs
== NULL
) {
237 success
= LE_NO_LAYOUT_ERROR
;
241 LE_ARRAY_COPY(glyphs
, fGlyphs
, fGlyphCount
);
244 LEGlyphID
LEGlyphStorage::getGlyphID(le_int32 glyphIndex
, LEErrorCode
&success
) const
246 if (LE_FAILURE(success
)) {
250 if (fGlyphs
== NULL
) {
251 success
= LE_NO_LAYOUT_ERROR
;
255 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
256 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
260 return fGlyphs
[glyphIndex
];
263 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex
, LEGlyphID glyphID
, LEErrorCode
&success
)
265 if (LE_FAILURE(success
)) {
269 if (fGlyphs
== NULL
) {
270 success
= LE_NO_LAYOUT_ERROR
;
274 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
275 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
279 fGlyphs
[glyphIndex
] = glyphID
;
282 le_int32
LEGlyphStorage::getCharIndex(le_int32 glyphIndex
, LEErrorCode
&success
) const
284 if (LE_FAILURE(success
)) {
288 if (fCharIndices
== NULL
) {
289 success
= LE_NO_LAYOUT_ERROR
;
293 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
294 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
298 return fCharIndices
[glyphIndex
];
301 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex
, le_int32 charIndex
, LEErrorCode
&success
)
303 if (LE_FAILURE(success
)) {
307 if (fCharIndices
== NULL
) {
308 success
= LE_NO_LAYOUT_ERROR
;
312 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
313 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
317 fCharIndices
[glyphIndex
] = charIndex
;
320 void LEGlyphStorage::getAuxData(le_uint32 auxData
[], LEErrorCode
&success
) const
322 if (LE_FAILURE(success
)) {
326 if (auxData
== NULL
) {
327 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
331 if (fAuxData
== NULL
) {
332 success
= LE_NO_LAYOUT_ERROR
;
336 LE_ARRAY_COPY(auxData
, fAuxData
, fGlyphCount
);
339 le_uint32
LEGlyphStorage::getAuxData(le_int32 glyphIndex
, LEErrorCode
&success
) const
341 if (LE_FAILURE(success
)) {
345 if (fAuxData
== NULL
) {
346 success
= LE_NO_LAYOUT_ERROR
;
350 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
351 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
355 return fAuxData
[glyphIndex
];
358 void LEGlyphStorage::setAuxData(le_int32 glyphIndex
, le_uint32 auxData
, LEErrorCode
&success
)
360 if (LE_FAILURE(success
)) {
364 if (fAuxData
== NULL
) {
365 success
= LE_NO_LAYOUT_ERROR
;
369 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
370 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
374 fAuxData
[glyphIndex
] = auxData
;
377 void LEGlyphStorage::getGlyphPositions(float positions
[], LEErrorCode
&success
) const
379 if (LE_FAILURE(success
)) {
383 if (positions
== NULL
) {
384 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
388 if (fPositions
== NULL
) {
389 success
= LE_NO_LAYOUT_ERROR
;
393 LE_ARRAY_COPY(positions
, fPositions
, fGlyphCount
* 2 + 2);
396 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex
, float &x
, float &y
, LEErrorCode
&success
) const
398 if (LE_FAILURE(success
)) {
402 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
403 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
407 if (fPositions
== NULL
) {
408 success
= LE_NO_LAYOUT_ERROR
;
412 x
= fPositions
[glyphIndex
* 2];
413 y
= fPositions
[glyphIndex
* 2 + 1];
416 void LEGlyphStorage::setPosition(le_int32 glyphIndex
, float x
, float y
, LEErrorCode
&success
)
418 if (LE_FAILURE(success
)) {
422 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
423 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
427 fPositions
[glyphIndex
* 2] = x
;
428 fPositions
[glyphIndex
* 2 + 1] = y
;
431 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex
, float xAdjust
, float yAdjust
, LEErrorCode
&success
)
433 if (LE_FAILURE(success
)) {
437 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
438 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
442 fPositions
[glyphIndex
* 2] += xAdjust
;
443 fPositions
[glyphIndex
* 2 + 1] += yAdjust
;
446 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage
&from
)
448 if (fGlyphs
!= NULL
) {
449 LE_DELETE_ARRAY(fGlyphs
);
452 fGlyphs
= from
.fGlyphs
;
455 if (fInsertionList
!= NULL
) {
456 delete fInsertionList
;
459 fInsertionList
= from
.fInsertionList
;
460 from
.fInsertionList
= NULL
;
463 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage
&from
)
465 if (fCharIndices
!= NULL
) {
466 LE_DELETE_ARRAY(fCharIndices
);
469 fCharIndices
= from
.fCharIndices
;
470 from
.fCharIndices
= NULL
;
473 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage
&from
)
475 if (fPositions
!= NULL
) {
476 LE_DELETE_ARRAY(fPositions
);
479 fPositions
= from
.fPositions
;
480 from
.fPositions
= NULL
;
483 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage
&from
)
485 if (fAuxData
!= NULL
) {
486 LE_DELETE_ARRAY(fAuxData
);
489 fAuxData
= from
.fAuxData
;
490 from
.fAuxData
= NULL
;
493 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage
&from
)
495 fGlyphCount
= from
.fGlyphCount
;
498 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount
)
500 fGlyphCount
= newGlyphCount
;
503 // FIXME: add error checking?
504 LEGlyphID
*LEGlyphStorage::insertGlyphs(le_int32 atIndex
, le_int32 insertCount
)
506 return fInsertionList
->insert(atIndex
, insertCount
);
509 le_int32
LEGlyphStorage::applyInsertions()
511 le_int32 growAmount
= fInsertionList
->getGrowAmount();
513 if (growAmount
== 0) {
517 le_int32 newGlyphCount
= fGlyphCount
+ growAmount
;
519 fGlyphs
= (LEGlyphID
*) LE_GROW_ARRAY(fGlyphs
, newGlyphCount
);
520 fCharIndices
= (le_int32
*) LE_GROW_ARRAY(fCharIndices
, newGlyphCount
);
522 if (fAuxData
!= NULL
) {
523 fAuxData
= (le_uint32
*) LE_GROW_ARRAY(fAuxData
, newGlyphCount
);
526 fSrcIndex
= fGlyphCount
- 1;
527 fDestIndex
= newGlyphCount
- 1;
530 // If the current position is at the end of the array
531 // update it to point to the end of the new array. The
532 // insertion callback will handle all other cases.
533 // FIXME: this is left over from GlyphIterator, but there's no easy
534 // way to implement this here... it seems that GlyphIterator doesn't
535 // really need it 'cause the insertions don't get applied until after a
536 // complete pass over the glyphs, after which the iterator gets reset anyhow...
537 // probably better to just document that for LEGlyphStorage and GlyphIterator...
538 if (position
== glyphCount
) {
539 position
= newGlyphCount
;
543 fInsertionList
->applyInsertions(this);
545 fInsertionList
->reset();
547 return fGlyphCount
= newGlyphCount
;
550 le_bool
LEGlyphStorage::applyInsertion(le_int32 atPosition
, le_int32 count
, LEGlyphID newGlyphs
[])
553 // if the current position is within the block we're shifting
554 // it needs to be updated to the current glyph's
556 // FIXME: this is left over from GlyphIterator, but there's no easy
557 // way to implement this here... it seems that GlyphIterator doesn't
558 // really need it 'cause the insertions don't get applied until after a
559 // complete pass over the glyphs, after which the iterator gets reset anyhow...
560 // probably better to just document that for LEGlyphStorage and GlyphIterator...
561 if (position
>= atPosition
&& position
<= fSrcIndex
) {
562 position
+= fDestIndex
- fSrcIndex
;
566 if (fAuxData
!= NULL
) {
567 le_int32 src
= fSrcIndex
, dest
= fDestIndex
;
569 while (src
> atPosition
) {
570 fAuxData
[dest
--] = fAuxData
[src
--];
573 for (le_int32 i
= count
- 1; i
>= 0; i
-= 1) {
574 fAuxData
[dest
--] = fAuxData
[atPosition
];
578 while (fSrcIndex
> atPosition
) {
579 fGlyphs
[fDestIndex
] = fGlyphs
[fSrcIndex
];
580 fCharIndices
[fDestIndex
] = fCharIndices
[fSrcIndex
];
586 for (le_int32 i
= count
- 1; i
>= 0; i
-= 1) {
587 fGlyphs
[fDestIndex
] = newGlyphs
[i
];
588 fCharIndices
[fDestIndex
] = fCharIndices
[atPosition
];
593 // the source glyph we're pointing at
594 // just got replaced by the insertion