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