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 "GlyphPositionAdjustments.h" sl@0: #include "LEGlyphStorage.h" sl@0: #include "LEFontInstance.h" sl@0: sl@0: U_NAMESPACE_BEGIN sl@0: sl@0: #define CHECK_ALLOCATE_ARRAY(array, type, size) \ sl@0: if (array == NULL) { \ sl@0: array = (type *) new type[size]; \ sl@0: } sl@0: sl@0: GlyphPositionAdjustments::GlyphPositionAdjustments(le_int32 glyphCount) sl@0: : fGlyphCount(glyphCount), fEntryExitPoints(NULL), fAdjustments(NULL) sl@0: { sl@0: fAdjustments = (Adjustment *) new Adjustment[glyphCount]; sl@0: } sl@0: sl@0: GlyphPositionAdjustments::~GlyphPositionAdjustments() sl@0: { sl@0: delete[] fEntryExitPoints; sl@0: delete[] fAdjustments; sl@0: } sl@0: sl@0: const LEPoint *GlyphPositionAdjustments::getEntryPoint(le_int32 index, LEPoint &entryPoint) const sl@0: { sl@0: if (fEntryExitPoints == NULL) { sl@0: return NULL; sl@0: } sl@0: sl@0: return fEntryExitPoints[index].getEntryPoint(entryPoint); sl@0: } sl@0: sl@0: const LEPoint *GlyphPositionAdjustments::getExitPoint(le_int32 index, LEPoint &exitPoint)const sl@0: { sl@0: if (fEntryExitPoints == NULL) { sl@0: return NULL; sl@0: } sl@0: sl@0: return fEntryExitPoints[index].getExitPoint(exitPoint); sl@0: } sl@0: sl@0: void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd) sl@0: { sl@0: CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); sl@0: sl@0: fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd); sl@0: } sl@0: sl@0: void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd) sl@0: { sl@0: CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); sl@0: sl@0: fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd); sl@0: } sl@0: sl@0: void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd) sl@0: { sl@0: CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); sl@0: sl@0: fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd); sl@0: } sl@0: sl@0: void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance) sl@0: { sl@0: if (! hasCursiveGlyphs()) { sl@0: return; sl@0: } sl@0: sl@0: le_int32 start = 0, end = fGlyphCount, dir = 1; sl@0: le_int32 firstExitPoint = -1, lastExitPoint = -1; sl@0: LEPoint entryAnchor, exitAnchor, pixels; sl@0: LEGlyphID lastExitGlyphID = 0; sl@0: float baselineAdjustment = 0; sl@0: sl@0: // This removes a possible warning about sl@0: // using exitAnchor before it's been initialized. sl@0: exitAnchor.fX = exitAnchor.fY = 0; sl@0: sl@0: if (rightToLeft) { sl@0: start = fGlyphCount - 1; sl@0: end = -1; sl@0: dir = -1; sl@0: } sl@0: sl@0: for (le_int32 i = start; i != end; i += dir) { sl@0: LEGlyphID glyphID = glyphStorage[i]; sl@0: sl@0: if (isCursiveGlyph(i)) { sl@0: if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) { sl@0: float anchorDiffX = exitAnchor.fX - entryAnchor.fX; sl@0: float anchorDiffY = exitAnchor.fY - entryAnchor.fY; sl@0: sl@0: baselineAdjustment += anchorDiffY; sl@0: adjustYPlacement(i, baselineAdjustment); sl@0: sl@0: if (rightToLeft) { sl@0: LEPoint secondAdvance; sl@0: sl@0: fontInstance->getGlyphAdvance(glyphID, pixels); sl@0: fontInstance->pixelsToUnits(pixels, secondAdvance); sl@0: sl@0: adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX)); sl@0: } else { sl@0: LEPoint firstAdvance; sl@0: sl@0: fontInstance->getGlyphAdvance(lastExitGlyphID, pixels); sl@0: fontInstance->pixelsToUnits(pixels, firstAdvance); sl@0: sl@0: adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX); sl@0: } sl@0: } sl@0: sl@0: lastExitPoint = i; sl@0: sl@0: if (getExitPoint(i, exitAnchor) != NULL) { sl@0: if (firstExitPoint < 0) { sl@0: firstExitPoint = i; sl@0: } sl@0: sl@0: lastExitGlyphID = glyphID; sl@0: } else { sl@0: if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) { sl@0: le_int32 limit = lastExitPoint + dir; sl@0: sl@0: for (le_int32 j = firstExitPoint; j != limit; j += dir) { sl@0: if (isCursiveGlyph(j)) { sl@0: adjustYPlacement(j, -baselineAdjustment); sl@0: } sl@0: } sl@0: } sl@0: sl@0: firstExitPoint = lastExitPoint = -1; sl@0: baselineAdjustment = 0; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const sl@0: { sl@0: if (fFlags & EEF_HAS_ENTRY_POINT) { sl@0: entryPoint = fEntryPoint; sl@0: return &entryPoint; sl@0: } sl@0: sl@0: return NULL; sl@0: } sl@0: sl@0: LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const sl@0: { sl@0: if (fFlags & EEF_HAS_EXIT_POINT) { sl@0: exitPoint = fExitPoint; sl@0: return &exitPoint; sl@0: } sl@0: sl@0: return NULL; sl@0: } sl@0: sl@0: U_NAMESPACE_END