Home | History | Annotate | Download | only in layout
      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