diff options
Diffstat (limited to 'Build/source/libs/icu-xetex/layout/GlyphIterator.cpp')
-rw-r--r-- | Build/source/libs/icu-xetex/layout/GlyphIterator.cpp | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp b/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp new file mode 100644 index 00000000000..eab023cf58b --- /dev/null +++ b/Build/source/libs/icu-xetex/layout/GlyphIterator.cpp @@ -0,0 +1,530 @@ +/* + * + * (C) Copyright IBM Corp. 1998-2007 - 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, + FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader) + : direction(1), position(-1), nextLimit(-1), prevLimit(-1), + glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments), + srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), featureParam(0), glyphGroup(0), + 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; + featureMask = that.featureMask; + featureParam = that.featureParam; + glyphGroup = that.glyphGroup; + glyphClassDefinitionTable = that.glyphClassDefinitionTable; + markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; +} + +GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask, le_int32 newFeatureParam) + : 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; + featureMask = newFeatureMask; + featureParam = newFeatureParam; + glyphGroup = 0; + 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; + featureMask = that.featureMask; + featureParam = that.featureParam; + glyphGroup = that.glyphGroup; + glyphClassDefinitionTable = that.glyphClassDefinitionTable; + markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; +} + +GlyphIterator::~GlyphIterator() +{ + // nothing to do, right? +} + +void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask) +{ + position = prevLimit; + featureMask = newFeatureMask; + featureParam = 0; + glyphGroup = 0; + lookupFlags = newLookupFlags; +} + +LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count) +{ + return glyphStorage.insertGlyphs(position, count); +} + +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_int32 GlyphIterator::getFeatureParam() const +{ + return featureParam; +} + +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::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) { + 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; + } +} + +le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) +{ + featureParam = 0; + + if (featureMask == 0) { + return TRUE; + } + + LEErrorCode success = LE_NO_ERROR; + FeatureMask fm = glyphStorage.getAuxData(position, success); + + if (((fm & featureMask) == featureMask) && (!matchGroup || (fm & LE_GLYPH_GROUP_MASK) == glyphGroup)) { + const le_int32 *paramList = (const le_int32 *) glyphStorage.getAuxParam(position, success); + if (paramList != NULL) { + fm = featureMask; + while ((fm & 0x80000000UL) == 0) { + ++paramList; + fm <<= 1; + } + featureParam = *paramList; + } + return TRUE; + } + + return FALSE; +} + +le_bool GlyphIterator::findFeatureTag() +{ + //glyphGroup = 0; + + while (nextInternal()) { + if (hasFeatureTag(FALSE)) { + LEErrorCode success = LE_NO_ERROR; + + glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK); + 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(TRUE); +} + +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(TRUE); +} + +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 |