~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/layout/ContextualSubstSubtables.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * @(#)ContextualSubstSubtables.cpp     1.11 00/03/15
3
 
 *
4
 
 * (C) Copyright IBM Corp. 1998, 1999, 2000, 2001 - All Rights Reserved
5
 
 *
6
 
 */
7
 
 
8
 
#include "LETypes.h"
9
 
#include "LEFontInstance.h"
10
 
#include "OpenTypeTables.h"
11
 
#include "GlyphSubstitutionTables.h"
12
 
#include "ContextualSubstSubtables.h"
13
 
#include "GlyphIterator.h"
14
 
#include "LookupProcessor.h"
15
 
#include "CoverageTables.h"
16
 
#include "LESwaps.h"
17
 
 
18
 
U_NAMESPACE_BEGIN
19
 
 
20
 
/*
21
 
    NOTE: This could be optimized somewhat by keeping track
22
 
    of the previous sequenceIndex in the loop and doing next()
23
 
    or prev() of the delta between that and the current
24
 
    sequenceIndex instead of always resetting to the front.
25
 
*/
26
 
void ContextualSubstitutionBase::applySubstitutionLookups(
27
 
        const LookupProcessor *lookupProcessor,
28
 
        const SubstitutionLookupRecord *substLookupRecordArray,
29
 
        le_uint16 substCount,
30
 
        GlyphIterator *glyphIterator,
31
 
        const LEFontInstance *fontInstance,
32
 
        le_int32 position)
33
 
{
34
 
    GlyphIterator tempIterator(*glyphIterator);
35
 
 
36
 
    for (le_int16 subst = 0; subst < substCount; subst += 1) {
37
 
        le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex);
38
 
        le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex);
39
 
 
40
 
        tempIterator.setCurrStreamPosition(position);
41
 
        tempIterator.next(sequenceIndex);
42
 
 
43
 
        lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance);
44
 
    }
45
 
}
46
 
 
47
 
le_bool ContextualSubstitutionBase::matchGlyphIDs(const LEGlyphID *glyphArray, le_uint16 glyphCount,
48
 
                                               GlyphIterator *glyphIterator)
49
 
{
50
 
    for (le_uint16 match = 0; match < glyphCount; match += 1) {
51
 
        if (! glyphIterator->next()) {
52
 
            return false;
53
 
        }
54
 
 
55
 
        LEGlyphID glyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
56
 
 
57
 
        if (glyph != SWAPW(glyphArray[match])) {
58
 
            return false;
59
 
        }
60
 
    }
61
 
 
62
 
    return true;
63
 
}
64
 
 
65
 
le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArray, le_uint16 glyphCount,
66
 
                                               GlyphIterator *glyphIterator,
67
 
                                               const ClassDefinitionTable *classDefinitionTable)
68
 
{
69
 
    for (le_uint16 match = 0; match < glyphCount; match += 1) {
70
 
        if (! glyphIterator->next()) {
71
 
            return false;
72
 
        }
73
 
 
74
 
        LEGlyphID glyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
75
 
        le_int32 glyphClass = classDefinitionTable->getGlyphClass(glyph);
76
 
        le_int32 matchClass = SWAPW(classArray[match]);
77
 
 
78
 
        if (glyphClass != matchClass) {
79
 
            // Some fonts, e.g. Traditional Arabic, have classes
80
 
            // in the class array which aren't in the class definition
81
 
            // table. If we're looking for such a class, pretend that
82
 
            // we found it.
83
 
            if (classDefinitionTable->hasGlyphClass(matchClass)) {
84
 
                return false;
85
 
            }
86
 
        }
87
 
    }
88
 
 
89
 
    return true;
90
 
}
91
 
 
92
 
le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTableOffsetArray, le_uint16 glyphCount,
93
 
                                                     GlyphIterator *glyphIterator, const char *offsetBase)
94
 
