Home | History | Annotate | Download | only in layout
      1 /*
      2  *
      3  * (C) Copyright IBM Corp and Others. 1998-2014 - All Rights Reserved
      4  *
      5  */
      6 
      7 #include "LETypes.h"
      8 #include "MorphTables.h"
      9 #include "StateTables.h"
     10 #include "MorphStateTables.h"
     11 #include "SubtableProcessor2.h"
     12 #include "StateTableProcessor2.h"
     13 #include "LigatureSubstProc2.h"
     14 #include "LEGlyphStorage.h"
     15 #include "LESwaps.h"
     16 
     17 U_NAMESPACE_BEGIN
     18 
     19 #define ExtendedComplement(m) ((le_int32) (~((le_uint32) (m))))
     20 #define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m))
     21 #define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v))
     22 
     23 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2)
     24 
     25 LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
     26   : StateTableProcessor2(morphSubtableHeader, success),
     27   ligActionOffset(0),
     28   componentOffset(0), ligatureOffset(0),  entryTable(), ligatureSubstitutionHeader(morphSubtableHeader, success)
     29 {
     30     if (LE_FAILURE(success)) return;
     31 
     32     ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset);
     33     componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset);
     34     ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset);
     35 
     36     entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
     37 }
     38 
     39 LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2()
     40 {
     41 }
     42 
     43 void LigatureSubstitutionProcessor2::beginStateTable()
     44 {
     45     m = -1;
     46 }
     47 
     48 le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success)
     49 {
     50     const LigatureSubstitutionStateEntry2 *entry = entryTable.getAlias(index, success);
     51     if(LE_FAILURE(success)) return 0;
     52 
     53     le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex);
     54     le_uint16 flags = SWAPW(entry->entryFlags);
     55     le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex);
     56 
     57     if (flags & lsfSetComponent) {
     58         if (++m >= nComponents) {
     59             m = 0;
     60         }
     61         componentStack[m] = currGlyph;
     62     } else if ( m == -1) {
     63         // bad font- skip this glyph.
     64         //LE_DEBUG_BAD_FONT("m==-1 (componentCount went negative)")
     65         currGlyph+= dir;
     66         return nextStateIndex;
     67     }
     68 
     69     ByteOffset actionOffset = flags & lsfPerformAction;
     70 
     71     if (actionOffset != 0) {
     72         LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
     73         ap.addObject(ligActionIndex - 1, success);  // index offset ( one before the actual start, because we will pre-increment)
     74         LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
     75         LigatureActionEntry action;
     76         le_int32 offset, i = 0;
     77         le_int32 stack[nComponents];
     78         le_int16 mm = -1;
     79 
     80         LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY);
     81         if(LE_FAILURE(success)) {
     82           currGlyph+= dir;
     83           return nextStateIndex; // get out! bad font
     84         }
     85 
     86         do {
     87             le_int32 componentGlyph = componentStack[m--]; // pop off
     88 
     89             ap.addObject(success);
     90             action = SWAPL(*ap.getAlias());
     91 
     92             if (m < 0) {
     93                 m = nComponents - 1;
     94             }
     95 
     96             offset = action & lafComponentOffsetMask;
     97             if (offset != 0) {
     98                 if(componentGlyph > glyphStorage.getGlyphCount() || componentGlyph < 0) {
     99                   LE_DEBUG_BAD_FONT("preposterous componentGlyph");
    100                   currGlyph+= dir;
    101                   return nextStateIndex; // get out! bad font
    102                 }
    103                 i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success));
    104 
    105                 if (action & (lafLast | lafStore))  {
    106                   TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success));
    107                     glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
    108                     if(mm==nComponents) {
    109                       LE_DEBUG_BAD_FONT("exceeded nComponents");
    110                       mm--; // don't overrun the stack.
    111                     }
    112                     stack[++mm] = componentGlyph;
    113                     i = 0;
    114                 } else {
    115                     glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
    116                 }
    117             }
    118 #if LE_ASSERT_BAD_FONT
    119             if(m<0) {
    120               LE_DEBUG_BAD_FONT("m<0")
    121             }
    122 #endif
    123         } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
    124 
    125         while (mm >= 0) {
    126             if (++m >= nComponents) {
    127                 m = 0;
    128             }
    129 
    130             componentStack[m] = stack[mm--];
    131         }
    132     }
    133 
    134     if (!(flags & lsfDontAdvance)) {
    135         currGlyph += dir;
    136     }
    137 
    138     return nextStateIndex;
    139 }
    140 
    141 void LigatureSubstitutionProcessor2::endStateTable()
    142 {
    143 }
    144 
    145 U_NAMESPACE_END
    146