]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/GlyphPositionAdjustments.cpp
ICU-59180.0.1.tar.gz
[apple/icu.git] / icuSources / layout / GlyphPositionAdjustments.cpp
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