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 |