1 /* 2 * 3 * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved 4 * 5 */ 6 7 #include "LETypes.h" 8 #include "GlyphPositionAdjustments.h" 9 #include "LEGlyphStorage.h" 10 #include "LEFontInstance.h" 11 12 U_NAMESPACE_BEGIN 13 14 #define CHECK_ALLOCATE_ARRAY(array, type, size) \ 15 if (array == NULL) { \ 16 array = (type *) new type[size]; \ 17 } 18 19 GlyphPositionAdjustments::GlyphPositionAdjustments(le_int32 glyphCount) 20 : fGlyphCount(glyphCount), fEntryExitPoints(NULL), fAdjustments(NULL) 21 { 22 fAdjustments = (Adjustment *) new Adjustment[glyphCount]; 23 } 24 25 GlyphPositionAdjustments::~GlyphPositionAdjustments() 26 { 27 delete[] fEntryExitPoints; 28 delete[] fAdjustments; 29 } 30 31 const LEPoint *GlyphPositionAdjustments::getEntryPoint(le_int32 index, LEPoint &entryPoint) const 32 { 33 if (fEntryExitPoints == NULL) { 34 return NULL; 35 } 36 37 return fEntryExitPoints[index].getEntryPoint(entryPoint); 38 } 39 40 const LEPoint *GlyphPositionAdjustments::getExitPoint(le_int32 index, LEPoint &exitPoint)const 41 { 42 if (fEntryExitPoints == NULL) { 43 return NULL; 44 } 45 46 return fEntryExitPoints[index].getExitPoint(exitPoint); 47 } 48 49 void GlyphPositionAdjustments::clearEntryPoint(le_int32 index) 50 { 51 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 52 53 fEntryExitPoints[index].clearEntryPoint(); 54 } 55 56 void GlyphPositionAdjustments::clearExitPoint(le_int32 index) 57 { 58 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 59 60 fEntryExitPoints[index].clearExitPoint(); 61 } 62 63 void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd) 64 { 65 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 66 67 fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd); 68 } 69 70 void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd) 71 { 72 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 73 74 fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd); 75 } 76 77 void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd) 78 { 79 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 80 81 fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd); 82 } 83 84 void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance) 85 { 86 if (! hasCursiveGlyphs()) { 87 return; 88 } 89 90 le_int32 start = 0, end = fGlyphCount, dir = 1; 91 le_int32 firstExitPoint = -1, lastExitPoint = -1; 92 LEPoint entryAnchor, exitAnchor, pixels; 93 LEGlyphID lastExitGlyphID = 0; 94 float baselineAdjustment = 0; 95 96 // This removes a possible warning about 97 // using exitAnchor before it's been initialized. 98 exitAnchor.fX = exitAnchor.fY = 0; 99 100 if (rightToLeft) { 101 start = fGlyphCount - 1; 102 end = -1; 103 dir = -1; 104 } 105 106 for (le_int32 i = start; i != end; i += dir) { 107 LEGlyphID glyphID = glyphStorage[i]; 108 109 if (isCursiveGlyph(i)) { 110 if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) { 111 float anchorDiffX = exitAnchor.fX - entryAnchor.fX; 112 float anchorDiffY = exitAnchor.fY - entryAnchor.fY; 113 114 baselineAdjustment += anchorDiffY; 115 adjustYPlacement(i, baselineAdjustment); 116 117 if (rightToLeft) { 118 LEPoint secondAdvance; 119 120 fontInstance->getGlyphAdvance(glyphID, pixels); 121 fontInstance->pixelsToUnits(pixels, secondAdvance); 122 123 adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX)); 124 } else { 125 LEPoint firstAdvance; 126 127 fontInstance->getGlyphAdvance(lastExitGlyphID, pixels); 128 fontInstance->pixelsToUnits(pixels, firstAdvance); 129 130 adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX); 131 } 132 } 133 134 lastExitPoint = i; 135 136 if (getExitPoint(i, exitAnchor) != NULL) { 137 if (firstExitPoint < 0) { 138 firstExitPoint = i; 139 } 140 141 lastExitGlyphID = glyphID; 142 } else { 143 if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) { 144 le_int32 limit = lastExitPoint /*+ dir*/; 145 LEPoint dummyAnchor; 146 147 if (getEntryPoint(i, dummyAnchor) != NULL) { 148 limit += dir; 149 } 150 151 for (le_int32 j = firstExitPoint; j != limit; j += dir) { 152 if (isCursiveGlyph(j)) { 153 adjustYPlacement(j, -baselineAdjustment); 154 } 155 } 156 } 157 158 firstExitPoint = lastExitPoint = -1; 159 baselineAdjustment = 0; 160 } 161 } 162 } 163 } 164 165 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const 166 { 167 if (fFlags & EEF_HAS_ENTRY_POINT) { 168 entryPoint = fEntryPoint; 169 return &entryPoint; 170 } 171 172 return NULL; 173 } 174 175 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const 176 { 177 if (fFlags & EEF_HAS_EXIT_POINT) { 178 exitPoint = fExitPoint; 179 return &exitPoint; 180 } 181 182 return NULL; 183 } 184 185 U_NAMESPACE_END 186