blob: 693f92f71232fb96e1a76dc041f9224bf756d841 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 *
24 */
25
26/*
27 *
28 **********************************************************************
29 * Copyright (C) 1998-2005, International Business Machines
30 * Corporation and others. All Rights Reserved.
31 **********************************************************************
32 */
33
34#include "LETypes.h"
35#include "LEInsertionList.h"
36#include "LEGlyphStorage.h"
37
38LEGlyphStorage::LEGlyphStorage()
39 : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
40 fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0)
41{
42 // nothing else to do!
43}
44
45LEGlyphStorage::~LEGlyphStorage()
46{
47 reset();
48}
49
50void LEGlyphStorage::reset()
51{
52 fGlyphCount = 0;
53
54 if (fPositions != NULL) {
55 LE_DELETE_ARRAY(fPositions);
56 fPositions = NULL;
57 }
58
59 if (fAuxData != NULL) {
60 LE_DELETE_ARRAY(fAuxData);
61 fAuxData = NULL;
62 }
63
64 if (fInsertionList != NULL) {
65 delete fInsertionList;
66 fInsertionList = NULL;
67 }
68
69 if (fCharIndices != NULL) {
70 LE_DELETE_ARRAY(fCharIndices);
71 fCharIndices = NULL;
72 }
73
74 if (fGlyphs != NULL) {
75 LE_DELETE_ARRAY(fGlyphs);
76 fGlyphs = NULL;
77 }
78}
79
80// FIXME: This might get called more than once, for various reasons. Is
81// testing for pre-existing glyph and charIndices arrays good enough?
82void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success)
83{
84 if (LE_FAILURE(success)) {
85 return;
86 }
87
88 if (initialGlyphCount <= 0) {
89 success = LE_ILLEGAL_ARGUMENT_ERROR;
90 return;
91 }
92
93 if (fGlyphs == NULL) {
94 fGlyphCount = initialGlyphCount;
95 fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount);
96
97 if (fGlyphs == NULL) {
98 success = LE_MEMORY_ALLOCATION_ERROR;
99 return;
100 }
101 }
102
103 if (fCharIndices == NULL) {
104 fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount);
105
106 if (fCharIndices == NULL) {
107 LE_DELETE_ARRAY(fGlyphs);
108 fGlyphs = NULL;
109 success = LE_MEMORY_ALLOCATION_ERROR;
110 return;
111 }
112
113 // Initialize the charIndices array
114 le_int32 i, count = fGlyphCount, dir = 1, out = 0;
115
116 if (rightToLeft) {
117 out = fGlyphCount - 1;
118 dir = -1;
119 }
120
121 for (i = 0; i < count; i += 1, out += dir) {
122 fCharIndices[out] = i;
123 }
124 }
125
126 if (fInsertionList == NULL) {
127 // FIXME: check this for failure?
128 fInsertionList = new LEInsertionList(rightToLeft);
129 }
130}
131
132// FIXME: do we want to initialize the positions to [0, 0]?
133le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
134{
135 if (LE_FAILURE(success)) {
136 return -1;
137 }
138
139 fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1));
140
141 if (fPositions == NULL) {
142 success = LE_MEMORY_ALLOCATION_ERROR;
143 return -1;
144 }
145
146 return fGlyphCount;
147}
148
149// FIXME: do we want to initialize the aux data to NULL?
150le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
151{
152 if (LE_FAILURE(success)) {
153 return -1;
154 }
155
156 fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount);
157
158 if (fAuxData == NULL) {
159 success = LE_MEMORY_ALLOCATION_ERROR;
160 return -1;
161 }
162
163 return fGlyphCount;
164}
165
166void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
167{
168 le_int32 i;
169
170 if (LE_FAILURE(success)) {
171 return;
172 }
173
174 if (charIndices == NULL) {
175 success = LE_ILLEGAL_ARGUMENT_ERROR;
176 return;
177 }
178
179 if (fCharIndices == NULL) {
180 success = LE_NO_LAYOUT_ERROR;
181 return;
182 }
183
184 for (i = 0; i < fGlyphCount; i += 1) {
185 charIndices[i] = fCharIndices[i] + indexBase;
186 }
187}
188
189void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
190{
191 if (LE_FAILURE(success)) {
192 return;
193 }
194
195 if (charIndices == NULL) {
196 success = LE_ILLEGAL_ARGUMENT_ERROR;
197 return;
198 }
199
200 if (fCharIndices == NULL) {
201 success = LE_NO_LAYOUT_ERROR;
202 return;
203 }
204
205 LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount);
206}
207
208// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
209void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
210{
211 le_int32 i;
212
213 if (LE_FAILURE(success)) {
214 return;
215 }
216
217 if (glyphs == NULL) {
218 success = LE_ILLEGAL_ARGUMENT_ERROR;
219 return;
220 }
221
222 if (fGlyphs == NULL) {
223 success = LE_NO_LAYOUT_ERROR;
224 return;
225 }
226
227 for (i = 0; i < fGlyphCount; i += 1) {
228 glyphs[i] = fGlyphs[i] | extraBits;
229 }
230}
231
232void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
233{
234 if (LE_FAILURE(success)) {
235 return;
236 }
237
238 if (glyphs == NULL) {
239 success = LE_ILLEGAL_ARGUMENT_ERROR;
240 return;
241 }
242
243 if (fGlyphs == NULL) {
244 success = LE_NO_LAYOUT_ERROR;
245 return;
246 }
247
248 LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
249}
250
251LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const
252{
253 if (LE_FAILURE(success)) {
254 return 0xFFFF;
255 }
256
257 if (fGlyphs == NULL) {
258 success = LE_NO_LAYOUT_ERROR;
259 return 0xFFFF;
260 }
261
262 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
263 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
264 return 0xFFFF;
265 }
266
267 return fGlyphs[glyphIndex];
268}
269
270void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success)
271{
272 if (LE_FAILURE(success)) {
273 return;
274 }
275
276 if (fGlyphs == NULL) {
277 success = LE_NO_LAYOUT_ERROR;
278 return;
279 }
280
281 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
282 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
283 return;
284 }
285
286 fGlyphs[glyphIndex] = glyphID;
287}
288
289le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const
290{
291 if (LE_FAILURE(success)) {
292 return -1;
293 }
294
295 if (fCharIndices == NULL) {
296 success = LE_NO_LAYOUT_ERROR;
297 return -1;
298 }
299
300 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
301 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
302 return -1;
303 }
304
305 return fCharIndices[glyphIndex];
306}
307
308void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success)
309{
310 if (LE_FAILURE(success)) {
311 return;
312 }
313
314 if (fCharIndices == NULL) {
315 success = LE_NO_LAYOUT_ERROR;
316 return;
317 }
318
319 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
320 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
321 return;
322 }
323
324 fCharIndices[glyphIndex] = charIndex;
325}
326
327void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const
328{
329 if (LE_FAILURE(success)) {
330 return;
331 }
332
333 if (auxData == NULL) {
334 success = LE_ILLEGAL_ARGUMENT_ERROR;
335 return;
336 }
337
338 if (fAuxData == NULL) {
339 success = LE_NO_LAYOUT_ERROR;
340 return;
341 }
342
343 LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount);
344}
345
346le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
347{
348 if (LE_FAILURE(success)) {
349 return 0;
350 }
351
352 if (fAuxData == NULL) {
353 success = LE_NO_LAYOUT_ERROR;
354 return 0;
355 }
356
357 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
358 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
359 return 0;
360 }
361
362 return fAuxData[glyphIndex];
363}
364
365void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success)
366{
367 if (LE_FAILURE(success)) {
368 return;
369 }
370
371 if (fAuxData == NULL) {
372 success = LE_NO_LAYOUT_ERROR;
373 return;
374 }
375
376 if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
377 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
378 return;
379 }
380
381 fAuxData[glyphIndex] = auxData;
382}
383
384void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const
385{
386 if (LE_FAILURE(success)) {
387 return;
388 }
389
390 if (positions == NULL) {
391 success = LE_ILLEGAL_ARGUMENT_ERROR;
392 return;
393 }
394
395 if (fPositions == NULL) {
396 success = LE_NO_LAYOUT_ERROR;
397 return;
398 }
399
400 LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2);
401}
402
403void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
404{
405 if (LE_FAILURE(success)) {
406 return;
407 }
408
409 if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
410 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
411 return;
412 }
413
414 if (fPositions == NULL) {
415 success = LE_NO_LAYOUT_ERROR;
416 return;
417 }
418
419 x = fPositions[glyphIndex * 2];
420 y = fPositions[glyphIndex * 2 + 1];
421}
422
423void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success)
424{
425 if (LE_FAILURE(success)) {
426 return;
427 }
428
429 if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
430 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
431 return;
432 }
433
434 fPositions[glyphIndex * 2] = x;
435 fPositions[glyphIndex * 2 + 1] = y;
436}
437
438void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success)
439{
440 if (LE_FAILURE(success)) {
441 return;
442 }
443
444 if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
445 success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
446 return;
447 }
448
449 fPositions[glyphIndex * 2] += xAdjust;
450 fPositions[glyphIndex * 2 + 1] += yAdjust;
451}
452
453void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from)
454{
455 if (fGlyphs != NULL) {
456 LE_DELETE_ARRAY(fGlyphs);
457 }
458
459 fGlyphs = from.fGlyphs;
460 from.fGlyphs = NULL;
461
462 if (fInsertionList != NULL) {
463 delete fInsertionList;
464 }
465
466 fInsertionList = from.fInsertionList;
467 from.fInsertionList = NULL;
468}
469
470void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from)
471{
472 if (fCharIndices != NULL) {
473 LE_DELETE_ARRAY(fCharIndices);
474 }
475
476 fCharIndices = from.fCharIndices;
477 from.fCharIndices = NULL;
478}
479
480void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from)
481{
482 if (fPositions != NULL) {
483 LE_DELETE_ARRAY(fPositions);
484 }
485
486 fPositions = from.fPositions;
487 from.fPositions = NULL;
488}
489
490void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from)
491{
492 if (fAuxData != NULL) {
493 LE_DELETE_ARRAY(fAuxData);
494 }
495
496 fAuxData = from.fAuxData;
497 from.fAuxData = NULL;
498}
499
500void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
501{
502 fGlyphCount = from.fGlyphCount;
503}
504
505void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
506{
507 fGlyphCount = newGlyphCount;
508}
509
510// FIXME: add error checking?
511LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32 atIndex, le_int32 insertCount)
512{
513 return fInsertionList->insert(atIndex, insertCount);
514}
515
516le_int32 LEGlyphStorage::applyInsertions()
517{
518 le_int32 growAmount = fInsertionList->getGrowAmount();
519
520 if (growAmount == 0) {
521 return fGlyphCount;
522 }
523
524 le_int32 newGlyphCount = fGlyphCount + growAmount;
525
526 fGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount);
527 fCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount);
528
529 if (fAuxData != NULL) {
530 fAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData, newGlyphCount);
531 }
532
533 fSrcIndex = fGlyphCount - 1;
534 fDestIndex = newGlyphCount - 1;
535
536#if 0
537 // If the current position is at the end of the array
538 // update it to point to the end of the new array. The
539 // insertion callback will handle all other cases.
540 // FIXME: this is left over from GlyphIterator, but there's no easy
541 // way to implement this here... it seems that GlyphIterator doesn't
542 // really need it 'cause the insertions don't get applied until after a
543 // complete pass over the glyphs, after which the iterator gets reset anyhow...
544 // probably better to just document that for LEGlyphStorage and GlyphIterator...
545 if (position == glyphCount) {
546 position = newGlyphCount;
547 }
548#endif
549
550 fInsertionList->applyInsertions(this);
551
552 fInsertionList->reset();
553
554 return fGlyphCount = newGlyphCount;
555}
556
557le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
558{
559#if 0
560 // if the current position is within the block we're shifting
561 // it needs to be updated to the current glyph's
562 // new location.
563 // FIXME: this is left over from GlyphIterator, but there's no easy
564 // way to implement this here... it seems that GlyphIterator doesn't
565 // really need it 'cause the insertions don't get applied until after a
566 // complete pass over the glyphs, after which the iterator gets reset anyhow...
567 // probably better to just document that for LEGlyphStorage and GlyphIterator...
568 if (position >= atPosition && position <= fSrcIndex) {
569 position += fDestIndex - fSrcIndex;
570 }
571#endif
572
573 if (fAuxData != NULL) {
574 le_int32 src = fSrcIndex, dest = fDestIndex;
575
576 while (src > atPosition) {
577 fAuxData[dest--] = fAuxData[src--];
578 }
579
580 for (le_int32 i = count - 1; i >= 0; i -= 1) {
581 fAuxData[dest--] = fAuxData[atPosition];
582 }
583 }
584
585 while (fSrcIndex > atPosition) {
586 fGlyphs[fDestIndex] = fGlyphs[fSrcIndex];
587 fCharIndices[fDestIndex] = fCharIndices[fSrcIndex];
588
589 fDestIndex -= 1;
590 fSrcIndex -= 1;
591 }
592
593 for (le_int32 i = count - 1; i >= 0; i -= 1) {
594 fGlyphs[fDestIndex] = newGlyphs[i];
595 fCharIndices[fDestIndex] = fCharIndices[atPosition];
596
597 fDestIndex -= 1;
598 }
599
600 // the source glyph we're pointing at
601 // just got replaced by the insertion
602 fSrcIndex -= 1;
603
604 return FALSE;
605}