Home | History | Annotate | Download | only in layout
      1 /*
      2  *
      3  * (C) Copyright IBM Corp. 1998-2015 - All Rights Reserved
      4  *
      5  */
      6 
      7 #include "LETypes.h"
      8 #include "LEGlyphFilter.h"
      9 #include "OpenTypeTables.h"
     10 #include "GlyphSubstitutionTables.h"
     11 #include "MultipleSubstSubtables.h"
     12 #include "GlyphIterator.h"
     13 #include "LESwaps.h"
     14 
     15 U_NAMESPACE_BEGIN
     16 
     17 le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const
     18 {
     19     if (LE_FAILURE(success)) {
     20         return 0;
     21     }
     22 
     23     LEGlyphID glyph = glyphIterator->getCurrGlyphID();
     24 
     25     // If there's a filter, we only want to do the
     26     // substitution if the *input* glyphs doesn't
     27     // exist.
     28     //
     29     // FIXME: is this always the right thing to do?
     30     // FIXME: should this only be done for a non-zero
     31     //        glyphCount?
     32     if (filter != NULL && filter->accept(glyph)) {
     33         return 0;
     34     }
     35 
     36     le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
     37     le_uint16 seqCount = SWAPW(sequenceCount);
     38     LEReferenceToArrayOf<Offset>
     39         sequenceTableOffsetArrayRef(base, success, sequenceTableOffsetArray, seqCount);
     40 
     41     if (LE_FAILURE(success)) {
     42         return 0;
     43     }
     44     if (coverageIndex >= 0 && coverageIndex < seqCount) {
     45         Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]);
     46         const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset);
     47         le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount);
     48 
     49         if (glyphCount == 0) {
     50             glyphIterator->setCurrGlyphID(0xFFFF);
     51             return 1;
     52         } else if (glyphCount == 1) {
     53             TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
     54 
     55             if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) {
     56                 return 0;
     57             }
     58 
     59             glyphIterator->setCurrGlyphID(substitute);
     60             return 1;
     61         } else {
     62             // If there's a filter, make sure all of the output glyphs
     63             // exist.
     64             if (filter != NULL) {
     65                 for (le_int32 i = 0; i < glyphCount; i += 1) {
     66                     TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
     67 
     68                     if (! filter->accept(substitute)) {
     69                         return 0;
     70                     }
     71                 }
     72             }
     73 
     74             LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount, success);
     75             if (LE_FAILURE(success)) {
     76                 return 0;
     77             }
     78 
     79             le_int32 insert = 0, direction = 1;
     80 
     81             if (glyphIterator->isRightToLeft()) {
     82                 insert = glyphCount - 1;
     83                 direction = -1;
     84             }
     85 
     86             for (le_int32 i = 0; i < glyphCount; i += 1) {
     87                 TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
     88 
     89                 newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute);
     90                 insert += direction;
     91             }
     92 
     93             return 1;
     94         }
     95     }
     96 
     97     return 0;
     98 }
     99 
    100 U_NAMESPACE_END
    101