| OLD | NEW |
| (Empty) |
| 1 /*************************************************************************** | |
| 2 * | |
| 3 * Copyright (C) 1998-2013, International Business Machines | |
| 4 * Corporation and others. All Rights Reserved. | |
| 5 * | |
| 6 ************************************************************************/ | |
| 7 | |
| 8 #include "layout/LETypes.h" | |
| 9 #include "layout/LESwaps.h" | |
| 10 | |
| 11 #include "sfnt.h" | |
| 12 #include "cmaps.h" | |
| 13 #include <stdio.h> | |
| 14 | |
| 15 #define SWAPU16(code) ((LEUnicode16) SWAPW(code)) | |
| 16 #define SWAPU32(code) ((LEUnicode32) SWAPL(code)) | |
| 17 | |
| 18 // | |
| 19 // Finds the high bit by binary searching | |
| 20 // through the bits in value. | |
| 21 // | |
| 22 le_int8 highBit(le_uint32 value) | |
| 23 { | |
| 24 le_uint8 bit = 0; | |
| 25 | |
| 26 if (value >= 1 << 16) { | |
| 27 value >>= 16; | |
| 28 bit += 16; | |
| 29 } | |
| 30 | |
| 31 if (value >= 1 << 8) { | |
| 32 value >>= 8; | |
| 33 bit += 8; | |
| 34 } | |
| 35 | |
| 36 if (value >= 1 << 4) { | |
| 37 value >>= 4; | |
| 38 bit += 4; | |
| 39 } | |
| 40 | |
| 41 if (value >= 1 << 2) { | |
| 42 value >>= 2; | |
| 43 bit += 2; | |
| 44 } | |
| 45 | |
| 46 if (value >= 1 << 1) { | |
| 47 value >>= 1; | |
| 48 bit += 1; | |
| 49 } | |
| 50 | |
| 51 return bit; | |
| 52 } | |
| 53 | |
| 54 CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap) | |
| 55 { | |
| 56 le_uint16 i; | |
| 57 le_uint16 nSubtables = SWAPW(cmap->numberSubtables); | |
| 58 const CMAPEncodingSubtable *subtable = NULL; | |
| 59 le_bool found = FALSE; | |
| 60 le_uint16 foundPlatformID = 0xFFFF; | |
| 61 le_uint16 foundPlatformSpecificID = 0xFFFF; | |
| 62 le_uint32 foundOffset = 0; | |
| 63 le_uint16 foundTable = 0xFFFF; | |
| 64 // first pass, look for MS table. (preferred?) | |
| 65 for (i = 0; i < nSubtables && !found; i += 1) { | |
| 66 const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i
]; | |
| 67 | |
| 68 le_uint16 platformID = SWAPW(esh->platformID); | |
| 69 le_uint16 platformSpecificID = SWAPW(esh->platformSpecificID); | |
| 70 if (platformID == 3) { // microsoft | |
| 71 switch (platformSpecificID) { | |
| 72 case 1: // Unicode BMP (UCS-2) | |
| 73 case 10: // Unicode UCS-4 | |
| 74 foundOffset = SWAPL(esh->encodingOffset); | |
| 75 foundPlatformID = platformID; | |
| 76 foundPlatformSpecificID = platformSpecificID; | |
| 77 found = TRUE; | |
| 78 foundTable = i; | |
| 79 break; | |
| 80 | |
| 81 //default: | |
| 82 // printf("%s:%d: microsoft (3) platform specific ID
%d (wanted 1 or 10) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platf
ormSpecificID)), i, nSubtables); | |
| 83 } | |
| 84 } else { | |
| 85 //printf("%s:%d: platform ID %d (wanted 3, microsoft) for subtable %d
/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformID)), i, nSubtables); | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 // second pass, allow non MS table | |
| 90 // first pass, look for MS table. (preferred?) | |
| 91 for (i = 0; i < nSubtables && !found; i += 1) { | |
| 92 const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i
]; | |
| 93 le_uint16 platformID = SWAPW(esh->platformID); | |
| 94 le_uint16 platformSpecificID = SWAPW(esh->platformSpecificID); | |
| 95 //printf("%s:%d: table %d/%d has platform:specific %d:%d\n", __FILE__, _
_LINE__, i, nSubtables, platformID, platformSpecificID); | |
| 96 switch(platformID) { | |
| 97 case 0: // Unicode platform | |
| 98 switch(platformSpecificID) { | |
| 99 case 0: | |
| 100 case 1: | |
| 101 case 2: | |
| 102 case 3: | |
| 103 foundOffset = SWAPL(esh->encodingOffset); | |
| 104 foundPlatformID = platformID; | |
| 105 foundPlatformSpecificID = platformSpecificID; | |
| 106 foundTable = i; | |
| 107 found = TRUE; | |
| 108 break; | |
| 109 | |
| 110 default: printf("Error: table %d (psid %d) is unknown. Skipping.\n", i
, platformSpecificID); break; | |
| 111 } | |
| 112 break; | |
| 113 | |
| 114 //default: | |
| 115 //printf("Skipping platform id %d\n", platformID); | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 | |
| 120 if (found) | |
| 121 { | |
| 122 subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + foundOffs
et); | |
| 123 //printf("%s:%d: using subtable #%d/%d type %d:%d\n", __FILE__, __LINE__,
foundTable, nSubtables, foundPlatformID, foundPlatformSpecificID); | |
| 124 } else { | |
| 125 printf("%s:%d: could not find subtable.\n", __FILE__, __LINE__); | |
| 126 return NULL; | |
| 127 } | |
| 128 | |
| 129 le_uint16 tableFormat = SWAPW(subtable->format); | |
| 130 //printf("%s:%d: table format %d\n", __FILE__, __LINE__, tableFormat); | |
| 131 | |
| 132 switch (tableFormat) { | |
| 133 case 4: | |
| 134 return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtabl
e); | |
| 135 | |
| 136 case 12: | |
| 137 { | |
| 138 const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) su
btable; | |
| 139 | |
| 140 return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGrou
ps)); | |
| 141 } | |
| 142 | |
| 143 default: | |
| 144 break; | |
| 145 } | |
| 146 | |
| 147 printf("%s:%d: Unknown format %x.\n", __FILE__, __LINE__, (SWAPW(subtable->f
ormat))); | |
| 148 return NULL; | |
| 149 } | |
| 150 | |
| 151 CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Enc
oding *header) | |
| 152 : CMAPMapper(cmap) | |
| 153 { | |
| 154 le_uint16 segCount = SWAPW(header->segCountX2) / 2; | |
| 155 | |
| 156 fEntrySelector = SWAPW(header->entrySelector); | |
| 157 fRangeShift = SWAPW(header->rangeShift) / 2; | |
| 158 fEndCodes = &header->endCodes[0]; | |
| 159 fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad... | |
| 160 fIdDelta = &fStartCodes[segCount]; | |
| 161 fIdRangeOffset = &fIdDelta[segCount]; | |
| 162 } | |
| 163 | |
| 164 LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const | |
| 165 { | |
| 166 if (unicode32 >= 0x10000) { | |
| 167 return 0; | |
| 168 } | |
| 169 | |
| 170 LEUnicode16 unicode = (LEUnicode16) unicode32; | |
| 171 le_uint16 index = 0; | |
| 172 le_uint16 probe = 1 << fEntrySelector; | |
| 173 TTGlyphID result = 0; | |
| 174 | |
| 175 if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) { | |
| 176 index = fRangeShift; | |
| 177 } | |
| 178 | |
| 179 while (probe > (1 << 0)) { | |
| 180 probe >>= 1; | |
| 181 | |
| 182 if (SWAPU16(fStartCodes[index + probe]) <= unicode) { | |
| 183 index += probe; | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[i
ndex])) { | |
| 188 if (fIdRangeOffset[index] == 0) { | |
| 189 result = (TTGlyphID) unicode; | |
| 190 } else { | |
| 191 le_uint16 offset = unicode - SWAPU16(fStartCodes[index]); | |
| 192 le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]); | |
| 193 le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset
[index] + rangeOffset); | |
| 194 | |
| 195 result = SWAPW(glyphIndexTable[offset]); | |
| 196 } | |
| 197 | |
| 198 result += SWAPW(fIdDelta[index]); | |
| 199 } else { | |
| 200 result = 0; | |
| 201 } | |
| 202 | |
| 203 return LE_SET_GLYPH(0, result); | |
| 204 } | |
| 205 | |
| 206 CMAPFormat4Mapper::~CMAPFormat4Mapper() | |
| 207 { | |
| 208 // parent destructor does it all | |
| 209 } | |
| 210 | |
| 211 CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups,
le_uint32 nGroups) | |
| 212 : CMAPMapper(cmap), fGroups(groups) | |
| 213 { | |
| 214 le_uint8 bit = highBit(nGroups); | |
| 215 fPower = 1 << bit; | |
| 216 fRangeOffset = nGroups - fPower; | |
| 217 } | |
| 218 | |
| 219 LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const | |
| 220 { | |
| 221 le_int32 probe = fPower; | |
| 222 le_int32 range = 0; | |
| 223 | |
| 224 if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) { | |
| 225 range = fRangeOffset; | |
| 226 } | |
| 227 | |
| 228 while (probe > (1 << 0)) { | |
| 229 probe >>= 1; | |
| 230 | |
| 231 if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) { | |
| 232 range += probe; | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[ra
nge].endCharCode) >= unicode32) { | |
| 237 return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 -
SWAPU32(fGroups[range].startCharCode)); | |
| 238 } | |
| 239 | |
| 240 return 0; | |
| 241 } | |
| 242 | |
| 243 CMAPGroupMapper::~CMAPGroupMapper() | |
| 244 { | |
| 245 // parent destructor does it all | |
| 246 } | |
| 247 | |
| OLD | NEW |