]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
374ca955 | 3 | * (C) Copyright IBM Corp. 1998-2004 - 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" | |
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 | { | |
374ca955 | 237 | static const le_int16 bitsInNibble[] = |
b75a7d8f A |
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 | { | |
374ca955 | 265 | static const le_uint16 beforeMasks[] = |
b75a7d8f A |
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 |