]>
Commit | Line | Data |
---|---|---|
374ca955 A |
1 | /* |
2 | ********************************************************************** | |
729e4ab9 | 3 | * Copyright (C) 1998-2009, International Business Machines |
374ca955 A |
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 | ||
14 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage) | |
15 | ||
73c04bcf A |
16 | LEInsertionCallback::~LEInsertionCallback() |
17 | { | |
18 | // nothing to do... | |
19 | } | |
20 | ||
374ca955 A |
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 | ||
28 | LEGlyphStorage::~LEGlyphStorage() | |
29 | { | |
30 | reset(); | |
31 | } | |
32 | ||
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? | |
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); | |
729e4ab9 A |
112 | if (fInsertionList == NULL) { |
113 | LE_DELETE_ARRAY(fCharIndices); | |
114 | fCharIndices = NULL; | |
115 | ||
116 | LE_DELETE_ARRAY(fGlyphs); | |
117 | fGlyphs = NULL; | |
118 | ||
119 | success = LE_MEMORY_ALLOCATION_ERROR; | |
120 | return; | |
121 | } | |
374ca955 A |
122 | } |
123 | } | |
124 | ||
125 | // FIXME: do we want to initialize the positions to [0, 0]? | |
126 | le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success) | |
127 | { | |
128 | if (LE_FAILURE(success)) { | |
129 | return -1; | |
130 | } | |
131 | ||
73c04bcf A |
132 | if (fPositions != NULL) { |
133 | success = LE_INTERNAL_ERROR; | |
134 | return -1; | |
135 | } | |
136 | ||
374ca955 A |
137 | fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1)); |
138 | ||
139 | if (fPositions == NULL) { | |
140 | success = LE_MEMORY_ALLOCATION_ERROR; | |
141 | return -1; | |
142 | } | |
143 | ||
144 | return fGlyphCount; | |
145 | } | |
146 | ||
147 | // FIXME: do we want to initialize the aux data to NULL? | |
148 | le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success) | |
149 | { | |
150 | if (LE_FAILURE(success)) { | |
151 | return -1; | |
152 | } | |
153 | ||
73c04bcf A |
154 | if (fAuxData != NULL) { |
155 | success = LE_INTERNAL_ERROR; | |
156 | return -1; | |
157 | } | |
158 | ||
159 | fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount); | |
374ca955 A |
160 | |
161 | if (fAuxData == NULL) { | |
162 | success = LE_MEMORY_ALLOCATION_ERROR; | |
163 | return -1; | |
164 | } | |
165 | ||
166 | return fGlyphCount; | |
167 | } | |
168 | ||
169 | void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const | |
170 | { | |
171 | le_int32 i; | |
172 | ||
173 | if (LE_FAILURE(success)) { | |
174 | return; | |
175 | } | |
176 | ||
177 | if (charIndices == NULL) { | |
178 | success = LE_ILLEGAL_ARGUMENT_ERROR; | |
179 | return; | |
180 | } | |
181 | ||
182 | if (fCharIndices == NULL) { | |
183 | success = LE_NO_LAYOUT_ERROR; | |
184 | return; | |
185 | } | |
186 | ||
187 | for (i = 0; i < fGlyphCount; i += 1) { | |
188 | charIndices[i] = fCharIndices[i] + indexBase; | |
189 | } | |
190 | } | |
191 | ||
192 | void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const | |
193 | { | |
194 | if (LE_FAILURE(success)) { | |
195 | return; | |
196 | } | |
197 | ||
198 | if (charIndices == NULL) { | |
199 | success = LE_ILLEGAL_ARGUMENT_ERROR; | |
200 | return; | |
201 | } | |
202 | ||
203 | if (fCharIndices == NULL) { | |
204 | success = LE_NO_LAYOUT_ERROR; | |
205 | return; | |
206 | } | |
207 | ||
208 | LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount); | |
209 | } | |
210 | ||
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 | |
213 | { | |
214 | le_int32 i; | |
215 | ||
216 | if (LE_FAILURE(success)) { | |
217 | return; | |
218 | } | |
219 | ||
220 | if (glyphs == NULL) { | |
221 | success = LE_ILLEGAL_ARGUMENT_ERROR; | |
222 | return; | |
223 | } | |
224 | ||
225 | if (fGlyphs == NULL) { | |
226 | success = LE_NO_LAYOUT_ERROR; | |
227 | return; | |
228 | } | |
229 | ||
230 | for (i = 0; i < fGlyphCount; i += 1) { | |
231 | glyphs[i] = fGlyphs[i] | extraBits; | |
232 | } | |
233 | } | |
234 | ||
235 | void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const | |
236 | { | |
237 | if (LE_FAILURE(success)) { | |
238 | return; | |
239 | } | |
240 | ||
241 | if (glyphs == NULL) { | |
242 | success = LE_ILLEGAL_ARGUMENT_ERROR; | |
243 | return; | |
244 | } | |
245 | ||
246 | if (fGlyphs == NULL) { | |
247 | success = LE_NO_LAYOUT_ERROR; | |
248 | return; | |
249 | } | |
250 | ||
251 | LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount); | |
252 | } | |
253 | ||
254 | LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const | |
255 | { | |
256 | if (LE_FAILURE(success)) { | |
257 | return 0xFFFF; | |
258 | } | |
259 | ||
260 | if (fGlyphs == NULL) { | |
261 | success = LE_NO_LAYOUT_ERROR; | |
262 | return 0xFFFF; | |
263 | } | |
264 | ||
265 | if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { | |
266 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
267 | return 0xFFFF; | |
268 | } | |
269 | ||
270 | return fGlyphs[glyphIndex]; | |
271 | } | |
272 | ||
273 | void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success) | |
274 | { | |
275 | if (LE_FAILURE(success)) { | |
276 | return; | |
277 | } | |
278 | ||
279 | if (fGlyphs == NULL) { | |
280 | success = LE_NO_LAYOUT_ERROR; | |
281 | return; | |
282 | } | |
283 | ||
284 | if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { | |
285 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
286 | return; | |
287 | } | |
288 | ||
289 | fGlyphs[glyphIndex] = glyphID; | |
290 | } | |
291 | ||
292 | le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const | |
293 | { | |
294 | if (LE_FAILURE(success)) { | |
295 | return -1; | |
296 | } | |
297 | ||
298 | if (fCharIndices == NULL) { | |
299 | success = LE_NO_LAYOUT_ERROR; | |
300 | return -1; | |
301 | } | |
302 | ||
303 | if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { | |
304 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
305 | return -1; | |
306 | } | |
307 | ||
308 | return fCharIndices[glyphIndex]; | |
309 | } | |
310 | ||
311 | void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success) | |
312 | { | |
313 | if (LE_FAILURE(success)) { | |
314 | return; | |
315 | } | |
316 | ||
317 | if (fCharIndices == NULL) { | |
318 | success = LE_NO_LAYOUT_ERROR; | |
319 | return; | |
320 | } | |
321 | ||
322 | if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { | |
323 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
324 | return; | |
325 | } | |
326 | ||
327 | fCharIndices[glyphIndex] = charIndex; | |
328 | } | |
329 | ||
73c04bcf | 330 | void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const |
374ca955 A |
331 | { |
332 | if (LE_FAILURE(success)) { | |
333 | return; | |
334 | } | |
335 | ||
336 | if (auxData == NULL) { | |
337 | success = LE_ILLEGAL_ARGUMENT_ERROR; | |
338 | return; | |
339 | } | |
340 | ||
341 | if (fAuxData == NULL) { | |
342 | success = LE_NO_LAYOUT_ERROR; | |
343 | return; | |
344 | } | |
345 | ||
346 | LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount); | |
347 | } | |
348 | ||
73c04bcf | 349 | le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const |
374ca955 A |
350 | { |
351 | if (LE_FAILURE(success)) { | |
73c04bcf | 352 | return 0; |
374ca955 A |
353 | } |
354 | ||
355 | if (fAuxData == NULL) { | |
356 | success = LE_NO_LAYOUT_ERROR; | |
73c04bcf | 357 | return 0; |
374ca955 A |
358 | } |
359 | ||
360 | if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { | |
361 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
73c04bcf | 362 | return 0; |
374ca955 A |
363 | } |
364 | ||
365 | return fAuxData[glyphIndex]; | |
366 | } | |
367 | ||
73c04bcf | 368 | void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success) |
374ca955 A |
369 | { |
370 | if (LE_FAILURE(success)) { | |
371 | return; | |
372 | } | |
373 | ||
374 | if (fAuxData == NULL) { | |
375 | success = LE_NO_LAYOUT_ERROR; | |
376 | return; | |
377 | } | |
378 | ||
379 | if (glyphIndex < 0 || glyphIndex >= fGlyphCount) { | |
380 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
381 | return; | |
382 | } | |
383 | ||
384 | fAuxData[glyphIndex] = auxData; | |
385 | } | |
386 | ||
387 | void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const | |
388 | { | |
389 | if (LE_FAILURE(success)) { | |
390 | return; | |
391 | } | |
392 | ||
393 | if (positions == NULL) { | |
394 | success = LE_ILLEGAL_ARGUMENT_ERROR; | |
395 | return; | |
396 | } | |
397 | ||
398 | if (fPositions == NULL) { | |
399 | success = LE_NO_LAYOUT_ERROR; | |
400 | return; | |
401 | } | |
402 | ||
403 | LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2); | |
404 | } | |
405 | ||
406 | void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const | |
407 | { | |
408 | if (LE_FAILURE(success)) { | |
409 | return; | |
410 | } | |
411 | ||
412 | if (glyphIndex < 0 || glyphIndex > fGlyphCount) { | |
413 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
414 | return; | |
415 | } | |
416 | ||
417 | if (fPositions == NULL) { | |
418 | success = LE_NO_LAYOUT_ERROR; | |
419 | return; | |
420 | } | |
421 | ||
422 | x = fPositions[glyphIndex * 2]; | |
423 | y = fPositions[glyphIndex * 2 + 1]; | |
424 | } | |
425 | ||
426 | void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success) | |
427 | { | |
428 | if (LE_FAILURE(success)) { | |
429 | return; | |
430 | } | |
431 | ||
432 | if (glyphIndex < 0 || glyphIndex > fGlyphCount) { | |
433 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
434 | return; | |
435 | } | |
436 | ||
437 | fPositions[glyphIndex * 2] = x; | |
438 | fPositions[glyphIndex * 2 + 1] = y; | |
439 | } | |
440 | ||
441 | void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success) | |
442 | { | |
443 | if (LE_FAILURE(success)) { | |
444 | return; | |
445 | } | |
446 | ||
447 | if (glyphIndex < 0 || glyphIndex > fGlyphCount) { | |
448 | success = LE_INDEX_OUT_OF_BOUNDS_ERROR; | |
449 | return; | |
450 | } | |
451 | ||
452 | fPositions[glyphIndex * 2] += xAdjust; | |
453 | fPositions[glyphIndex * 2 + 1] += yAdjust; | |
454 | } | |
455 | ||
456 | void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from) | |
457 | { | |
458 | if (fGlyphs != NULL) { | |
459 | LE_DELETE_ARRAY(fGlyphs); | |
460 | } | |
461 | ||
462 | fGlyphs = from.fGlyphs; | |
463 | from.fGlyphs = NULL; | |
464 | ||
465 | if (fInsertionList != NULL) { | |
466 | delete fInsertionList; | |
467 | } | |
468 | ||
469 | fInsertionList = from.fInsertionList; | |
470 | from.fInsertionList = NULL; | |
471 | } | |
472 | ||
473 | void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from) | |
474 | { | |
475 | if (fCharIndices != NULL) { | |
476 | LE_DELETE_ARRAY(fCharIndices); | |
477 | } | |
478 | ||
479 | fCharIndices = from.fCharIndices; | |
480 | from.fCharIndices = NULL; | |
481 | } | |
482 | ||
483 | void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from) | |
484 | { | |
485 | if (fPositions != NULL) { | |
486 | LE_DELETE_ARRAY(fPositions); | |
487 | } | |
488 | ||
489 | fPositions = from.fPositions; | |
490 | from.fPositions = NULL; | |
491 | } | |
492 | ||
493 | void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from) | |
494 | { | |
495 | if (fAuxData != NULL) { | |
496 | LE_DELETE_ARRAY(fAuxData); | |
497 | } | |
498 | ||
499 | fAuxData = from.fAuxData; | |
500 | from.fAuxData = NULL; | |
501 | } | |
502 | ||
503 | void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from) | |
504 | { | |
505 | fGlyphCount = from.fGlyphCount; | |
506 | } | |
507 | ||
508 | void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount) | |
509 | { | |
510 | fGlyphCount = newGlyphCount; | |
511 | } | |
512 | ||
729e4ab9 A |
513 | // Move a glyph to a different position in the LEGlyphStorage ( used for Indic v2 processing ) |
514 | ||
515 | void LEGlyphStorage::moveGlyph(le_int32 fromPosition, le_int32 toPosition, le_uint32 marker ) | |
516 | { | |
517 | ||
518 | LEErrorCode success = LE_NO_ERROR; | |
519 | ||
520 | LEGlyphID holdGlyph = getGlyphID(fromPosition,success); | |
521 | le_int32 holdCharIndex = getCharIndex(fromPosition,success); | |
522 | le_uint32 holdAuxData = getAuxData(fromPosition,success); | |
523 | ||
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); | |
529 | } | |
530 | } else { | |
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); | |
535 | ||
536 | } | |
537 | } | |
538 | ||
539 | setGlyphID(toPosition,holdGlyph,success); | |
540 | setCharIndex(toPosition,holdCharIndex,success); | |
541 | setAuxData(toPosition,holdAuxData | marker,success); | |
542 | ||
543 | } | |
544 | ||
545 | // Glue code for existing stable API | |
374ca955 A |
546 | LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount) |
547 | { | |
729e4ab9 A |
548 | LEErrorCode ignored = LE_NO_LAYOUT_ERROR; |
549 | return insertGlyphs(atIndex, insertCount, ignored); | |
550 | } | |
551 | ||
552 | // FIXME: add error checking? | |
553 | LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount, LEErrorCode& success) | |
554 | { | |
555 | return fInsertionList->insert(atIndex, insertCount, success); | |
374ca955 A |
556 | } |
557 | ||
558 | le_int32 LEGlyphStorage::applyInsertions() | |
559 | { | |
560 | le_int32 growAmount = fInsertionList->getGrowAmount(); | |
561 | ||
562 | if (growAmount == 0) { | |
563 | return fGlyphCount; | |
564 | } | |
565 | ||
566 | le_int32 newGlyphCount = fGlyphCount + growAmount; | |
567 | ||
729e4ab9 A |
568 | LEGlyphID *newGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount); |
569 | if (newGlyphs == NULL) { | |
570 | // Could not grow the glyph array | |
571 | return fGlyphCount; | |
572 | } | |
573 | fGlyphs = newGlyphs; | |
574 | ||
575 | le_int32 *newCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount); | |
576 | if (newCharIndices == NULL) { | |
577 | // Could not grow the glyph array | |
578 | return fGlyphCount; | |
579 | } | |
580 | fCharIndices = newCharIndices; | |
581 | ||
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 | |
586 | return fGlyphCount; | |
587 | } | |
588 | fAuxData = (le_uint32 *)newAuxData; | |
374ca955 A |
589 | } |
590 | ||
591 | fSrcIndex = fGlyphCount - 1; | |
592 | fDestIndex = newGlyphCount - 1; | |
593 | ||
594 | #if 0 | |
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; | |
605 | } | |
606 | #endif | |
607 | ||
608 | fInsertionList->applyInsertions(this); | |
609 | ||
610 | fInsertionList->reset(); | |
611 | ||
612 | return fGlyphCount = newGlyphCount; | |
613 | } | |
614 | ||
615 | le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]) | |
616 | { | |
617 | #if 0 | |
618 | // if the current position is within the block we're shifting | |
619 | // it needs to be updated to the current glyph's | |
620 | // new location. | |
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; | |
628 | } | |
629 | #endif | |
630 | ||
631 | if (fAuxData != NULL) { | |
632 | le_int32 src = fSrcIndex, dest = fDestIndex; | |
633 | ||
634 | while (src > atPosition) { | |
635 | fAuxData[dest--] = fAuxData[src--]; | |
636 | } | |
637 | ||
638 | for (le_int32 i = count - 1; i >= 0; i -= 1) { | |
639 | fAuxData[dest--] = fAuxData[atPosition]; | |
640 | } | |
641 | } | |
642 | ||
643 | while (fSrcIndex > atPosition) { | |
644 | fGlyphs[fDestIndex] = fGlyphs[fSrcIndex]; | |
645 | fCharIndices[fDestIndex] = fCharIndices[fSrcIndex]; | |
646 | ||
647 | fDestIndex -= 1; | |
648 | fSrcIndex -= 1; | |
649 | } | |
650 | ||
651 | for (le_int32 i = count - 1; i >= 0; i -= 1) { | |
652 | fGlyphs[fDestIndex] = newGlyphs[i]; | |
653 | fCharIndices[fDestIndex] = fCharIndices[atPosition]; | |
654 | ||
655 | fDestIndex -= 1; | |
656 | } | |
657 | ||
658 | // the source glyph we're pointing at | |
659 | // just got replaced by the insertion | |
660 | fSrcIndex -= 1; | |
661 | ||
662 | return FALSE; | |
663 | } | |
664 | ||
665 | U_NAMESPACE_END | |
666 |