• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  **********************************************************************
3  *   Copyright (C) 1998-2006, International Business Machines
4  *   Corporation and others.  All Rights Reserved.
5  **********************************************************************
6  */
7 
8 #include "LETypes.h"
9 #include "LEInsertionList.h"
10 #include "LEGlyphStorage.h"
11 
12 U_NAMESPACE_BEGIN
13 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage)14 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage)
15 
16 LEInsertionCallback::~LEInsertionCallback()
17 {
18 	// nothing to do...
19 }
20 
LEGlyphStorage()21 LEGlyphStorage::LEGlyphStorage()
22     : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
23       fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0)
24 {
25     // nothing else to do!
26 }
27 
~LEGlyphStorage()28 LEGlyphStorage::~LEGlyphStorage()
29 {
30     reset();
31 }
32 
reset()33 void LEGlyphStorage::reset()
34 {
35     fGlyphCount = 0;
36 
37     if (fPositions != NULL) {
38         LE_DELETE_ARRAY(fPositions);
39         fPositions = NULL;
40     }
41 
42     if (fAuxData != NULL) {
43         LE_DELETE_ARRAY(fAuxData);
44         fAuxData = NULL;
45     }
46 
47     if (fInsertionList != NULL) {
48         delete fInsertionList;
49         fInsertionList = NULL;
50     }
51 
52     if (fCharIndices != NULL) {
53         LE_DELETE_ARRAY(fCharIndices);
54         fCharIndices = NULL;
55     }
56 
57     if (fGlyphs != NULL) {
58         LE_DELETE_ARRAY(fGlyphs);
59         fGlyphs = NULL;
60     }
61 }
62 
63 // FIXME: This might get called more than once, for various reasons. Is
64 // testing for pre-existing glyph and charIndices arrays good enough?
allocateGlyphArray(le_int32 initialGlyphCount,le_bool rightToLeft,LEErrorCode & success)65 void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success)
66 {
67     if (LE_FAILURE(success)) {
68         return;
69     }
70 
71     if (initialGlyphCount <= 0) {
72         success = LE_ILLEGAL_ARGUMENT_ERROR;
73         return;
74     }
75 
76     if (fGlyphs == NULL) {
77         fGlyphCount = initialGlyphCount;
78         fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount);
79 
80         if (fGlyphs == NULL) {
81             success = LE_MEMORY_ALLOCATION_ERROR;
82             return;
83         }
84     }
85 
86     if (fCharIndices == NULL) {
87         fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount);
88 
89         if (fCharIndices == NULL) {
90             LE_DELETE_ARRAY(fGlyphs);
91             fGlyphs = NULL;
92             success = LE_MEMORY_ALLOCATION_ERROR;
93             return;
94         }
95 
96         // Initialize the charIndices array
97         le_int32 i, count = fGlyphCount, dir = 1, out = 0;
98 
99         if (rightToLeft) {
100             out = fGlyphCount - 1;
101             dir = -1;
102         }
103 
104         for (i = 0; i < count; i += 1, out += dir) {
105             fCharIndices[out] = i;
106         }
107     }
108 
109     if (fInsertionList == NULL) {
110         // FIXME: check this for failure?
111         fInsertionList = new LEInsertionList(rightToLeft);
112     }
113 }
114 
115 // FIXME: do we want to initialize the positions to [0, 0]?
allocatePositions(LEErrorCode & success)116 le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
117 {
118     if (LE_FAILURE(success)) {
119         return -1;
120     }
121 
122     if (fPositions != NULL) {
123         success = LE_INTERNAL_ERROR;
124         return -1;
125     }
126 
127     fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1));
128 
129     if (fPositions == NULL) {
130         success = LE_MEMORY_ALLOCATION_ERROR;
131         return -1;
132     }
133 
134     return fGlyphCount;
135 }
136 
137 // FIXME: do we want to initialize the aux data to NULL?
allocateAuxData(LEErrorCode & success)138 le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
139 {
140     if (LE_FAILURE(success)) {
141         return -1;
142     }
143 
144     if (fAuxData != NULL) {
145         success = LE_INTERNAL_ERROR;
146         return -1;
147     }
148 
149     fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount);
150 
151     if (fAuxData == NULL) {
152         success = LE_MEMORY_ALLOCATION_ERROR;
153         return -1;
154     }
155 
156     return fGlyphCount;
157 }
158 
getCharIndices(le_int32 charIndices[],le_int32 indexBase,LEErrorCode & success) const159 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
160 {
161     le_int32 i;
162 
163     if (LE_FAILURE(success)) {
164         return;
165     }
166 
167     if (charIndices == NULL) {
168         success = LE_ILLEGAL_ARGUMENT_ERROR;
169         return;
170     }
171 
172     if (fCharIndices == NULL) {
173         success = LE_NO_LAYOUT_ERROR;
174         return;
175     }
176 
177     for (i = 0; i < fGlyphCount; i += 1) {
178         charIndices[i] = fCharIndices[i] + indexBase;
179     }
180 }
181 
getCharIndices(le_int32 charIndices[],LEErrorCode & success) const182 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
183 {
184     if (LE_FAILURE(success)) {
185       return;
186     }
187 
188     if (charIndices == NULL) {
189       success = LE_ILLEGAL_ARGUMENT_ERROR;
190       return;
191     }
192 
193     if (fCharIndices == NULL) {
194       success = LE_NO_LAYOUT_ERROR;
195       return;
196     }
197 
198     LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount);
199 }
200 
201 // Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
getGlyphs(le_uint32 glyphs[],le_uint32 extraBits,LEErrorCode & success) const202 void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
203 {
204     le_int32 i;
205 
206     if (LE_FAILURE(success)) {
207         return;
208     }
209 
210     if (glyphs == NULL) {
211         success = LE_ILLEGAL_ARGUMENT_ERROR;
212         return;
213     }
214 
215     if (fGlyphs == NULL) {
216         success = LE_NO_LAYOUT_ERROR;
217         return;
218     }
219 
220     for (i = 0; i < fGlyphCount; i += 1) {
221         glyphs[i] = fGlyphs[i] | extraBits;
222     }
223 }
224 
getGlyphs(LEGlyphID glyphs[],LEErrorCode & success) const225 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
226 {
227     if (LE_FAILURE(success)) {
228       return;
229     }
230 
231     if (glyphs == NULL) {
232       success = LE_ILLEGAL_ARGUMENT_ERROR;
233       return;
234     }
235 
236     if (fGlyphs == NULL) {
237       success = LE_NO_LAYOUT_ERROR;
238       return;
239     }
240 
241     LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
242 }
243 
getGlyphID(le_int32 glyphIndex,LEErrorCode & success) const244 LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const
245 {
246     if (LE_FAILURE(success)) {
247         return 0xFFFF;
248     }
249 
250     if (fGlyphs == NULL) {
251         success = LE_NO_LAYOUT_ERROR;
252         return 0xFFFF;
253     }
254 
255     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
256         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
257         return 0xFFFF;
258     }
259 
260     return fGlyphs[glyphIndex];
261 }
262 
setGlyphID(le_int32 glyphIndex,LEGlyphID glyphID,LEErrorCode & success)263 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success)
264 {
265     if (LE_FAILURE(success)) {
266         return;
267     }
268 
269     if (fGlyphs == NULL) {
270         success = LE_NO_LAYOUT_ERROR;
271         return;
272     }
273 
274     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
275         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
276         return;
277     }
278 
279     fGlyphs[glyphIndex] = glyphID;
280 }
281 
getCharIndex(le_int32 glyphIndex,LEErrorCode & success) const282 le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const
283 {
284     if (LE_FAILURE(success)) {
285         return -1;
286     }
287 
288     if (fCharIndices == NULL) {
289         success = LE_NO_LAYOUT_ERROR;
290         return -1;
291     }
292 
293     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
294         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
295         return -1;
296     }
297 
298     return fCharIndices[glyphIndex];
299 }
300 
setCharIndex(le_int32 glyphIndex,le_int32 charIndex,LEErrorCode & success)301 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success)
302 {
303     if (LE_FAILURE(success)) {
304         return;
305     }
306 
307     if (fCharIndices == NULL) {
308         success = LE_NO_LAYOUT_ERROR;
309         return;
310     }
311 
312     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
313         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
314         return;
315     }
316 
317     fCharIndices[glyphIndex] = charIndex;
318 }
319 
getAuxData(le_uint32 auxData[],LEErrorCode & success) const320 void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const
321 {
322     if (LE_FAILURE(success)) {
323       return;
324     }
325 
326     if (auxData == NULL) {
327       success = LE_ILLEGAL_ARGUMENT_ERROR;
328       return;
329     }
330 
331     if (fAuxData == NULL) {
332       success = LE_NO_LAYOUT_ERROR;
333       return;
334     }
335 
336     LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount);
337 }
338 
getAuxData(le_int32 glyphIndex,LEErrorCode & success) const339 le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
340 {
341     if (LE_FAILURE(success)) {
342         return 0;
343     }
344 
345     if (fAuxData == NULL) {
346         success = LE_NO_LAYOUT_ERROR;
347         return 0;
348     }
349 
350     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
351         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
352         return 0;
353     }
354 
355     return fAuxData[glyphIndex];
356 }
357 
setAuxData(le_int32 glyphIndex,le_uint32 auxData,LEErrorCode & success)358 void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success)
359 {
360     if (LE_FAILURE(success)) {
361         return;
362     }
363 
364     if (fAuxData == NULL) {
365         success = LE_NO_LAYOUT_ERROR;
366         return;
367     }
368 
369     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
370         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
371         return;
372     }
373 
374     fAuxData[glyphIndex] = auxData;
375 }
376 
getGlyphPositions(float positions[],LEErrorCode & success) const377 void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const
378 {
379     if (LE_FAILURE(success)) {
380       return;
381     }
382 
383     if (positions == NULL) {
384       success = LE_ILLEGAL_ARGUMENT_ERROR;
385       return;
386     }
387 
388     if (fPositions == NULL) {
389       success = LE_NO_LAYOUT_ERROR;
390       return;
391     }
392 
393     LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2);
394 }
395 
getGlyphPosition(le_int32 glyphIndex,float & x,float & y,LEErrorCode & success) const396 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
397 {
398     if (LE_FAILURE(success)) {
399       return;
400     }
401 
402     if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
403       success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
404       return;
405     }
406 
407     if (fPositions == NULL) {
408       success = LE_NO_LAYOUT_ERROR;
409       return;
410     }
411 
412     x = fPositions[glyphIndex * 2];
413     y = fPositions[glyphIndex * 2 + 1];
414 }
415 
setPosition(le_int32 glyphIndex,float x,float y,LEErrorCode & success)416 void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success)
417 {
418     if (LE_FAILURE(success)) {
419         return;
420     }
421 
422     if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
423       success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
424       return;
425     }
426 
427     fPositions[glyphIndex * 2]     = x;
428     fPositions[glyphIndex * 2 + 1] = y;
429 }
430 
adjustPosition(le_int32 glyphIndex,float xAdjust,float yAdjust,LEErrorCode & success)431 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success)
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     fPositions[glyphIndex * 2]     += xAdjust;
443     fPositions[glyphIndex * 2 + 1] += yAdjust;
444 }
445 
adoptGlyphArray(LEGlyphStorage & from)446 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from)
447 {
448     if (fGlyphs != NULL) {
449         LE_DELETE_ARRAY(fGlyphs);
450     }
451 
452     fGlyphs = from.fGlyphs;
453     from.fGlyphs = NULL;
454 
455     if (fInsertionList != NULL) {
456         delete fInsertionList;
457     }
458 
459     fInsertionList = from.fInsertionList;
460     from.fInsertionList = NULL;
461 }
462 
adoptCharIndicesArray(LEGlyphStorage & from)463 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from)
464 {
465     if (fCharIndices != NULL) {
466         LE_DELETE_ARRAY(fCharIndices);
467     }
468 
469     fCharIndices = from.fCharIndices;
470     from.fCharIndices = NULL;
471 }
472 
adoptPositionArray(LEGlyphStorage & from)473 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from)
474 {
475     if (fPositions != NULL) {
476         LE_DELETE_ARRAY(fPositions);
477     }
478 
479     fPositions = from.fPositions;
480     from.fPositions = NULL;
481 }
482 
adoptAuxDataArray(LEGlyphStorage & from)483 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from)
484 {
485     if (fAuxData != NULL) {
486         LE_DELETE_ARRAY(fAuxData);
487     }
488 
489     fAuxData = from.fAuxData;
490     from.fAuxData = NULL;
491 }
492 
adoptGlyphCount(LEGlyphStorage & from)493 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
494 {
495     fGlyphCount = from.fGlyphCount;
496 }
497 
adoptGlyphCount(le_int32 newGlyphCount)498 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
499 {
500     fGlyphCount = newGlyphCount;
501 }
502 
503 // FIXME: add error checking?
insertGlyphs(le_int32 atIndex,le_int32 insertCount)504 LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32  atIndex, le_int32 insertCount)
505 {
506     return fInsertionList->insert(atIndex, insertCount);
507 }
508 
applyInsertions()509 le_int32 LEGlyphStorage::applyInsertions()
510 {
511     le_int32 growAmount = fInsertionList->getGrowAmount();
512 
513     if (growAmount == 0) {
514         return fGlyphCount;
515     }
516 
517     le_int32 newGlyphCount = fGlyphCount + growAmount;
518 
519     fGlyphs      = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs,      newGlyphCount);
520     fCharIndices = (le_int32 *)  LE_GROW_ARRAY(fCharIndices, newGlyphCount);
521 
522     if (fAuxData != NULL) {
523         fAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData,     newGlyphCount);
524     }
525 
526     fSrcIndex  = fGlyphCount - 1;
527     fDestIndex = newGlyphCount - 1;
528 
529 #if 0
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;
540     }
541 #endif
542 
543     fInsertionList->applyInsertions(this);
544 
545     fInsertionList->reset();
546 
547     return fGlyphCount = newGlyphCount;
548 }
549 
applyInsertion(le_int32 atPosition,le_int32 count,LEGlyphID newGlyphs[])550 le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
551 {
552 #if 0
553     // if the current position is within the block we're shifting
554     // it needs to be updated to the current glyph's
555     // new location.
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;
563     }
564 #endif
565 
566     if (fAuxData != NULL) {
567         le_int32 src = fSrcIndex, dest = fDestIndex;
568 
569         while (src > atPosition) {
570             fAuxData[dest--] = fAuxData[src--];
571         }
572 
573         for (le_int32 i = count - 1; i >= 0; i -= 1) {
574             fAuxData[dest--] = fAuxData[atPosition];
575         }
576     }
577 
578     while (fSrcIndex > atPosition) {
579         fGlyphs[fDestIndex]      = fGlyphs[fSrcIndex];
580         fCharIndices[fDestIndex] = fCharIndices[fSrcIndex];
581 
582         fDestIndex -= 1;
583         fSrcIndex  -= 1;
584     }
585 
586     for (le_int32 i = count - 1; i >= 0; i -= 1) {
587         fGlyphs[fDestIndex]      = newGlyphs[i];
588         fCharIndices[fDestIndex] = fCharIndices[atPosition];
589 
590         fDestIndex -= 1;
591     }
592 
593     // the source glyph we're pointing at
594     // just got replaced by the insertion
595     fSrcIndex -= 1;
596 
597     return FALSE;
598 }
599 
600 U_NAMESPACE_END
601 
602