]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/layout/GlyphIterator.cpp
ICU-531.48.tar.gz
[apple/icu.git] / icuSources / layout / GlyphIterator.cpp
index 91c5d5684caf34cd6ff86cf96e3bc464fd18cd1a..72d2dd13156d8273269010d93575e30d76de63f2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * (C) Copyright IBM Corp. 1998-2005 - 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),
-    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();
 
-    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)
@@ -53,8 +57,10 @@ GlyphIterator::GlyphIterator(GlyphIterator &that)
     destIndex = that.destIndex;
     lookupFlags = that.lookupFlags;
     featureMask = that.featureMask;
+    glyphGroup  = that.glyphGroup;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
@@ -70,8 +76,10 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
     destIndex = that.destIndex;
     lookupFlags = that.lookupFlags;
     featureMask = newFeatureMask;
+    glyphGroup  = 0;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
@@ -87,8 +95,10 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
     destIndex = that.destIndex;
     lookupFlags = newLookupFlags;
     featureMask = that.featureMask;
+    glyphGroup  = that.glyphGroup;
     glyphClassDefinitionTable = that.glyphClassDefinitionTable;
     markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+    filterResetCache();
 }
 
 GlyphIterator::~GlyphIterator()
@@ -100,12 +110,14 @@ void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
 {
     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()
@@ -274,6 +286,36 @@ void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float
     glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
 }
 
+void GlyphIterator::clearCursiveEntryPoint()
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->clearEntryPoint(position);
+}
+
+void GlyphIterator::clearCursiveExitPoint()
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->clearExitPoint(position);
+}
+
 void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
 {
     if (direction < 0) {
@@ -319,54 +361,71 @@ 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() const
+le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const
 {
     if (featureMask == 0) {
         return TRUE;
@@ -375,14 +434,18 @@ le_bool GlyphIterator::hasFeatureTag() const
     LEErrorCode success = LE_NO_ERROR;
     FeatureMask fm = glyphStorage.getAuxData(position, success);
 
-    return (fm & featureMask) != 0;
+    return ((fm & featureMask) == featureMask) && (!matchGroup || (le_int32)(fm & LE_GLYPH_GROUP_MASK) == glyphGroup);
 }
 
 le_bool GlyphIterator::findFeatureTag()
 {
+  //glyphGroup = 0;
+
     while (nextInternal()) {
-        if (hasFeatureTag()) {
-            prevInternal();
+        if (hasFeatureTag(FALSE)) {
+            LEErrorCode success = LE_NO_ERROR;
+
+            glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK);
             return TRUE;
         }
     }
@@ -398,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;
@@ -405,12 +469,13 @@ 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;
 }
 
 le_bool GlyphIterator::next(le_uint32 delta)
 {
-    return nextInternal(delta) && hasFeatureTag();
+    return nextInternal(delta) && hasFeatureTag(TRUE);
 }
 
 le_bool GlyphIterator::prevInternal(le_uint32 delta)
@@ -420,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;
@@ -427,12 +493,13 @@ 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;
 }
 
 le_bool GlyphIterator::prev(le_uint32 delta)
 {
-    return prevInternal(delta) && hasFeatureTag();
+    return prevInternal(delta) && hasFeatureTag(TRUE);
 }
 
 le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const