]> git.saurik.com Git - apple/icu.git/blame - icuSources/layout/LEGlyphStorage.cpp
ICU-8.11.2.tar.gz
[apple/icu.git] / icuSources / layout / LEGlyphStorage.cpp
CommitLineData
374ca955
A
1/*
2 **********************************************************************
73c04bcf 3 * Copyright (C) 1998-2006, 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
12U_NAMESPACE_BEGIN
13
14UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage)
15
73c04bcf
A
16LEInsertionCallback::~LEInsertionCallback()
17{
18 // nothing to do...
19}
20
374ca955
A
21LEGlyphStorage::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
28LEGlyphStorage::~LEGlyphStorage()
29{
30 reset();
31}
32
33void 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?
65void 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]?
116le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
117{
118 if (LE_FAILURE(success)) {
119 return -1;
120 }
121
73c04bcf
A
122 if (fPositions != NULL) {
123 success = LE_INTERNAL_ERROR;
124 return -1;
125 }
126
374ca955
A
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?
138le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
139{
140 if (LE_FAILURE(success)) {
141 return -1;
142 }
143
73c04bcf
A
144 if (fAuxData != NULL) {
145 success = LE_INTERNAL_ERROR;
146 return -1;
147 }
148
149 fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount);
374ca955
A
150
151 if (fAuxData == NULL) {
152 success = LE_MEMORY_ALLOCATION_ERROR;
153 return -1;
154 }
155
156 return fGlyphCount;
157}
158
159void 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
182void 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
202void 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
225void 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
244LEGlyphID 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
263void 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
282le_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
301void 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
73c04bcf 320void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const
374ca955
A
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
73c04bcf 339le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
374ca955
A
340{
341 if (LE_FAILURE(success)) {
73c04bcf 342 return 0;
374ca955
A
343 }
344
345 if (fAuxData == NULL) {
346 success = LE_NO_LAYOUT_ERROR;
73c04bcf 347 return 0;
374ca955
A
348 }
349
350 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
351 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
73c04bcf 352 return 0;
374ca955
A
353 }
354
355 return fAuxData[glyphIndex];
356}
357
73c04bcf 358void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success)
374ca955
A
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
377void 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
396void 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
416void 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
431void 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
446void 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
463void 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
473void 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
483void 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
493void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
494{
495 fGlyphCount = from.fGlyphCount;
496}
497
498void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
499{
500 fGlyphCount = newGlyphCount;
501}
502
503// FIXME: add error checking?
504LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount)
505{
506 return fInsertionList->insert(atIndex, insertCount);
507}
508
509le_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) {
73c04bcf 523 fAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData, newGlyphCount);
374ca955
A
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
550le_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
600U_NAMESPACE_END
601