]> git.saurik.com Git - apple/icu.git/blame - icuSources/layout/GlyphIterator.cpp
ICU-6.2.14.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
CommitLineData
b75a7d8f 1/*
b75a7d8f 2 *
374ca955 3 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
b75a7d8f
A
4 *
5 */
6
7#include "LETypes.h"
8#include "OpenTypeTables.h"
9#include "GlyphDefinitionTables.h"
10#include "GlyphPositionAdjustments.h"
11#include "GlyphIterator.h"
374ca955 12#include "LEGlyphStorage.h"
b75a7d8f
A
13#include "Lookups.h"
14#include "LESwaps.h"
15
16U_NAMESPACE_BEGIN
17
374ca955 18GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag,
b75a7d8f 19 const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
374ca955 20 : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
b75a7d8f 21 cursiveFirstPosition(-1), cursiveLastPosition(-1), cursiveBaselineAdjustment(0),
374ca955
A
22 glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
23 srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureTag(theFeatureTag),
24 glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
b75a7d8f
A
25
26{
374ca955
A
27 le_int32 glyphCount = glyphStorage.getGlyphCount();
28
b75a7d8f
A
29 if (theGlyphDefinitionTableHeader != NULL) {
30 glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
31 markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
32 }
33
374ca955
A
34 nextLimit = glyphCount;
35
b75a7d8f
A
36 if (rightToLeft) {
37 direction = -1;
374ca955 38 position = glyphCount;
b75a7d8f 39 nextLimit = -1;
374ca955 40 prevLimit = glyphCount;
b75a7d8f
A
41 }
42}
43
44GlyphIterator::GlyphIterator(GlyphIterator &that)
374ca955 45 : glyphStorage(that.glyphStorage)
b75a7d8f
A
46{
47 direction = that.direction;
48 position = that.position;
49 nextLimit = that.nextLimit;
50 prevLimit = that.prevLimit;
51
52 cursiveFirstPosition = that.cursiveFirstPosition;
53 cursiveLastPosition = that.cursiveLastPosition;
54
b75a7d8f 55 glyphPositionAdjustments = that.glyphPositionAdjustments;
374ca955
A
56 srcIndex = that.srcIndex;
57 destIndex = that.destIndex;
b75a7d8f
A
58 lookupFlags = that.lookupFlags;
59 featureTag = that.featureTag;
b75a7d8f
A
60 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
61 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
62}
63
64GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag)
374ca955 65 : glyphStorage(that.glyphStorage)
b75a7d8f
A
66{
67 direction = that.direction;
68 position = that.position;
69 nextLimit = that.nextLimit;
70 prevLimit = that.prevLimit;
71
72 cursiveFirstPosition = that.cursiveFirstPosition;
73 cursiveLastPosition = that.cursiveLastPosition;
74
b75a7d8f 75 glyphPositionAdjustments = that.glyphPositionAdjustments;
374ca955
A
76 srcIndex = that.srcIndex;
77 destIndex = that.destIndex;
b75a7d8f
A
78 lookupFlags = that.lookupFlags;
79 featureTag = newFeatureTag;
b75a7d8f
A
80 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
81 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
82}
83
84GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
374ca955 85 : glyphStorage(that.glyphStorage)
b75a7d8f
A
86{
87 direction = that.direction;
88 position = that.position;
89 nextLimit = that.nextLimit;
90 prevLimit = that.prevLimit;
91
92
93 cursiveFirstPosition = that.cursiveFirstPosition;
94 cursiveLastPosition = that.cursiveLastPosition;
95
b75a7d8f 96 glyphPositionAdjustments = that.glyphPositionAdjustments;
374ca955
A
97 srcIndex = that.srcIndex;
98 destIndex = that.destIndex;
b75a7d8f
A
99 lookupFlags = newLookupFlags;
100 featureTag = that.featureTag;
b75a7d8f
A
101 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
102 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
103}
104
374ca955 105GlyphIterator::~GlyphIterator()
b75a7d8f 106{
374ca955
A
107 // nothing to do, right?
108}
b75a7d8f 109
374ca955
A
110void GlyphIterator::reset(le_uint16 newLookupFlags, LETag newFeatureTag)
111{
112 position = prevLimit;
113 featureTag = newFeatureTag;
114 lookupFlags = newLookupFlags;
115}
116
117LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count)
118{
119 return glyphStorage.insertGlyphs(position, count);
120}
121
122le_int32 GlyphIterator::applyInsertions()
b75a7d8f 123{
374ca955
A
124 le_int32 newGlyphCount = glyphStorage.applyInsertions();
125
126 if (direction < 0) {
127 prevLimit = newGlyphCount;
128 } else {
129 nextLimit = newGlyphCount;
130 }
131
132 return newGlyphCount;
b75a7d8f
A
133}
134
135le_int32 GlyphIterator::getCurrStreamPosition() const
136{
137 return position;
138}
139
140le_bool GlyphIterator::isRightToLeft() const
141{
142 return direction < 0;
143}
144
145le_bool GlyphIterator::ignoresMarks() const
146{
147 return (lookupFlags & lfIgnoreMarks) != 0;
148}
149
150le_bool GlyphIterator::baselineIsLogicalEnd() const
151{
152 return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
153}
154
155le_bool GlyphIterator::hasCursiveFirstExitPoint() const
156{
157 return cursiveFirstPosition >= 0;
158}
159
160le_bool GlyphIterator::hasCursiveLastExitPoint() const
161{
162 return cursiveLastPosition >= 0;
163}
164
165LEGlyphID GlyphIterator::getCurrGlyphID() const
166{
167 if (direction < 0) {
168 if (position <= nextLimit || position >= prevLimit) {
169 return 0xFFFF;
170 }
171 } else {
172 if (position <= prevLimit || position >= nextLimit) {
173 return 0xFFFF;
174 }
175 }
176
374ca955 177 return glyphStorage[position];
b75a7d8f
A
178}
179
180LEGlyphID GlyphIterator::getCursiveLastGlyphID() const
181{
182 if (direction < 0) {
183 if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
184 return 0xFFFF;
185 }
186 } else {
187 if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
188 return 0xFFFF;
189 }
190 }
191
374ca955 192 return glyphStorage[cursiveLastPosition];
b75a7d8f
A
193}
194
195void GlyphIterator::getCursiveLastExitPoint(LEPoint &exitPoint) const
196{
197 if (cursiveLastPosition >= 0) {
198 exitPoint = cursiveLastExitPoint;
199 }
200}
201
202float GlyphIterator::getCursiveBaselineAdjustment() const
203{
204 return cursiveBaselineAdjustment;
205}
206
207void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment &adjustment) const
208{
209 if (direction < 0)
210 {
211 if (position <= nextLimit || position >= prevLimit)
212 {
213 return;
214 }
215 } else {
216 if (position <= prevLimit || position >= nextLimit) {
217 return;
218 }
219 }
220
221 adjustment = glyphPositionAdjustments[position];
222}
223
224void GlyphIterator::getCursiveLastPositionAdjustment(GlyphPositionAdjustment &adjustment) const
225{
226 if (direction < 0)
227 {
228 if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit)
229 {
230 return;
231 }
232 } else {
233 if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
234 return;
235 }
236 }
237
238 adjustment = glyphPositionAdjustments[cursiveLastPosition];
239}
240
241void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
242{
374ca955
A
243 LEGlyphID glyph = glyphStorage[position];
244
245 glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
b75a7d8f
A
246}
247
248void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
249{
250 cursiveFirstPosition = -1;
251 cursiveLastPosition = -1;
252 cursiveBaselineAdjustment = 0;
253
254 if (direction < 0) {
255 if (newPosition >= prevLimit) {
256 position = prevLimit;
257 return;
258 }
259
260 if (newPosition <= nextLimit) {
261 position = nextLimit;
262 return;
263 }
264 } else {
265 if (newPosition <= prevLimit) {
266 position = prevLimit;
267 return;
268 }
269
270 if (newPosition >= nextLimit) {
271 position = nextLimit;
272 return;
273 }
274 }
275
276 position = newPosition - direction;
277 next();
278}
279
280void GlyphIterator::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment *adjustment)
281{
282 if (direction < 0) {
283 if (position <= nextLimit || position >= prevLimit) {
284 return;
285 }
286 } else {
287 if (position <= prevLimit || position >= nextLimit) {
288 return;
289 }
290 }
291
292 glyphPositionAdjustments[position] = *adjustment;
293}
294
295void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
296{
297 if (direction < 0) {
298 if (position <= nextLimit || position >= prevLimit) {
299 return;
300 }
301 } else {
302 if (position <= prevLimit || position >= nextLimit) {
303 return;
304 }
305 }
306
307 glyphPositionAdjustments[position].setBaseOffset(baseOffset);
308}
309
310void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
311 float xAdvanceAdjust, float yAdvanceAdjust)
312{
313 if (direction < 0) {
314 if (position <= nextLimit || position >= prevLimit) {
315 return;
316 }
317 } else {
318 if (position <= prevLimit || position >= nextLimit) {
319 return;
320 }
321 }
322
323 glyphPositionAdjustments[position].adjustXPlacement(xPlacementAdjust);
324 glyphPositionAdjustments[position].adjustYPlacement(yPlacementAdjust);
325 glyphPositionAdjustments[position].adjustXAdvance(xAdvanceAdjust);
326 glyphPositionAdjustments[position].adjustYAdvance(yAdvanceAdjust);
327}
328
374ca955
A
329void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
330 float xAdvanceAdjust, float yAdvanceAdjust)
331{
332 if (direction < 0) {
333 if (position <= nextLimit || position >= prevLimit) {
334 return;
335 }
336 } else {
337 if (position <= prevLimit || position >= nextLimit) {
338 return;
339 }
340 }
341
342 glyphPositionAdjustments[position].setXPlacement(xPlacementAdjust);
343 glyphPositionAdjustments[position].setYPlacement(yPlacementAdjust);
344 glyphPositionAdjustments[position].setXAdvance(xAdvanceAdjust);
345 glyphPositionAdjustments[position].setYAdvance(yAdvanceAdjust);
346}
347
b75a7d8f
A
348void GlyphIterator::setCursiveFirstExitPoint()
349{
350 if (direction < 0) {
351 if (position <= nextLimit || position >= prevLimit) {
352 return;
353 }
354 } else {
355 if (position <= prevLimit || position >= nextLimit) {
356 return;
357 }
358 }
359
360 cursiveFirstPosition = position;
361}
362
363void GlyphIterator::resetCursiveLastExitPoint()
364{
365 if ((lookupFlags & lfBaselineIsLogicalEnd) != 0 && cursiveFirstPosition >= 0 && cursiveLastPosition >= 0) {
366 le_int32 savePosition = position, saveLimit = nextLimit;
367
368 position = cursiveFirstPosition - direction;
369 nextLimit = cursiveLastPosition + direction;
370
371 while (nextInternal()) {
372 glyphPositionAdjustments[position].adjustYPlacement(-cursiveBaselineAdjustment);
373 }
374
375 position = savePosition;
376 nextLimit = saveLimit;
377 }
378
379 cursiveLastPosition = -1;
380 cursiveFirstPosition = -1;
381 cursiveBaselineAdjustment = 0;
382}
383
384void GlyphIterator::setCursiveLastExitPoint(LEPoint &exitPoint)
385{
386 if (direction < 0) {
387 if (position <= nextLimit || position >= prevLimit) {
388 return;
389 }
390 } else {
391 if (position <= prevLimit || position >= nextLimit) {
392 return;
393 }
394 }
395
396 cursiveLastPosition = position;
397 cursiveLastExitPoint = exitPoint;
398
399}
400
401void GlyphIterator::setCursiveBaselineAdjustment(float adjustment)
402{
403 cursiveBaselineAdjustment = adjustment;
404}
405
406void GlyphIterator::adjustCursiveLastGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
407 float xAdvanceAdjust, float yAdvanceAdjust)
408{
409 if (direction < 0) {
410 if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
411 return;
412 }
413 } else {
414 if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
415 return;
416 }
417 }
418
419 glyphPositionAdjustments[cursiveLastPosition].adjustXPlacement(xPlacementAdjust);
420 glyphPositionAdjustments[cursiveLastPosition].adjustYPlacement(yPlacementAdjust);
421 glyphPositionAdjustments[cursiveLastPosition].adjustXAdvance(xAdvanceAdjust);
422 glyphPositionAdjustments[cursiveLastPosition].adjustYAdvance(yAdvanceAdjust);
423}
424
425le_bool GlyphIterator::filterGlyph(le_uint32 index) const
426{
374ca955 427 LEGlyphID glyphID = glyphStorage[index];
b75a7d8f
A
428 le_int32 glyphClass = gcdNoGlyphClass;
429
430 if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
374ca955 431 return TRUE;
b75a7d8f
A
432 }
433
434 if (glyphClassDefinitionTable != NULL) {
435 glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
436 }
437
438 switch (glyphClass)
439 {
440 case gcdNoGlyphClass:
374ca955 441 return FALSE;
b75a7d8f
A
442
443 case gcdSimpleGlyph:
444 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
445
446 case gcdLigatureGlyph:
447 return (lookupFlags & lfIgnoreLigatures) != 0;
448
449 case gcdMarkGlyph:
450 {
451 if ((lookupFlags & lfIgnoreMarks) != 0) {
374ca955 452 return TRUE;
b75a7d8f
A
453 }
454
455 le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
456
457 if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
458 return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
459 }
460
374ca955 461 return FALSE;
b75a7d8f
A
462 }
463
464 case gcdComponentGlyph:
465 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
466
467 default:
374ca955 468 return FALSE;
b75a7d8f
A
469 }
470}
471
374ca955
A
472static const LETag emptyTag = 0;
473static const LETag defaultTag = 0xFFFFFFFF;
b75a7d8f
A
474
475le_bool GlyphIterator::hasFeatureTag() const
476{
477 if (featureTag == defaultTag || featureTag == emptyTag) {
374ca955 478 return TRUE;
b75a7d8f
A
479 }
480
374ca955
A
481 LEErrorCode success = LE_NO_ERROR;
482 const LETag *tagList = (const LETag *) glyphStorage.getAuxData(position, success);
b75a7d8f 483
374ca955 484 if (tagList != NULL) {
b75a7d8f
A
485 for (le_int32 tag = 0; tagList[tag] != emptyTag; tag += 1) {
486 if (tagList[tag] == featureTag) {
374ca955 487 return TRUE;
b75a7d8f
A
488 }
489 }
490 }
491
374ca955 492 return FALSE;
b75a7d8f
A
493}
494
495le_bool GlyphIterator::findFeatureTag()
496{
497 while (nextInternal()) {
498 if (hasFeatureTag()) {
499 prevInternal();
374ca955 500 return TRUE;
b75a7d8f
A
501 }
502 }
503
374ca955 504 return FALSE;
b75a7d8f
A
505}
506
507
508le_bool GlyphIterator::nextInternal(le_uint32 delta)
509{
510 le_int32 newPosition = position;
511
512 while (newPosition != nextLimit && delta > 0) {
513 do {
514 newPosition += direction;
515 } while (newPosition != nextLimit && filterGlyph(newPosition));
516
517 delta -= 1;
518 }
519
520 position = newPosition;
521
522 return position != nextLimit;
523}
524
525le_bool GlyphIterator::next(le_uint32 delta)
526{
527 return nextInternal(delta) && hasFeatureTag();
528}
529
530le_bool GlyphIterator::prevInternal(le_uint32 delta)
531{
532 le_int32 newPosition = position;
533
534 while (newPosition != prevLimit && delta > 0) {
535 do {
536 newPosition -= direction;
537 } while (newPosition != prevLimit && filterGlyph(newPosition));
538
539 delta -= 1;
540 }
541
542 position = newPosition;
543
544 return position != prevLimit;
545}
546
547le_bool GlyphIterator::prev(le_uint32 delta)
548{
549 return prevInternal(delta) && hasFeatureTag();
550}
551
552le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
553{
554 le_int32 component = 0;
555 le_int32 posn;
556
557 for (posn = position; posn != markPosition; posn += direction) {
374ca955 558 if (glyphStorage[posn] == 0xFFFE) {
b75a7d8f
A
559 component += 1;
560 }
561 }
562
563 return component;
564}
565
566// This is basically prevInternal except that it
567// doesn't take a delta argument, and it doesn't
568// filter out 0xFFFE glyphs.
569le_bool GlyphIterator::findMark2Glyph()
570{
571 le_int32 newPosition = position;
572
573 do {
574 newPosition -= direction;
374ca955 575 } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition));
b75a7d8f
A
576
577 position = newPosition;
578
579 return position != prevLimit;
580}
581
582U_NAMESPACE_END