]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
73c04bcf | 3 | * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved |
b75a7d8f A |
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" | |
b75a7d8f A |
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 | ||
20 | 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 | ||
28 | 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 | ||
73c04bcf | 37 | void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, GlyphIterator &glyphIterator, |
b75a7d8f A |
38 | const LEFontInstance *fontInstance) const |
39 | { | |
73c04bcf A |
40 | float xPlacementAdjustment = 0; |
41 | float yPlacementAdjustment = 0; | |
42 | float xAdvanceAdjustment = 0; | |
43 | float yAdvanceAdjustment = 0; | |
44 | ||
b75a7d8f A |
45 | if ((valueFormat & vfbXPlacement) != 0) { |
46 | le_int16 value = getFieldValue(valueFormat, vrfXPlacement); | |
47 | LEPoint pixels; | |
48 | ||
49 | fontInstance->transformFunits(value, 0, pixels); | |
50 | ||
73c04bcf A |
51 | xPlacementAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
52 | yPlacementAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf A |
61 | xPlacementAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
62 | yPlacementAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf A |
71 | xAdvanceAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
72 | yAdvanceAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf A |
81 | xAdvanceAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
82 | yAdvanceAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf | 99 | xPlacementAdjustment += fontInstance->xPixelsToUnits(xAdj); |
b75a7d8f A |
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 | ||
73c04bcf | 110 | yPlacementAdjustment += fontInstance->yPixelsToUnits(yAdj); |
b75a7d8f A |
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 | ||
73c04bcf | 121 | xAdvanceAdjustment += fontInstance->xPixelsToUnits(xAdj); |
b75a7d8f A |
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 | ||
73c04bcf | 132 | yAdvanceAdjustment += fontInstance->yPixelsToUnits(yAdj); |
b75a7d8f A |
133 | } |
134 | } | |
135 | } | |
73c04bcf A |
136 | |
137 | glyphIterator.adjustCurrGlyphPositionAdjustment( | |
138 | xPlacementAdjustment, yPlacementAdjustment, xAdvanceAdjustment, yAdvanceAdjustment); | |
b75a7d8f A |
139 | } |
140 | ||
73c04bcf | 141 | void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const char *base, GlyphIterator &glyphIterator, |
b75a7d8f A |
142 | const LEFontInstance *fontInstance) const |
143 | { | |
73c04bcf A |
144 | float xPlacementAdjustment = 0; |
145 | float yPlacementAdjustment = 0; | |
146 | float xAdvanceAdjustment = 0; | |
147 | float yAdvanceAdjustment = 0; | |
148 | ||
b75a7d8f A |
149 | if ((valueFormat & vfbXPlacement) != 0) { |
150 | le_int16 value = getFieldValue(index, valueFormat, vrfXPlacement); | |
151 | LEPoint pixels; | |
152 | ||
153 | fontInstance->transformFunits(value, 0, pixels); | |
154 | ||
73c04bcf A |
155 | xPlacementAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
156 | yPlacementAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf A |
165 | xPlacementAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
166 | yPlacementAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf A |
175 | xAdvanceAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
176 | yAdvanceAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf A |
185 | xAdvanceAdjustment += fontInstance->xPixelsToUnits(pixels.fX); |
186 | yAdvanceAdjustment += fontInstance->yPixelsToUnits(pixels.fY); | |
b75a7d8f A |
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 | ||
73c04bcf | 203 | xPlacementAdjustment += fontInstance->xPixelsToUnits(xAdj); |
b75a7d8f A |
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 | ||
73c04bcf | 214 | yPlacementAdjustment += fontInstance->yPixelsToUnits(yAdj); |
b75a7d8f A |
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 | ||
73c04bcf | 225 | xAdvanceAdjustment += fontInstance->xPixelsToUnits(xAdj); |
b75a7d8f A |
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 | ||
73c04bcf | 236 | yAdvanceAdjustment += fontInstance->yPixelsToUnits(yAdj); |
b75a7d8f A |
237 | } |
238 | } | |
239 | } | |
73c04bcf A |
240 | |
241 | glyphIterator.adjustCurrGlyphPositionAdjustment( | |
242 | xPlacementAdjustment, yPlacementAdjustment, xAdvanceAdjustment, yAdvanceAdjustment); | |
b75a7d8f A |
243 | } |
244 | ||
245 | le_int16 ValueRecord::getSize(ValueFormat valueFormat) | |
246 | { | |
247 | return getFieldCount(valueFormat) * sizeof(le_int16); | |
248 | } | |
249 | ||
250 | le_int16 ValueRecord::getFieldCount(ValueFormat valueFormat) | |
251 | { | |
374ca955 | 252 | static const le_int16 bitsInNibble[] = |
b75a7d8f A |
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 | ||
278 | le_int16 ValueRecord::getFieldIndex(ValueFormat valueFormat, ValueRecordField field) | |
279 | { | |
374ca955 | 280 | static const le_uint16 beforeMasks[] = |
b75a7d8f A |
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 |