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 // FIXME: check this for failure?
106 fInsertionList
= new LEInsertionList(rightToLeft
);
110 // FIXME: do we want to initialize the positions to [0, 0]?
111 le_int32
LEGlyphStorage::allocatePositions(LEErrorCode
&success
)
113 if (LE_FAILURE(success
)) {
117 fPositions
= LE_NEW_ARRAY(float, 2 * (fGlyphCount
+ 1));
119 if (fPositions
== NULL
) {
120 success
= LE_MEMORY_ALLOCATION_ERROR
;
127 // FIXME: do we want to initialize the aux data to NULL?
128 le_int32
LEGlyphStorage::allocateAuxData(LEErrorCode
&success
)
130 if (LE_FAILURE(success
)) {
134 fAuxData
= LE_NEW_ARRAY(void *, fGlyphCount
);
136 if (fAuxData
== NULL
) {
137 success
= LE_MEMORY_ALLOCATION_ERROR
;
144 void LEGlyphStorage::getCharIndices(le_int32 charIndices
[], le_int32 indexBase
, LEErrorCode
&success
) const
148 if (LE_FAILURE(success
)) {
152 if (charIndices
== NULL
) {
153 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
157 if (fCharIndices
== NULL
) {
158 success
= LE_NO_LAYOUT_ERROR
;
162 for (i
= 0; i
< fGlyphCount
; i
+= 1) {
163 charIndices
[i
] = fCharIndices
[i
] + indexBase
;
167 void LEGlyphStorage::getCharIndices(le_int32 charIndices
[], LEErrorCode
&success
) const
169 if (LE_FAILURE(success
)) {
173 if (charIndices
== NULL
) {
174 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
178 if (fCharIndices
== NULL
) {
179 success
= LE_NO_LAYOUT_ERROR
;
183 LE_ARRAY_COPY(charIndices
, fCharIndices
, fGlyphCount
);
186 // Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
187 void LEGlyphStorage::getGlyphs(le_uint32 glyphs
[], le_uint32 extraBits
, LEErrorCode
&success
) const
191 if (LE_FAILURE(success
)) {
195 if (glyphs
== NULL
) {
196 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
200 if (fGlyphs
== NULL
) {
201 success
= LE_NO_LAYOUT_ERROR
;
205 for (i
= 0; i
< fGlyphCount
; i
+= 1) {
206 glyphs
[i
] = fGlyphs
[i
] | extraBits
;
210 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs
[], LEErrorCode
&success
) const
212 if (LE_FAILURE(success
)) {
216 if (glyphs
== NULL
) {
217 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
221 if (fGlyphs
== NULL
) {
222 success
= LE_NO_LAYOUT_ERROR
;
226 LE_ARRAY_COPY(glyphs
, fGlyphs
, fGlyphCount
);
229 LEGlyphID
LEGlyphStorage::getGlyphID(le_int32 glyphIndex
, LEErrorCode
&success
) const
231 if (LE_FAILURE(success
)) {
235 if (fGlyphs
== NULL
) {
236 success
= LE_NO_LAYOUT_ERROR
;
240 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
241 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
245 return fGlyphs
[glyphIndex
];
248 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex
, LEGlyphID glyphID
, LEErrorCode
&success
)
250 if (LE_FAILURE(success
)) {
254 if (fGlyphs
== NULL
) {
255 success
= LE_NO_LAYOUT_ERROR
;
259 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
260 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
264 fGlyphs
[glyphIndex
] = glyphID
;
267 le_int32
LEGlyphStorage::getCharIndex(le_int32 glyphIndex
, LEErrorCode
&success
) const
269 if (LE_FAILURE(success
)) {
273 if (fCharIndices
== NULL
) {
274 success
= LE_NO_LAYOUT_ERROR
;
278 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
279 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
283 return fCharIndices
[glyphIndex
];
286 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex
, le_int32 charIndex
, LEErrorCode
&success
)
288 if (LE_FAILURE(success
)) {
292 if (fCharIndices
== NULL
) {
293 success
= LE_NO_LAYOUT_ERROR
;
297 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
298 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
302 fCharIndices
[glyphIndex
] = charIndex
;
305 void LEGlyphStorage::getAuxData(void *auxData
[], LEErrorCode
&success
) const
307 if (LE_FAILURE(success
)) {
311 if (auxData
== NULL
) {
312 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
316 if (fAuxData
== NULL
) {
317 success
= LE_NO_LAYOUT_ERROR
;
321 LE_ARRAY_COPY(auxData
, fAuxData
, fGlyphCount
);
324 void *LEGlyphStorage::getAuxData(le_int32 glyphIndex
, LEErrorCode
&success
) const
326 if (LE_FAILURE(success
)) {
330 if (fAuxData
== NULL
) {
331 success
= LE_NO_LAYOUT_ERROR
;
335 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
336 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
340 return fAuxData
[glyphIndex
];
343 void LEGlyphStorage::setAuxData(le_int32 glyphIndex
, void *auxData
, LEErrorCode
&success
)
345 if (LE_FAILURE(success
)) {
349 if (fAuxData
== NULL
) {
350 success
= LE_NO_LAYOUT_ERROR
;
354 if (glyphIndex
< 0 || glyphIndex
>= fGlyphCount
) {
355 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
359 fAuxData
[glyphIndex
] = auxData
;
362 void LEGlyphStorage::getGlyphPositions(float positions
[], LEErrorCode
&success
) const
364 if (LE_FAILURE(success
)) {
368 if (positions
== NULL
) {
369 success
= LE_ILLEGAL_ARGUMENT_ERROR
;
373 if (fPositions
== NULL
) {
374 success
= LE_NO_LAYOUT_ERROR
;
378 LE_ARRAY_COPY(positions
, fPositions
, fGlyphCount
* 2 + 2);
381 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex
, float &x
, float &y
, LEErrorCode
&success
) const
383 if (LE_FAILURE(success
)) {
387 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
388 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
392 if (fPositions
== NULL
) {
393 success
= LE_NO_LAYOUT_ERROR
;
397 x
= fPositions
[glyphIndex
* 2];
398 y
= fPositions
[glyphIndex
* 2 + 1];
401 void LEGlyphStorage::setPosition(le_int32 glyphIndex
, float x
, float y
, LEErrorCode
&success
)
403 if (LE_FAILURE(success
)) {
407 if (glyphIndex
< 0 || glyphIndex
> fGlyphCount
) {
408 success
= LE_INDEX_OUT_OF_BOUNDS_ERROR
;
412 fPositions
[glyphIndex
* 2] = x
;
413 fPositions
[glyphIndex
* 2 + 1] = y
;
416 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex
, float xAdjust
, float yAdjust
, 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] += xAdjust
;
428 fPositions
[glyphIndex
* 2 + 1] += yAdjust
;
431 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage
&from
)
433 if (fGlyphs
!= NULL
) {
434 LE_DELETE_ARRAY(fGlyphs
);
437 fGlyphs
= from
.fGlyphs
;
440 if (fInsertionList
!= NULL
) {
441 delete fInsertionList
;
444 fInsertionList
= from
.fInsertionList
;
445 from
.fInsertionList
= NULL
;
448 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage
&from
)
450 if (fCharIndices
!= NULL
) {
451 LE_DELETE_ARRAY(fCharIndices
);
454 fCharIndices
= from
.fCharIndices
;
455 from
.fCharIndices
= NULL
;
458 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage
&from
)
460 if (fPositions
!= NULL
) {
461 LE_DELETE_ARRAY(fPositions
);
464 fPositions
= from
.fPositions
;
465 from
.fPositions
= NULL
;
468 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage
&from
)
470 if (fAuxData
!= NULL
) {
471 LE_DELETE_ARRAY(fAuxData
);
474 fAuxData
= from
.fAuxData
;
475 from
.fAuxData
= NULL
;
478 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage
&from
)
480 fGlyphCount
= from
.fGlyphCount
;
483 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount
)
485 fGlyphCount
= newGlyphCount
;
488 // FIXME: add error checking?
489 LEGlyphID
*LEGlyphStorage::insertGlyphs(le_int32 atIndex
, le_int32 insertCount
)
491 return fInsertionList
->insert(atIndex
, insertCount
);
494 le_int32
LEGlyphStorage::applyInsertions()
496 le_int32 growAmount
= fInsertionList
->getGrowAmount();
498 if (growAmount
== 0) {
502 le_int32 newGlyphCount
= fGlyphCount
+ growAmount
;
504 fGlyphs
= (LEGlyphID
*) LE_GROW_ARRAY(fGlyphs
, newGlyphCount
);
505 fCharIndices
= (le_int32
*) LE_GROW_ARRAY(fCharIndices
, newGlyphCount
);
507 if (fAuxData
!= NULL
) {
508 fAuxData
= (void **) LE_GROW_ARRAY(fAuxData
, newGlyphCount
);
511 fSrcIndex
= fGlyphCount
- 1;
512 fDestIndex
= newGlyphCount
- 1;
515 // If the current position is at the end of the array
516 // update it to point to the end of the new array. The
517 // insertion callback will handle all other cases.
518 // FIXME: this is left over from GlyphIterator, but there's no easy
519 // way to implement this here... it seems that GlyphIterator doesn't
520 // really need it 'cause the insertions don't get applied until after a
521 // complete pass over the glyphs, after which the iterator gets reset anyhow...
522 // probably better to just document that for LEGlyphStorage and GlyphIterator...
523 if (position
== glyphCount
) {
524 position
= newGlyphCount
;
528 fInsertionList
->applyInsertions(this);
530 fInsertionList
->reset();
532 return fGlyphCount
= newGlyphCount
;
535 le_bool
LEGlyphStorage::applyInsertion(le_int32 atPosition
, le_int32 count
, LEGlyphID newGlyphs
[])
538 // if the current position is within the block we're shifting
539 // it needs to be updated to the current glyph's
541 // FIXME: this is left over from GlyphIterator, but there's no easy
542 // way to implement this here... it seems that GlyphIterator doesn't
543 // really need it 'cause the insertions don't get applied until after a
544 // complete pass over the glyphs, after which the iterator gets reset anyhow...
545 // probably better to just document that for LEGlyphStorage and GlyphIterator...
546 if (position
>= atPosition
&& position
<= fSrcIndex
) {
547 position
+= fDestIndex
- fSrcIndex
;
551 if (fAuxData
!= NULL
) {
552 le_int32 src
= fSrcIndex
, dest
= fDestIndex
;
554 while (src
> atPosition
) {
555 fAuxData
[dest
--] = fAuxData
[src
--];
558 for (le_int32 i
= count
- 1; i
>= 0; i
-= 1) {
559 fAuxData
[dest
--] = fAuxData
[atPosition
];
563 while (fSrcIndex
> atPosition
) {
564 fGlyphs
[fDestIndex
] = fGlyphs
[fSrcIndex
];
565 fCharIndices
[fDestIndex
] = fCharIndices
[fSrcIndex
];
571 for (le_int32 i
= count
- 1; i
>= 0; i
-= 1) {
572 fGlyphs
[fDestIndex
] = newGlyphs
[i
];
573 fCharIndices
[fDestIndex
] = fCharIndices
[atPosition
];
578 // the source glyph we're pointing at
579 // just got replaced by the insertion