ContextualSubstSubtables.cpp 30.3 KB
Newer Older
D
duke 已提交
1 2 3 4 5
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
6
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
7
 * particular file as subject to the "Classpath" exception as provided
8
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
20 21 22
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
 *
 */

/*
 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
 *
 */

#include "LETypes.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
#include "GlyphSubstitutionTables.h"
#include "ContextualSubstSubtables.h"
#include "GlyphIterator.h"
#include "LookupProcessor.h"
#include "CoverageTables.h"
#include "LESwaps.h"

41 42
U_NAMESPACE_BEGIN

D
duke 已提交
43 44 45 46 47 48 49 50
/*
    NOTE: This could be optimized somewhat by keeping track
    of the previous sequenceIndex in the loop and doing next()
    or prev() of the delta between that and the current
    sequenceIndex instead of always resetting to the front.
*/
void ContextualSubstitutionBase::applySubstitutionLookups(
        const LookupProcessor *lookupProcessor,
P
prr 已提交
51
        const LEReferenceToArrayOf<SubstitutionLookupRecord>& substLookupRecordArray,
D
duke 已提交
52 53 54
        le_uint16 substCount,
        GlyphIterator *glyphIterator,
        const LEFontInstance *fontInstance,
S
srl 已提交
55 56
        le_int32 position,
        LEErrorCode& success)
D
duke 已提交
57
{
S
srl 已提交
58 59 60 61
    if (LE_FAILURE(success)) {
        return;
    }

D
duke 已提交
62
    GlyphIterator tempIterator(*glyphIterator);
P
prr 已提交
63
    const SubstitutionLookupRecord *substLookupRecordArrayPtr = substLookupRecordArray.getAlias(); // OK to dereference, range checked against substCount below.
D
duke 已提交
64

S
srl 已提交
65
    for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
P
prr 已提交
66 67
        le_uint16 sequenceIndex = SWAPW(substLookupRecordArrayPtr[subst].sequenceIndex);
        le_uint16 lookupListIndex = SWAPW(substLookupRecordArrayPtr[subst].lookupListIndex);
D
duke 已提交
68 69

        tempIterator.setCurrStreamPosition(position);
70 71 72 73
        if (!tempIterator.next(sequenceIndex)) {
            success = LE_INTERNAL_ERROR;
            return;
        }
D
duke 已提交
74

S
srl 已提交
75
        lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance, success);
D
duke 已提交
76 77 78
    }
}

P
prr 已提交
79
le_bool ContextualSubstitutionBase::matchGlyphIDs(const LEReferenceToArrayOf<TTGlyphID>& glyphArray, le_uint16 glyphCount,
D
duke 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
                                               GlyphIterator *glyphIterator, le_bool backtrack)
{
    le_int32 direction = 1;
    le_int32 match = 0;

    if (backtrack) {
        match = glyphCount -1;
        direction = -1;
    }

    while (glyphCount > 0) {
        if (! glyphIterator->next()) {
            return FALSE;
        }

        TTGlyphID glyph = (TTGlyphID) glyphIterator->getCurrGlyphID();

        if (glyph != SWAPW(glyphArray[match])) {
            return FALSE;
        }

        glyphCount -= 1;
        match += direction;
    }

    return TRUE;
}

P
prr 已提交
108 109 110 111 112 113 114
le_bool ContextualSubstitutionBase::matchGlyphClasses(
    const LEReferenceToArrayOf<le_uint16> &classArray,
    le_uint16 glyphCount,
    GlyphIterator *glyphIterator,
    const LEReferenceTo<ClassDefinitionTable> &classDefinitionTable,
    LEErrorCode &success,
    le_bool backtrack)
