0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A *
0N/A */
0N/A
0N/A/*
0N/A * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
0N/A *
0N/A */
0N/A
0N/A#include "LETypes.h"
0N/A#include "LEFontInstance.h"
0N/A#include "OpenTypeTables.h"
0N/A#include "GlyphSubstitutionTables.h"
0N/A#include "ContextualSubstSubtables.h"
0N/A#include "GlyphIterator.h"
0N/A#include "LookupProcessor.h"
0N/A#include "CoverageTables.h"
0N/A#include "LESwaps.h"
0N/A
1693N/AU_NAMESPACE_BEGIN
1693N/A
0N/A/*
0N/A NOTE: This could be optimized somewhat by keeping track
0N/A of the previous sequenceIndex in the loop and doing next()
0N/A or prev() of the delta between that and the current
0N/A sequenceIndex instead of always resetting to the front.
0N/A*/
0N/Avoid ContextualSubstitutionBase::applySubstitutionLookups(
0N/A const LookupProcessor *lookupProcessor,
0N/A const SubstitutionLookupRecord *substLookupRecordArray,
0N/A le_uint16 substCount,
0N/A GlyphIterator *glyphIterator,
0N/A const LEFontInstance *fontInstance,
3171N/A le_int32 position,
3171N/A LEErrorCode& success)
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return;
3171N/A }
3171N/A
0N/A GlyphIterator tempIterator(*glyphIterator);
0N/A
3171N/A for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
0N/A le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex);
0N/A le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex);
0N/A
0N/A tempIterator.setCurrStreamPosition(position);
0N/A tempIterator.next(sequenceIndex);
0N/A
3171N/A lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance, success);
0N/A }
0N/A}
0N/A
0N/Ale_bool ContextualSubstitutionBase::matchGlyphIDs(const TTGlyphID *glyphArray, le_uint16 glyphCount,
0N/A GlyphIterator *glyphIterator, le_bool backtrack)
0N/A{
0N/A le_int32 direction = 1;
0N/A le_int32 match = 0;
0N/A
0N/A if (backtrack) {
0N/A match = glyphCount -1;
0N/A direction = -1;
0N/A }
0N/A
0N/A while (glyphCount > 0) {
0N/A if (! glyphIterator->next()) {
0N/A return FALSE;
0N/A }
0N/A
0N/A TTGlyphID glyph = (TTGlyphID) glyphIterator->getCurrGlyphID();
0N/A
0N/A if (glyph != SWAPW(glyphArray[match])) {
0N/A return FALSE;
0N/A }
0N/A
0N/A glyphCount -= 1;
0N/A match += direction;
0N/A }
0N/A
0N/A return TRUE;
0N/A}
0N/A
0N/Ale_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArray, le_uint16 glyphCount,
0N/A GlyphIterator *glyphIterator,
0N/A const ClassDefinitionTable *classDefinitionTable,
0N/A le_bool backtrack)
0N/A{
0N/A le_int32 direction = 1;
0N/A le_int32 match = 0;
0N/A
0N/A if (backtrack) {
0N/A match = glyphCount - 1;
0N/A direction = -1;
0N/A }
0N/A
0N/A while (glyphCount > 0) {
0N/A if (! glyphIterator->next()) {
0N/A return FALSE;
0N/A }
0N/A
0N/A LEGlyphID glyph = glyphIterator->getCurrGlyphID();
0N/A le_int32 glyphClass = classDefinitionTable->getGlyphClass(glyph);
0N/A le_int32 matchClass = SWAPW(classArray[match]);
0N/A
0N/A if (glyphClass != matchClass) {
0N/A // Some fonts, e.g. Traditional Arabic, have classes
0N/A // in the class array which aren't in the class definition
0N/A // table. If we're looking for such a class, pretend that
0N/A // we found it.
0N/A if (classDefinitionTable->hasGlyphClass(matchClass)) {
0N/A return FALSE;
0N/A }
0N/A }
0N/A
0N/A glyphCount -= 1;
0N/A match += direction;
0N/A }
0N/A
0N/A return TRUE;
0N/A}
0N/A
0N/Ale_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTableOffsetArray, le_uint16 glyphCount,
0N/A GlyphIterator *glyphIterator, const char *offsetBase, le_bool backtrack)
0N/A{
0N/A le_int32 direction = 1;
0N/A le_int32 glyph = 0;
0N/A
0N/A if (backtrack) {
0N/A glyph = glyphCount - 1;
0N/A direction = -1;
0N/A }
0N/A
0N/A while (glyphCount > 0) {
0N/A Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]);
0N/A const CoverageTable *coverageTable = (const CoverageTable *) (offsetBase + coverageTableOffset);
0N/A
0N/A if (! glyphIterator->next()) {
0N/A return FALSE;
0N/A }
0N/A
0N/A if (coverageTable->getGlyphCoverage((LEGlyphID) glyphIterator->getCurrGlyphID()) < 0) {
0N/A return FALSE;
0N/A }
0N/A
0N/A glyphCount -= 1;
0N/A glyph += direction;
0N/A }
0N/A
0N/A return TRUE;
0N/A}
0N/A
3171N/Ale_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A switch(SWAPW(subtableFormat))
0N/A {
0N/A case 0:
0N/A return 0;
0N/A
0N/A case 1:
0N/A {
0N/A const ContextualSubstitutionFormat1Subtable *subtable = (const ContextualSubstitutionFormat1Subtable *) this;
3171N/A return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A const ContextualSubstitutionFormat2Subtable *subtable = (const ContextualSubstitutionFormat2Subtable *) this;
3171N/A return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
0N/A }
0N/A
0N/A case 3:
0N/A {
0N/A const ContextualSubstitutionFormat3Subtable *subtable = (const ContextualSubstitutionFormat3Subtable *) this;
3171N/A return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
0N/A }
0N/A
0N/A default:
0N/A return 0;
0N/A }
0N/A}
0N/A
3171N/Ale_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A LEGlyphID glyph = glyphIterator->getCurrGlyphID();
5980N/A le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
6371N/A if (LE_FAILURE(success)) {
6371N/A return 0;
6371N/A }
0N/A
0N/A if (coverageIndex >= 0) {
0N/A le_uint16 srSetCount = SWAPW(subRuleSetCount);
0N/A
0N/A if (coverageIndex < srSetCount) {
0N/A Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]);
0N/A const SubRuleSetTable *subRuleSetTable =
0N/A (const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset);
0N/A le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount);
0N/A le_int32 position = glyphIterator->getCurrStreamPosition();
0N/A
0N/A for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) {
0N/A Offset subRuleTableOffset =
0N/A SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]);
0N/A const SubRuleTable *subRuleTable =
0N/A (const SubRuleTable *) ((char *) subRuleSetTable + subRuleTableOffset);
0N/A le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
0N/A le_uint16 substCount = SWAPW(subRuleTable->substCount);
0N/A
0N/A if (matchGlyphIDs(subRuleTable->inputGlyphArray, matchCount, glyphIterator)) {
0N/A const SubstitutionLookupRecord *substLookupRecordArray =
0N/A (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount];
0N/A
3171N/A applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
0N/A
0N/A return matchCount + 1;
0N/A }
0N/A
0N/A glyphIterator->setCurrStreamPosition(position);
0N/A }
0N/A }
0N/A
0N/A // XXX If we get here, the table is mal-formed...
0N/A }
0N/A
0N/A return 0;
0N/A}
0N/A
3171N/Ale_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A LEGlyphID glyph = glyphIterator->getCurrGlyphID();
5980N/A le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
6371N/A if (LE_FAILURE(success)) {
6371N/A return 0;
6371N/A }
0N/A
0N/A if (coverageIndex >= 0) {
0N/A const ClassDefinitionTable *classDefinitionTable =
0N/A (const ClassDefinitionTable *) ((char *) this + SWAPW(classDefTableOffset));
0N/A le_uint16 scSetCount = SWAPW(subClassSetCount);
0N/A le_int32 setClass = classDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID());
0N/A
0N/A if (setClass < scSetCount && subClassSetTableOffsetArray[setClass] != 0) {
0N/A Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]);
0N/A const SubClassSetTable *subClassSetTable =
0N/A (const SubClassSetTable *) ((char *) this + subClassSetTableOffset);
0N/A le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount);
0N/A le_int32 position = glyphIterator->getCurrStreamPosition();
0N/A
0N/A for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) {
0N/A Offset subClassRuleTableOffset =
0N/A SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]);
0N/A const SubClassRuleTable *subClassRuleTable =
0N/A (const SubClassRuleTable *) ((char *) subClassSetTable + subClassRuleTableOffset);
0N/A le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1;
0N/A le_uint16 substCount = SWAPW(subClassRuleTable->substCount);
0N/A
0N/A if (matchGlyphClasses(subClassRuleTable->classArray, matchCount, glyphIterator, classDefinitionTable)) {
0N/A const SubstitutionLookupRecord *substLookupRecordArray =
0N/A (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount];
0N/A
3171N/A applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
0N/A
0N/A return matchCount + 1;
0N/A }
0N/A
0N/A glyphIterator->setCurrStreamPosition(position);
0N/A }
0N/A }
0N/A
0N/A // XXX If we get here, the table is mal-formed...
0N/A }
0N/A
0N/A return 0;
0N/A}
0N/A
3171N/Ale_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success)const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A le_uint16 gCount = SWAPW(glyphCount);
0N/A le_uint16 subCount = SWAPW(substCount);
0N/A le_int32 position = glyphIterator->getCurrStreamPosition();
0N/A
0N/A // Back up the glyph iterator so that we
0N/A // can call next() before the check, which
0N/A // will leave it pointing at the last glyph
0N/A // that matched when we're done.
0N/A glyphIterator->prev();
0N/A
0N/A if (ContextualSubstitutionBase::matchGlyphCoverages(coverageTableOffsetArray, gCount, glyphIterator, (const char *) this)) {
0N/A const SubstitutionLookupRecord *substLookupRecordArray =
0N/A (const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount];
0N/A
3171N/A ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position, success);
0N/A
0N/A return gCount + 1;
0N/A }
0N/A
0N/A glyphIterator->setCurrStreamPosition(position);
0N/A
0N/A return 0;
0N/A}
0N/A
3171N/Ale_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A switch(SWAPW(subtableFormat))
0N/A {
0N/A case 0:
0N/A return 0;
0N/A
0N/A case 1:
0N/A {
0N/A const ChainingContextualSubstitutionFormat1Subtable *subtable = (const ChainingContextualSubstitutionFormat1Subtable *) this;
3171N/A return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A const ChainingContextualSubstitutionFormat2Subtable *subtable = (const ChainingContextualSubstitutionFormat2Subtable *) this;
3171N/A return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
0N/A }
0N/A
0N/A case 3:
0N/A {
0N/A const ChainingContextualSubstitutionFormat3Subtable *subtable = (const ChainingContextualSubstitutionFormat3Subtable *) this;
3171N/A return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
0N/A }
0N/A
0N/A default:
0N/A return 0;
0N/A }
0N/A}
0N/A
0N/A// NOTE: This could be a #define, but that seems to confuse
0N/A// the Visual Studio .NET 2003 compiler on the calls to the
1693N/A// GlyphIterator constructor. It somehow can't decide if
0N/A// emptyFeatureList matches an le_uint32 or an le_uint16...
0N/Astatic const FeatureMask emptyFeatureList = 0x00000000UL;
0N/A
3171N/Ale_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A LEGlyphID glyph = glyphIterator->getCurrGlyphID();
5980N/A le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
6371N/A if (LE_FAILURE(success)) {
6371N/A return 0;
6371N/A }
0N/A
0N/A if (coverageIndex >= 0) {
0N/A le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
0N/A
0N/A if (coverageIndex < srSetCount) {
0N/A Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
0N/A const ChainSubRuleSetTable *chainSubRuleSetTable =
0N/A (const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset);
0N/A le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
0N/A le_int32 position = glyphIterator->getCurrStreamPosition();
0N/A GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
0N/A
0N/A for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
0N/A Offset chainSubRuleTableOffset =
0N/A SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
0N/A const ChainSubRuleTable *chainSubRuleTable =
0N/A (const ChainSubRuleTable *) ((char *) chainSubRuleSetTable + chainSubRuleTableOffset);
0N/A le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
0N/A le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
0N/A const TTGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1];
0N/A le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
0N/A const TTGlyphID *lookaheadGlyphArray = &inputGlyphArray[inputGlyphCount + 1];
0N/A le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);
0N/A
0N/A tempIterator.setCurrStreamPosition(position);
0N/A
0N/A if (! tempIterator.prev(backtrackGlyphCount)) {
0N/A continue;
0N/A }
0N/A
0N/A tempIterator.prev();
0N/A if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
0N/A continue;
0N/A }
0N/A
0N/A tempIterator.setCurrStreamPosition(position);
0N/A tempIterator.next(inputGlyphCount);
0N/A if (!matchGlyphIDs(lookaheadGlyphArray, lookaheadGlyphCount, &tempIterator)) {
0N/A continue;
0N/A }
0N/A
0N/A if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
0N/A const SubstitutionLookupRecord *substLookupRecordArray =
0N/A (const SubstitutionLookupRecord *) &lookaheadGlyphArray[lookaheadGlyphCount + 1];
0N/A
3171N/A applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
0N/A
0N/A return inputGlyphCount + 1;
0N/A }
0N/A
0N/A glyphIterator->setCurrStreamPosition(position);
0N/A }
0N/A }
0N/A
0N/A // XXX If we get here, the table is mal-formed...
0N/A }
0N/A
0N/A return 0;
0N/A}
0N/A
3171N/Ale_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode& success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A LEGlyphID glyph = glyphIterator->getCurrGlyphID();
5980N/A le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
6371N/A if (LE_FAILURE(success)) {
6371N/A return 0;
6371N/A }
0N/A
0N/A if (coverageIndex >= 0) {
0N/A const ClassDefinitionTable *backtrackClassDefinitionTable =
0N/A (const ClassDefinitionTable *) ((char *) this + SWAPW(backtrackClassDefTableOffset));
0N/A const ClassDefinitionTable *inputClassDefinitionTable =
0N/A (const ClassDefinitionTable *) ((char *) this + SWAPW(inputClassDefTableOffset));
0N/A const ClassDefinitionTable *lookaheadClassDefinitionTable =
0N/A (const ClassDefinitionTable *) ((char *) this + SWAPW(lookaheadClassDefTableOffset));
0N/A le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
0N/A le_int32 setClass = inputClassDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID());
0N/A
0N/A if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
0N/A Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
0N/A const ChainSubClassSetTable *chainSubClassSetTable =
0N/A (const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset);
0N/A le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
0N/A le_int32 position = glyphIterator->getCurrStreamPosition();
0N/A GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
0N/A
0N/A for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
0N/A Offset chainSubClassRuleTableOffset =
0N/A SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
0N/A const ChainSubClassRuleTable *chainSubClassRuleTable =
0N/A (const ChainSubClassRuleTable *) ((char *) chainSubClassSetTable + chainSubClassRuleTableOffset);
0N/A le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
0N/A le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
0N/A const le_uint16 *inputClassArray = &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1];
0N/A le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray[inputGlyphCount]);
0N/A const le_uint16 *lookaheadClassArray = &inputClassArray[inputGlyphCount + 1];
0N/A le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);
0N/A
0N/A
0N/A tempIterator.setCurrStreamPosition(position);
0N/A
0N/A if (! tempIterator.prev(backtrackGlyphCount)) {
0N/A continue;
0N/A }
0N/A
0N/A tempIterator.prev();
0N/A if (! matchGlyphClasses(chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount,
0N/A &tempIterator, backtrackClassDefinitionTable, TRUE)) {
0N/A continue;
0N/A }
0N/A
0N/A tempIterator.setCurrStreamPosition(position);
0N/A tempIterator.next(inputGlyphCount);
0N/A if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable)) {
0N/A continue;
0N/A }
0N/A
0N/A if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable)) {
0N/A const SubstitutionLookupRecord *substLookupRecordArray =
0N/A (const SubstitutionLookupRecord *) &lookaheadClassArray[lookaheadGlyphCount + 1];
0N/A
3171N/A applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
0N/A
0N/A return inputGlyphCount + 1;
0N/A }
0N/A
0N/A glyphIterator->setCurrStreamPosition(position);
0N/A }
0N/A }
0N/A
0N/A // XXX If we get here, the table is mal-formed...
0N/A }
0N/A
0N/A return 0;
0N/A}
0N/A
3171N/Ale_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor,
3171N/A GlyphIterator *glyphIterator,
3171N/A const LEFontInstance *fontInstance,
3171N/A LEErrorCode & success) const
0N/A{
3171N/A if (LE_FAILURE(success)) {
3171N/A return 0;
3171N/A }
3171N/A
0N/A le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
0N/A le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
0N/A const Offset *inputCoverageTableOffsetArray = &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1];
0N/A const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
0N/A const Offset *lookaheadCoverageTableOffsetArray = &inputCoverageTableOffsetArray[inputGlyphCount + 1];
0N/A le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]);
0N/A le_int32 position = glyphIterator->getCurrStreamPosition();
0N/A GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
0N/A
0N/A if (! tempIterator.prev(backtrkGlyphCount)) {
0N/A return 0;
0N/A }
0N/A
0N/A tempIterator.prev();
0N/A if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray,
0N/A backtrkGlyphCount, &tempIterator, (const char *) this, TRUE)) {
0N/A return 0;
0N/A }
0N/A
0N/A tempIterator.setCurrStreamPosition(position);
0N/A tempIterator.next(inputGlyphCount - 1);
0N/A if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
0N/A lookaheadGlyphCount, &tempIterator, (const char *) this)) {
0N/A return 0;
0N/A }
0N/A
0N/A // Back up the glyph iterator so that we
0N/A // can call next() before the check, which
0N/A // will leave it pointing at the last glyph
0N/A // that matched when we're done.
0N/A glyphIterator->prev();
0N/A
0N/A if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray,
0N/A inputGlyphCount, glyphIterator, (const char *) this)) {
0N/A const SubstitutionLookupRecord *substLookupRecordArray =
0N/A (const SubstitutionLookupRecord *) &lookaheadCoverageTableOffsetArray[lookaheadGlyphCount + 1];
0N/A
3171N/A ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
0N/A
0N/A return inputGlyphCount;
0N/A }
0N/A
0N/A glyphIterator->setCurrStreamPosition(position);
0N/A
0N/A return 0;
0N/A}
1693N/A
1693N/AU_NAMESPACE_END