]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/ValueRecords.cpp
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / layout / ValueRecords.cpp
1 /*
2 *
3 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
4 *
5 */
6
7 #include "LETypes.h"
8 #include "LEFontInstance.h"
9 #include "OpenTypeTables.h"
10 #include "ValueRecords.h"
11 #include "DeviceTables.h"
12 #include "GlyphIterator.h"
13 #include "GlyphPositionAdjustments.h"
14 #include "LESwaps.h"
15
16 U_NAMESPACE_BEGIN
17
18 #define Nibble(value, nibble) ((value >> (nibble * 4)) & 0xF)
19 #define NibbleBits(value, nibble) (bitsInNibble[Nibble(value, nibble)])
20
21 le_int16 ValueRecord::getFieldValue(ValueFormat valueFormat, ValueRecordField field) const
22 {
23 le_int16 valueIndex = getFieldIndex(valueFormat, field);
24 le_int16 value = values[valueIndex];
25
26 return SWAPW(value);
27 }
28
29 le_int16 ValueRecord::getFieldValue(le_int16 index, ValueFormat valueFormat, ValueRecordField field) const
30 {
31 le_int16 baseIndex = getFieldCount(valueFormat) * index;
32 le_int16 valueIndex = getFieldIndex(valueFormat, field);
33 le_int16 value = values[baseIndex + valueIndex];
34
35 return SWAPW(value);
36 }
37
38 void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, GlyphPositionAdjustment &positionAdjustment,
39 const LEFontInstance *fontInstance) const
40 {
41 if ((valueFormat & vfbXPlacement) != 0) {
42 le_int16 value = getFieldValue(valueFormat, vrfXPlacement);
43 LEPoint pixels;
44
45 fontInstance->transformFunits(value, 0, pixels);
46
47 positionAdjustment.adjustXPlacement(fontInstance->xPixelsToUnits(pixels.fX));
48 positionAdjustment.adjustYPlacement(fontInstance->yPixelsToUnits(pixels.fY));
49 }
50
51 if ((valueFormat & vfbYPlacement) != 0) {
52 le_int16 value = getFieldValue(valueFormat, vrfYPlacement);
53 LEPoint pixels;
54
55 fontInstance->transformFunits(0, value, pixels);
56
57 positionAdjustment.adjustXPlacement(fontInstance->xPixelsToUnits(pixels.fX));
58 positionAdjustment.adjustYPlacement(fontInstance->yPixelsToUnits(pixels.fY));
59 }
60
61 if ((valueFormat & vfbXAdvance) != 0) {
62 le_int16 value = getFieldValue(valueFormat, vrfXAdvance);
63 LEPoint pixels;
64
65 fontInstance->transformFunits(value, 0, pixels);
66
67 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(pixels.fX));
68 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(pixels.fY));
69 }
70
71 if ((valueFormat & vfbYAdvance) != 0) {
72 le_int16 value = getFieldValue(valueFormat, vrfYAdvance);
73 LEPoint pixels;
74
75 fontInstance->transformFunits(0, value, pixels);
76
77 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(pixels.fX));
78 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(pixels.fY));
79 }
80
81 // FIXME: The device adjustments should really be transformed, but
82 // the only way I know how to do that is to convert them to le_int16 units,
83 // transform them, and then convert them back to pixels. Sigh...
84 if ((valueFormat & vfbAnyDevice) != 0) {
85 le_int16 xppem = (le_int16) fontInstance->getXPixelsPerEm();
86 le_int16 yppem = (le_int16) fontInstance->getYPixelsPerEm();
87
88 if ((valueFormat & vfbXPlaDevice) != 0) {
89 Offset dtOffset = getFieldValue(valueFormat, vrfXPlaDevice);
90
91 if (dtOffset != 0) {
92 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
93 le_int16 xAdj = dt->getAdjustment(xppem);
94
95 positionAdjustment.adjustXPlacement(fontInstance->xPixelsToUnits(xAdj));
96 }
97 }
98
99 if ((valueFormat & vfbYPlaDevice) != 0) {
100 Offset dtOffset = getFieldValue(valueFormat, vrfYPlaDevice);
101
102 if (dtOffset != 0) {
103 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
104 le_int16 yAdj = dt->getAdjustment(yppem);
105
106 positionAdjustment.adjustYPlacement(fontInstance->yPixelsToUnits(yAdj));
107 }
108 }
109
110 if ((valueFormat & vfbXAdvDevice) != 0) {
111 Offset dtOffset = getFieldValue(valueFormat, vrfXAdvDevice);
112
113 if (dtOffset != 0) {
114 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
115 le_int16 xAdj = dt->getAdjustment(xppem);
116
117 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(xAdj));
118 }
119 }
120
121 if ((valueFormat & vfbYAdvDevice) != 0) {
122 Offset dtOffset = getFieldValue(valueFormat, vrfYAdvDevice);
123
124 if (dtOffset != 0) {
125 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
126 le_int16 yAdj = dt->getAdjustment(yppem);
127
128 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(yAdj));
129 }
130 }
131 }
132 }
133
134 void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const char *base, GlyphPositionAdjustment &positionAdjustment,
135 const LEFontInstance *fontInstance) const
136 {
137 if ((valueFormat & vfbXPlacement) != 0) {
138 le_int16 value = getFieldValue(index, valueFormat, vrfXPlacement);
139 LEPoint pixels;
140
141 fontInstance->transformFunits(value, 0, pixels);
142
143 positionAdjustment.adjustXPlacement(fontInstance->xPixelsToUnits(pixels.fX));
144 positionAdjustment.adjustYPlacement(fontInstance->yPixelsToUnits(pixels.fY));
145 }
146
147 if ((valueFormat & vfbYPlacement) != 0) {
148 le_int16 value = getFieldValue(index, valueFormat, vrfYPlacement);
149 LEPoint pixels;
150
151 fontInstance->transformFunits(0, value, pixels);
152
153 positionAdjustment.adjustXPlacement(fontInstance->xPixelsToUnits(pixels.fX));
154 positionAdjustment.adjustYPlacement(fontInstance->yPixelsToUnits(pixels.fY));
155 }
156
157 if ((valueFormat & vfbXAdvance) != 0) {
158 le_int16 value = getFieldValue(index, valueFormat, vrfXAdvance);
159 LEPoint pixels;
160
161 fontInstance->transformFunits(value, 0, pixels);
162
163 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(pixels.fX));
164 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(pixels.fY));
165 }
166
167 if ((valueFormat & vfbYAdvance) != 0) {
168 le_int16 value = getFieldValue(index, valueFormat, vrfYAdvance);
169 LEPoint pixels;
170
171 fontInstance->transformFunits(0, value, pixels);
172
173 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(pixels.fX));
174 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(pixels.fY));
175 }
176
177 // FIXME: The device adjustments should really be transformed, but
178 // the only way I know how to do that is to convert them to le_int16 units,
179 // transform them, and then convert them back to pixels. Sigh...
180 if ((valueFormat & vfbAnyDevice) != 0) {
181 le_int16 xppem = (le_int16) fontInstance->getXPixelsPerEm();
182 le_int16 yppem = (le_int16) fontInstance->getYPixelsPerEm();
183
184 if ((valueFormat & vfbXPlaDevice) != 0) {
185 Offset dtOffset = getFieldValue(index, valueFormat, vrfXPlaDevice);
186
187 if (dtOffset != 0) {
188 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
189 le_int16 xAdj = dt->getAdjustment(xppem);
190
191 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(xAdj));
192 }
193 }
194
195 if ((valueFormat & vfbYPlaDevice) != 0) {
196 Offset dtOffset = getFieldValue(index, valueFormat, vrfYPlaDevice);
197
198 if (dtOffset != 0) {
199 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
200 le_int16 yAdj = dt->getAdjustment(yppem);
201
202 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(yAdj));
203 }
204 }
205
206 if ((valueFormat & vfbXAdvDevice) != 0) {
207 Offset dtOffset = getFieldValue(index, valueFormat, vrfXAdvDevice);
208
209 if (dtOffset != 0) {
210 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
211 le_int16 xAdj = dt->getAdjustment(xppem);
212
213 positionAdjustment.adjustXAdvance(fontInstance->xPixelsToUnits(xAdj));
214 }
215 }
216
217 if ((valueFormat & vfbYAdvDevice) != 0) {
218 Offset dtOffset = getFieldValue(index, valueFormat, vrfYAdvDevice);
219
220 if (dtOffset != 0) {
221 const DeviceTable *dt = (const DeviceTable *) (base + dtOffset);
222 le_int16 yAdj = dt->getAdjustment(yppem);
223
224 positionAdjustment.adjustYAdvance(fontInstance->yPixelsToUnits(yAdj));
225 }
226 }
227 }
228 }
229
230 le_int16 ValueRecord::getSize(ValueFormat valueFormat)
231 {
232 return getFieldCount(valueFormat) * sizeof(le_int16);
233 }
234
235 le_int16 ValueRecord::getFieldCount(ValueFormat valueFormat)
236 {
237 static const le_int16 bitsInNibble[] =
238 {
239 0 + 0 + 0 + 0,
240 0 + 0 + 0 + 1,
241 0 + 0 + 1 + 0,
242 0 + 0 + 1 + 1,
243 0 + 1 + 0 + 0,
244 0 + 1 + 0 + 1,
245 0 + 1 + 1 + 0,
246 0 + 1 + 1 + 1,
247 1 + 0 + 0 + 0,
248 1 + 0 + 0 + 1,
249 1 + 0 + 1 + 0,
250 1 + 0 + 1 + 1,
251 1 + 1 + 0 + 0,
252 1 + 1 + 0 + 1,
253 1 + 1 + 1 + 0,
254 1 + 1 + 1 + 1
255 };
256
257 valueFormat &= ~vfbReserved;
258
259 return NibbleBits(valueFormat, 0) + NibbleBits(valueFormat, 1) +
260 NibbleBits(valueFormat, 2) + NibbleBits(valueFormat, 3);
261 }
262
263 le_int16 ValueRecord::getFieldIndex(ValueFormat valueFormat, ValueRecordField field)
264 {
265 static const le_uint16 beforeMasks[] =
266 {
267 0x0000,
268 0x0001,
269 0x0003,
270 0x0007,
271 0x000F,
272 0x001F,
273 0x003F,
274 0x007F,
275 0x00FF,
276 0x01FF,
277 0x03FF,
278 0x07FF,
279 0x0FFF,
280 0x1FFF,
281 0x3FFF,
282 0x7FFF,
283 0xFFFF
284 };
285
286 return getFieldCount(valueFormat & beforeMasks[field]);
287 }
288
289 U_NAMESPACE_END