| OLD | NEW |
| (Empty) |
| 1 /*************************************************************************** | |
| 2 * | |
| 3 * Copyright (C) 1998-2014, 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 (void)foundPlatformID; // Suppress unused variable compiler warnings. | |
| 125 (void)foundTable; | |
| 126 (void)foundPlatformSpecificID; | |
| 127 } else { | |
| 128 printf("%s:%d: could not find subtable.\n", __FILE__, __LINE__); | |
| 129 return NULL; | |
| 130 } | |
| 131 | |
| 132 le_uint16 tableFormat = SWAPW(subtable->format); | |
| 133 //printf("%s:%d: table format %d\n", __FILE__, __LINE__, tableFormat); | |
| 134 | |
| 135 switch (tableFormat) { | |
| 136 case 4: | |
| 137 return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtabl
e); | |
| 138 | |
| 139 case 12: | |
| 140 { | |
| 141 const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) su
btable; | |
| 142 | |
| 143 return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGrou
ps)); | |
| 144 } | |
| 145 | |
| 146 default: | |
| 147 break; | |
| 148 } | |
| 149 | |
| 150 printf("%s:%d: Unknown format %x.\n", __FILE__, __LINE__, (SWAPW(subtable->f
ormat))); | |
| 151 return NULL; | |
| 152 } | |
| 153 | |
| 154 CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Enc
oding *header) | |
| 155 : CMAPMapper(cmap) | |
| 156 { | |
| 157 le_uint16 segCount = SWAPW(header->segCountX2) / 2; | |
| 158 | |
| 159 fEntrySelector = SWAPW(header->entrySelector); | |
| 160 fRangeShift = SWAPW(header->rangeShift) / 2; | |
| 161 fEndCodes = &header->endCodes[0]; | |
| 162 fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad... | |
| 163 fIdDelta = &fStartCodes[segCount]; | |
| 164 fIdRangeOffset = &fIdDelta[segCount]; | |
| 165 } | |
| 166 | |
| 167 LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const | |
| 168 { | |
| 169 if (unicode32 >= 0x10000) { | |
| 170 return 0; | |
| 171 } | |
| 172 | |
| 173 LEUnicode16 unicode = (LEUnicode16) unicode32; | |
| 174 le_uint16 index = 0; | |
| 175 le_uint16 probe = 1 << fEntrySelector; | |
| 176 TTGlyphID result = 0; | |
| 177 | |
| 178 if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) { | |
| 179 index = fRangeShift; | |
| 180 } | |
| 181 | |
| 182 while (probe > (1 << 0)) { | |
| 183 probe >>= 1; | |
| 184 | |
| 185 if (SWAPU16(fStartCodes[index + probe]) <= unicode) { | |
| 186 index += probe; | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[i
ndex])) { | |
| 191 if (fIdRangeOffset[index] == 0) { | |
| 192 result = (TTGlyphID) unicode; | |
| 193 } else { | |
| 194 le_uint16 offset = unicode - SWAPU16(fStartCodes[index]); | |
| 195 le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]); | |
| 196 le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset
[index] + rangeOffset); | |
| 197 | |
| 198 result = SWAPW(glyphIndexTable[offset]); | |
| 199 } | |
| 200 | |
| 201 result += SWAPW(fIdDelta[index]); | |
| 202 } else { | |
| 203 result = 0; | |
| 204 } | |
| 205 | |
| 206 return LE_SET_GLYPH(0, result); | |
| 207 } | |
| 208 | |
| 209 CMAPFormat4Mapper::~CMAPFormat4Mapper() | |
| 210 { | |
| 211 // parent destructor does it all | |
| 212 } | |
| 213 | |
| 214 CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups,
le_uint32 nGroups) | |
| 215 : CMAPMapper(cmap), fGroups(groups) | |
| 216 { | |
| 217 le_uint8 bit = highBit(nGroups); | |
| 218 fPower = 1 << bit; | |
| 219 fRangeOffset = nGroups - fPower; | |
| 220 } | |
| 221 | |
| 222 LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const | |
| 223 { | |
| 224 le_int32 probe = fPower; | |
| 225 le_int32 range = 0; | |
| 226 | |
| 227 if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) { | |
| 228 range = fRangeOffset; | |
| 229 } | |
| 230 | |
| 231 while (probe > (1 << 0)) { | |
| 232 probe >>= 1; | |
| 233 | |
| 234 if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) { | |
| 235 range += probe; | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[ra
nge].endCharCode) >= unicode32) { | |
| 240 return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 -
SWAPU32(fGroups[range].startCharCode)); | |
| 241 } | |
| 242 | |
| 243 return 0; | |
| 244 } | |
| 245 | |
| 246 CMAPGroupMapper::~CMAPGroupMapper() | |
| 247 { | |
| 248 // parent destructor does it all | |
| 249 } | |
| 250 | |
| OLD | NEW |