le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const { LEGlyphID glyph = glyphIterator->getCurrGlyphID(); le_int32 coverageIndex = getGlyphCoverage(glyph); if (coverageIndex >= 0) { le_uint16 srSetCount = SWAPW(chainSubRuleSetCount); if (coverageIndex < srSetCount) { Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]); const ChainSubRuleSetTable *chainSubRuleSetTable = (const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset); le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount); le_int32 position = glyphIterator->getCurrStreamPosition(); GlyphIterator tempIterator(*glyphIterator, emptyFeatureList); for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) { Offset chainSubRuleTableOffset = SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]); const ChainSubRuleTable *chainSubRuleTable = (const ChainSubRuleTable *) ((char *) chainSubRuleSetTable + chainSubRuleTableOffset); le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount); le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1; const TTGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1]; le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]); const TTGlyphID *lookaheadGlyphArray = &inputGlyphArray[inputGlyphCount + 1]; le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]); tempIterator.setCurrStreamPosition(position); if (! tempIterator.prev(backtrackGlyphCount)) { continue; } tempIterator.prev(); if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) { continue; } tempIterator.setCurrStreamPosition(position); tempIterator.next(inputGlyphCount); if (!matchGlyphIDs(lookaheadGlyphArray, lookaheadGlyphCount, &tempIterator)) { continue; } if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) { const SubstitutionLookupRecord *substLookupRecordArray = (const SubstitutionLookupRecord *) &lookaheadGlyphArray[lookaheadGlyphCount + 1]; applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position); return inputGlyphCount + 1; } glyphIterator->setCurrStreamPosition(position); } } // XXX If we get here, the table is mal-formed... } return 0; }
U_NAMESPACE_BEGIN le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const { if (LE_FAILURE(success)) { return 0; } LEGlyphID glyph = glyphIterator->getCurrGlyphID(); // If there's a filter, we only want to do the // substitution if the *input* glyphs doesn't // exist. // // FIXME: is this always the right thing to do? // FIXME: should this only be done for a non-zero // glyphCount? if (filter != NULL && filter->accept(glyph)) { return 0; } le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_uint16 seqCount = SWAPW(sequenceCount); LEReferenceToArrayOf<Offset> sequenceTableOffsetArrayRef(base, success, sequenceTableOffsetArray, seqCount); if (LE_FAILURE(success)) { return 0; } if (coverageIndex >= 0 && coverageIndex < seqCount) { Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]); const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset); le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount); if (glyphCount == 0) { glyphIterator->setCurrGlyphID(0xFFFF); return 1; } else if (glyphCount == 1) { TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]); if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) { return 0; } glyphIterator->setCurrGlyphID(substitute); return 1; } else { // If there's a filter, make sure all of the output glyphs // exist. if (filter != NULL) { for (le_int32 i = 0; i < glyphCount; i += 1) { TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); if (! filter->accept(substitute)) { return 0; } } } LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount, success); if (LE_FAILURE(success)) { return 0; } le_int32 insert = 0, direction = 1; if (glyphIterator->isRightToLeft()) { insert = glyphCount - 1; direction = -1; } for (le_int32 i = 0; i < glyphCount; i += 1) { TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute); insert += direction; } return 1; } } return 0; }