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 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 37 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 141 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 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 { 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 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