blob: 3f4bf76673b20d2707de5641e2880ba35ecfb6e3 [file] [log] [blame]
/*
* %W% %E%
*
* (C) Copyright IBM Corp. 1998, 1999, 2000, 2001, 2002 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
#include "GlyphPositioningTables.h"
#include "CursiveAttachmentSubtables.h"
#include "AnchorTables.h"
#include "GlyphIterator.h"
#include "GlyphPositionAdjustments.h"
#include "OpenTypeUtilities.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
LEGlyphID glyphID = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyphID);
le_uint16 eeCount = SWAPW(entryExitCount);
if (coverageIndex < 0 || coverageIndex >= eeCount) {
glyphIterator->resetCursiveLastExitPoint();
return 0;
}
LEPoint entryAnchor, exitAnchor, pixels;
if (glyphIterator->hasCursiveLastExitPoint() && entryExitRecords[coverageIndex].entryAnchor != 0) {
Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor);
const AnchorTable *entryAnchorTable = (const AnchorTable *) ((char *) this + entryOffset);
entryAnchorTable->getAnchor(glyphID, fontInstance, entryAnchor);
glyphIterator->getCursiveLastExitPoint(exitAnchor);
float anchorDiffX = exitAnchor.fX - entryAnchor.fX;
float anchorDiffY = exitAnchor.fY - entryAnchor.fY;
float baselineAdjustment = glyphIterator->getCursiveBaselineAdjustment();
if (glyphIterator->isRightToLeft()) {
LEPoint secondAdvance;
fontInstance->getGlyphAdvance(glyphID, pixels);
fontInstance->pixelsToUnits(pixels, secondAdvance);
glyphIterator->adjustCurrGlyphPositionAdjustment(0, anchorDiffY + baselineAdjustment, -(anchorDiffX + secondAdvance.fX), 0);
} else {
LEPoint firstAdvance;
fontInstance->getGlyphAdvance(glyphIterator->getCursiveLastGlyphID(), pixels);
fontInstance->pixelsToUnits(pixels, firstAdvance);
glyphIterator->adjustCursiveLastGlyphPositionAdjustment(0, 0, anchorDiffX - firstAdvance.fX, 0);
glyphIterator->adjustCurrGlyphPositionAdjustment(0, anchorDiffY + baselineAdjustment, 0, 0);
}
glyphIterator->setCursiveBaselineAdjustment(anchorDiffY + baselineAdjustment);
}
Offset exitOffset = SWAPW(entryExitRecords[coverageIndex].exitAnchor);
if (exitOffset != 0) {
const AnchorTable *exitAnchorTable = (const AnchorTable *) ((char *) this + exitOffset);
exitAnchorTable->getAnchor(glyphID, fontInstance, exitAnchor);
if (!glyphIterator->hasCursiveFirstExitPoint()) {
glyphIterator->setCursiveFirstExitPoint();
}
glyphIterator->setCursiveLastExitPoint(exitAnchor);
} else {
/*
* We've got a glyph which is covered but doesn't have an
* exit point. We call setCursiveLastExitPoint just to set
* the position of this glyph, then resetCursiveLastExitPoint
* to do any baseline adjustments that are required for the
* sequence of attached glyphs.
*
* NOTE: we don't really care about the value of
* extiAnchor, because after we reset the last exit
* point, it won't be used. This is a bit of a hack.
* There should probably be a setCursiveLastExitPoint
* call that doesn't take an anchor...
*/
glyphIterator->setCursiveLastExitPoint(exitAnchor);
glyphIterator->resetCursiveLastExitPoint();
}
return 1;
}
U_NAMESPACE_END