]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/layout/GlyphIterator.cpp
ICU-57132.0.1.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
index 20bcc8600e405af1d29c6d38b1cd7e1027f1df94..72d2dd13156d8273269010d93575e30d76de63f2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
 /*
  *
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
  *
  */
 
  *
  */
 
 
 U_NAMESPACE_BEGIN
 
 
 U_NAMESPACE_BEGIN
 
-GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag,
-    const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
+GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
+                             FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader)
   : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
   : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
-    cursiveFirstPosition(-1), cursiveLastPosition(-1), cursiveBaselineAdjustment(0),
     glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
     glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
-    srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureTag(theFeatureTag),
-    glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
+    srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
+    glyphClassDefinitionTable(), markAttachClassDefinitionTable()
 
 {
 
 {
+  LEErrorCode success = LE_NO_ERROR; // TODO
     le_int32 glyphCount = glyphStorage.getGlyphCount();
 
     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;
     }
 
     nextLimit = glyphCount;
@@ -39,6 +41,7 @@ GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjus
         nextLimit = -1;
         prevLimit = glyphCount;
     }
         nextLimit = -1;
         prevLimit = glyphCount;
     }
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that)
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that)
@@ -49,19 +52,18 @@ GlyphIterator::GlyphIterator(GlyphIterator &that)
     nextLimit    = that.nextLimit;
     prevLimit    = that.prevLimit;
 
     nextLimit    = that.nextLimit;
     prevLimit    = that.prevLimit;
 
-    cursiveFirstPosition = that.cursiveFirstPosition;
-    cursiveLastPosition  = that.cursiveLastPosition;
-
     glyphPositionAdjustments = that.glyphPositionAdjustments;
     srcIndex = that.srcIndex;
     destIndex = that.destIndex;
     lookupFlags = that.lookupFlags;
     glyphPositionAdjustments = that.glyphPositionAdjustments;
     srcIndex = that.srcIndex;
     destIndex = that.destIndex;
     lookupFlags = that.lookupFlags;
-    featureTag = that.featureTag;
+    featureMask = that.featureMask;
+    glyphGroup  = that.glyphGroup;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 }
 
-GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag)
+GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
   : glyphStorage(that.glyphStorage)
 {
     direction    = that.direction;
   : glyphStorage(that.glyphStorage)
 {
     direction    = that.direction;
@@ -69,16 +71,15 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag)
     nextLimit    = that.nextLimit;
     prevLimit    = that.prevLimit;
 
     nextLimit    = that.nextLimit;
     prevLimit    = that.prevLimit;
 
-    cursiveFirstPosition = that.cursiveFirstPosition;
-    cursiveLastPosition  = that.cursiveLastPosition;
-
     glyphPositionAdjustments = that.glyphPositionAdjustments;
     srcIndex = that.srcIndex;
     destIndex = that.destIndex;
     lookupFlags = that.lookupFlags;
     glyphPositionAdjustments = that.glyphPositionAdjustments;
     srcIndex = that.srcIndex;
     destIndex = that.destIndex;
     lookupFlags = that.lookupFlags;
-    featureTag = newFeatureTag;
+    featureMask = newFeatureMask;
+    glyphGroup  = 0;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
@@ -89,17 +90,15 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
     nextLimit    = that.nextLimit;
     prevLimit    = that.prevLimit;
 
     nextLimit    = that.nextLimit;
     prevLimit    = that.prevLimit;
 
-
-    cursiveFirstPosition = that.cursiveFirstPosition;
-    cursiveLastPosition  = that.cursiveLastPosition;
-
     glyphPositionAdjustments = that.glyphPositionAdjustments;
     srcIndex = that.srcIndex;
     destIndex = that.destIndex;
     lookupFlags = newLookupFlags;
     glyphPositionAdjustments = that.glyphPositionAdjustments;
     srcIndex = that.srcIndex;
     destIndex = that.destIndex;
     lookupFlags = newLookupFlags;
-    featureTag = that.featureTag;
+    featureMask = that.featureMask;
+    glyphGroup  = that.glyphGroup;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::~GlyphIterator()
 }
 
 GlyphIterator::~GlyphIterator()
