]> git.saurik.com Git - apple/icu.git/blame - icuSources/layout/GlyphIterator.cpp
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
CommitLineData
b75a7d8f 1/*
b75a7d8f 2 *
46f4442e 3 * (C) Copyright IBM Corp. 1998-2008 - 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
73c04bcf
A
18GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
19 FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
374ca955 20 : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
374ca955 21 glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
46f4442e 22 srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
374ca955 23 glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
b75a7d8f
A
24
25{
374ca955
A
26 le_int32 glyphCount = glyphStorage.getGlyphCount();
27
b75a7d8f
A
28 if (theGlyphDefinitionTableHeader != NULL) {
29 glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
30 markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
31 }
32
374ca955
A
33 nextLimit = glyphCount;
34
b75a7d8f
A
35 if (rightToLeft) {
36 direction = -1;
374ca955 37 position = glyphCount;
b75a7d8f 38 nextLimit = -1;
374ca955 39 prevLimit = glyphCount;
b75a7d8f
A
40 }
41}
42
43GlyphIterator::GlyphIterator(GlyphIterator &that)
374ca955 44 : glyphStorage(that.glyphStorage)
b75a7d8f
A
45{
46 direction = that.direction;
47 position = that.position;
48 nextLimit = that.nextLimit;
49 prevLimit = that.prevLimit;
50
b75a7d8f 51 glyphPositionAdjustments = that.glyphPositionAdjustments;
374ca955
A
52 srcIndex = that.srcIndex;
53 destIndex = that.destIndex;
b75a7d8f 54 lookupFlags = that.lookupFlags;
73c04bcf 55 featureMask = that.featureMask;
46f4442e 56 glyphGroup = that.glyphGroup;
b75a7d8f
A
57 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
58 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
59}
60
73c04bcf 61GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
374ca955 62 : glyphStorage(that.glyphStorage)
b75a7d8f
A
63{
64 direction = that.direction;
65 position = that.position;
66 nextLimit = that.nextLimit;
67 prevLimit = that.prevLimit;
68
b75a7d8f 69 glyphPositionAdjustments = that.glyphPositionAdjustments;
374ca955
A
70 srcIndex = that.srcIndex;
71 destIndex = that.destIndex;
b75a7d8f 72 lookupFlags = that.lookupFlags;
73c04bcf 73 featureMask = newFeatureMask;
46f4442e 74 glyphGroup = 0;
b75a7d8f
A
75 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
76 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
77}
78
79GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
374ca955 80 : glyphStorage(that.glyphStorage)
b75a7d8f
A
81{
82 direction = that.direction;
83 position = that.position;
84 nextLimit = that.nextLimit;
85 prevLimit = that.prevLimit;
86
b75a7d8f 87 glyphPositionAdjustments = that.glyphPositionAdjustments;
374ca955
A
88 srcIndex = that.srcIndex;
89 destIndex = that.destIndex;
b75a7d8f 90 lookupFlags = newLookupFlags;
73c04bcf 91 featureMask = that.featureMask;
46f4442e 92 glyphGroup = that.glyphGroup;
b75a7d8f
A
93 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
94 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
95}
96
374ca955 97GlyphIterator::~GlyphIterator()
b75a7d8f 98{
374ca955
A
99 // nothing to do, right?
100}
b75a7d8f 101
73c04bcf 102void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
374ca955 103{
73c04bcf
A
104 position = prevLimit;
105 featureMask = newFeatureMask;
46f4442e 106 glyphGroup = 0;
73c04bcf 107 lookupFlags = newLookupFlags;
374ca955
A
108}
109
729e4ab9 110LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)
374ca955 111{
729e4ab9 112 return glyphStorage.insertGlyphs(position, count, success);
374ca955
A
113}
114
115le_int32 GlyphIterator::applyInsertions()
b75a7d8f 116{
374ca955
A
117 le_int32 newGlyphCount = glyphStorage.applyInsertions();
118
119 if (direction < 0) {
120 prevLimit = newGlyphCount;
121 } else {
122 nextLimit = newGlyphCount;
123 }
124
125 return newGlyphCount;
b75a7d8f
A
126}
127
128le_int32 GlyphIterator::getCurrStreamPosition() const
129{
130 return position;
131}
132
133le_bool GlyphIterator::isRightToLeft() const
134{
135 return direction < 0;
136}
137
138le_bool GlyphIterator::ignoresMarks() const
139{
140 return (lookupFlags & lfIgnoreMarks) != 0;
141}
142
143le_bool GlyphIterator::baselineIsLogicalEnd() const
144{
145 return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
146}
147
b75a7d8f
A
148LEGlyphID GlyphIterator::getCurrGlyphID() const
149{
150 if (direction < 0) {
151 if (position <= nextLimit || position >= prevLimit) {
152 return 0xFFFF;
153 }
154 } else {
155 if (position <= prevLimit || position >= nextLimit) {
156 return 0xFFFF;
157 }
158 }
159
374ca955 160 return glyphStorage[position];
b75a7d8f
A
161}
162
73c04bcf 163void GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const
b75a7d8f
A
164{
165 if (direction < 0) {
73c04bcf 166 if (position <= nextLimit || position >= prevLimit) {
b75a7d8f
A
167 return;
168 }
169 } else {
170 if (position <= prevLimit || position >= nextLimit) {
171 return;
172 }
173 }
174
73c04bcf 175 glyphPositionAdjustments->getEntryPoint(position, entryPoint);
b75a7d8f
A
176}
177
73c04bcf 178void GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const
b75a7d8f 179{
73c04bcf
A
180 if (direction < 0) {
181 if (position <= nextLimit || position >= prevLimit) {
b75a7d8f
A
182 return;
183 }
184 } else {
73c04bcf 185 if (position <= prevLimit || position >= nextLimit) {
b75a7d8f
A
186 return;
187 }
188 }
189
73c04bcf 190 glyphPositionAdjustments->getExitPoint(position, exitPoint);
b75a7d8f
A
191}
192
193void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
194{
374ca955
A
195 LEGlyphID glyph = glyphStorage[position];
196
197 glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
b75a7d8f
A
198}
199
200void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
201{
b75a7d8f
A
202 if (direction < 0) {
203 if (newPosition >= prevLimit) {
204 position = prevLimit;
205 return;
206 }
207
208 if (newPosition <= nextLimit) {
209 position = nextLimit;
210 return;
211 }
212 } else {
213 if (newPosition <= prevLimit) {
214 position = prevLimit;
215 return;
216 }
217
218 if (newPosition >= nextLimit) {
219 position = nextLimit;
220 return;
221 }
222 }
223
224 position = newPosition - direction;
225 next();
226}
227
b75a7d8f
A
228void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
229{
230 if (direction < 0) {
231 if (position <= nextLimit || position >= prevLimit) {
232 return;
233 }
234 } else {
235 if (position <= prevLimit || position >= nextLimit) {
236 return;
237 }
238 }
239
73c04bcf 240 glyphPositionAdjustments->setBaseOffset(position, baseOffset);
b75a7d8f
A
241}
242
243void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
244 float xAdvanceAdjust, float yAdvanceAdjust)
245{
246 if (direction < 0) {
247 if (position <= nextLimit || position >= prevLimit) {
248 return;
249 }
250 } else {
251 if (position <= prevLimit || position >= nextLimit) {
252 return;
253 }
254 }
255
73c04bcf
A
256 glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);
257 glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);
258 glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);
259 glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);
b75a7d8f
A
260}
261
374ca955
A
262void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
263 float xAdvanceAdjust, float yAdvanceAdjust)
264{
265 if (direction < 0) {
266 if (position <= nextLimit || position >= prevLimit) {
267 return;
268 }
269 } else {
270 if (position <= prevLimit || position >= nextLimit) {
271 return;
272 }
273 }
274
73c04bcf
A
275 glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);
276 glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);
277 glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);
278 glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
374ca955
A
279}
280
46f4442e
A
281void GlyphIterator::clearCursiveEntryPoint()
282{
283 if (direction < 0) {
284 if (position <= nextLimit || position >= prevLimit) {
285 return;
286 }
287 } else {
288 if (position <= prevLimit || position >= nextLimit) {
289 return;
290 }
291 }
292
293 glyphPositionAdjustments->clearEntryPoint(position);
294}
295
296void GlyphIterator::clearCursiveExitPoint()
297{
298 if (direction < 0) {
299 if (position <= nextLimit || position >= prevLimit) {
300 return;
301 }
302 } else {
303 if (position <= prevLimit || position >= nextLimit) {
304 return;
305 }
306 }
307
308 glyphPositionAdjustments->clearExitPoint(position);
309}
310
73c04bcf 311void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
b75a7d8f
A
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
73c04bcf 323 glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());
b75a7d8f
A
324}
325
73c04bcf 326void GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)
b75a7d8f
A
327{
328 if (direction < 0) {
329 if (position <= nextLimit || position >= prevLimit) {
330 return;
331 }
332 } else {
333 if (position <= prevLimit || position >= nextLimit) {
334 return;
335 }
336 }
337
73c04bcf 338 glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());
b75a7d8f
A
339}
340
73c04bcf 341void GlyphIterator::setCursiveGlyph()
b75a7d8f
A
342{
343 if (direction < 0) {
73c04bcf 344 if (position <= nextLimit || position >= prevLimit) {
b75a7d8f
A
345 return;
346 }
347 } else {
73c04bcf 348 if (position <= prevLimit || position >= nextLimit) {
b75a7d8f
A
349 return;
350 }
351 }
352
73c04bcf 353 glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());
b75a7d8f
A
354}
355
356le_bool GlyphIterator::filterGlyph(le_uint32 index) const
357{
374ca955 358 LEGlyphID glyphID = glyphStorage[index];
b75a7d8f
A
359 le_int32 glyphClass = gcdNoGlyphClass;
360
361 if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
374ca955 362 return TRUE;
b75a7d8f
A
363 }
364
365 if (glyphClassDefinitionTable != NULL) {
366 glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
367 }
368
369 switch (glyphClass)
370 {
371 case gcdNoGlyphClass:
374ca955 372 return FALSE;
b75a7d8f
A
373
374 case gcdSimpleGlyph:
375 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
376
377 case gcdLigatureGlyph:
378 return (lookupFlags & lfIgnoreLigatures) != 0;
379
380 case gcdMarkGlyph:
381 {
382 if ((lookupFlags & lfIgnoreMarks) != 0) {
374ca955 383 return TRUE;
b75a7d8f
A
384 }
385
386 le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
387
388 if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
389 return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
390 }
391
374ca955 392 return FALSE;
b75a7d8f
A
393 }
394
395 case gcdComponentGlyph:
396 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
397
398 default:
374ca955 399 return FALSE;
b75a7d8f
A
400 }
401}
402
46f4442e 403le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const
b75a7d8f 404{
73c04bcf 405 if (featureMask == 0) {
374ca955 406 return TRUE;
b75a7d8f
A
407 }
408
374ca955 409 LEErrorCode success = LE_NO_ERROR;
73c04bcf 410 FeatureMask fm = glyphStorage.getAuxData(position, success);
b75a7d8f 411
46f4442e 412 return ((fm & featureMask) == featureMask) && (!matchGroup || (le_int32)(fm & LE_GLYPH_GROUP_MASK) == glyphGroup);
b75a7d8f
A
413}
414
415le_bool GlyphIterator::findFeatureTag()
416{
46f4442e
A
417 //glyphGroup = 0;
418
b75a7d8f 419 while (nextInternal()) {
46f4442e
A
420 if (hasFeatureTag(FALSE)) {
421 LEErrorCode success = LE_NO_ERROR;
422
423 glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK);
374ca955 424 return TRUE;
b75a7d8f
A
425 }
426 }
427
374ca955 428 return FALSE;
b75a7d8f
A
429}
430
431
432le_bool GlyphIterator::nextInternal(le_uint32 delta)
433{
434 le_int32 newPosition = position;
435
436 while (newPosition != nextLimit && delta > 0) {
437 do {
438 newPosition += direction;
439 } while (newPosition != nextLimit && filterGlyph(newPosition));
440
441 delta -= 1;
442 }
443
444 position = newPosition;
445
446 return position != nextLimit;
447}
448
449le_bool GlyphIterator::next(le_uint32 delta)
450{
46f4442e 451 return nextInternal(delta) && hasFeatureTag(TRUE);
b75a7d8f
A
452}
453
454le_bool GlyphIterator::prevInternal(le_uint32 delta)
455{
456 le_int32 newPosition = position;
457
458 while (newPosition != prevLimit && delta > 0) {
459 do {
460 newPosition -= direction;
461 } while (newPosition != prevLimit && filterGlyph(newPosition));
462
463 delta -= 1;
464 }
465
466 position = newPosition;
467
468 return position != prevLimit;
469}
470
471le_bool GlyphIterator::prev(le_uint32 delta)
472{
46f4442e 473 return prevInternal(delta) && hasFeatureTag(TRUE);
b75a7d8f
A
474}
475
476le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
477{
478 le_int32 component = 0;
479 le_int32 posn;
480
481 for (posn = position; posn != markPosition; posn += direction) {
374ca955 482 if (glyphStorage[posn] == 0xFFFE) {
b75a7d8f
A
483 component += 1;
484 }
485 }
486
487 return component;
488}
489
490// This is basically prevInternal except that it
491// doesn't take a delta argument, and it doesn't
492// filter out 0xFFFE glyphs.
493le_bool GlyphIterator::findMark2Glyph()
494{
495 le_int32 newPosition = position;
496
497 do {
498 newPosition -= direction;
374ca955 499 } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition));
b75a7d8f
A
500
501 position = newPosition;
502
503 return position != prevLimit;
504}
505
506U_NAMESPACE_END