Home | History | Annotate | Download | only in layout
      1 /*
      2  *
      3  * (C) Copyright IBM Corp. 1998-2008 - 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(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(glyph);
     37     le_uint16 seqCount = SWAPW(sequenceCount);
     38 
     39     if (coverageIndex >= 0 && coverageIndex < seqCount) {
     40         Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]);
     41         const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset);
     42         le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount);
     43 
     44         if (glyphCount == 0) {
     45             glyphIterator->setCurrGlyphID(0xFFFF);
     46             return 1;
     47         } else if (glyphCount == 1) {
     48             TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
     49 
     50             if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) {
     51                 return 0;
     52             }
     53 
     54             glyphIterator->setCurrGlyphID(substitute);
     55             return 1;
     56         } else {
     57             // If there's a filter, make sure all of the output glyphs
     58             // exist.
     59             if (filter != NULL) {
     60                 for (le_int32 i = 0; i < glyphCount; i += 1) {
     61                     TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
     62 
     63                     if (! filter->accept(substitute)) {
     64                         return 0;
     65                     }
     66                 }
     67             }
     68 
     69             LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount, success);
     70             if (LE_FAILURE(success)) {
     71                 return 0;
     72             }
     73 
     74             le_int32 insert = 0, direction = 1;
     75 
     76             if (glyphIterator->isRightToLeft()) {
     77                 insert = glyphCount - 1;
     78                 direction = -1;
     79             }
     80 
     81             for (le_int32 i = 0; i < glyphCount; i += 1) {
     82                 TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
     83 
     84                 newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute);
     85                 insert += direction;
     86             }
     87 
     88             return 1;
     89         }
     90     }
     91 
     92     return 0;
     93 }
     94 
     95 U_NAMESPACE_END
     96