1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
359d709d503bab6e2b61931737e662dd293b40578ccornelius * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LETypes.h"
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "OpenTypeTables.h"
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "GlyphDefinitionTables.h"
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "GlyphPositionAdjustments.h"
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "GlyphIterator.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LEGlyphStorage.h"
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "Lookups.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LESwaps.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
1959d709d503bab6e2b61931737e662dd293b40578ccornelius                             FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader)
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
2359d709d503bab6e2b61931737e662dd293b40578ccornelius    glyphClassDefinitionTable(), markAttachClassDefinitionTable()
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2659d709d503bab6e2b61931737e662dd293b40578ccornelius  LEErrorCode success = LE_NO_ERROR; // TODO
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyphCount = glyphStorage.getGlyphCount();
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (theGlyphDefinitionTableHeader.isValid()) {
3059d709d503bab6e2b61931737e662dd293b40578ccornelius      glyphClassDefinitionTable = theGlyphDefinitionTableHeader
3159d709d503bab6e2b61931737e662dd293b40578ccornelius        -> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader, success);
3259d709d503bab6e2b61931737e662dd293b40578ccornelius      markAttachClassDefinitionTable = theGlyphDefinitionTableHeader
3359d709d503bab6e2b61931737e662dd293b40578ccornelius        ->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader, success);
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nextLimit = glyphCount;
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (rightToLeft) {
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        direction = -1;
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        position = glyphCount;
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nextLimit = -1;
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        prevLimit = glyphCount;
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
4459d709d503bab6e2b61931737e662dd293b40578ccornelius    filterResetCache();
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGlyphIterator::GlyphIterator(GlyphIterator &that)
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : glyphStorage(that.glyphStorage)
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    direction    = that.direction;
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position     = that.position;
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nextLimit    = that.nextLimit;
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    prevLimit    = that.prevLimit;
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments = that.glyphPositionAdjustments;
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcIndex = that.srcIndex;
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    destIndex = that.destIndex;
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lookupFlags = that.lookupFlags;
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    featureMask = that.featureMask;
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphGroup  = that.glyphGroup;
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphClassDefinitionTable = that.glyphClassDefinitionTable;
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
6359d709d503bab6e2b61931737e662dd293b40578ccornelius    filterResetCache();
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : glyphStorage(that.glyphStorage)
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    direction    = that.direction;
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position     = that.position;
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nextLimit    = that.nextLimit;
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    prevLimit    = that.prevLimit;
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments = that.glyphPositionAdjustments;
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcIndex = that.srcIndex;
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    destIndex = that.destIndex;
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lookupFlags = that.lookupFlags;
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    featureMask = newFeatureMask;
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphGroup  = 0;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphClassDefinitionTable = that.glyphClassDefinitionTable;
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
8259d709d503bab6e2b61931737e662dd293b40578ccornelius    filterResetCache();
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : glyphStorage(that.glyphStorage)
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    direction    = that.direction;
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position     = that.position;
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nextLimit    = that.nextLimit;
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    prevLimit    = that.prevLimit;
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments = that.glyphPositionAdjustments;
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcIndex = that.srcIndex;
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    destIndex = that.destIndex;
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lookupFlags = newLookupFlags;
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    featureMask = that.featureMask;
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphGroup  = that.glyphGroup;
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphClassDefinitionTable = that.glyphClassDefinitionTable;
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
10159d709d503bab6e2b61931737e662dd293b40578ccornelius    filterResetCache();
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGlyphIterator::~GlyphIterator()
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // nothing to do, right?
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position     = prevLimit;
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    featureMask  = newFeatureMask;
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphGroup   = 0;
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lookupFlags  = newLookupFlags;
11559d709d503bab6e2b61931737e662dd293b40578ccornelius    filterResetCache();
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoLEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return glyphStorage.insertGlyphs(position, count, success);
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 GlyphIterator::applyInsertions()
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 newGlyphCount = glyphStorage.applyInsertions();
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        prevLimit = newGlyphCount;
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nextLimit = newGlyphCount;
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return newGlyphCount;
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 GlyphIterator::getCurrStreamPosition() const
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return position;
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::isRightToLeft() const
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return direction < 0;
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::ignoresMarks() const
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (lookupFlags & lfIgnoreMarks) != 0;
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::baselineIsLogicalEnd() const
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLEGlyphID GlyphIterator::getCurrGlyphID() const
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0xFFFF;
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0xFFFF;
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return glyphStorage[position];
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->getEntryPoint(position, entryPoint);
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->getExitPoint(position, exitPoint);
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEGlyphID glyph = glyphStorage[position];
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (newPosition >= prevLimit) {
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            position = prevLimit;
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (newPosition <= nextLimit) {
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            position = nextLimit;
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (newPosition <= prevLimit) {
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            position = prevLimit;
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (newPosition >= nextLimit) {
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            position = nextLimit;
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position = newPosition - direction;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    next();
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setBaseOffset(position, baseOffset);
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                      float xAdvanceAdjust, float yAdvanceAdjust)
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                      float xAdvanceAdjust, float yAdvanceAdjust)
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::clearCursiveEntryPoint()
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->clearEntryPoint(position);
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::clearCursiveExitPoint()
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->clearExitPoint(position);
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GlyphIterator::setCursiveGlyph()
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (direction < 0) {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= nextLimit || position >= prevLimit) {
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (position <= prevLimit || position >= nextLimit) {
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
36459d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid GlyphIterator::filterResetCache(void) {
36559d709d503bab6e2b61931737e662dd293b40578ccornelius  filterCacheValid = FALSE;
36659d709d503bab6e2b61931737e662dd293b40578ccornelius}
36759d709d503bab6e2b61931737e662dd293b40578ccornelius
36859d709d503bab6e2b61931737e662dd293b40578ccorneliusle_bool GlyphIterator::filterGlyph(le_uint32 index)
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEGlyphID glyphID = glyphStorage[index];
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!filterCacheValid || filterCache.id != glyphID) {
37359d709d503bab6e2b61931737e662dd293b40578ccornelius      filterCache.id = glyphID;
37459d709d503bab6e2b61931737e662dd293b40578ccornelius
37559d709d503bab6e2b61931737e662dd293b40578ccornelius      le_bool &filterResult = filterCache.result;  // NB: Making this a reference to accept the updated value, in case
37659d709d503bab6e2b61931737e662dd293b40578ccornelius                                               // we want more fancy cacheing in the future.
37759d709d503bab6e2b61931737e662dd293b40578ccornelius      if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
37859d709d503bab6e2b61931737e662dd293b40578ccornelius        filterResult = TRUE;
37959d709d503bab6e2b61931737e662dd293b40578ccornelius      } else {
38059d709d503bab6e2b61931737e662dd293b40578ccornelius        LEErrorCode success = LE_NO_ERROR;
38159d709d503bab6e2b61931737e662dd293b40578ccornelius        le_int32 glyphClass = gcdNoGlyphClass;
38259d709d503bab6e2b61931737e662dd293b40578ccornelius        if (glyphClassDefinitionTable.isValid()) {
38359d709d503bab6e2b61931737e662dd293b40578ccornelius          glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
38559d709d503bab6e2b61931737e662dd293b40578ccornelius        switch (glyphClass) {
38659d709d503bab6e2b61931737e662dd293b40578ccornelius        case gcdNoGlyphClass:
38759d709d503bab6e2b61931737e662dd293b40578ccornelius          filterResult = FALSE;
38859d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
38959d709d503bab6e2b61931737e662dd293b40578ccornelius
39059d709d503bab6e2b61931737e662dd293b40578ccornelius        case gcdSimpleGlyph:
39159d709d503bab6e2b61931737e662dd293b40578ccornelius          filterResult = (lookupFlags & lfIgnoreBaseGlyphs) != 0;
39259d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
39359d709d503bab6e2b61931737e662dd293b40578ccornelius
39459d709d503bab6e2b61931737e662dd293b40578ccornelius        case gcdLigatureGlyph:
39559d709d503bab6e2b61931737e662dd293b40578ccornelius          filterResult = (lookupFlags & lfIgnoreLigatures) != 0;
39659d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
39759d709d503bab6e2b61931737e662dd293b40578ccornelius
39859d709d503bab6e2b61931737e662dd293b40578ccornelius        case gcdMarkGlyph:
39959d709d503bab6e2b61931737e662dd293b40578ccornelius          if ((lookupFlags & lfIgnoreMarks) != 0) {
40059d709d503bab6e2b61931737e662dd293b40578ccornelius            filterResult = TRUE;
40159d709d503bab6e2b61931737e662dd293b40578ccornelius          } else {
40259d709d503bab6e2b61931737e662dd293b40578ccornelius            le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
40359d709d503bab6e2b61931737e662dd293b40578ccornelius
40459d709d503bab6e2b61931737e662dd293b40578ccornelius            if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {
40559d709d503bab6e2b61931737e662dd293b40578ccornelius              filterResult = (markAttachClassDefinitionTable
40659d709d503bab6e2b61931737e662dd293b40578ccornelius                          -> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType);
40759d709d503bab6e2b61931737e662dd293b40578ccornelius            } else {
40859d709d503bab6e2b61931737e662dd293b40578ccornelius              filterResult = FALSE;
40959d709d503bab6e2b61931737e662dd293b40578ccornelius            }
41059d709d503bab6e2b61931737e662dd293b40578ccornelius          }
41159d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
41259d709d503bab6e2b61931737e662dd293b40578ccornelius
41359d709d503bab6e2b61931737e662dd293b40578ccornelius        case gcdComponentGlyph:
41459d709d503bab6e2b61931737e662dd293b40578ccornelius          filterResult = ((lookupFlags & lfIgnoreBaseGlyphs) != 0);
41559d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
41659d709d503bab6e2b61931737e662dd293b40578ccornelius
41759d709d503bab6e2b61931737e662dd293b40578ccornelius        default:
41859d709d503bab6e2b61931737e662dd293b40578ccornelius          filterResult = FALSE;
41959d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
42159d709d503bab6e2b61931737e662dd293b40578ccornelius      }
42259d709d503bab6e2b61931737e662dd293b40578ccornelius      filterCacheValid = TRUE;
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
42459d709d503bab6e2b61931737e662dd293b40578ccornelius
42559d709d503bab6e2b61931737e662dd293b40578ccornelius    return filterCache.result;
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (featureMask == 0) {
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEErrorCode success = LE_NO_ERROR;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FeatureMask fm = glyphStorage.getAuxData(position, success);
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
43785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return ((fm & featureMask) == featureMask) && (!matchGroup || (le_int32)(fm & LE_GLYPH_GROUP_MASK) == glyphGroup);
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::findFeatureTag()
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  //glyphGroup = 0;
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (nextInternal()) {
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (hasFeatureTag(FALSE)) {
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            LEErrorCode success = LE_NO_ERROR;
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK);
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return TRUE;
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::nextInternal(le_uint32 delta)
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 newPosition = position;
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (newPosition != nextLimit && delta > 0) {
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        do {
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            newPosition += direction;
46459d709d503bab6e2b61931737e662dd293b40578ccornelius            //fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } while (newPosition != nextLimit && filterGlyph(newPosition));
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delta -= 1;
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position = newPosition;
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
47259d709d503bab6e2b61931737e662dd293b40578ccornelius    //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return position != nextLimit;
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::next(le_uint32 delta)
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return nextInternal(delta) && hasFeatureTag(TRUE);
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::prevInternal(le_uint32 delta)
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 newPosition = position;
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (newPosition != prevLimit && delta > 0) {
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        do {
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            newPosition -= direction;
48859d709d503bab6e2b61931737e662dd293b40578ccornelius            //fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } while (newPosition != prevLimit && filterGlyph(newPosition));
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delta -= 1;
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position = newPosition;
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49659d709d503bab6e2b61931737e662dd293b40578ccornelius    //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return position != prevLimit;
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::prev(le_uint32 delta)
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return prevInternal(delta) && hasFeatureTag(TRUE);
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 component = 0;
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 posn;
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (posn = position; posn != markPosition; posn += direction) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (glyphStorage[posn] == 0xFFFE) {
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            component += 1;
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return component;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is basically prevInternal except that it
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// doesn't take a delta argument, and it doesn't
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// filter out 0xFFFE glyphs.
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_bool GlyphIterator::findMark2Glyph()
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 newPosition = position;
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    do {
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        newPosition -= direction;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition));
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    position = newPosition;
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return position != prevLimit;
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
536