17d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod/***************************************************************************
27d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod*
37d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod*   Copyright (C) 1998-2003, International Business Machines
47d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod*   Corporation and others.  All Rights Reserved.
57d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod*
67d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod************************************************************************/
77d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
87d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "layout/LETypes.h"
97d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "layout/LESwaps.h"
107d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
117d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "sfnt.h"
127d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "cmaps.h"
137d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
147d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#define SWAPU16(code) ((LEUnicode16) SWAPW(code))
157d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#define SWAPU32(code) ((LEUnicode32) SWAPL(code))
167d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
177d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod//
187d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod// Finds the high bit by binary searching
197d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod// through the bits in value.
207d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod//
212eef71737ea29ffadbb5a2be4a898b44f53f66acBehdad Esfahbodstatic inline le_int8 highBit(le_uint32 value)
227d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
237d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint8 bit = 0;
247d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
257d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (value >= 1 << 16) {
267d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        value >>= 16;
277d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        bit += 16;
287d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
297d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
307d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (value >= 1 << 8) {
317d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        value >>= 8;
327d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        bit += 8;
337d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
347d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
357d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (value >= 1 << 4) {
367d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        value >>= 4;
377d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        bit += 4;
387d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
397d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
407d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (value >= 1 << 2) {
417d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        value >>= 2;
427d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        bit += 2;
437d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
447d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
457d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (value >= 1 << 1) {
467d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        value >>= 1;
477d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        bit += 1;
487d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
497d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
507d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    return bit;
517d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
527d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
537d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
547d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
557d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint16 i;
567d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
577d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    const CMAPEncodingSubtable *subtable = NULL;
587d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint32 offset1 = 0, offset10 = 0;
597d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
607d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    for (i = 0; i < nSubtables; i += 1) {
617d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
627d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
637d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        if (SWAPW(esh->platformID) == 3) {
647d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            switch (SWAPW(esh->platformSpecificID)) {
657d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            case 1:
667d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod                offset1 = SWAPL(esh->encodingOffset);
677d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod                break;
687d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
697d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            case 10:
707d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod                offset10 = SWAPL(esh->encodingOffset);
717d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod                break;
727d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            }
737d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        }
747d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
757d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
767d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
777d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (offset10 != 0)
787d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    {
797d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10);
807d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    } else if (offset1 != 0) {
817d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1);
827d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    } else {
837d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        return NULL;
847d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
857d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
867d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    switch (SWAPW(subtable->format)) {
877d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    case 4:
887d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
897d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
907d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    case 12:
917d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    {
927d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
937d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
947d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
957d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
967d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
977d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    default:
987d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        break;
997d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1007d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1017d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    return NULL;
1027d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
1037d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1047d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
1057d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    : CMAPMapper(cmap)
1067d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
1077d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint16 segCount = SWAPW(header->segCountX2) / 2;
1087d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1097d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fEntrySelector = SWAPW(header->entrySelector);
1107d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fRangeShift = SWAPW(header->rangeShift) / 2;
1117d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fEndCodes = &header->endCodes[0];
1127d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
1137d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fIdDelta = &fStartCodes[segCount];
1147d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fIdRangeOffset = &fIdDelta[segCount];
1157d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
1167d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1177d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodLEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
1187d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
1197d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (unicode32 >= 0x10000) {
1207d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        return 0;
1217d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1227d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1237d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    LEUnicode16 unicode = (LEUnicode16) unicode32;
1247d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint16 index = 0;
1257d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint16 probe = 1 << fEntrySelector;
1267d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    TTGlyphID result = 0;
1277d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1287d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
1297d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        index = fRangeShift;
1307d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1317d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1327d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    while (probe > (1 << 0)) {
1337d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        probe >>= 1;
1347d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1357d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
1367d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            index += probe;
1377d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        }
1387d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1397d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1407d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
1417d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        if (fIdRangeOffset[index] == 0) {
1427d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            result = (TTGlyphID) unicode;
1437d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        } else {
1447d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
1457d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
1467d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
1477d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1487d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            result = SWAPW(glyphIndexTable[offset]);
1497d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        }
1507d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1517d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        result += SWAPW(fIdDelta[index]);
1527d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    } else {
1537d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        result = 0;
1547d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1557d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1567d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    return LE_SET_GLYPH(0, result);
1577d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
1587d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1597d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPFormat4Mapper::~CMAPFormat4Mapper()
1607d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
1617d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    // parent destructor does it all
1627d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
1637d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1647d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
1657d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    : CMAPMapper(cmap), fGroups(groups)
1667d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
1677d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_uint8 bit = highBit(nGroups);
1687d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fPower = 1 << bit;
1697d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    fRangeOffset = nGroups - fPower;
1707d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
1717d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1727d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodLEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
1737d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
1747d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_int32 probe = fPower;
1757d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    le_int32 range = 0;
1767d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1777d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
1787d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        range = fRangeOffset;
1797d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1807d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1817d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    while (probe > (1 << 0)) {
1827d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        probe >>= 1;
1837d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1847d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
1857d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod            range += probe;
1867d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        }
1877d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1887d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1897d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
1907d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod        return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
1917d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    }
1927d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1937d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    return 0;
1947d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
1957d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
1967d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPGroupMapper::~CMAPGroupMapper()
1977d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{
1987d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod    // parent destructor does it all
1997d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod}
2007d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod
201