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