| /* |
| * %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 |