/* * %W% %E% * * (C) Copyright IBM Corp. 1998, 1999, 2000, 2001 - All Rights Reserved * */ #include "LETypes.h" #include "OpenTypeTables.h" #include "GlyphDefinitionTables.h" #include "GlyphPositionAdjustments.h" #include "GlyphIterator.h" #include "Lookups.h" #include "LESwaps.h" U_NAMESPACE_BEGIN GlyphIterator::GlyphIterator(LEGlyphID *theGlyphs, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_int32 theGlyphCount, le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, const LETag *theGlyphTags[], const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader) : direction(1), position(-1), nextLimit(theGlyphCount), prevLimit(-1), glyphs(theGlyphs), glyphPositionAdjustments(theGlyphPositionAdjustments), lookupFlags(theLookupFlags), featureTag(theFeatureTag), glyphTags(theGlyphTags), glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL) { if (theGlyphDefinitionTableHeader != NULL) { glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable(); markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable(); } if (rightToLeft) { direction = -1; position = theGlyphCount; nextLimit = -1; prevLimit = theGlyphCount; } } GlyphIterator::GlyphIterator(GlyphIterator &that) { direction = that.direction; position = that.position; nextLimit = that.nextLimit; prevLimit = that.prevLimit; glyphs = that.glyphs; glyphPositionAdjustments = that.glyphPositionAdjustments; lookupFlags = that.lookupFlags; featureTag = that.featureTag; glyphTags = that.glyphTags; glyphClassDefinitionTable = that.glyphClassDefinitionTable; markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; } GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags) { direction = that.direction; position = that.position; nextLimit = that.nextLimit; prevLimit = that.prevLimit; glyphs = that.glyphs; glyphPositionAdjustments = that.glyphPositionAdjustments; lookupFlags = newLookupFlags; featureTag = that.featureTag; glyphTags = that.glyphTags; glyphClassDefinitionTable = that.glyphClassDefinitionTable; markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; } GlyphIterator::GlyphIterator() { }; GlyphIterator::~GlyphIterator() { } le_int32 GlyphIterator::getCurrStreamPosition() const { return position; } le_bool GlyphIterator::isRightToLeft() const { return direction < 0; } le_bool GlyphIterator::ignoresMarks() const { return (lookupFlags & lfIgnoreMarks) != 0; } LEGlyphID GlyphIterator::getCurrGlyphID() const { if (direction < 0) { if (position <= nextLimit || position >= prevLimit) { return 0xFFFF; } } else { if (position <= prevLimit || position >= nextLimit) { return 0xFFFF; } } return glyphs[position]; } void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment &adjustment) const { if (direction < 0) { if (position <= nextLimit || position >= prevLimit) { return; } } else { if (position <= prevLimit || position >= nextLimit) { return; } } adjustment = glyphPositionAdjustments[position]; } void GlyphIterator::setCurrGlyphID(LEGlyphID glyphID) { glyphs[position] = 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::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment *adjustment) { if (direction < 0) { if (position <= nextLimit || position >= prevLimit) { return; } } else { if (position <= prevLimit || position >= nextLimit) { return; } } glyphPositionAdjustments[position] = *adjustment; } 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[position].adjustXPlacement(xPlacementAdjust); glyphPositionAdjustments[position].adjustYPlacement(yPlacementAdjust); glyphPositionAdjustments[position].adjustXAdvance(xAdvanceAdjust); glyphPositionAdjustments[position].adjustYAdvance(yAdvanceAdjust); } le_bool GlyphIterator::filterGlyph(le_uint32 index) const { LEGlyphID glyphID = (LEGlyphID) glyphs[index]; le_int32 glyphClass = gcdNoGlyphClass; // FIXME: is this test really safe? if (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; } } const LETag emptyTag = 0; const LETag defaultTag = 0xFFFFFFFF; le_bool GlyphIterator::hasFeatureTag() const { if (featureTag == defaultTag || featureTag == emptyTag) { return true; } if (glyphTags != NULL) { const LETag *tagList = glyphTags[position]; 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, start = position, end = markPosition; if (markPosition < position) { start = markPosition; end = position; } for (posn = start; posn <= end; posn += 1) { if (glyphs[posn] == 0xFFFE) { component += 1; } } return component; } U_NAMESPACE_END