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 201