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