fontservices/textshaperplugin/IcuSource/layout/GlyphIterator.cpp
changeset 0 1fb32624e06b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/textshaperplugin/IcuSource/layout/GlyphIterator.cpp	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,479 @@
+/*
+ *
+ * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "OpenTypeTables.h"
+#include "GlyphDefinitionTables.h"
+#include "GlyphPositionAdjustments.h"
+#include "GlyphIterator.h"
+#include "LEGlyphStorage.h"
+#include "Lookups.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag,
+    const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
+  : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
+    glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
+    srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureTag(theFeatureTag),
+    glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
+
+{
+    le_int32 glyphCount = glyphStorage.getGlyphCount();
+
+    if (theGlyphDefinitionTableHeader != NULL) {
+        glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
+        markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
+    }
+
+    nextLimit = glyphCount;
+
+    if (rightToLeft) {
+        direction = -1;
+        position = glyphCount;
+        nextLimit = -1;
+        prevLimit = glyphCount;
+    }
+}
+
+GlyphIterator::GlyphIterator(GlyphIterator &that)
+  : glyphStorage(that.glyphStorage)
+{
+    direction    = that.direction;
+    position     = that.position;
+    nextLimit    = that.nextLimit;
+    prevLimit    = that.prevLimit;
+
+    glyphPositionAdjustments = that.glyphPositionAdjustments;
+    srcIndex = that.srcIndex;
+    destIndex = that.destIndex;
+    lookupFlags = that.lookupFlags;
+    featureTag = that.featureTag;
+    glyphClassDefinitionTable = that.glyphClassDefinitionTable;
+    markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+}
+
+GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag)
+  : glyphStorage(that.glyphStorage)
+{
+    direction    = that.direction;
+    position     = that.position;
+    nextLimit    = that.nextLimit;
+    prevLimit    = that.prevLimit;
+
+    glyphPositionAdjustments = that.glyphPositionAdjustments;
+    srcIndex = that.srcIndex;
+    destIndex = that.destIndex;
+    lookupFlags = that.lookupFlags;
+    featureTag = newFeatureTag;
+    glyphClassDefinitionTable = that.glyphClassDefinitionTable;
+    markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+}
+
+GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
+  : glyphStorage(that.glyphStorage)
+{
+    direction    = that.direction;
+    position     = that.position;
+    nextLimit    = that.nextLimit;
+    prevLimit    = that.prevLimit;
+
+    glyphPositionAdjustments = that.glyphPositionAdjustments;
+    srcIndex = that.srcIndex;
+    destIndex = that.destIndex;
+    lookupFlags = newLookupFlags;
+    featureTag = that.featureTag;
+    glyphClassDefinitionTable = that.glyphClassDefinitionTable;
+    markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
+}
+
+GlyphIterator::~GlyphIterator()
+{
+    // nothing to do, right?
+}
+
+void GlyphIterator::reset(le_uint16 newLookupFlags, LETag newFeatureTag)
+{
+    position    = prevLimit;
+    featureTag  = newFeatureTag;
+    lookupFlags = newLookupFlags;
+}
+
+LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)
+{
+    return glyphStorage.insertGlyphs(position, count, success);
+}
+
+le_int32 GlyphIterator::applyInsertions()
+{
+    le_int32 newGlyphCount = glyphStorage.applyInsertions();
+
+    if (direction < 0) {
+        prevLimit = newGlyphCount;
+    } else {
+        nextLimit = newGlyphCount;
+    }
+
+    return newGlyphCount;
+}
+
+le_int32 GlyphIterator::getCurrStreamPosition() const
+{
+    return position;
+}
+
+le_bool GlyphIterator::isRightToLeft() const
+{
+    return direction < 0;
+}
+
+le_bool GlyphIterator::ignoresMarks() const
+{
+    return (lookupFlags & lfIgnoreMarks) != 0;
+}
+
+le_bool GlyphIterator::baselineIsLogicalEnd() const
+{
+    return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
+}
+
+LEGlyphID GlyphIterator::getCurrGlyphID() const
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return 0xFFFF;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return 0xFFFF;
+        }
+    }
+
+    return glyphStorage[position];
+}
+
+void GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->getEntryPoint(position, entryPoint);
+}
+
+void GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->getExitPoint(position, exitPoint);
+}
+
+void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
+{
+    LEGlyphID glyph = glyphStorage[position];
+
+    glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
+}
+
+void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
+{
+    if (direction < 0) {
+        if (newPosition >= prevLimit) {
+            position = prevLimit;
+            return;
+        }
+
+        if (newPosition <= nextLimit) {
+            position = nextLimit;
+            return;
+        }
+    } else {
+        if (newPosition <= prevLimit) {
+            position = prevLimit;
+            return;
+        }
+
+        if (newPosition >= nextLimit) {
+            position = nextLimit;
+            return;
+        }
+    }
+
+    position = newPosition - direction;
+    next();
+}
+
+void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->setBaseOffset(position, baseOffset);
+}
+
+void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
+                                                      float xAdvanceAdjust, float yAdvanceAdjust)
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);
+    glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);
+    glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);
+    glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);
+}
+
+void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
+                                                      float xAdvanceAdjust, float yAdvanceAdjust)
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);
+    glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);
+    glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);
+    glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
+}
+
+void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());
+}
+
+void GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());
+}
+
+void GlyphIterator::setCursiveGlyph()
+{
+    if (direction < 0) {
+        if (position <= nextLimit || position >= prevLimit) {
+            return;
+        }
+    } else {
+        if (position <= prevLimit || position >= nextLimit) {
+            return;
+        }
+    }
+
+    glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());
+}
+
+le_bool GlyphIterator::filterGlyph(le_uint32 index) const
+{
+    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;
+        }
+
+        le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
+
+        if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
+            return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
+        }
+
+        return FALSE;
+    }
+
+    case gcdComponentGlyph:
+        return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
+
+    default:
+        return FALSE;
+    }
+}
+
+static const LETag emptyTag = 0;
+static const LETag defaultTag = 0xFFFFFFFF;
+
+le_bool GlyphIterator::hasFeatureTag() const
+{
+    if (featureTag == defaultTag || featureTag == emptyTag) {
+        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;
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+le_bool GlyphIterator::findFeatureTag()
+{
+    while (nextInternal()) {
+        if (hasFeatureTag()) {
+            prevInternal();
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+
+le_bool GlyphIterator::nextInternal(le_uint32 delta)
+{
+    le_int32 newPosition = position;
+
+    while (newPosition != nextLimit && delta > 0) {
+        do {
+            newPosition += direction;
+        } while (newPosition != nextLimit && filterGlyph(newPosition));
+
+        delta -= 1;
+    }
+
+    position = newPosition;
+
+    return position != nextLimit;
+}
+
+le_bool GlyphIterator::next(le_uint32 delta)
+{
+    return nextInternal(delta) && hasFeatureTag();
+}
+
+le_bool GlyphIterator::prevInternal(le_uint32 delta)
+{
+    le_int32 newPosition = position;
+
+    while (newPosition != prevLimit && delta > 0) {
+        do {
+            newPosition -= direction;
+        } while (newPosition != prevLimit && filterGlyph(newPosition));
+
+        delta -= 1;
+    }
+
+    position = newPosition;
+
+    return position != prevLimit;
+}
+
+le_bool GlyphIterator::prev(le_uint32 delta)
+{
+    return prevInternal(delta) && hasFeatureTag();
+}
+
+le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
+{
+    le_int32 component = 0;
+    le_int32 posn;
+
+    for (posn = position; posn != markPosition; posn += direction) {
+        if (glyphStorage[posn] == 0xFFFE) {
+            component += 1;
+        }
+    }
+
+    return component;
+}
+
+// This is basically prevInternal except that it
+// doesn't take a delta argument, and it doesn't
+// filter out 0xFFFE glyphs.
+le_bool GlyphIterator::findMark2Glyph()
+{
+    le_int32 newPosition = position;
+
+    do {
+        newPosition -= direction;
+    } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition));
+
+    position = newPosition;
+
+    return position != prevLimit;
+}
+
+U_NAMESPACE_END