Home | History | Annotate | Download | only in letest
      1 /***************************************************************************
      2 *
      3 *   Copyright (C) 1998-2003, International Business Machines
      4 *   Corporation and others.  All Rights Reserved.
      5 *
      6 ************************************************************************/
      7 
      8 #include "LETypes.h"
      9 #include "LESwaps.h"
     10 
     11 #include "sfnt.h"
     12 #include "cmaps.h"
     13 
     14 #define SWAPU16(code) ((LEUnicode16) SWAPW(code))
     15 #define SWAPU32(code) ((LEUnicode32) SWAPL(code))
     16 
     17 //
     18 // Finds the high bit by binary searching
     19 // through the bits in value.
     20 //
     21 le_int8 highBit(le_uint32 value)
     22 {
     23     le_uint8 bit = 0;
     24 
     25     if (value >= 1 << 16) {
     26         value >>= 16;
     27         bit += 16;
     28     }
     29 
     30     if (value >= 1 << 8) {
     31         value >>= 8;
     32         bit += 8;
     33     }
     34 
     35     if (value >= 1 << 4) {
     36         value >>= 4;
     37         bit += 4;
     38     }
     39 
     40     if (value >= 1 << 2) {
     41         value >>= 2;
     42         bit += 2;
     43     }
     44 
     45     if (value >= 1 << 1) {
     46         value >>= 1;
     47         bit += 1;
     48     }
     49 
     50     return bit;
     51 }
     52 
     53 CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
     54 {
     55     le_uint16 i;
     56     le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
     57     const CMAPEncodingSubtable *subtable = NULL;
     58     le_uint32 offset1 = 0, offset10 = 0;
     59 
     60     for (i = 0; i < nSubtables; i += 1) {
     61         const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
     62 
     63         if (SWAPW(esh->platformID) == 3) {
     64             switch (SWAPW(esh->platformSpecificID)) {
     65             case 1:
     66                 offset1 = SWAPL(esh->encodingOffset);
     67                 break;
     68 
     69             case 10:
     70                 offset10 = SWAPL(esh->encodingOffset);
     71                 break;
     72             }
     73         }
     74     }
     75 
     76 
     77     if (offset10 != 0)
     78     {
     79         subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10);
     80     } else if (offset1 != 0) {
     81         subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1);
     82     } else {
     83         return NULL;
     84     }
     85 
     86     switch (SWAPW(subtable->format)) {
     87     case 4:
     88         return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
     89 
     90     case 12:
     91     {
     92         const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
     93 
     94         return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
     95     }
     96 
     97     default:
     98         break;
     99     }
    100 
    101     return NULL;
    102 }
    103 
    104 CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
    105     : CMAPMapper(cmap)
    106 {
    107     le_uint16 segCount = SWAPW(header->segCountX2) / 2;
    108 
    109     fEntrySelector = SWAPW(header->entrySelector);
    110     fRangeShift = SWAPW(header->rangeShift) / 2;
    111     fEndCodes = &header->endCodes[0];
    112     fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
    113     fIdDelta = &fStartCodes[segCount];
    114     fIdRangeOffset = &fIdDelta[segCount];
    115 }
    116 
    117 LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
    118 {
    119     if (unicode32 >= 0x10000) {
    120         return 0;
    121     }
    122 
    123     LEUnicode16 unicode = (LEUnicode16) unicode32;
    124     le_uint16 index = 0;
    125     le_uint16 probe = 1 << fEntrySelector;
    126     TTGlyphID result = 0;
    127 
    128     if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
    129         index = fRangeShift;
    130     }
    131 
    132     while (probe > (1 << 0)) {
    133         probe >>= 1;
    134 
    135         if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
    136             index += probe;
    137         }
    138     }
    139 
    140     if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
    141         if (fIdRangeOffset[index] == 0) {
    142             result = (TTGlyphID) unicode;
    143         } else {
    144             le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
    145             le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
    146             le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
    147 
    148             result = SWAPW(glyphIndexTable[offset]);
    149         }
    150 
    151         result += SWAPW(fIdDelta[index]);
    152     } else {
    153         result = 0;
    154     }
    155 
    156     return LE_SET_GLYPH(0, result);
    157 }
    158 
    159 CMAPFormat4Mapper::~CMAPFormat4Mapper()
    160 {
    161     // parent destructor does it all
    162 }
    163 
    164 CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
    165     : CMAPMapper(cmap), fGroups(groups)
    166 {
    167     le_uint8 bit = highBit(nGroups);
    168     fPower = 1 << bit;
    169     fRangeOffset = nGroups - fPower;
    170 }
    171 
    172 LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
    173 {
    174     le_int32 probe = fPower;
    175     le_int32 range = 0;
    176 
    177     if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
    178         range = fRangeOffset;
    179     }
    180 
    181     while (probe > (1 << 0)) {
    182         probe >>= 1;
    183 
    184         if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
    185             range += probe;
    186         }
    187     }
    188 
    189     if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
    190         return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
    191     }
    192 
    193     return 0;
    194 }
    195 
    196 CMAPGroupMapper::~CMAPGroupMapper()
    197 {
    198     // parent destructor does it all
    199 }
    200 
    201