{
95
 
    for (le_uint16 glyph = 0; glyph < glyphCount; glyph += 1) {
96
 
        Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]);
97
 
        const CoverageTable *coverageTable = (const CoverageTable *) (offsetBase + coverageTableOffset);
98
 
 
99
 
        if (! glyphIterator->next()) {
100
 
            return false;
101
 
        }
102
 
 
103
 
        if (coverageTable->getGlyphCoverage((LEGlyphID) glyphIterator->getCurrGlyphID()) < 0) {
104
 
            return false;
105
 
        }
106
 
    }
107
 
 
108
 
    return true;
109
 
}
110
 
 
111
 
le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
112
 
                                               const LEFontInstance *fontInstance) const
113
 
{
114
 
    switch(SWAPW(subtableFormat))
115
 
    {
116
 
    case 0:
117
 
        return 0;
118
 
 
119
 
    case 1:
120
 
    {
121
 
        const ContextualSubstitutionFormat1Subtable *subtable = (const ContextualSubstitutionFormat1Subtable *) this;
122
 
 
123
 
        return subtable->process(lookupProcessor, glyphIterator, fontInstance);
124
 
    }
125
 
 
126
 
    case 2:
127
 
    {
128
 
        const ContextualSubstitutionFormat2Subtable *subtable = (const ContextualSubstitutionFormat2Subtable *) this;
129
 
 
130
 
        return subtable->process(lookupProcessor, glyphIterator, fontInstance);
131
 
    }
132
 
 
133
 
    case 3:
134
 
    {
135
 
        const ContextualSubstitutionFormat3Subtable *subtable = (const ContextualSubstitutionFormat3Subtable *) this;
136
 
 
137
 
        return subtable->process(lookupProcessor, glyphIterator, fontInstance);
138
 
    }
139
 
 
140
 
    default:
141
 
        return 0;
142
 
    }
143
 
}
144
 
 
145
 
le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
146
 
                                                      const LEFontInstance *fontInstance) const
147
 
{
148
 
    LEGlyphID glyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
149
 
    le_int32 coverageIndex = getGlyphCoverage(glyph);
150
 
 
151
 
    if (coverageIndex >= 0) {
152
 
        le_uint16 srSetCount = SWAPW(subRuleSetCount);
153
 
 
154
 
        if (coverageIndex < srSetCount) {
155
 
            Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]);
156
 
            const SubRuleSetTable *subRuleSetTable =
157
 
                (const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset);
158
 
            le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount);
159
 
            le_int32 position = glyphIterator->getCurrStreamPosition();
160
 
 
161
 
            for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) {
162
 
                Offset subRuleTableOffset =
163
 
                    SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]);
164
 
                const SubRuleTable *subRuleTable =
165
 
                    (const SubRuleTable *) ((char *) subRuleSetTable + subRuleTableOffset);
166
 
                le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
167
 
                le_uint16 substCount = SWAPW(subRuleTable->substCount);
168
 
 
169
 
                if (matchGlyphIDs(subRuleTable->inputGlyphArray, matchCount, glyphIterator)) {
170
 
                    const SubstitutionLookupRecord *substLookupRecordArray = 
171
 
                        (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount];
172
 
 
173
 
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position);
174
 
 
175
 
                    return matchCount + 1;
176
 
                }
177
 
 
178
 
                glyphIterator->setCurrStreamPosition(position);
179
 
            }
180
 
        }
181
 
 
182
 
        // XXX If we get here, the table is mal-formed...
183
 
    }
184
 
    
185
 
    return 0;
186
 
}
187
 
 
188
 
le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
189
 
                                                      const LEFontInstance *fontInstance) const
190
 
{
191
 
    LEGlyphID glyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
192
 
    le_int32 coverageIndex = getGlyphCoverage(glyph);
193
 
 
194
 
    if (coverageIndex >= 0) {
195
 
        const ClassDefinitionTable *classDefinitionTable =
196
 
            (const ClassDefinitionTable *) ((char *) this + SWAPW(classDefTableOffset));
197
 
        le_uint16 scSetCount = SWAPW(subClassSetCount);
198
 
        le_int32 setClass = classDefinitionTable->getGlyphClass((LEGlyphID) glyphIterator->getCurrGlyphID());
199
 
 
200
 
        if (setClass < scSetCount && subClassSetTableOffsetArray[setClass] != 0) {
201
 
            Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]);
202
 
            const SubClassSetTable *subClassSetTable =
203
 
                (const SubClassSetTable *) ((char *) this + subClassSetTableOffset);
204
 
            le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount);
205
 
            le_int32 position = glyphIterator->getCurrStreamPosition();
206
 
 
207
 
            for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) {
208
 
                Offset subClassRuleTableOffset =
209
 
                    SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]);
210
 
                const SubClassRuleTable *subClassRuleTable =
211
 
                    (const SubClassRuleTable *) ((char *) subClassSetTable + subClassRuleTableOffset);
212
 
                le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1;
213
 
                le_uint16 substCount = SWAPW(subClassRuleTable->substCount);
214
 
 
215
 
                if (matchGlyphClasses(subClassRuleTable->classArray, matchCount, glyphIterator, classDefinitionTable)) {
216
 
                    const SubstitutionLookupRecord *substLookupRecordArray = 
217
 
                        (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount];
218
 
 
219
 
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position);
220
 
 
221
 
                    return matchCount + 1;
222
 
                }
223
 
 
224
 
                glyphIterator->setCurrStreamPosition(position);
225
 
            }
226
 
        }
227
 
 
228
 
        // XXX If we get here, the table is mal-formed...
229
 
    }
230
 
    
231
 
    return 0;
232
 
}
233
 
 
234
 
le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
235
 
                                                      const LEFontInstance *fontInstance)const 
236
 
{
237
 
    le_uint16 gCount = SWAPW(glyphCount);
238
 
    le_uint16 subCount = SWAPW(substCount);
239
 
    le_int32 position = glyphIterator->getCurrStreamPosition();
240
 
 
241
 
    // Back up the glyph iterator so that we
242
 
    // can call next() before the check, which
243
 
    // will leave it pointing at the last glyph
244
 
    // that matched when we're done.
245
 
    glyphIterator->prev();
246
 
 
247
 
    if (ContextualSubstitutionBase::matchGlyphCoverages(coverageTableOffsetArray, gCount, glyphIterator, (const char *) this)) {
248
 
        const SubstitutionLookupRecord *substLookupRecordArray = 
249
 
            (const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount];
250
 
 
251
 
        ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position);
252
 
 
253
 
        return gCount + 1;
254
 
    }
255
 
 
256
 
    glyphIterator->setCurrStreamPosition(position);
257
 
 
258
 
    return 0;
259
 
}
260
 
 
261
 
le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
262
 
                                                       const LEFontInstance *fontInstance) const
263
 
{
264
 
    switch(SWAPW(subtableFormat))
265
 
    {
266
 
    case 0:
267
 
        return 0;
268
 
 
269
 
    case 1:
270
 
    {
271
 
        const ChainingContextualSubstitutionFormat1Subtable *subtable = (const ChainingContextualSubstitutionFormat1Subtable *) this;
272
 
 
273
 
        return subtable->process(lookupProcessor, glyphIterator, fontInstance);
274
 
    }
275
 
 
276
 
    case 2:
277
 
    {
278
 
        const ChainingContextualSubstitutionFormat2Subtable *subtable = (const ChainingContextualSubstitutionFormat2Subtable *) this;
279
 
 
280
 
        return subtable->process(lookupProcessor, glyphIterator, fontInstance);
281
 
    }
282
 
 
283
 
    case 3:
284
 
    {
285
 
        const ChainingContextualSubstitutionFormat3Subtable *subtable = (const ChainingContextualSubstitutionFormat3Subtable *) this;
286
 
 
287
 
        return subtable->process(lookupProcessor, glyphIterator, fontInstance);
288
 
    }
289
 
 
290
 
    default:
291
 
        return 0;
292
 
    }
293
 
}
294
 
 
295
 
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
296
 
                                                              const LEFontInstance *fontInstance) const
297
 
{
298
 
    LEGlyphID glyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
299
 
    le_int32 coverageIndex = getGlyphCoverage(glyph);
300
 
 
301
 
    if (coverageIndex >= 0) {
302
 
        le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
303
 
 
304
 
        if (coverageIndex < srSetCount) {
305
 
            Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
306
 
            const ChainSubRuleSetTable *chainSubRuleSetTable =
307
 
                (const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset);
308
 
            le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
309
 
            le_int32 position = glyphIterator->getCurrStreamPosition();
310
 
            GlyphIterator tempIterator(*glyphIterator);
311
 
 
312
 
            for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
313
 
                Offset chainSubRuleTableOffset =
314
 
                    SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
315
 
                const ChainSubRuleTable *chainSubRuleTable =
316
 
                    (const ChainSubRuleTable *) ((char *) chainSubRuleSetTable + chainSubRuleTableOffset);
317
 
                le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
318
 
                le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
319
 
                const LEGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1];
320
 
                le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
321
 
                const LEGlyphID *lookaheadGlyphArray = &inputGlyphArray[inputGlyphCount + 1];
322
 
                le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);
323
 
 
324
 
                tempIterator.setCurrStreamPosition(position);
325
 
                tempIterator.prev(backtrackGlyphCount + 1);
326
 
                if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator)) {
327
 
                    continue;
328
 
                }
329
 
 
330
 
                tempIterator.setCurrStreamPosition(position);
331
 
                tempIterator.next(inputGlyphCount);
332
 
                if (!matchGlyphIDs(lookaheadGlyphArray, lookaheadGlyphCount, &tempIterator)) {
333
 
                    continue;
334
 
                }
335
 
 
336
 
                if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
337
 
                    const SubstitutionLookupRecord *substLookupRecordArray = 
338
 
                        (const SubstitutionLookupRecord *) &lookaheadGlyphArray[lookaheadGlyphCount + 1];
339
 
 
340
 
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position);
341
 
 
342
 
                    return inputGlyphCount + 1;
343
 
                }
344
 
 
345
 
                glyphIterator->setCurrStreamPosition(position);
346
 
            }
347
 
        }
348
 
 
349
 
        // XXX If we get here, the table is mal-formed...
350
 
    }
351
 
    
352
 
    return 0;
353
 
}
354
 
 
355
 
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
356
 
                                                              const LEFontInstance *fontInstance) const
357
 
{
358
 
    LEGlyphID glyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
359
 
    le_int32 coverageIndex = getGlyphCoverage(glyph);
360
 
 
361
 
    if (coverageIndex >= 0) {
362
 
        const ClassDefinitionTable *backtrackClassDefinitionTable =
363
 
            (const ClassDefinitionTable *) ((char *) this + SWAPW(backtrackClassDefTableOffset));
364
 
        const ClassDefinitionTable *inputClassDefinitionTable =
365
 
            (const ClassDefinitionTable *) ((char *) this + SWAPW(inputClassDefTableOffset));
366
 
        const ClassDefinitionTable *lookaheadClassDefinitionTable =
367
 
            (const ClassDefinitionTable *) ((char *) this + SWAPW(lookaheadClassDefTableOffset));
368
 
        le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
369
 
        le_int32 setClass = inputClassDefinitionTable->getGlyphClass((LEGlyphID) glyphIterator->getCurrGlyphID());
370
 
 
371
 
        if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
372
 
            Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
373
 
            const ChainSubClassSetTable *chainSubClassSetTable =
374
 
                (const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset);
375
 
            le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
376
 
            le_int32 position = glyphIterator->getCurrStreamPosition();
377
 
            GlyphIterator tempIterator(*glyphIterator);
378
 
 
379
 
            for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
380
 
                Offset chainSubClassRuleTableOffset =
381
 
                    SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
382
 
                const ChainSubClassRuleTable *chainSubClassRuleTable =
383
 
                    (const ChainSubClassRuleTable *) ((char *) chainSubClassSetTable + chainSubClassRuleTableOffset);
384
 
                le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
385
 
                le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
386
 
                const le_uint16 *inputClassArray = &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1];
387
 
                le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray[inputGlyphCount]);
388
 
                const le_uint16 *lookaheadClassArray = &inputClassArray[inputGlyphCount + 1];
389
 
                le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);
390
 
                
391
 
 
392
 
                tempIterator.setCurrStreamPosition(position);
393
 
                tempIterator.prev(backtrackGlyphCount + 1);
394
 
                if (! matchGlyphClasses(chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount,
395
 
                    &tempIterator, backtrackClassDefinitionTable)) {
396
 
                    continue;
397
 
                }
398
 
 
399
 
                tempIterator.setCurrStreamPosition(position);
400
 
                tempIterator.next(inputGlyphCount);
401
 
                if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable)) {
402
 
                    continue;
403
 
                }
404
 
 
405
 
                if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable)) {
406
 
                    const SubstitutionLookupRecord *substLookupRecordArray = 
407
 
                        (const SubstitutionLookupRecord *) &lookaheadClassArray[lookaheadGlyphCount + 1];
408
 
 
409
 
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position);
410
 
 
411
 
                    return inputGlyphCount + 1;
412
 
                }
413
 
 
414
 
                glyphIterator->setCurrStreamPosition(position);
415
 
            }
416
 
        }
417
 
 
418
 
        // XXX If we get here, the table is mal-formed...
419
 
    }
420
 
    
421
 
    return 0;
422
 
}
423
 
 
424
 
le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
425
 
                                                              const LEFontInstance *fontInstance) const
426
 
{
427
 
    le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
428
 
    le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
429
 
    const Offset *inputCoverageTableOffsetArray = &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1];
430
 
    const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
431
 
    const Offset *lookaheadCoverageTableOffsetArray = &inputCoverageTableOffsetArray[inputGlyphCount + 1];
432
 
    le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]);
433
 
    le_int32 position = glyphIterator->getCurrStreamPosition();
434
 
    GlyphIterator tempIterator(*glyphIterator);
435
 
 
436
 
    tempIterator.prev(backtrkGlyphCount + 1);
437
 
    if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray,
438
 
        backtrkGlyphCount, &tempIterator, (const char *) this)) {
439
 
        return 0;
440
 
    }
441
 
 
442
 
    tempIterator.setCurrStreamPosition(position);
443
 
    tempIterator.next(inputGlyphCount - 1);
444
 
    if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
445
 
        lookaheadGlyphCount, &tempIterator, (const char *) this)) {
446
 
        return 0;
447
 
    }
448
 
 
449
 
    // Back up the glyph iterator so that we
450
 
    // can call next() before the check, which
451
 
    // will leave it pointing at the last glyph
452
 
    // that matched when we're done.
453
 
    glyphIterator->prev();
454
 
 
455
 
    if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray,
456
 
        inputGlyphCount, glyphIterator, (const char *) this)) {
457
 
        const SubstitutionLookupRecord *substLookupRecordArray = 
458
 
            (const SubstitutionLookupRecord *) &lookaheadCoverageTableOffsetArray[lookaheadGlyphCount + 1];
459
 
 
460
 
        ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position);
461
 
 
462
 
        return inputGlyphCount + 1;
463
 
    }
464
 
 
465
 
    glyphIterator->setCurrStreamPosition(position);
466
 
 
467
 
    return 0;
468
 
}
469
 
 
470
 
U_NAMESPACE_END