os/textandloc/fontservices/textshaperplugin/source/cmaps.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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