sl@0: /*************************************************************************** sl@0: * sl@0: * Copyright (C) 1998-2003, International Business Machines sl@0: * Corporation and others. All Rights Reserved. sl@0: * sl@0: ************************************************************************/ sl@0: sl@0: #include "LETypes.h" sl@0: #include "LESwaps.h" sl@0: sl@0: #include "sfnt.h" sl@0: #include "cmaps.h" sl@0: sl@0: #define SWAPU16(code) ((LEUnicode16) SWAPW(code)) sl@0: #define SWAPU32(code) ((LEUnicode32) SWAPL(code)) sl@0: sl@0: // sl@0: // Finds the high bit by binary searching sl@0: // through the bits in value. sl@0: // sl@0: le_int8 highBit(le_uint32 value) sl@0: { sl@0: le_uint8 bit = 0; sl@0: sl@0: if (value >= 1 << 16) { sl@0: value >>= 16; sl@0: bit += 16; sl@0: } sl@0: sl@0: if (value >= 1 << 8) { sl@0: value >>= 8; sl@0: bit += 8; sl@0: } sl@0: sl@0: if (value >= 1 << 4) { sl@0: value >>= 4; sl@0: bit += 4; sl@0: } sl@0: sl@0: if (value >= 1 << 2) { sl@0: value >>= 2; sl@0: bit += 2; sl@0: } sl@0: sl@0: if (value >= 1 << 1) { sl@0: value >>= 1; sl@0: bit += 1; sl@0: } sl@0: sl@0: return bit; sl@0: } sl@0: sl@0: CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap) sl@0: { sl@0: le_uint16 i; sl@0: le_uint16 nSubtables = SWAPW(cmap->numberSubtables); sl@0: const CMAPEncodingSubtable *subtable = NULL; sl@0: le_uint32 offset1 = 0, offset10 = 0; sl@0: sl@0: for (i = 0; i < nSubtables; i += 1) { sl@0: const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i]; sl@0: sl@0: if (SWAPW(esh->platformID) == 3) { sl@0: switch (SWAPW(esh->platformSpecificID)) { sl@0: case 1: sl@0: offset1 = SWAPL(esh->encodingOffset); sl@0: break; sl@0: sl@0: case 10: sl@0: offset10 = SWAPL(esh->encodingOffset); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: if (offset10 != 0) sl@0: { sl@0: subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10); sl@0: } else if (offset1 != 0) { sl@0: subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1); sl@0: } else { sl@0: return NULL; sl@0: } sl@0: sl@0: switch (SWAPW(subtable->format)) { sl@0: case 4: sl@0: return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable); sl@0: sl@0: case 12: sl@0: { sl@0: const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable; sl@0: sl@0: return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups)); sl@0: } sl@0: sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: return NULL; sl@0: } sl@0: sl@0: CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header) sl@0: : CMAPMapper(cmap) sl@0: { sl@0: le_uint16 segCount = SWAPW(header->segCountX2) / 2; sl@0: sl@0: fEntrySelector = SWAPW(header->entrySelector); sl@0: fRangeShift = SWAPW(header->rangeShift) / 2; sl@0: fEndCodes = &header->endCodes[0]; sl@0: fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad... sl@0: fIdDelta = &fStartCodes[segCount]; sl@0: fIdRangeOffset = &fIdDelta[segCount]; sl@0: } sl@0: sl@0: LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const sl@0: { sl@0: if (unicode32 >= 0x10000) { sl@0: return 0; sl@0: } sl@0: sl@0: LEUnicode16 unicode = (LEUnicode16) unicode32; sl@0: le_uint16 index = 0; sl@0: le_uint16 probe = 1 << fEntrySelector; sl@0: TTGlyphID result = 0; sl@0: sl@0: if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) { sl@0: index = fRangeShift; sl@0: } sl@0: sl@0: while (probe > (1 << 0)) { sl@0: probe >>= 1; sl@0: sl@0: if (SWAPU16(fStartCodes[index + probe]) <= unicode) { sl@0: index += probe; sl@0: } sl@0: } sl@0: sl@0: if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) { sl@0: if (fIdRangeOffset[index] == 0) { sl@0: result = (TTGlyphID) unicode; sl@0: } else { sl@0: le_uint16 offset = unicode - SWAPU16(fStartCodes[index]); sl@0: le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]); sl@0: le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset); sl@0: sl@0: result = SWAPW(glyphIndexTable[offset]); sl@0: } sl@0: sl@0: result += SWAPW(fIdDelta[index]); sl@0: } else { sl@0: result = 0; sl@0: } sl@0: sl@0: return LE_SET_GLYPH(0, result); sl@0: } sl@0: sl@0: CMAPFormat4Mapper::~CMAPFormat4Mapper() sl@0: { sl@0: // parent destructor does it all sl@0: } sl@0: sl@0: CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups) sl@0: : CMAPMapper(cmap), fGroups(groups) sl@0: { sl@0: le_uint8 bit = highBit(nGroups); sl@0: fPower = 1 << bit; sl@0: fRangeOffset = nGroups - fPower; sl@0: } sl@0: sl@0: LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const sl@0: { sl@0: le_int32 probe = fPower; sl@0: le_int32 range = 0; sl@0: sl@0: if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) { sl@0: range = fRangeOffset; sl@0: } sl@0: sl@0: while (probe > (1 << 0)) { sl@0: probe >>= 1; sl@0: sl@0: if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) { sl@0: range += probe; sl@0: } sl@0: } sl@0: sl@0: if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) { sl@0: return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode)); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: CMAPGroupMapper::~CMAPGroupMapper() sl@0: { sl@0: // parent destructor does it all sl@0: } sl@0: