1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LETypes.h"
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphFilter.h"
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeTables.h"
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphSubstitutionTables.h"
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "MultipleSubstSubtables.h"
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphIterator.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LESwaps.h"
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hole_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (LE_FAILURE(success)) {
2085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return 0;
2185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEGlyphID glyph = glyphIterator->getCurrGlyphID();
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If there's a filter, we only want to do the
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // substitution if the *input* glyphs doesn't
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // exist.
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // FIXME: is this always the right thing to do?
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // FIXME: should this only be done for a non-zero
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //        glyphCount?
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (filter != NULL && filter->accept(glyph)) {
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 coverageIndex = getGlyphCoverage(glyph);
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 seqCount = SWAPW(sequenceCount);
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (coverageIndex >= 0 && coverageIndex < seqCount) {
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]);
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset);
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount);
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (glyphCount == 0) {
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            glyphIterator->setCurrGlyphID(0xFFFF);
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 1;
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (glyphCount == 1) {
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) {
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            glyphIterator->setCurrGlyphID(substitute);
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 1;
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // If there's a filter, make sure all of the output glyphs
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // exist.
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (filter != NULL) {
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                for (le_int32 i = 0; i < glyphCount; i += 1) {
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (! filter->accept(substitute)) {
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        return 0;
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount, success);
7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (LE_FAILURE(success)) {
7185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return 0;
7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
7385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32 insert = 0, direction = 1;
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (glyphIterator->isRightToLeft()) {
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                insert = glyphCount - 1;
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                direction = -1;
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (le_int32 i = 0; i < glyphCount; i += 1) {
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute);
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                insert += direction;
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 1;
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
96