]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/GlyphPositionAdjustments.cpp
ICU-8.11.1.tar.gz
[apple/icu.git] / icuSources / layout / GlyphPositionAdjustments.cpp
1 /*
2 *
3 * (C) Copyright IBM Corp. 1998-2005 - 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::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd)
50 {
51 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
52
53 fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd);
54 }
55
56 void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd)
57 {
58 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
59
60 fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd);
61 }
62
63 void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd)
64 {
65 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
66
67 fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd);
68 }
69
70 void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance)
71 {
72 if (! hasCursiveGlyphs()) {
73 return;
74 }
75
76 le_int32 start = 0, end = fGlyphCount, dir = 1;
77 le_int32 firstExitPoint = -1, lastExitPoint = -1;
78 LEPoint entryAnchor, exitAnchor, pixels;
79 LEGlyphID lastExitGlyphID = 0;
80 float baselineAdjustment = 0;
81
82 // This removes a possible warning about
83 // using exitAnchor before it's been initialized.
84 exitAnchor.fX = exitAnchor.fY = 0;
85
86 if (rightToLeft) {
87 start = fGlyphCount - 1;
88 end = -1;
89 dir = -1;
90 }
91
92 for (le_int32 i = start; i != end; i += dir) {
93 LEGlyphID glyphID = glyphStorage[i];
94
95 if (isCursiveGlyph(i)) {
96 if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) {
97 float anchorDiffX = exitAnchor.fX - entryAnchor.fX;
98 float anchorDiffY = exitAnchor.fY - entryAnchor.fY;
99
100 baselineAdjustment += anchorDiffY;
101 adjustYPlacement(i, baselineAdjustment);
102
103 if (rightToLeft) {
104 LEPoint secondAdvance;
105
106 fontInstance->getGlyphAdvance(glyphID, pixels);
107 fontInstance->pixelsToUnits(pixels, secondAdvance);
108
109 adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX));
110 } else {
111 LEPoint firstAdvance;
112
113 fontInstance->getGlyphAdvance(lastExitGlyphID, pixels);
114 fontInstance->pixelsToUnits(pixels, firstAdvance);
115
116 adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX);
117 }
118 }
119
120 lastExitPoint = i;
121
122 if (getExitPoint(i, exitAnchor) != NULL) {
123 if (firstExitPoint < 0) {
124 firstExitPoint = i;
125 }
126
127 lastExitGlyphID = glyphID;
128 } else {
129 if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) {
130 le_int32 limit = lastExitPoint + dir;
131
132 for (le_int32 j = firstExitPoint; j != limit; j += dir) {
133 if (isCursiveGlyph(j)) {
134 adjustYPlacement(j, -baselineAdjustment);
135 }
136 }
137 }
138
139 firstExitPoint = lastExitPoint = -1;
140 baselineAdjustment = 0;
141 }
142 }
143 }
144 }
145
146 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const
147 {
148 if (fFlags & EEF_HAS_ENTRY_POINT) {
149 entryPoint = fEntryPoint;
150 return &entryPoint;
151 }
152
153 return NULL;
154 }
155
156 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const
157 {
158 if (fFlags & EEF_HAS_EXIT_POINT) {
159 exitPoint = fExitPoint;
160 return &exitPoint;
161 }
162
163 return NULL;
164 }
165
166 U_NAMESPACE_END