U_NAMESPACE_BEGIN

/*
    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,
        const LEReferenceToArrayOf<SubstitutionLookupRecord>& substLookupRecordArray,
        le_uint16 substCount,
        GlyphIterator *glyphIterator,
        const LEFontInstance *fontInstance,
        le_int32 position,
        LEErrorCode& success)
{
    if (LE_FAILURE(success)) {
        return;
    }

    GlyphIterator tempIterator(*glyphIterator);
    const SubstitutionLookupRecord *substLookupRecordArrayPtr = substLookupRecordArray.getAlias(); // OK to dereference, range checked against substCount below.

    for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
        le_uint16 sequenceIndex = SWAPW(substLookupRecordArrayPtr[subst].sequenceIndex);
        le_uint16 lookupListIndex = SWAPW(substLookupRecordArrayPtr[subst].lookupListIndex);

        tempIterator.setCurrStreamPosition(position);
        tempIterator.next(sequenceIndex);

        lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance, success);
    }
}
U_NAMESPACE_BEGIN

void ContextualSubstitutionBase::applySubstitutionLookups(
        const LookupProcessor *lookupProcessor,
        const SubstitutionLookupRecord *substLookupRecordArray,
        le_uint16 substCount,
        GlyphIterator *glyphIterator,
        const LEFontInstance *fontInstance,
        le_int32 position,
        LEErrorCode& success)
{
    if (LE_FAILURE(success)) { 
        return;
    }

    GlyphIterator tempIterator(*glyphIterator);

    for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
        le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex);
        le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex);

        tempIterator.setCurrStreamPosition(position);
        tempIterator.next(sequenceIndex);

        lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance, success);
    }
}
U_NAMESPACE_BEGIN

/*
    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,
        const SubstitutionLookupRecord *substLookupRecordArray,
        le_uint16 substCount,
        GlyphIterator *glyphIterator,
        const LEFontInstance *fontInstance,
        le_int32 position)
{
    GlyphIterator tempIterator(*glyphIterator);

    for (le_int16 subst = 0; subst < substCount; subst += 1) {
        le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex);
        le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex);

        tempIterator.setCurrStreamPosition(position);
        tempIterator.next(sequenceIndex);

        lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance);
    }
}
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
                                                              const LEFontInstance *fontInstance) const
{
    LEGlyphID glyph = (LEGlyphID) 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);

            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 LEGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1];
                le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
                const LEGlyphID *lookaheadGlyphArray = &inputGlyphArray[inputGlyphCount + 1];
                le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);

                tempIterator.setCurrStreamPosition(position);
                tempIterator.prev(backtrackGlyphCount + 1);
                if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator)) {
                    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;
}
Пример #5
0
U_NAMESPACE_BEGIN

le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);

    if (coverageIndex >= 0) {
        Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]);
        const LigatureSetTable *ligSetTable = (const LigatureSetTable *) ((char *) this + ligSetTableOffset);
        le_uint16 ligCount = SWAPW(ligSetTable->ligatureCount);

        for (le_uint16 lig = 0; lig < ligCount; lig += 1) {
            Offset ligTableOffset = SWAPW(ligSetTable->ligatureTableOffsetArray[lig]);
            const LigatureTable *ligTable = (const LigatureTable *) ((char *)ligSetTable + ligTableOffset);
            le_uint16 compCount = SWAPW(ligTable->compCount) - 1;
            LEReferenceToArrayOf<TTGlyphID>
                componentArrayRef(base, success, ligTable->componentArray, compCount);
            if (LE_FAILURE(success)) { return 0; }
            le_int32 startPosition = glyphIterator->getCurrStreamPosition();
            TTGlyphID ligGlyph = SWAPW(ligTable->ligGlyph);
            le_uint16 comp;

            for (comp = 0; comp < compCount; comp += 1) {
                if (! glyphIterator->next()) {
                    break;
                }

                if (LE_GET_GLYPH(glyphIterator->getCurrGlyphID()) != SWAPW(ligTable->componentArray[comp])) {
                    break;
                }
            }

            if (comp == compCount && (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, ligGlyph)))) {
                GlyphIterator tempIterator(*glyphIterator);
                TTGlyphID deletedGlyph = tempIterator.ignoresMarks()? 0xFFFE : 0xFFFF;

                while (comp > 0) {
                    tempIterator.setCurrGlyphID(deletedGlyph);
                    tempIterator.prev();

                    comp -= 1;
                }

                tempIterator.setCurrGlyphID(ligGlyph);

                return compCount + 1;
            }

            glyphIterator->setCurrStreamPosition(startPosition);
        }

    }

    return 0;
}
Пример #6
0
le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
                                          const LEFontInstance *fontInstance) const
{
    const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
    le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
    GlyphIterator tempIterator(*glyphIterator, lookupFlags);
    le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance);

    return delta;
}
le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, 
                                                                 GlyphIterator *glyphIterator,
                                                                 const LEFontInstance *fontInstance,
                                                                 LEErrorCode & success) const
{
    if (LE_FAILURE(success)) { 
        return 0;
    }

    le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
    le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
    const Offset *inputCoverageTableOffsetArray = &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1];
    const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
    const Offset *lookaheadCoverageTableOffsetArray = &inputCoverageTableOffsetArray[inputGlyphCount + 1];
    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,
        backtrkGlyphCount, &tempIterator, (const char *) this, TRUE)) {
        return 0;
    }

    tempIterator.setCurrStreamPosition(position);
    tempIterator.next(inputGlyphCount - 1);
    if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
        lookaheadGlyphCount, &tempIterator, (const char *) this)) {
        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,
        inputGlyphCount, glyphIterator, (const char *) this)) {
        const SubstitutionLookupRecord *substLookupRecordArray = 
            (const SubstitutionLookupRecord *) &lookaheadCoverageTableOffsetArray[lookaheadGlyphCount + 1];

        ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);

        return inputGlyphCount;
    }

    glyphIterator->setCurrStreamPosition(position);

    return 0;
}
Пример #8
0
le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
                                          const LEFontInstance *fontInstance, LEErrorCode& success) const
{
    if (LE_FAILURE(success)) {
        return 0;
    }    

    const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
    le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
    GlyphIterator tempIterator(*glyphIterator, lookupFlags);
    le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success);

    return delta;
}
le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
    LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);

    if (LE_FAILURE(success)) {
      return 0;
    }
    GlyphIterator tempIterator(*glyphIterator);

    if (coverageIndex >= 0 && glyphIterator->next()) {
        Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
        LEReferenceTo<PairSetTable> pairSetTable(base, success, ((char *) this + pairSetTableOffset));
        if (LE_FAILURE(success)) {
          return 0;
        }
        le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount);
        le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
        le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
        le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
        LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
        LEReferenceTo<PairValueRecord> pairValueRecord;

        if (pairValueCount != 0) {
            pairValueRecord = findPairValueRecord(base, (TTGlyphID) LE_GET_GLYPH(secondGlyph), pairSetTable->pairValueRecordArray, pairValueCount, recordSize, success);
        }

        if (pairValueRecord.isEmpty()) {
            return 0;
        }

        if (valueFormat1 != 0) {
            pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
        }

        if (valueFormat2 != 0) {
            const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size);

            valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, *glyphIterator, fontInstance);
        }

        // back up glyphIterator so second glyph can be
        // first glyph in the next pair
        glyphIterator->prev();
        return 1;
    }

    return 0;
}
Пример #10
0
le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
                                          const LEFontInstance *fontInstance, LEErrorCode& success) const
{
    if (LE_FAILURE(success)) {
        return 0;
    }

    const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookupTableIndex, success);
    if (!lookupTable.isValid()) {
        success = LE_INTERNAL_ERROR;
        return 0;
    }
    le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
    GlyphIterator tempIterator(*glyphIterator, lookupFlags);
    le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success);

    return delta;
}
le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
    LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);

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

    GlyphIterator tempIterator(*glyphIterator);

    if (coverageIndex >= 0 && glyphIterator->next()) {
        LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
        const ClassDefinitionTable *classDef1 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef1Offset));
        const ClassDefinitionTable *classDef2 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef2Offset));
        le_int32 class1 = classDef1->getGlyphClass(firstGlyph);
        le_int32 class2 = classDef2->getGlyphClass(secondGlyph);
        le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
        le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
        le_int16 class2RecordSize = valueRecord1Size + valueRecord2Size;
        le_int16 class1RecordSize = class2RecordSize * SWAPW(class2Count);
        const Class1Record *class1Record = (const Class1Record *) ((char *) class1RecordArray + (class1RecordSize * class1));
        const Class2Record *class2Record = (const Class2Record *) ((char *) class1Record->class2RecordArray + (class2RecordSize * class2));


        if (valueFormat1 != 0) {
            class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
        }

        if (valueFormat2 != 0) {
            const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size);

            valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, *glyphIterator, fontInstance);
        }

        // back up glyphIterator so second glyph can be
        // first glyph in the next pair
        glyphIterator->prev();
        return 1;
    }

    return 0;
}
le_uint32 PairPositioningFormat2Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
    LEGlyphID firstGlyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
    GlyphIterator tempIterator(*glyphIterator);

    if (coverageIndex >= 0 && glyphIterator->next()) {
        LEGlyphID secondGlyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
        const ClassDefinitionTable *classDef1 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef1Offset));
        const ClassDefinitionTable *classDef2 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef2Offset));
        le_int32 class1 = classDef1->getGlyphClass(firstGlyph);
        le_int32 class2 = classDef2->getGlyphClass(secondGlyph);
        le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
        le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
        le_int16 class2RecordSize = valueRecord1Size + valueRecord2Size;
        le_int16 class1RecordSize = class2RecordSize * SWAPW(class2Count);
        const Class1Record *class1Record = (const Class1Record *) ((char *) class1RecordArray + (class1RecordSize * class1));
        const Class2Record *class2Record = (const Class2Record *) ((char *) class1Record->class2RecordArray + (class2RecordSize * class2));


        if (valueFormat1 != 0) {
            GlyphPositionAdjustment adjustment;

            tempIterator.getCurrGlyphPositionAdjustment(adjustment);
            class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, adjustment, fontInstance);
            tempIterator.setCurrGlyphPositionAdjustment(&adjustment);
        }

        if (valueFormat2 != 0) {
            const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size);
            GlyphPositionAdjustment adjustment;

            glyphIterator->getCurrGlyphPositionAdjustment(adjustment);
            valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, adjustment, fontInstance);
            glyphIterator->setCurrGlyphPositionAdjustment(&adjustment);
        }

        return 2;
    }

    return 0;
}
le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
    LEGlyphID firstGlyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
    GlyphIterator tempIterator(*glyphIterator);

    if (coverageIndex >= 0 && glyphIterator->next()) {
        Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
        PairSetTable *pairSetTable = (PairSetTable *) ((char *) this + pairSetTableOffset);
        le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
        le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
        le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
        LEGlyphID secondGlyph = (LEGlyphID) glyphIterator->getCurrGlyphID();
        const PairValueRecord *pairValueRecord =
            findPairValueRecord(secondGlyph, pairSetTable->pairValueRecordArray, SWAPW(pairSetTable->pairValueCount), recordSize);

        if (pairValueRecord == NULL) {
            return 0;
        }

        if (valueFormat1 != 0) {
            GlyphPositionAdjustment adjustment;

            tempIterator.getCurrGlyphPositionAdjustment(adjustment);
            pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, adjustment, fontInstance);
            tempIterator.setCurrGlyphPositionAdjustment(&adjustment);
        }

        if (valueFormat2 != 0) {
            const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size);
            GlyphPositionAdjustment adjustment;

            glyphIterator->getCurrGlyphPositionAdjustment(adjustment);
            valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, adjustment, fontInstance);
            glyphIterator->setCurrGlyphPositionAdjustment(&adjustment);
        }

        return 2;
    }

    return 0;
}
le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
    LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
    GlyphIterator tempIterator(*glyphIterator);

    if (coverageIndex >= 0 && glyphIterator->next()) {
        Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
        PairSetTable *pairSetTable = (PairSetTable *) ((char *) this + pairSetTableOffset);
        le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount);
        le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
        le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
        le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
        LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
        const PairValueRecord *pairValueRecord = NULL;

        if (pairValueCount != 0) {
            pairValueRecord = findPairValueRecord((TTGlyphID) LE_GET_GLYPH(secondGlyph), pairSetTable->pairValueRecordArray, pairValueCount, recordSize);
        }

        if (pairValueRecord == NULL) {
            return 0;
        }

        if (valueFormat1 != 0) {
            pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
        }

        if (valueFormat2 != 0) {
            const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size);

            valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, *glyphIterator, fontInstance);
        }

        // back up glyphIterator so second glyph can be
        // first glyph in the next pair
        glyphIterator->prev();
        return 1;
    }

    return 0;
}
/*
    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,
        const SubstitutionLookupRecord *substLookupRecordArray,
        le_uint16 substCount,
        GlyphIterator *glyphIterator,
        const LEFontInstance *fontInstance,
        le_int32 position)
{
    GlyphIterator tempIterator(*glyphIterator);

    for (le_int16 subst = 0; subst < substCount; subst += 1) {
        le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex);
        le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex);

        tempIterator.setCurrStreamPosition(position);
        tempIterator.next(sequenceIndex);

        lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance);
    }
}
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
                                                              const LEFontInstance *fontInstance) const
{
    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(glyph);

    if (coverageIndex >= 0) {
        const ClassDefinitionTable *backtrackClassDefinitionTable =
            (const ClassDefinitionTable *) ((char *) this + SWAPW(backtrackClassDefTableOffset));
        const ClassDefinitionTable *inputClassDefinitionTable =
            (const ClassDefinitionTable *) ((char *) this + SWAPW(inputClassDefTableOffset));
        const ClassDefinitionTable *lookaheadClassDefinitionTable =
            (const ClassDefinitionTable *) ((char *) this + SWAPW(lookaheadClassDefTableOffset));
        le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
        le_int32 setClass = inputClassDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID());

        if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
            Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
            const ChainSubClassSetTable *chainSubClassSetTable =
                (const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset);
            le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
            le_int32 position = glyphIterator->getCurrStreamPosition();
            GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);

            for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
                Offset chainSubClassRuleTableOffset =
                    SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
                const ChainSubClassRuleTable *chainSubClassRuleTable =
                    (const ChainSubClassRuleTable *) ((char *) chainSubClassSetTable + chainSubClassRuleTableOffset);
                le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
                le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
                const le_uint16 *inputClassArray = &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1];
                le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray[inputGlyphCount]);
                const le_uint16 *lookaheadClassArray = &inputClassArray[inputGlyphCount + 1];
                le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);
                

                tempIterator.setCurrStreamPosition(position);

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

                tempIterator.prev();
                if (! matchGlyphClasses(chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount,
                    &tempIterator, backtrackClassDefinitionTable, TRUE)) {
                    continue;
                }

                tempIterator.setCurrStreamPosition(position);
                tempIterator.next(inputGlyphCount);
                if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable)) {
                    continue;
                }

                if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable)) {
                    const SubstitutionLookupRecord *substLookupRecordArray = 
                        (const SubstitutionLookupRecord *) &lookaheadClassArray[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;
}
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
                                                                 GlyphIterator *glyphIterator,
                                                                 const LEFontInstance *fontInstance,
                                                                 LEErrorCode& success) const
{
    if (LE_FAILURE(success)) {
        return 0;
    }

    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
    if (LE_FAILURE(success)) {
        return 0;
    }

    if (coverageIndex >= 0) {
        LEReferenceTo<ClassDefinitionTable>
             backtrackClassDefinitionTable(base, success, SWAPW(backtrackClassDefTableOffset));
        LEReferenceTo<ClassDefinitionTable>
             inputClassDefinitionTable(base, success, SWAPW(inputClassDefTableOffset));
        LEReferenceTo<ClassDefinitionTable>
             lookaheadClassDefinitionTable(base, success, SWAPW(lookaheadClassDefTableOffset));
        le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
        le_int32 setClass = inputClassDefinitionTable->getGlyphClass(inputClassDefinitionTable,
                                                                     glyphIterator->getCurrGlyphID(),
                                                                     success);
        LEReferenceToArrayOf<Offset>
            chainSubClassSetTableOffsetArrayRef(base, success, chainSubClassSetTableOffsetArray, scSetCount);
        if (LE_FAILURE(success)) {
            return 0;
        }

        if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
            Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
            LEReferenceTo<ChainSubClassSetTable>
                 chainSubClassSetTable(base, success, chainSubClassSetTableOffset);
            if (LE_FAILURE(success)) { return 0; }
            le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
            le_int32 position = glyphIterator->getCurrStreamPosition();
            GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
            LEReferenceToArrayOf<Offset>
                chainSubClassRuleTableOffsetArrayRef(base, success, chainSubClassSetTable->chainSubClassRuleTableOffsetArray, chainSubClassRuleCount);
            if (LE_FAILURE(success)) {
                return 0;
            }
            for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
                Offset chainSubClassRuleTableOffset =
                    SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
                LEReferenceTo<ChainSubClassRuleTable>
                     chainSubClassRuleTable(chainSubClassSetTable, success, chainSubClassRuleTableOffset);
                if (LE_FAILURE(success)) { return 0; }
                le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
                LEReferenceToArrayOf<le_uint16>   backtrackClassArray(base, success, chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount);
                if( LE_FAILURE(success) ) { return 0; }
                le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
                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; }
                le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);


                tempIterator.setCurrStreamPosition(position);

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

                tempIterator.prev();
                if (! matchGlyphClasses(backtrackClassArray, backtrackGlyphCount,
                                        &tempIterator, backtrackClassDefinitionTable, success, TRUE)) {
                    continue;
                }

                tempIterator.setCurrStreamPosition(position);
                tempIterator.next(inputGlyphCount);
                if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable, success)) {
                    continue;
                }

                if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) {
                    LEReferenceToArrayOf<SubstitutionLookupRecord>
                      substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadClassArray.getAlias(lookaheadGlyphCount + 1, success), substCount);
                    if (LE_FAILURE(success)) { return 0; }
                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);

                    return inputGlyphCount + 1;
                }

                glyphIterator->setCurrStreamPosition(position);
            }
        }

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

    return 0;
}
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
                                                                 GlyphIterator *glyphIterator,
                                                                 const LEFontInstance *fontInstance,
                                                                 LEErrorCode& success) const
{
    if (LE_FAILURE(success)) {
        return 0;
    }

    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
    le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
    if (LE_FAILURE(success)) {
        return 0;
    }

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

        if (coverageIndex < srSetCount) {
            LEReferenceToArrayOf<Offset>
                chainSubRuleSetTableOffsetArrayRef(base, success, chainSubRuleSetTableOffsetArray, srSetCount);
            if (LE_FAILURE(success)) {
                return 0;
            }
            Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
            LEReferenceTo<ChainSubRuleSetTable> chainSubRuleSetTable(base, success, chainSubRuleSetTableOffset);
            if (LE_FAILURE(success)) { return 0; }
            le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
            le_int32 position = glyphIterator->getCurrStreamPosition();
            GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
            LEReferenceToArrayOf<Offset>
                chainSubRuleTableOffsetArrayRef(base, success, chainSubRuleSetTable->chainSubRuleTableOffsetArray, chainSubRuleCount);
            if (LE_FAILURE(success)) {
                return 0;
            }
            for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
                Offset chainSubRuleTableOffset =
                    SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
                LEReferenceTo<ChainSubRuleTable>
                     chainSubRuleTable = LEReferenceTo<ChainSubRuleTable>(chainSubRuleSetTable, success, chainSubRuleTableOffset);
                if( LE_FAILURE(success) ) { return 0; }
                le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
                LEReferenceToArrayOf<TTGlyphID> backtrackGlyphArray(base, success, chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount);
                if( LE_FAILURE(success) ) { return 0; }
                le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
                LEReferenceToArrayOf<TTGlyphID>   inputGlyphArray(base, success, &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1], inputGlyphCount+2);

                if( LE_FAILURE(success) ) { return 0; }
                le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
                LEReferenceToArrayOf<TTGlyphID>   lookaheadGlyphArray(base, success, inputGlyphArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2);
                if( LE_FAILURE(success) ) { return 0; }
                le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);

                tempIterator.setCurrStreamPosition(position);

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

                tempIterator.prev();

                if (! matchGlyphIDs(backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
                    continue;
                }

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

                if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
                    LEReferenceToArrayOf<SubstitutionLookupRecord>
                      substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadGlyphArray.getAlias(lookaheadGlyphCount + 1,success), substCount);

                    applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);

                    return inputGlyphCount + 1;
                }

                glyphIterator->setCurrStreamPosition(position);
            }
        }

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

    return 0;
}
Пример #19
0
am_Error_e CAmRouter::findBestWay(am_sinkID_t sinkID, am_sourceID_t sourceID, std::vector<am_RoutingElement_s> & listRoute, std::vector<am_RoutingElement_s>::iterator routeIterator, std::vector<am_gatewayID_t>::iterator gatewayIterator)
{
    am_Error_e returnError = E_NOT_POSSIBLE;
    std::vector<am_ConnectionFormat_e> listConnectionFormats;
    std::vector<am_ConnectionFormat_e> listMergeConnectionFormats;
    std::vector<am_ConnectionFormat_e> listPriorityConnectionFormats;
    std::vector<am_RoutingElement_s>::iterator nextIterator = routeIterator + 1;
    //get best connection format
    listPossibleConnectionFormats(routeIterator->sourceID, routeIterator->sinkID, listConnectionFormats);

    //if we have not just started, we need to take care about the gateways...
    if (routeIterator != listRoute.begin())
    {
        //since we have to deal with Gateways, there are restrictions what connectionFormat we can take. So we need to take the subset of connections that are restricted:
        std::vector<am_ConnectionFormat_e> listRestrictedConnectionFormats;
        std::insert_iterator<std::vector<am_ConnectionFormat_e> > inserter(listMergeConnectionFormats, listMergeConnectionFormats.begin());
        std::vector<am_RoutingElement_s>::iterator tempIterator(routeIterator);
        tempIterator--;
        listRestrictedOutputFormatsGateways(*gatewayIterator, (tempIterator)->connectionFormat, listRestrictedConnectionFormats);
        std::sort(listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end()); //todo: this might be not needed if we use strictly sorted input
        set_intersection(listConnectionFormats.begin(), listConnectionFormats.end(), listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end(), inserter);
        gatewayIterator++;
    }
    else
    {
        listMergeConnectionFormats = listConnectionFormats;
    }

    am_Route_s route;
    route.sinkID = sinkID;
    route.sourceID = sourceID;
    route.route = listRoute;

    //let the controller decide:
    mpControlSender->getConnectionFormatChoice(routeIterator->sourceID, routeIterator->sinkID, route, listMergeConnectionFormats, listPriorityConnectionFormats);

    //we have the list sorted after prios - now we try one after the other with the next part of the route
    std::vector<am_ConnectionFormat_e>::iterator connectionFormatIterator = listPriorityConnectionFormats.begin();

    //here we need to check if we are at the end and stop
    if (nextIterator == listRoute.end())
    {
        if (!listPriorityConnectionFormats.empty())
        {
            routeIterator->connectionFormat = listPriorityConnectionFormats.front();
            return (E_OK);
        }
        else
            return (E_NOT_POSSIBLE);
    }

    for (; connectionFormatIterator != listPriorityConnectionFormats.end(); ++connectionFormatIterator)
    {
        routeIterator->connectionFormat = *connectionFormatIterator;
        if ((returnError = findBestWay(sinkID, sourceID, listRoute, nextIterator, gatewayIterator)) == E_OK)
        {
            break;
        }
    }

    return (returnError);
}