D
duke 已提交
115
{
P
prr 已提交
116 117
    if (LE_FAILURE(success)) { return FALSE; }

D
duke 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131
    le_int32 direction = 1;
    le_int32 match = 0;

    if (backtrack) {
        match = glyphCount - 1;
        direction = -1;
    }

    while (glyphCount > 0) {
        if (! glyphIterator->next()) {
            return FALSE;
        }

        LEGlyphID glyph = glyphIterator->getCurrGlyphID();
P
prr 已提交
132
        le_int32 glyphClass = classDefinitionTable->getGlyphClass(classDefinitionTable, glyph, success);
D
duke 已提交
133 134 135 136 137 138 139
        le_int32 matchClass = SWAPW(classArray[match]);

        if (glyphClass != matchClass) {
            // Some fonts, e.g. Traditional Arabic, have classes
            // in the class array which aren't in the class definition
            // table. If we're looking for such a class, pretend that
            // we found it.
P
prr 已提交
140
            if (classDefinitionTable->hasGlyphClass(classDefinitionTable, matchClass, success)) {
D
duke 已提交
141 142 143 144 145 146 147 148 149 150 151
                return FALSE;
            }
        }

        glyphCount -= 1;
        match += direction;
    }

    return TRUE;
}

P
prr 已提交
152 153
le_bool ContextualSubstitutionBase::matchGlyphCoverages(const LEReferenceToArrayOf<Offset> &coverageTableOffsetArray, le_uint16 glyphCount,
GlyphIterator *glyphIterator, const LETableReference &offsetBase, LEErrorCode &success, le_bool backtrack)
D
duke 已提交
154 155 156 157 158 159 160 161 162 163 164
{
    le_int32 direction = 1;
    le_int32 glyph = 0;

    if (backtrack) {
        glyph = glyphCount - 1;
        direction = -1;
    }

    while (glyphCount > 0) {
        Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]);
P
prr 已提交
165
        LEReferenceTo<CoverageTable> coverageTable(offsetBase, success, coverageTableOffset);
D
duke 已提交
166

P
prr 已提交
167
        if (LE_FAILURE(success) || ! glyphIterator->next()) {
D
duke 已提交
168 169 170
            return FALSE;
        }

P
prr 已提交
171 172 173
        if (coverageTable->getGlyphCoverage(coverageTable,
                                            (LEGlyphID) glyphIterator->getCurrGlyphID(),
                                            success) < 0) {
D
duke 已提交
174 175 176 177 178 179 180 181 182 183
            return FALSE;
        }

        glyphCount -= 1;
        glyph += direction;
    }

    return TRUE;
}

P
prr 已提交
184
le_uint32 ContextualSubstitutionSubtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
S
srl 已提交
185 186 187
                                                  GlyphIterator *glyphIterator,
                                                  const LEFontInstance *fontInstance,
                                                  LEErrorCode& success) const
D
duke 已提交
188
{
S
srl 已提交
189 190 191 192
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
193 194 195 196 197 198 199
    switch(SWAPW(subtableFormat))
    {
    case 0:
        return 0;

    case 1:
    {
P
prr 已提交
200 201 202 203 204
      LEReferenceTo<ContextualSubstitutionFormat1Subtable> subtable(base, success, (const ContextualSubstitutionFormat1Subtable *) this);
      if( LE_FAILURE(success) ) {
        return 0;
      }
      return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
D
duke 已提交
205 206 207 208
    }

    case 2:
    {
P
prr 已提交
209 210 211 212 213
      LEReferenceTo<ContextualSubstitutionFormat2Subtable> subtable(base, success, (const ContextualSubstitutionFormat2Subtable *) this);
      if( LE_FAILURE(success) ) {
        return 0;
      }
      return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
D
duke 已提交
214 215 216 217
    }

    case 3:
    {
P
prr 已提交
218 219 220 221 222
      LEReferenceTo<ContextualSubstitutionFormat3Subtable> subtable(base, success, (const ContextualSubstitutionFormat3Subtable *) this);
      if( LE_FAILURE(success) ) {
        return 0;
      }
      return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
D
duke 已提交
223 224 225 226 227 228 229
    }

    default:
        return 0;
    }
}

P
prr 已提交
230
le_uint32 ContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
S
srl 已提交
231 232 233
                                                         GlyphIterator *glyphIterator,
                                                         const LEFontInstance *fontInstance,
                                                         LEErrorCode& success) const
