OLD | NEW |
(Empty) | |
| 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 + offset1
0); |
| 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 *) subtabl
e); |
| 89 |
| 90 case 12: |
| 91 { |
| 92 const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) su
btable; |
| 93 |
| 94 return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGrou
ps)); |
| 95 } |
| 96 |
| 97 default: |
| 98 break; |
| 99 } |
| 100 |
| 101 return NULL; |
| 102 } |
| 103 |
| 104 CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Enc
oding *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[i
ndex])) { |
| 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[ra
nge].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 |
OLD | NEW |