@@ -107,16 +106,18 @@ GlyphIterator::~GlyphIterator()
     // nothing to do, right?
 }
 
     // nothing to do, right?
 }
 
-void GlyphIterator::reset(le_uint16 newLookupFlags, LETag newFeatureTag)
+void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
 {
 {
-    position    = prevLimit;
-    featureTag  = newFeatureTag;
-    lookupFlags = newLookupFlags;
+    position     = prevLimit;
+    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()
 }
 
 le_int32 GlyphIterator::applyInsertions()
@@ -152,16 +153,6 @@ le_bool GlyphIterator::baselineIsLogicalEnd() const
     return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
 }
 
     return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
 }
 
-le_bool GlyphIterator::hasCursiveFirstExitPoint() const
-{
-    return cursiveFirstPosition >= 0;
-}
-
-le_bool GlyphIterator::hasCursiveLastExitPoint() const
-{
-    return cursiveLastPosition >= 0;
-}
-
 LEGlyphID GlyphIterator::getCurrGlyphID() const
 {
     if (direction < 0) {
 LEGlyphID GlyphIterator::getCurrGlyphID() const
 {
     if (direction < 0) {
@@ -177,39 +168,10 @@ LEGlyphID GlyphIterator::getCurrGlyphID() const
     return glyphStorage[position];
 }
 
     return glyphStorage[position];
 }
 
-LEGlyphID GlyphIterator::getCursiveLastGlyphID() const
+void GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const
 {
     if (direction < 0) {
 {
     if (direction < 0) {
-        if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
-            return 0xFFFF;
-        }
-    } else {
-        if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
-            return 0xFFFF;
-        }
-    }
-
-    return glyphStorage[cursiveLastPosition];
-}
-
-void GlyphIterator::getCursiveLastExitPoint(LEPoint &exitPoint) const
-{
-    if (cursiveLastPosition >= 0) {
-        exitPoint = cursiveLastExitPoint;
-    }
-}
-
-float GlyphIterator::getCursiveBaselineAdjustment() const
-{
-    return cursiveBaselineAdjustment;
-}
-
-void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment &adjustment) const
-{
-    if (direction < 0)
-    {
-        if (position <= nextLimit || position >= prevLimit)
-        {
+        if (position <= nextLimit || position >= prevLimit) {
             return;
         }
     } else {
             return;
         }
     } else {
@@ -218,24 +180,22 @@ void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment &adju
         }
     }
 
         }
     }
 
-    adjustment = glyphPositionAdjustments[position];
+    glyphPositionAdjustments->getEntryPoint(position, entryPoint);
 }
 
 }
 
-void GlyphIterator::getCursiveLastPositionAdjustment(GlyphPositionAdjustment &adjustment) const
+void GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const
 {
 {
-    if (direction < 0)
-    {
-        if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit)
-        {
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
             return;
         }
     } else {
             return;
         }
     } else {
-        if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
+        if (position <= prevLimit || position >= nextLimit) {
             return;
         }
     }
 
             return;
         }
     }
 
-    adjustment = glyphPositionAdjustments[cursiveLastPosition];
+    glyphPositionAdjustments->getExitPoint(position, exitPoint);
 }
 
 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
 }
 
 void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
@@ -247,10 +207,6 @@ void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
 
 void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
 {
 
 void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
 {
-    cursiveFirstPosition      = -1;
-    cursiveLastPosition       = -1;
-    cursiveBaselineAdjustment =  0;
-
     if (direction < 0) {
         if (newPosition >= prevLimit) {
             position = prevLimit;
     if (direction < 0) {
         if (newPosition >= prevLimit) {
             position = prevLimit;
@@ -277,7 +233,7 @@ void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
     next();
 }
 
     next();
 }
 
-void GlyphIterator::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment *adjustment)
+void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
@@ -289,10 +245,11 @@ void GlyphIterator::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment
         }
     }
 
         }
     }
 
-    glyphPositionAdjustments[position] = *adjustment;
+    glyphPositionAdjustments->setBaseOffset(position, baseOffset);
 }
 
 }
 
-void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
+void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
+                                                      float xAdvanceAdjust, float yAdvanceAdjust)
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
@@ -304,10 +261,13 @@ void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
         }
     }
 
         }
     }
 