D
duke 已提交
234
{
S
srl 已提交
235 236 237 238
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
239
    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
P
prr 已提交
240
    le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
241 242 243
    if (LE_FAILURE(success)) {
        return 0;
    }
D
duke 已提交
244 245 246 247 248

    if (coverageIndex >= 0) {
        le_uint16 srSetCount = SWAPW(subRuleSetCount);

        if (coverageIndex < srSetCount) {
V
vadim 已提交
249 250
            LEReferenceToArrayOf<Offset>
                subRuleSetTableOffsetArrayRef(base, success, subRuleSetTableOffsetArray, srSetCount);
251 252 253
            if (LE_FAILURE(success)) {
                return 0;
            }
D
duke 已提交
254
            Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]);
V
vadim 已提交
255 256
            LEReferenceTo<SubRuleSetTable> subRuleSetTable(base, success, subRuleSetTableOffset);
            if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
257 258 259
            le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount);
            le_int32 position = glyphIterator->getCurrStreamPosition();

260 261 262 263 264
            LEReferenceToArrayOf<Offset> subRuleTableOffsetArrayRef(base, success,
                    subRuleSetTable->subRuleTableOffsetArray, subRuleCount);
            if (LE_FAILURE(success)) {
                return 0;
            }
D
duke 已提交
265 266 267
            for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) {
                Offset subRuleTableOffset =
                    SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]);
P
prr 已提交
268 269
                LEReferenceTo<SubRuleTable>
                     subRuleTable(subRuleSetTable, success, subRuleTableOffset);
V
vadim 已提交
270
                if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
271 272
                le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
                le_uint16 substCount = SWAPW(subRuleTable->substCount);
P
prr 已提交
273
                LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, subRuleTable->inputGlyphArray, matchCount+2);
P
prr 已提交
274
                if (LE_FAILURE(success)) { return 0; }
P
prr 已提交
275 276 277
                if (matchGlyphIDs(inputGlyphArray, matchCount, glyphIterator)) {
                  LEReferenceToArrayOf<SubstitutionLookupRecord>
                    substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount], substCount);
D
duke 已提交
278

S
srl 已提交
279
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
D
duke 已提交
280 281 282 283 284 285 286 287 288 289 290 291 292 293

                    return matchCount + 1;
                }

                glyphIterator->setCurrStreamPosition(position);
            }
        }

        // XXX If we get here, the table is mal-formed...
    }

    return 0;
}

P
prr 已提交
294 295 296 297 298
le_uint32 ContextualSubstitutionFormat2Subtable::process(const LETableReference &base,
         const LookupProcessor *lookupProcessor,
         GlyphIterator *glyphIterator,
         const LEFontInstance *fontInstance,
         LEErrorCode& success) const
D
duke 已提交
299
{
S
srl 已提交
300 301 302 303
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
304
    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
P
prr 已提交
305
    le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
306 307 308
    if (LE_FAILURE(success)) {
        return 0;
    }
D
duke 已提交
309 310

    if (coverageIndex >= 0) {
V
vadim 已提交
311 312
        LEReferenceTo<ClassDefinitionTable> classDefinitionTable(base, success, SWAPW(classDefTableOffset));
        if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
313
        le_uint16 scSetCount = SWAPW(subClassSetCount);
P
prr 已提交
314 315 316
        le_int32 setClass = classDefinitionTable->getGlyphClass(classDefinitionTable,
                                                                glyphIterator->getCurrGlyphID(),
                                                                success);
D
duke 已提交
317

318 319
        if (setClass < scSetCount) {
            LEReferenceToArrayOf<Offset>
V
vadim 已提交
320
                subClassSetTableOffsetArrayRef(base, success, subClassSetTableOffsetArray, scSetCount);
321 322 323
            if (LE_FAILURE(success)) { return 0; }
            if (subClassSetTableOffsetArray[setClass] != 0) {

V
vadim 已提交
324 325 326 327 328
                Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]);
                LEReferenceTo<SubClassSetTable> subClassSetTable(base, success, subClassSetTableOffset);
                if (LE_FAILURE(success)) { return 0; }
                le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount);
                le_int32 position = glyphIterator->getCurrStreamPosition();
329 330 331 332 333
                LEReferenceToArrayOf<Offset>
                    subClassRuleTableOffsetArrayRef(base, success, subClassSetTable->subClassRuleTableOffsetArray, subClassRuleCount);
                if (LE_FAILURE(success)) {
                    return 0;
                }
V
vadim 已提交
334 335 336 337 338 339 340 341
                for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) {
                    Offset subClassRuleTableOffset =
                        SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]);
                    LEReferenceTo<SubClassRuleTable>
                        subClassRuleTable(subClassSetTable, success, subClassRuleTableOffset);
                    if (LE_FAILURE(success)) { return 0; }
                    le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1;
                    le_uint16 substCount = SWAPW(subClassRuleTable->substCount);
