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