-    glyphPositionAdjustments[position].setBaseOffset(baseOffset);
+    glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);
+    glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);
+    glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);
+    glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);
 }
 
 }
 
-void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
+void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
                                                       float xAdvanceAdjust, float yAdvanceAdjust)
 {
     if (direction < 0) {
                                                       float xAdvanceAdjust, float yAdvanceAdjust)
 {
     if (direction < 0) {
@@ -320,14 +280,13 @@ void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, fl
         }
     }
 
         }
     }
 
-    glyphPositionAdjustments[position].adjustXPlacement(xPlacementAdjust);
-    glyphPositionAdjustments[position].adjustYPlacement(yPlacementAdjust);
-    glyphPositionAdjustments[position].adjustXAdvance(xAdvanceAdjust);
-    glyphPositionAdjustments[position].adjustYAdvance(yAdvanceAdjust);
+    glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);
+    glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);
+    glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);
+    glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
 }
 
 }
 
-void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
-                                                      float xAdvanceAdjust, float yAdvanceAdjust)
+void GlyphIterator::clearCursiveEntryPoint()
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
@@ -339,13 +298,10 @@ void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float
         }
     }
 
         }
     }
 
-    glyphPositionAdjustments[position].setXPlacement(xPlacementAdjust);
-    glyphPositionAdjustments[position].setYPlacement(yPlacementAdjust);
-    glyphPositionAdjustments[position].setXAdvance(xAdvanceAdjust);
-    glyphPositionAdjustments[position].setYAdvance(yAdvanceAdjust);
+    glyphPositionAdjustments->clearEntryPoint(position);
 }
 
 }
 
-void GlyphIterator::setCursiveFirstExitPoint()
+void GlyphIterator::clearCursiveExitPoint()
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
@@ -357,31 +313,25 @@ void GlyphIterator::setCursiveFirstExitPoint()
         }
     }
 
         }
     }
 
-    cursiveFirstPosition = position;
+    glyphPositionAdjustments->clearExitPoint(position);
 }
 
 }
 
-void GlyphIterator::resetCursiveLastExitPoint()
+void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
 {
 {
-    if ((lookupFlags & lfBaselineIsLogicalEnd) != 0 && cursiveFirstPosition >= 0 && cursiveLastPosition >= 0) {
-        le_int32 savePosition = position, saveLimit = nextLimit;
-
-        position  = cursiveFirstPosition - direction;
-        nextLimit = cursiveLastPosition  + direction;
-
-        while (nextInternal()) {
-            glyphPositionAdjustments[position].adjustYPlacement(-cursiveBaselineAdjustment);
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
         }
         }
-
-        position  = savePosition;
-        nextLimit = saveLimit;
     }
 
     }
 
-    cursiveLastPosition       = -1;
-    cursiveFirstPosition      = -1;
-    cursiveBaselineAdjustment =  0;
+    glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());
 }
 
 }
 
-void GlyphIterator::setCursiveLastExitPoint(LEPoint &exitPoint)
+void GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
 {
     if (direction < 0) {
         if (position <= nextLimit || position >= prevLimit) {
@@ -393,110 +343,109 @@ void GlyphIterator::setCursiveLastExitPoint(LEPoint &exitPoint)
         }
     }
 
         }
     }
 
-    cursiveLastPosition  = position;
-    cursiveLastExitPoint = exitPoint;
-
+    glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());
 }
 
 }
 
-void GlyphIterator::setCursiveBaselineAdjustment(float adjustment)
-{
-    cursiveBaselineAdjustment = adjustment;
-}
-
-void GlyphIterator::adjustCursiveLastGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
-                                              float xAdvanceAdjust, float yAdvanceAdjust)
+void GlyphIterator::setCursiveGlyph()
 {
     if (direction < 0) {
 {
     if (direction < 0) {
-        if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) {
+        if (position <= nextLimit || position >= prevLimit) {
             return;
         }
     } else {
             return;
         }
     } else {
-        if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) {
+        if (position <= prevLimit || position >= nextLimit) {
             return;
         }
     }
 
             return;
         }
     }
 
