]> git.saurik.com Git - apple/icu.git/blame - icuSources/layout/GlyphPositionAdjustments.cpp
ICU-491.11.2.tar.gz
[apple/icu.git] / icuSources / layout / GlyphPositionAdjustments.cpp
CommitLineData
73c04bcf
A
1/*
2 *
46f4442e 3 * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
73c04bcf
A
4 *
5 */
6
7#include "LETypes.h"
8#include "GlyphPositionAdjustments.h"
9#include "LEGlyphStorage.h"
10#include "LEFontInstance.h"
11
12U_NAMESPACE_BEGIN
13
14#define CHECK_ALLOCATE_ARRAY(array, type, size) \
15 if (array == NULL) { \
16 array = (type *) new type[size]; \
17 }
18
19GlyphPositionAdjustments::GlyphPositionAdjustments(le_int32 glyphCount)
20 : fGlyphCount(glyphCount), fEntryExitPoints(NULL), fAdjustments(NULL)
21{
22 fAdjustments = (Adjustment *) new Adjustment[glyphCount];
23}
24
25GlyphPositionAdjustments::~GlyphPositionAdjustments()
26{
27 delete[] fEntryExitPoints;
28 delete[] fAdjustments;
29}
30
31const 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
40const 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
46f4442e
A
49void GlyphPositionAdjustments::clearEntryPoint(le_int32 index)
50{
51 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
52
53 fEntryExitPoints[index].clearEntryPoint();
54}
55
56void GlyphPositionAdjustments::clearExitPoint(le_int32 index)
57{
58 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
59
60 fEntryExitPoints[index].clearExitPoint();
61}
62
73c04bcf
A
63void 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
70void 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
77void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd)
78{
79 CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
80
81 fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd);
82}
83
84void 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) {
46f4442e
A
144 le_int32 limit = lastExitPoint /*+ dir*/;
145 LEPoint dummyAnchor;
146
147 if (getEntryPoint(i, dummyAnchor) != NULL) {
148 limit += dir;
149 }
73c04bcf
A
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
165LEPoint *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
175LEPoint *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
185U_NAMESPACE_END