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