1/* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26/* 27 * 28 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved 29 * 30 */ 31 32#include "LETypes.h" 33#include "GlyphPositionAdjustments.h" 34#include "LEGlyphStorage.h" 35#include "LEFontInstance.h" 36 37U_NAMESPACE_BEGIN 38 39#define CHECK_ALLOCATE_ARRAY(array, type, size) \ 40 if (array == NULL) { \ 41 array = (type *) new type[size]; \ 42 } 43 44GlyphPositionAdjustments::GlyphPositionAdjustments(le_int32 glyphCount) 45 : fGlyphCount(glyphCount), fEntryExitPoints(NULL), fAdjustments(NULL) 46{ 47 fAdjustments = (Adjustment *) new Adjustment[glyphCount]; 48} 49 50GlyphPositionAdjustments::~GlyphPositionAdjustments() 51{ 52 delete[] fEntryExitPoints; 53 delete[] fAdjustments; 54} 55 56const LEPoint *GlyphPositionAdjustments::getEntryPoint(le_int32 index, LEPoint &entryPoint) const 57{ 58 if (fEntryExitPoints == NULL) { 59 return NULL; 60 } 61 62 return fEntryExitPoints[index].getEntryPoint(entryPoint); 63} 64 65const LEPoint *GlyphPositionAdjustments::getExitPoint(le_int32 index, LEPoint &exitPoint)const 66{ 67 if (fEntryExitPoints == NULL) { 68 return NULL; 69 } 70 71 return fEntryExitPoints[index].getExitPoint(exitPoint); 72} 73 74void GlyphPositionAdjustments::clearEntryPoint(le_int32 index) 75{ 76 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 77 78 fEntryExitPoints[index].clearEntryPoint(); 79} 80 81void GlyphPositionAdjustments::clearExitPoint(le_int32 index) 82{ 83 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 84 85 fEntryExitPoints[index].clearExitPoint(); 86} 87 88void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd) 89{ 90 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 91 92 fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd); 93} 94 95void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd) 96{ 97 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 98 99 fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd); 100} 101 102void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd) 103{ 104 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); 105 106 fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd); 107} 108 109void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance) 110{ 111 if (! hasCursiveGlyphs()) { 112 return; 113 } 114 115 le_int32 start = 0, end = fGlyphCount, dir = 1; 116 le_int32 firstExitPoint = -1, lastExitPoint = -1; 117 LEPoint entryAnchor, exitAnchor, pixels; 118 LEGlyphID lastExitGlyphID = 0; 119 float baselineAdjustment = 0; 120 121 // This removes a possible warning about 122 // using exitAnchor before it's been initialized. 123 exitAnchor.fX = exitAnchor.fY = 0; 124 125 if (rightToLeft) { 126 start = fGlyphCount - 1; 127 end = -1; 128 dir = -1; 129 } 130 131 for (le_int32 i = start; i != end; i += dir) { 132 LEGlyphID glyphID = glyphStorage[i]; 133 134 if (isCursiveGlyph(i)) { 135 if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) { 136 float anchorDiffX = exitAnchor.fX - entryAnchor.fX; 137 float anchorDiffY = exitAnchor.fY - entryAnchor.fY; 138 139 baselineAdjustment += anchorDiffY; 140 adjustYPlacement(i, baselineAdjustment); 141 142 if (rightToLeft) { 143 LEPoint secondAdvance; 144 145 fontInstance->getGlyphAdvance(glyphID, pixels); 146 fontInstance->pixelsToUnits(pixels, secondAdvance); 147 148 adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX)); 149 } else { 150 LEPoint firstAdvance; 151 152 fontInstance->getGlyphAdvance(lastExitGlyphID, pixels); 153 fontInstance->pixelsToUnits(pixels, firstAdvance); 154 155 adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX); 156 } 157 } 158 159 lastExitPoint = i; 160 161 if (getExitPoint(i, exitAnchor) != NULL) { 162 if (firstExitPoint < 0) { 163 firstExitPoint = i; 164 } 165 166 lastExitGlyphID = glyphID; 167 } else { 168 if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) { 169 le_int32 limit = lastExitPoint /*+ dir*/; 170 LEPoint dummyAnchor; 171 172 if (getEntryPoint(i, dummyAnchor) != NULL) { 173 limit += dir; 174 } 175 176 for (le_int32 j = firstExitPoint; j != limit; j += dir) { 177 if (isCursiveGlyph(j)) { 178 adjustYPlacement(j, -baselineAdjustment); 179 } 180 } 181 } 182 183 firstExitPoint = lastExitPoint = -1; 184 baselineAdjustment = 0; 185 } 186 } 187 } 188} 189 190LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const 191{ 192 if (fFlags & EEF_HAS_ENTRY_POINT) { 193 entryPoint = fEntryPoint; 194 return &entryPoint; 195 } 196 197 return NULL; 198} 199 200LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const 201{ 202 if (fFlags & EEF_HAS_EXIT_POINT) { 203 exitPoint = fExitPoint; 204 return &exitPoint; 205 } 206 207 return NULL; 208} 209 210U_NAMESPACE_END 211