D
duke 已提交
342

V
vadim 已提交
343
                    LEReferenceToArrayOf<le_uint16> classArray(base, success, subClassRuleTable->classArray, matchCount+1);
P
prr 已提交
344

V
vadim 已提交
345 346 347 348
                    if (LE_FAILURE(success)) { return 0; }
                    if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) {
                        LEReferenceToArrayOf<SubstitutionLookupRecord>
                          substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount);
D
duke 已提交
349

V
vadim 已提交
350
                        applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
D
duke 已提交
351

V
vadim 已提交
352 353
                        return matchCount + 1;
                    }
D
duke 已提交
354

V
vadim 已提交
355 356
                    glyphIterator->setCurrStreamPosition(position);
                }
D
duke 已提交
357 358 359 360 361 362 363 364 365
            }
        }

        // XXX If we get here, the table is mal-formed...
    }

    return 0;
}

P
prr 已提交
366 367
le_uint32 ContextualSubstitutionFormat3Subtable::process(const LETableReference &base,
                                                         const LookupProcessor *lookupProcessor,
S
srl 已提交
368 369 370
                                                         GlyphIterator *glyphIterator,
                                                         const LEFontInstance *fontInstance,
                                                         LEErrorCode& success)const
D
duke 已提交
371
{
S
srl 已提交
372 373 374 375
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
376 377 378 379 380 381 382 383 384 385
    le_uint16 gCount = SWAPW(glyphCount);
    le_uint16 subCount = SWAPW(substCount);
    le_int32 position = glyphIterator->getCurrStreamPosition();

    // Back up the glyph iterator so that we
    // can call next() before the check, which
    // will leave it pointing at the last glyph
    // that matched when we're done.
    glyphIterator->prev();

P
prr 已提交
386 387 388 389 390 391 392
    LEReferenceToArrayOf<Offset> covTableOffsetArray(base, success, coverageTableOffsetArray, gCount);

    if( LE_FAILURE(success) ) { return 0; }

    if (ContextualSubstitutionBase::matchGlyphCoverages(covTableOffsetArray, gCount, glyphIterator, base, success)) {
        LEReferenceToArrayOf<SubstitutionLookupRecord>
          substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount], subCount);
D
duke 已提交
393

S
srl 已提交
394
        ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position, success);
D
duke 已提交
395 396 397 398 399 400 401 402 403

        return gCount + 1;
    }

    glyphIterator->setCurrStreamPosition(position);

    return 0;
}

P
prr 已提交
404 405
le_uint32 ChainingContextualSubstitutionSubtable::process(const LEReferenceTo<ChainingContextualSubstitutionSubtable> &base,
                                                          const LookupProcessor *lookupProcessor,
S
srl 已提交
406 407 408
                                                          GlyphIterator *glyphIterator,
                                                          const LEFontInstance *fontInstance,
                                                          LEErrorCode& success) const
D
duke 已提交
409
{
S
srl 已提交
410 411 412 413
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
414 415 416 417 418 419 420
    switch(SWAPW(subtableFormat))
    {
    case 0:
        return 0;

    case 1:
    {
P
prr 已提交
421 422 423
      LEReferenceTo<ChainingContextualSubstitutionFormat1Subtable> subtable(base, success,  (ChainingContextualSubstitutionFormat1Subtable *) this);
      if(LE_FAILURE(success)) return 0;
      return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
D
duke 已提交
424 425 426 427
    }

    case 2:
    {
P
prr 已提交
428 429 430
      LEReferenceTo<ChainingContextualSubstitutionFormat2Subtable> subtable(base, success, (const ChainingContextualSubstitutionFormat2Subtable *) this);
      if( LE_FAILURE(success) ) { return 0; }
      return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
D
duke 已提交
431 432 433 434
    }

    case 3:
    {
P
prr 已提交
435 436 437
      LEReferenceTo<ChainingContextualSubstitutionFormat3Subtable> subtable(base, success, (const ChainingContextualSubstitutionFormat3Subtable *) this);
      if( LE_FAILURE(success) ) { return 0; }
      return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
D
duke 已提交
438 439 440 441 442 443 444 445 446
    }

    default:
        return 0;
    }
}

// NOTE: This could be a #define, but that seems to confuse
// the Visual Studio .NET 2003 compiler on the calls to the
447
// GlyphIterator constructor. It somehow can't decide if
D
duke 已提交
448 449 450
// emptyFeatureList matches an le_uint32 or an le_uint16...
static const FeatureMask emptyFeatureList = 0x00000000UL;

P
prr 已提交
451
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
S
srl 已提交
452 453 454
                                                                 GlyphIterator *glyphIterator,
                                                                 const LEFontInstance *fontInstance,
                                                                 LEErrorCode& success) const
D
duke 已提交
455
{
S
srl 已提交
456 457 458 459
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
460
    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
P
prr 已提交
461
    le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
462 463 464
    if (LE_FAILURE(success)) {
        return 0;
    }
D
duke 已提交
465 466 467 468 469

    if (coverageIndex >= 0) {
        le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);

        if (coverageIndex < srSetCount) {
470
            LEReferenceToArrayOf<Offset>
V
vadim 已提交
471
                chainSubRuleSetTableOffsetArrayRef(base, success, chainSubRuleSetTableOffsetArray, srSetCount);
472 473 474
            if (LE_FAILURE(success)) {
                return 0;
            }
D
duke 已提交
475
            Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
V
vadim 已提交
476 477
            LEReferenceTo<ChainSubRuleSetTable> chainSubRuleSetTable(base, success, chainSubRuleSetTableOffset);
            if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
478 479 480
            le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
            le_int32 position = glyphIterator->getCurrStreamPosition();
            GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
481 482 483 484 485
            LEReferenceToArrayOf<Offset>
                chainSubRuleTableOffsetArrayRef(base, success, chainSubRuleSetTable->chainSubRuleTableOffsetArray, chainSubRuleCount);
            if (LE_FAILURE(success)) {
                return 0;
            }
D
duke 已提交
486 487 488
            for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
                Offset chainSubRuleTableOffset =
                    SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
P
prr 已提交
489 490 491
                LEReferenceTo<ChainSubRuleTable>
                     chainSubRuleTable = LEReferenceTo<ChainSubRuleTable>(chainSubRuleSetTable, success, chainSubRuleTableOffset);
                if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
492
                le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
P
prr 已提交
493 494
                LEReferenceToArrayOf<TTGlyphID> backtrackGlyphArray(base, success, chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount);
                if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
495
                le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
P
prr 已提交
496 497 498
                LEReferenceToArrayOf<TTGlyphID>   inputGlyphArray(base, success, &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1], inputGlyphCount+2);

                if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
499
                le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
P
prr 已提交
500 501
                LEReferenceToArrayOf<TTGlyphID>   lookaheadGlyphArray(base, success, inputGlyphArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2);
                if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
502 503 504 505 506 507 508 509 510
                le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);

                tempIterator.setCurrStreamPosition(position);

                if (! tempIterator.prev(backtrackGlyphCount)) {
                    continue;
                }

                tempIterator.prev();