-    glyphPositionAdjustments[cursiveLastPosition].adjustXPlacement(xPlacementAdjust);
-    glyphPositionAdjustments[cursiveLastPosition].adjustYPlacement(yPlacementAdjust);
-    glyphPositionAdjustments[cursiveLastPosition].adjustXAdvance(xAdvanceAdjust);
-    glyphPositionAdjustments[cursiveLastPosition].adjustYAdvance(yAdvanceAdjust);
+    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];
 {
     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);
+        }
+        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;
 
 
-        le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
+        case gcdComponentGlyph:
+          filterResult = ((lookupFlags & lfIgnoreBaseGlyphs) != 0);
+          break;
 
 
-        if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
-            return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
+        default:
+          filterResult = FALSE;
+          break;
         }
         }
-
-        return FALSE;
-    }
-
-    case gcdComponentGlyph:
-        return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
-
-    default:
-        return FALSE;
+      }
+      filterCacheValid = TRUE;
     }
     }
+    
+    return filterCache.result;
 }
 
 }
 
-static const LETag emptyTag = 0;
-static const LETag defaultTag = 0xFFFFFFFF;
-
-le_bool GlyphIterator::hasFeatureTag() const
+le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const
 {
 {
-    if (featureTag == defaultTag || featureTag == emptyTag) {
+    if (featureMask == 0) {
         return TRUE;
     }
 
     LEErrorCode success = LE_NO_ERROR;
         return TRUE;
     }
 
     LEErrorCode success = LE_NO_ERROR;
-    const LETag *tagList = (const LETag *) glyphStorage.getAuxData(position, success);
-
-    if (tagList != NULL) {
-        for (le_int32 tag = 0; tagList[tag] != emptyTag; tag += 1) {
-            if (tagList[tag] == featureTag) {
-                return TRUE;
-            }
-        }
-    }
+    FeatureMask fm = glyphStorage.getAuxData(position, success);
 
 
-    return FALSE;
+    return ((fm & featureMask) == featureMask) && (!matchGroup || (le_int32)(fm & LE_GLYPH_GROUP_MASK) == glyphGroup);
 }
 
 le_bool GlyphIterator::findFeatureTag()
 {
 }
 
 le_bool GlyphIterator::findFeatureTag()
 {
+  //glyphGroup = 0;
+
     while (nextInternal()) {
     while (nextInternal()) {
-        if (hasFeatureTag()) {
-            prevInternal();
+        if (hasFeatureTag(FALSE)) {
+            LEErrorCode success = LE_NO_ERROR;
+
+            glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK);
             return TRUE;
         }
     }
             return TRUE;
         }
     }
@@ -512,6 +461,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
     while (newPosition != nextLimit && delta > 0) {
         do {
             newPosition += direction;
     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;
         } while (newPosition != nextLimit && filterGlyph(newPosition));
 
         delta -= 1;
@@ -519,12 +469,13 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
 
     position = newPosition;
 
 
     position = newPosition;
 
+    //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
     return position != nextLimit;
 }
 
 le_bool GlyphIterator::next(le_uint32 delta)
 {
     return position != nextLimit;
 }
 
 le_bool GlyphIterator::next(le_uint32 delta)
 {
-    return nextInternal(delta) && hasFeatureTag();
+    return nextInternal(delta) && hasFeatureTag(TRUE);
 }
 
 le_bool GlyphIterator::prevInternal(le_uint32 delta)
 }
 
 le_bool GlyphIterator::prevInternal(le_uint32 delta)
@@ -534,6 +485,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
     while (newPosition != prevLimit && delta > 0) {
         do {
             newPosition -= direction;
     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;
         } while (newPosition != prevLimit && filterGlyph(newPosition));
 
         delta -= 1;
@@ -541,12 +493,13 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
 
     position = newPosition;
 
 
     position = newPosition;
 
+    //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
     return position != prevLimit;
 }
 
 le_bool GlyphIterator::prev(le_uint32 delta)
 {
     return position != prevLimit;
 }
 
 le_bool GlyphIterator::prev(le_uint32 delta)
 {
-    return prevInternal(delta) && hasFeatureTag();
+    return prevInternal(delta) && hasFeatureTag(TRUE);
 }
 
 le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
 }
 
 le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const