1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/***************************************************************************
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
359d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 1998-2013, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru************************************************************************/
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
859d709d503bab6e2b61931737e662dd293b40578ccornelius#include "layout/LETypes.h"
959d709d503bab6e2b61931737e662dd293b40578ccornelius#include "layout/LESwaps.h"
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "sfnt.h"
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmaps.h"
1359d709d503bab6e2b61931737e662dd293b40578ccornelius#include <stdio.h>
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SWAPU16(code) ((LEUnicode16) SWAPW(code))
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SWAPU32(code) ((LEUnicode32) SWAPL(code))
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Finds the high bit by binary searching
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// through the bits in value.
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int8 highBit(le_uint32 value)
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint8 bit = 0;
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (value >= 1 << 16) {
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value >>= 16;
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bit += 16;
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (value >= 1 << 8) {
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value >>= 8;
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bit += 8;
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (value >= 1 << 4) {
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value >>= 4;
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bit += 4;
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (value >= 1 << 2) {
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value >>= 2;
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bit += 2;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (value >= 1 << 1) {
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value >>= 1;
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bit += 1;
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return bit;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 i;
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const CMAPEncodingSubtable *subtable = NULL;
5959d709d503bab6e2b61931737e662dd293b40578ccornelius    le_bool found = FALSE;
6059d709d503bab6e2b61931737e662dd293b40578ccornelius    le_uint16 foundPlatformID = 0xFFFF;
6159d709d503bab6e2b61931737e662dd293b40578ccornelius    le_uint16 foundPlatformSpecificID = 0xFFFF;
6259d709d503bab6e2b61931737e662dd293b40578ccornelius    le_uint32 foundOffset = 0;
6359d709d503bab6e2b61931737e662dd293b40578ccornelius    le_uint16 foundTable = 0xFFFF;
6459d709d503bab6e2b61931737e662dd293b40578ccornelius    // first pass, look for MS table. (preferred?)
6559d709d503bab6e2b61931737e662dd293b40578ccornelius    for (i = 0; i < nSubtables && !found; i += 1) {
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6859d709d503bab6e2b61931737e662dd293b40578ccornelius        le_uint16 platformID = SWAPW(esh->platformID);
6959d709d503bab6e2b61931737e662dd293b40578ccornelius        le_uint16 platformSpecificID = SWAPW(esh->platformSpecificID);
7059d709d503bab6e2b61931737e662dd293b40578ccornelius        if (platformID == 3) { // microsoft
7159d709d503bab6e2b61931737e662dd293b40578ccornelius          switch (platformSpecificID) {
7259d709d503bab6e2b61931737e662dd293b40578ccornelius            case 1: // Unicode BMP (UCS-2)
7359d709d503bab6e2b61931737e662dd293b40578ccornelius            case 10: // Unicode UCS-4
7459d709d503bab6e2b61931737e662dd293b40578ccornelius                foundOffset = SWAPL(esh->encodingOffset);
7559d709d503bab6e2b61931737e662dd293b40578ccornelius                foundPlatformID = platformID;
7659d709d503bab6e2b61931737e662dd293b40578ccornelius                foundPlatformSpecificID = platformSpecificID;
7759d709d503bab6e2b61931737e662dd293b40578ccornelius                found = TRUE;
7859d709d503bab6e2b61931737e662dd293b40578ccornelius                foundTable = i;
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
8159d709d503bab6e2b61931737e662dd293b40578ccornelius                //default:
8259d709d503bab6e2b61931737e662dd293b40578ccornelius              //              printf("%s:%d: microsoft (3) platform specific ID %d (wanted 1 or 10) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformSpecificID)), i, nSubtables);
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
8459d709d503bab6e2b61931737e662dd293b40578ccornelius        } else {
8559d709d503bab6e2b61931737e662dd293b40578ccornelius          //printf("%s:%d: platform  ID %d (wanted 3, microsoft) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformID)), i, nSubtables);
8659d709d503bab6e2b61931737e662dd293b40578ccornelius        }
8759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
8859d709d503bab6e2b61931737e662dd293b40578ccornelius
8959d709d503bab6e2b61931737e662dd293b40578ccornelius    // second pass, allow non MS table
9059d709d503bab6e2b61931737e662dd293b40578ccornelius    // first pass, look for MS table. (preferred?)
9159d709d503bab6e2b61931737e662dd293b40578ccornelius      for (i = 0; i < nSubtables && !found; i += 1) {
9259d709d503bab6e2b61931737e662dd293b40578ccornelius        const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
9359d709d503bab6e2b61931737e662dd293b40578ccornelius        le_uint16 platformID = SWAPW(esh->platformID);
9459d709d503bab6e2b61931737e662dd293b40578ccornelius        le_uint16 platformSpecificID = SWAPW(esh->platformSpecificID);
9559d709d503bab6e2b61931737e662dd293b40578ccornelius        //printf("%s:%d: table %d/%d has platform:specific %d:%d\n", __FILE__, __LINE__, i, nSubtables, platformID, platformSpecificID);
9659d709d503bab6e2b61931737e662dd293b40578ccornelius        switch(platformID) {
9759d709d503bab6e2b61931737e662dd293b40578ccornelius        case 0: // Unicode platform
9859d709d503bab6e2b61931737e662dd293b40578ccornelius          switch(platformSpecificID) {
9959d709d503bab6e2b61931737e662dd293b40578ccornelius          case 0:
10059d709d503bab6e2b61931737e662dd293b40578ccornelius          case 1:
10159d709d503bab6e2b61931737e662dd293b40578ccornelius          case 2:
10259d709d503bab6e2b61931737e662dd293b40578ccornelius          case 3:
10359d709d503bab6e2b61931737e662dd293b40578ccornelius            foundOffset = SWAPL(esh->encodingOffset);
10459d709d503bab6e2b61931737e662dd293b40578ccornelius            foundPlatformID = platformID;
10559d709d503bab6e2b61931737e662dd293b40578ccornelius            foundPlatformSpecificID = platformSpecificID;
10659d709d503bab6e2b61931737e662dd293b40578ccornelius            foundTable = i;
10759d709d503bab6e2b61931737e662dd293b40578ccornelius            found = TRUE;
10859d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
10959d709d503bab6e2b61931737e662dd293b40578ccornelius
11059d709d503bab6e2b61931737e662dd293b40578ccornelius          default: printf("Error: table %d (psid %d) is unknown. Skipping.\n", i, platformSpecificID); break;
11159d709d503bab6e2b61931737e662dd293b40578ccornelius          }
11259d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
11359d709d503bab6e2b61931737e662dd293b40578ccornelius
11459d709d503bab6e2b61931737e662dd293b40578ccornelius          //default:
11559d709d503bab6e2b61931737e662dd293b40578ccornelius          //printf("Skipping platform id %d\n", platformID);
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (found)
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
12259d709d503bab6e2b61931737e662dd293b40578ccornelius      subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + foundOffset);
12359d709d503bab6e2b61931737e662dd293b40578ccornelius      //printf("%s:%d: using subtable #%d/%d type %d:%d\n", __FILE__, __LINE__, foundTable, nSubtables, foundPlatformID, foundPlatformSpecificID);
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
12559d709d503bab6e2b61931737e662dd293b40578ccornelius      printf("%s:%d: could not find subtable.\n", __FILE__, __LINE__);
12659d709d503bab6e2b61931737e662dd293b40578ccornelius      return NULL;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12959d709d503bab6e2b61931737e662dd293b40578ccornelius    le_uint16 tableFormat = SWAPW(subtable->format);
13059d709d503bab6e2b61931737e662dd293b40578ccornelius    //printf("%s:%d: table format %d\n", __FILE__, __LINE__, tableFormat);
13159d709d503bab6e2b61931737e662dd293b40578ccornelius
13259d709d503bab6e2b61931737e662dd293b40578ccornelius    switch (tableFormat) {
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case 4:
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case 12:
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default:
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14759d709d503bab6e2b61931737e662dd293b40578ccornelius    printf("%s:%d: Unknown format %x.\n", __FILE__, __LINE__, (SWAPW(subtable->format)));
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    : CMAPMapper(cmap)
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 segCount = SWAPW(header->segCountX2) / 2;
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fEntrySelector = SWAPW(header->entrySelector);
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fRangeShift = SWAPW(header->rangeShift) / 2;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fEndCodes = &header->endCodes[0];
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fIdDelta = &fStartCodes[segCount];
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fIdRangeOffset = &fIdDelta[segCount];
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (unicode32 >= 0x10000) {
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEUnicode16 unicode = (LEUnicode16) unicode32;
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 index = 0;
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 probe = 1 << fEntrySelector;
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TTGlyphID result = 0;
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        index = fRangeShift;
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (probe > (1 << 0)) {
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        probe >>= 1;
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            index += probe;
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fIdRangeOffset[index] == 0) {
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = (TTGlyphID) unicode;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = SWAPW(glyphIndexTable[offset]);
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result += SWAPW(fIdDelta[index]);
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = 0;
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return LE_SET_GLYPH(0, result);
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCMAPFormat4Mapper::~CMAPFormat4Mapper()
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // parent destructor does it all
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    : CMAPMapper(cmap), fGroups(groups)
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint8 bit = highBit(nGroups);
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fPower = 1 << bit;
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fRangeOffset = nGroups - fPower;
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 probe = fPower;
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 range = 0;
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        range = fRangeOffset;
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (probe > (1 << 0)) {
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        probe >>= 1;
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            range += probe;
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCMAPGroupMapper::~CMAPGroupMapper()
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // parent destructor does it all
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248