]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/layout/GlyphIterator.cpp
ICU-59180.0.1.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
index d859c57cbf215b9bc4da0092d31e644f46abae1c..72d2dd13156d8273269010d93575e30d76de63f2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
  *
  */
 
 U_NAMESPACE_BEGIN
 
 GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
-                             FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
+                             FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader)
   : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
     glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
     srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
-    glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
+    glyphClassDefinitionTable(), markAttachClassDefinitionTable()
 
 {
+  LEErrorCode success = LE_NO_ERROR; // TODO
     le_int32 glyphCount = glyphStorage.getGlyphCount();
 
-    if (theGlyphDefinitionTableHeader != NULL) {
-        glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
-        markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
+    if (theGlyphDefinitionTableHeader.isValid()) {
+      glyphClassDefinitionTable = theGlyphDefinitionTableHeader
+        -> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader, success);
+      markAttachClassDefinitionTable = theGlyphDefinitionTableHeader
+        ->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader, success);
     }
 
     nextLimit = glyphCount;
@@ -38,6 +41,7 @@ GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjus
         nextLimit = -1;
         prevLimit = glyphCount;
     }
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that)
@@ -56,6 +60,7 @@ GlyphIterator::GlyphIterator(GlyphIterator &that)
     glyphGroup  = that.glyphGroup;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
@@ -74,6 +79,7 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
     glyphGroup  = 0;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
@@ -92,6 +98,7 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
     glyphGroup  = that.glyphGroup;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::~GlyphIterator()
@@ -105,11 +112,12 @@ void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
     featureMask  = newFeatureMask;
     glyphGroup   = 0;
     lookupFlags  = newLookupFlags;
+    filterResetCache();
 }
 
-LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count)
+LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)
 {
-    return glyphStorage.insertGlyphs(position, count);
+    return glyphStorage.insertGlyphs(position, count, success);
 }
 
 le_int32 GlyphIterator::applyInsertions()
@@ -353,51 +361,68 @@ void GlyphIterator::setCursiveGlyph()
     glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());
 }
 
-le_bool GlyphIterator::filterGlyph(le_uint32 index) const
+void GlyphIterator::filterResetCache(void) {
+  filterCacheValid = FALSE;
+}
+
+le_bool GlyphIterator::filterGlyph(le_uint32 index)
 {
     LEGlyphID glyphID = glyphStorage[index];
-    le_int32 glyphClass = gcdNoGlyphClass;
-
-    if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
-        return TRUE;
-    }
-
-    if (glyphClassDefinitionTable != NULL) {
-        glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
-    }
-
-    switch (glyphClass)
-    {
-    case gcdNoGlyphClass:
-        return FALSE;
-
-    case gcdSimpleGlyph:
-        return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
 
-    case gcdLigatureGlyph:
-        return (lookupFlags & lfIgnoreLigatures) != 0;
-
-    case gcdMarkGlyph:
-    {
-        if ((lookupFlags & lfIgnoreMarks) != 0) {
-            return TRUE;
+    if (!filterCacheValid || filterCache.id != glyphID) {
+      filterCache.id = glyphID;
+
+      le_bool &filterResult = filterCache.result;  // NB: Making this a reference to accept the updated value, in case
+                                               // we want more fancy cacheing in the future.
+      if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
+        filterResult = TRUE;
+      } else {
+        LEErrorCode success = LE_NO_ERROR;
+        le_int32 glyphClass = gcdNoGlyphClass;
+        if (glyphClassDefinitionTable.isValid()) {
+          glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);
         }
-
-        le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
-
-        if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
-            return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
+        switch (glyphClass) {
+        case gcdNoGlyphClass:
+          filterResult = FALSE;
+          break;
+
+        case gcdSimpleGlyph:
+          filterResult = (lookupFlags & lfIgnoreBaseGlyphs) != 0;
+          break;
+
+        case gcdLigatureGlyph:
+          filterResult = (lookupFlags & lfIgnoreLigatures) != 0;
+          break;
+
+        case gcdMarkGlyph: 
+          if ((lookupFlags & lfIgnoreMarks) != 0) {
+            filterResult = TRUE;
+          } else {
+            le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
+            
+            if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {
+              filterResult = (markAttachClassDefinitionTable
+                          -> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType);
+            } else {
+              filterResult = FALSE;
+            }
+          }
+          break;
+
+        case gcdComponentGlyph:
+          filterResult = ((lookupFlags & lfIgnoreBaseGlyphs) != 0);
+          break;
+
+        default:
+          filterResult = FALSE;
+          break;
         }
-
-        return FALSE;
-    }
-
-    case gcdComponentGlyph:
-        return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
-
-    default:
-        return FALSE;
+      }
+      filterCacheValid = TRUE;
     }
+    
+    return filterCache.result;
 }
 
 le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const
@@ -436,6 +461,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
     while (newPosition != nextLimit && delta > 0) {
         do {
             newPosition += direction;
+            //fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
         } while (newPosition != nextLimit && filterGlyph(newPosition));
 
         delta -= 1;
@@ -443,6 +469,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
 
     position = newPosition;
 
+    //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
     return position != nextLimit;
 }
 
@@ -458,6 +485,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
     while (newPosition != prevLimit && delta > 0) {
         do {
             newPosition -= direction;
+            //fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
         } while (newPosition != prevLimit && filterGlyph(newPosition));
 
         delta -= 1;
@@ -465,6 +493,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
 
     position = newPosition;
 
+    //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
     return position != prevLimit;
 }