]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/layout/StateTableProcessor2.cpp
ICU-551.24.tar.gz
[apple/icu.git] / icuSources / layout / StateTableProcessor2.cpp
index 5741ab7371271ee91e417affc80f1c0684c39aa6..88621f374f47fbf391b1521d05bd24a3f7ee9293 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * (C) Copyright IBM Corp.  and others 1998-2013 - All Rights Reserved
+ * (C) Copyright IBM Corp.  and others 1998-2014 - All Rights Reserved
  *
  */
 
@@ -13,7 +13,6 @@
 #include "LEGlyphStorage.h"
 #include "LESwaps.h"
 #include "LookupTables.h"
-#include <stdio.h>
 
 U_NAMESPACE_BEGIN
 
@@ -21,32 +20,47 @@ StateTableProcessor2::StateTableProcessor2()
 {
 }
 
-StateTableProcessor2::StateTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
-  : SubtableProcessor2(morphSubtableHeader)
+StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+  : SubtableProcessor2(morphSubtableHeader, success), 
+    dir(1),
+    format(0),
+    nClasses(0), 
+    classTableOffset(0), 
+    stateArrayOffset(0), 
+    entryTableOffset(0), 
+    classTable(), 
+    stateArray(),
+    stateTableHeader(morphSubtableHeader, success),
+    stHeader(stateTableHeader, success, (const StateTableHeader2*)&stateTableHeader->stHeader)
 {
-    stateTableHeader = (const MorphStateTableHeader2 *) morphSubtableHeader;
-    nClasses = SWAPL(stateTableHeader->stHeader.nClasses);
-    classTableOffset = SWAPL(stateTableHeader->stHeader.classTableOffset);
-    stateArrayOffset = SWAPL(stateTableHeader->stHeader.stateArrayOffset);
-    entryTableOffset = SWAPL(stateTableHeader->stHeader.entryTableOffset);
-    
-    classTable = (LookupTable *) ((char *) &stateTableHeader->stHeader + classTableOffset);
-    format = SWAPW(classTable->format);
-    
-    stateArray = (const EntryTableIndex2 *) ((char *) &stateTableHeader->stHeader + stateArrayOffset);
+  if (LE_FAILURE(success)) {
+    return;
+  }
+  nClasses = SWAPL(stHeader->nClasses);
+  classTableOffset = SWAPL(stHeader->classTableOffset);
+  stateArrayOffset = SWAPL(stHeader->stateArrayOffset);
+  entryTableOffset = SWAPL(stHeader->entryTableOffset);
+  
+  classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset);
+  format = SWAPW(classTable->format);
+  
+  stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY);
 }
 
 StateTableProcessor2::~StateTableProcessor2()
 {
 }
 
-void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
+void StateTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
 {
+    if (LE_FAILURE(success)) return;
     // Start at state 0
     // XXX: How do we know when to start at state 1?
     le_uint16 currentState = 0;
     le_int32 glyphCount = glyphStorage.getGlyphCount();
-   
+    
+    LE_STATE_PATIENCE_INIT();
+
     le_int32 currGlyph = 0;
     if ((coverage & scfReverse2) != 0) {  // process glyphs in descending order
         currGlyph = glyphCount - 1;
@@ -59,8 +73,14 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
     switch (format) {
         case ltfSimpleArray: {
 #ifdef TEST_FORMAT
-            SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable;
+          LEReferenceTo<SimpleArrayLookupTable> lookupTable0(classTable, success);
+          if(LE_FAILURE(success)) break;
             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+                if (LE_FAILURE(success)) break;
+                if (LE_STATE_PATIENCE_DECR()) {
+                  LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+                  break; // patience exceeded.
+                }
                 LookupValue classCode = classCodeOOB;
                 if (currGlyph == glyphCount || currGlyph == -1) {
                     // XXX: How do we handle EOT vs. EOL?
@@ -75,15 +95,23 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
                         classCode = SWAPW(lookupTable0->valueArray[gid]);
                     }
                 }
-                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
+                EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
+                LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
                 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset
+                LE_STATE_PATIENCE_INCR(currGlyph);
             }
 #endif
             break;
         }
         case ltfSegmentSingle: {
-            SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable;
+          LEReferenceTo<SegmentSingleLookupTable> lookupTable2(classTable, success);
+          if(LE_FAILURE(success)) break;
             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+                if (LE_FAILURE(success)) break;
+                if (LE_STATE_PATIENCE_DECR()) {
+                  LE_DEBUG_BAD_FONT("patience exceeded  - state table not moving")
+                  break; // patience exceeded.
+                }
                 LookupValue classCode = classCodeOOB;
                 if (currGlyph == glyphCount || currGlyph == -1) {
                     // XXX: How do we handle EOT vs. EOL?
@@ -95,28 +123,40 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
                     if (glyphCode == 0xFFFF) {
                         classCode = classCodeDEL;
                     } else {
-                        const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
-                        if (segment != NULL) {
+                      const LookupSegment *segment = 
+                        lookupTable2->lookupSegment(lookupTable2, lookupTable2->segments, gid, success);
+                        if (segment != NULL && LE_SUCCESS(success)) {
                             classCode = SWAPW(segment->value);
                         }
                     }
                 }                
-                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
-                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
+                EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses,success));
+                LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
+                LE_STATE_PATIENCE_INCR(currGlyph);
             }
             break;
         }
         case ltfSegmentArray: {
-            printf("Lookup Table Format4: specific interpretation needed!\n");
+          //printf("Lookup Table Format4: specific interpretation needed!\n");
             break;
         }
         case ltfSingleTable: {
-            SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable;
+            LEReferenceTo<SingleTableLookupTable> lookupTable6(classTable, success);
             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+                if (LE_FAILURE(success)) break;
+                if (LE_STATE_PATIENCE_DECR()) {
+                  LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+                  break; // patience exceeded.
+                }
                 LookupValue classCode = classCodeOOB;
                 if (currGlyph == glyphCount || currGlyph == -1) {
                     // XXX: How do we handle EOT vs. EOL?
                     classCode = classCodeEOT;
+                } else if(currGlyph > glyphCount) {
+                  // note if > glyphCount, we've run off the end (bad font)
+                  currGlyph = glyphCount;
+                  classCode = classCodeEOT;
                 } else {
                     LEGlyphID gid = glyphStorage[currGlyph];
                     TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
@@ -124,23 +164,31 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
                     if (glyphCode == 0xFFFF) {
                         classCode = classCodeDEL;
                     } else {
-                        const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
+                      const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6, lookupTable6->entries, gid, success);
                         if (segment != NULL) {
                             classCode = SWAPW(segment->value);
                         }
                     }
                 }
-                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
-                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
+                EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
+                LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
+                LE_STATE_PATIENCE_INCR(currGlyph);
             }
             break;
         }
         case ltfTrimmedArray: {
-            TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) classTable;
+            LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(classTable, success);
+            if (LE_FAILURE(success)) break;
             TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);    
             TTGlyphID lastGlyph  = firstGlyph + SWAPW(lookupTable8->glyphCount);
             
             while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+                if(LE_STATE_PATIENCE_DECR()) {
+                  LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+                  break; // patience exceeded.
+                }
+                       
                 LookupValue classCode = classCodeOOB;
                 if (currGlyph == glyphCount || currGlyph == -1) {
                     // XXX: How do we handle EOT vs. EOL?
@@ -153,8 +201,10 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
                         classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
                     }
                 }
-                EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);                
-                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
+                EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
+                LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+                currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
+                LE_STATE_PATIENCE_INCR(currGlyph);
             }
             break;
         }