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 "LEGlyphStorage.h"
     14 #include "LESwaps.h"
     15 #include "LookupTables.h"
     16 
     17 U_NAMESPACE_BEGIN
     18 
     19 StateTableProcessor2::StateTableProcessor2()
     20 {
     21 }
     22 
     23 StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
     24   : SubtableProcessor2(morphSubtableHeader, success),
     25     dir(1),
     26     format(0),
     27     nClasses(0),
     28     classTableOffset(0),
     29     stateArrayOffset(0),
     30     entryTableOffset(0),
     31     classTable(),
     32     stateArray(),
     33     stateTableHeader(morphSubtableHeader, success),
     34     stHeader(stateTableHeader, success, (const StateTableHeader2*)&stateTableHeader->stHeader)
     35 {
     36   if (LE_FAILURE(success)) {
     37     return;
     38   }
     39   nClasses = SWAPL(stHeader->nClasses);
     40   classTableOffset = SWAPL(stHeader->classTableOffset);
     41   stateArrayOffset = SWAPL(stHeader->stateArrayOffset);
     42   entryTableOffset = SWAPL(stHeader->entryTableOffset);
     43 
     44   classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset);
     45   format = SWAPW(classTable->format);
     46 
     47   stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY);
     48 }
     49 
     50 StateTableProcessor2::~StateTableProcessor2()
     51 {
     52 }
     53 
     54 void StateTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
     55 {
     56     if (LE_FAILURE(success)) return;
     57     // Start at state 0
     58     // XXX: How do we know when to start at state 1?
     59     le_uint16 currentState = 0;
     60     le_int32 glyphCount = glyphStorage.getGlyphCount();
     61 
     62     LE_STATE_PATIENCE_INIT();
     63 
     64     le_int32 currGlyph = 0;
     65     if ((coverage & scfReverse2) != 0) {  // process glyphs in descending order
     66         currGlyph = glyphCount - 1;
     67         dir = -1;
     68     } else {
     69         dir = 1;
     70     }
     71 
     72     beginStateTable();
     73     switch (format) {
     74         case ltfSimpleArray: {
     75 #ifdef TEST_FORMAT
     76           LEReferenceTo<SimpleArrayLookupTable> lookupTable0(classTable, success);
     77           if(LE_FAILURE(success)) break;
     78             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
     79                 if (LE_FAILURE(success)) break;
     80                 if (LE_STATE_PATIENCE_DECR()) {
     81                   LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
     82                   break; // patience exceeded.
     83                 }
     84                 LookupValue classCode = classCodeOOB;
     85                 if (currGlyph == glyphCount || currGlyph == -1) {
     86                     // XXX: How do we handle EOT vs. EOL?
     87                     classCode = classCodeEOT;
     88                 } else {
     89                     LEGlyphID gid = glyphStorage[currGlyph];
     90                     TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
     91 
     92                     if (glyphCode == 0xFFFF) {
     93                         classCode = classCodeDEL;
     94                     } else {
     95                         classCode = SWAPW(lookupTable0->valueArray[gid]);
     96                     }
     97                 }
     98                 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
     99                 LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
    100                 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset
    101                 LE_STATE_PATIENCE_INCR(currGlyph);
    102             }
    103 #endif
    104             break;
    105         }
    106         case ltfSegmentSingle: {
    107           LEReferenceTo<SegmentSingleLookupTable> lookupTable2(classTable, success);
    108           if(LE_FAILURE(success)) break;
    109             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
    110                 if (LE_FAILURE(success)) break;
    111                 if (LE_STATE_PATIENCE_DECR()) {
    112                   LE_DEBUG_BAD_FONT("patience exceeded  - state table not moving")
    113                   break; // patience exceeded.
    114                 }
    115                 LookupValue classCode = classCodeOOB;
    116                 if (currGlyph == glyphCount || currGlyph == -1) {
    117                     // XXX: How do we handle EOT vs. EOL?
    118                     classCode = classCodeEOT;
    119                 } else {
    120                     LEGlyphID gid = glyphStorage[currGlyph];
    121                     TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
    122 
    123                     if (glyphCode == 0xFFFF) {
    124                         classCode = classCodeDEL;
    125                     } else {
    126                       const LookupSegment *segment =
    127                         lookupTable2->lookupSegment(lookupTable2, lookupTable2->segments, gid, success);
    128                         if (segment != NULL && LE_SUCCESS(success)) {
    129                             classCode = SWAPW(segment->value);
    130                         }
    131                     }
    132                 }
    133                 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses,success));
    134                 LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
    135                 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
    136                 LE_STATE_PATIENCE_INCR(currGlyph);
    137             }
    138             break;
    139         }
    140         case ltfSegmentArray: {
    141           //printf("Lookup Table Format4: specific interpretation needed!\n");
    142             break;
    143         }
    144         case ltfSingleTable: {
    145             LEReferenceTo<SingleTableLookupTable> lookupTable6(classTable, success);
    146             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
    147                 if (LE_FAILURE(success)) break;
    148                 if (LE_STATE_PATIENCE_DECR()) {
    149                   LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
    150                   break; // patience exceeded.
    151                 }
    152                 LookupValue classCode = classCodeOOB;
    153                 if (currGlyph == glyphCount || currGlyph == -1) {
    154                     // XXX: How do we handle EOT vs. EOL?
    155                     classCode = classCodeEOT;
    156                 } else if(currGlyph > glyphCount) {
    157                   // note if > glyphCount, we've run off the end (bad font)
    158                   currGlyph = glyphCount;
    159                   classCode = classCodeEOT;
    160                 } else {
    161                     LEGlyphID gid = glyphStorage[currGlyph];
    162                     TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
    163 
    164                     if (glyphCode == 0xFFFF) {
    165                         classCode = classCodeDEL;
    166                     } else {
    167                       const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6, lookupTable6->entries, gid, success);
    168                         if (segment != NULL) {
    169                             classCode = SWAPW(segment->value);
    170                         }
    171                     }
    172                 }
    173                 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
    174                 LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
    175                 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
    176                 LE_STATE_PATIENCE_INCR(currGlyph);
    177             }
    178             break;
    179         }
    180         case ltfTrimmedArray: {
    181             LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(classTable, success);
    182             if (LE_FAILURE(success)) break;
    183             TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
    184             TTGlyphID lastGlyph  = firstGlyph + SWAPW(lookupTable8->glyphCount);
    185 
    186             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
    187                 if(LE_STATE_PATIENCE_DECR()) {
    188                   LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
    189                   break; // patience exceeded.
    190                 }
    191 
    192                 LookupValue classCode = classCodeOOB;
    193                 if (currGlyph == glyphCount || currGlyph == -1) {
    194                     // XXX: How do we handle EOT vs. EOL?
    195                     classCode = classCodeEOT;
    196                 } else {
    197                     TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]);
    198                     if (glyphCode == 0xFFFF) {
    199                         classCode = classCodeDEL;
    200                     } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
    201                         classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
    202                     }
    203                 }
    204                 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
    205                 LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
    206                 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
    207                 LE_STATE_PATIENCE_INCR(currGlyph);
    208             }
    209             break;
    210         }
    211         default:
    212             break;
    213     }
    214 
    215     endStateTable();
    216 }
    217 
    218 U_NAMESPACE_END
    219