P
prr 已提交
511 512

                if (! matchGlyphIDs(backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
D
duke 已提交
513 514 515 516 517 518 519 520 521 522
                    continue;
                }

                tempIterator.setCurrStreamPosition(position);
                tempIterator.next(inputGlyphCount);
                if (!matchGlyphIDs(lookaheadGlyphArray, lookaheadGlyphCount, &tempIterator)) {
                    continue;
                }

                if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
P
prr 已提交
523 524
                    LEReferenceToArrayOf<SubstitutionLookupRecord>
                      substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadGlyphArray.getAlias(lookaheadGlyphCount + 1,success), substCount);
D
duke 已提交
525

S
srl 已提交
526
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
D
duke 已提交
527 528 529 530 531 532 533 534 535 536 537 538 539 540

                    return inputGlyphCount + 1;
                }

                glyphIterator->setCurrStreamPosition(position);
            }
        }

        // XXX If we get here, the table is mal-formed...
    }

    return 0;
}

P
prr 已提交
541
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
S
srl 已提交
542 543 544
                                                                 GlyphIterator *glyphIterator,
                                                                 const LEFontInstance *fontInstance,
                                                                 LEErrorCode& success) const
D
duke 已提交
545
{
S
srl 已提交
546 547 548 549
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
550
    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
P
prr 已提交
551
    le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
552 553 554
    if (LE_FAILURE(success)) {
        return 0;
    }
D
duke 已提交
555 556

    if (coverageIndex >= 0) {
P
prr 已提交
557
        LEReferenceTo<ClassDefinitionTable>
V
vadim 已提交
558
             backtrackClassDefinitionTable(base, success, SWAPW(backtrackClassDefTableOffset));
P
prr 已提交
559
        LEReferenceTo<ClassDefinitionTable>
V
vadim 已提交
560
             inputClassDefinitionTable(base, success, SWAPW(inputClassDefTableOffset));
P
prr 已提交
561
        LEReferenceTo<ClassDefinitionTable>
V
vadim 已提交
562
             lookaheadClassDefinitionTable(base, success, SWAPW(lookaheadClassDefTableOffset));
D
duke 已提交
563
        le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
P
prr 已提交
564 565 566
        le_int32 setClass = inputClassDefinitionTable->getGlyphClass(inputClassDefinitionTable,
                                                                     glyphIterator->getCurrGlyphID(),
                                                                     success);
567
        LEReferenceToArrayOf<Offset>
V
vadim 已提交
568
            chainSubClassSetTableOffsetArrayRef(base, success, chainSubClassSetTableOffsetArray, scSetCount);
569 570 571
        if (LE_FAILURE(success)) {
            return 0;
        }
D
duke 已提交
572 573 574

        if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
            Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
P
prr 已提交
575
            LEReferenceTo<ChainSubClassSetTable>
V
vadim 已提交
576 577
                 chainSubClassSetTable(base, success, chainSubClassSetTableOffset);
            if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
578 579 580
            le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
            le_int32 position = glyphIterator->getCurrStreamPosition();
            GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
581 582 583 584 585
            LEReferenceToArrayOf<Offset>
                chainSubClassRuleTableOffsetArrayRef(base, success, chainSubClassSetTable->chainSubClassRuleTableOffsetArray, chainSubClassRuleCount);
            if (LE_FAILURE(success)) {
                return 0;
            }
D
duke 已提交
586 587 588
            for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
                Offset chainSubClassRuleTableOffset =
                    SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
P
prr 已提交
589 590
                LEReferenceTo<ChainSubClassRuleTable>
                     chainSubClassRuleTable(chainSubClassSetTable, success, chainSubClassRuleTableOffset);
V
vadim 已提交
591
                if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
592
                le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
P
prr 已提交
593 594
                LEReferenceToArrayOf<le_uint16>   backtrackClassArray(base, success, chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount);
                if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
595
                le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
P
prr 已提交
596 597 598 599 600
                LEReferenceToArrayOf<le_uint16>   inputClassArray(base, success, &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1],inputGlyphCount+2); // +2 for the lookaheadGlyphCount count
                le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray.getObject(inputGlyphCount, success));
                LEReferenceToArrayOf<le_uint16>   lookaheadClassArray(base, success, inputClassArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2); // +2 for the substCount

                if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
601 602 603 604 605 606 607 608 609 610
                le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);


                tempIterator.setCurrStreamPosition(position);

                if (! tempIterator.prev(backtrackGlyphCount)) {
                    continue;
                }

                tempIterator.prev();
P
prr 已提交
611 612
                if (! matchGlyphClasses(backtrackClassArray, backtrackGlyphCount,
                                        &tempIterator, backtrackClassDefinitionTable, success, TRUE)) {
D
duke 已提交
613 614 615 616 617
                    continue;
                }

                tempIterator.setCurrStreamPosition(position);
                tempIterator.next(inputGlyphCount);
P
prr 已提交
618
                if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable, success)) {
D
duke 已提交
619 620 621
                    continue;
                }

P
prr 已提交
622 623 624
                if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) {
                    LEReferenceToArrayOf<SubstitutionLookupRecord>
                      substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadClassArray.getAlias(lookaheadGlyphCount + 1, success), substCount);
P
prr 已提交
625
                    if (LE_FAILURE(success)) { return 0; }
S
srl 已提交
626
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
D
duke 已提交
627 628 629 630 631 632 633 634 635 636 637 638 639 640

                    return inputGlyphCount + 1;
                }

                glyphIterator->setCurrStreamPosition(position);
            }
        }

        // XXX If we get here, the table is mal-formed...
    }

    return 0;
}

P
prr 已提交
641
le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
S
srl 已提交
642 643 644
                                                                 GlyphIterator *glyphIterator,
                                                                 const LEFontInstance *fontInstance,
                                                                 LEErrorCode & success) const
D
duke 已提交
645
{
S
srl 已提交
646 647 648 649
    if (LE_FAILURE(success)) {
        return 0;
    }

D
duke 已提交
650
    le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
651 652 653 654
    LEReferenceToArrayOf<Offset> backtrackGlyphArrayRef(base, success, backtrackCoverageTableOffsetArray, backtrkGlyphCount);
    if (LE_FAILURE(success)) {
        return 0;
    }
D
duke 已提交
655
    le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
P
prr 已提交
656
    LEReferenceToArrayOf<Offset>   inputCoverageTableOffsetArray(base, success, &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1], inputGlyphCount+2); // offset
P
prr 已提交
657
    if (LE_FAILURE(success)) { return 0; }
D
duke 已提交
658
    const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
P
prr 已提交
659 660 661
    LEReferenceToArrayOf<Offset>   lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2);

    if( LE_FAILURE(success) ) { return 0; }
D
duke 已提交
662 663 664 665 666 667 668 669 670 671
    le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]);
    le_int32 position = glyphIterator->getCurrStreamPosition();
    GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);

    if (! tempIterator.prev(backtrkGlyphCount)) {
        return 0;
    }

    tempIterator.prev();
    if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray,
P
prr 已提交
672
                       backtrkGlyphCount, &tempIterator, base, success, TRUE)) {
D
duke 已提交
673 674 675 676 677 678
        return 0;
    }

    tempIterator.setCurrStreamPosition(position);
    tempIterator.next(inputGlyphCount - 1);
    if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
P
prr 已提交
679
                        lookaheadGlyphCount, &tempIterator, base, success)) {
D
duke 已提交
680 681 682 683 684 685 686 687 688 689
        return 0;
    }

    // Back up the glyph iterator so that we
    // can call next() before the check, which
    // will leave it pointing at the last glyph
    // that matched when we're done.
    glyphIterator->prev();

    if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray,
P
prr 已提交
690 691 692 693
                                                        inputGlyphCount, glyphIterator, base, success)) {
        LEReferenceToArrayOf<SubstitutionLookupRecord>
          substLookupRecordArray(base, success,
                                 (const SubstitutionLookupRecord *) lookaheadCoverageTableOffsetArray.getAlias(lookaheadGlyphCount + 1,success), substCount);
D
duke 已提交
694

S
srl 已提交
695
        ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
D
duke 已提交
696 697 698 699 700 701 702 703

        return inputGlyphCount;
    }

    glyphIterator->setCurrStreamPosition(position);

    return 0;
}
704 705

U_NAMESPACE_END