]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
57a6839d | 3 | * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved |
b75a7d8f A |
4 | * |
5 | */ | |
6 | ||
7 | #include "LETypes.h" | |
8 | #include "OpenTypeTables.h" | |
9 | #include "OpenTypeUtilities.h" | |
10 | #include "LESwaps.h" | |
11 | ||
12 | U_NAMESPACE_BEGIN | |
13 | ||
14 | // | |
15 | // Finds the high bit by binary searching | |
16 | // through the bits in n. | |
17 | // | |
18 | le_int8 OpenTypeUtilities::highBit(le_int32 value) | |
19 | { | |
20 | if (value <= 0) { | |
21 | return -32; | |
22 | } | |
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 | ||
b75a7d8f | 54 | |
57a6839d A |
55 | Offset OpenTypeUtilities::getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success) |
56 | { | |
57 | const TagAndOffsetRecord *r0 = (const TagAndOffsetRecord*)records.getAlias(); | |
58 | if(LE_FAILURE(success)) return 0; | |
59 | ||
60 | le_uint32 recordCount = records.getCount(); | |
61 | le_uint8 bit = highBit(recordCount); | |
62 | le_int32 power = 1 << bit; | |
63 | le_int32 extra = recordCount - power; | |
64 | le_int32 probe = power; | |
65 | le_int32 index = 0; | |
66 | ||
67 | { | |
68 | const ATag &aTag = (r0+extra)->tag; | |
69 | if (SWAPT(aTag) <= tag) { | |
70 | index = extra; | |
71 | } | |
72 | } | |
73 | ||
74 | while (probe > (1 << 0)) { | |
75 | probe >>= 1; | |
76 | ||
77 | { | |
78 | const ATag &aTag = (r0+index+probe)->tag; | |
79 | if (SWAPT(aTag) <= tag) { | |
80 | index += probe; | |
81 | } | |
82 | } | |
83 | } | |
84 | ||
85 | { | |
86 | const ATag &aTag = (r0+index)->tag; | |
87 | if (SWAPT(aTag) == tag) { | |
88 | return SWAPW((r0+index)->offset); | |
89 | } | |
90 | } | |
91 | ||
92 | return 0; | |
b75a7d8f A |
93 | } |
94 | ||
57a6839d | 95 | le_int32 OpenTypeUtilities::getGlyphRangeIndex(TTGlyphID glyphID, const LEReferenceToArrayOf<GlyphRangeRecord> &records, LEErrorCode &success) |
b75a7d8f | 96 | { |
57a6839d A |
97 | if(LE_FAILURE(success)) return -1; |
98 | ||
99 | le_uint32 recordCount = records.getCount(); | |
b75a7d8f A |
100 | le_uint8 bit = highBit(recordCount); |
101 | le_int32 power = 1 << bit; | |
102 | le_int32 extra = recordCount - power; | |
103 | le_int32 probe = power; | |
104 | le_int32 range = 0; | |
105 | ||
57a6839d A |
106 | if (recordCount == 0) { |
107 | return -1; | |
108 | } | |
46f4442e | 109 | |
57a6839d | 110 | if (SWAPW(records(extra,success).firstGlyph) <= glyphID) { |
b75a7d8f A |
111 | range = extra; |
112 | } | |
113 | ||
57a6839d | 114 | while (probe > (1 << 0) && LE_SUCCESS(success)) { |
b75a7d8f A |
115 | probe >>= 1; |
116 | ||
57a6839d | 117 | if (SWAPW(records(range + probe,success).firstGlyph) <= glyphID) { |
b75a7d8f A |
118 | range += probe; |
119 | } | |
120 | } | |
121 | ||
57a6839d | 122 | if (SWAPW(records(range,success).firstGlyph) <= glyphID && SWAPW(records(range,success).lastGlyph) >= glyphID) { |
b75a7d8f A |
123 | return range; |
124 | } | |
125 | ||
126 | return -1; | |
127 | } | |
128 | ||
129 | le_int32 OpenTypeUtilities::search(le_uint32 value, const le_uint32 array[], le_int32 count) | |
130 | { | |
131 | le_int32 power = 1 << highBit(count); | |
132 | le_int32 extra = count - power; | |
133 | le_int32 probe = power; | |
134 | le_int32 index = 0; | |
135 | ||
136 | if (value >= array[extra]) { | |
137 | index = extra; | |
138 | } | |
139 | ||
140 | while (probe > (1 << 0)) { | |
141 | probe >>= 1; | |
142 | ||
143 | if (value >= array[index + probe]) { | |
144 | index += probe; | |
145 | } | |
146 | } | |
147 | ||
148 | return index; | |
149 | } | |
150 | ||
151 | le_int32 OpenTypeUtilities::search(le_uint16 value, const le_uint16 array[], le_int32 count) | |
152 | { | |
153 | le_int32 power = 1 << highBit(count); | |
154 | le_int32 extra = count - power; | |
155 | le_int32 probe = power; | |
156 | le_int32 index = 0; | |
157 | ||
158 | if (value >= array[extra]) { | |
159 | index = extra; | |
160 | } | |
161 | ||
162 | while (probe > (1 << 0)) { | |
163 | probe >>= 1; | |
164 | ||
165 | if (value >= array[index + probe]) { | |
166 | index += probe; | |
167 | } | |
168 | } | |
169 | ||
170 | return index; | |
171 | } | |
172 | ||
173 | // | |
174 | // Straight insertion sort from Knuth vol. III, pg. 81 | |
175 | // | |
176 | void OpenTypeUtilities::sort(le_uint16 *array, le_int32 count) | |
177 | { | |
178 | for (le_int32 j = 1; j < count; j += 1) { | |
179 | le_int32 i; | |
180 | le_uint16 v = array[j]; | |
181 | ||
182 | for (i = j - 1; i >= 0; i -= 1) { | |
183 | if (v >= array[i]) { | |
184 | break; | |
185 | } | |
186 | ||
187 | array[i + 1] = array[i]; | |
188 | } | |
189 | ||
190 | array[i + 1] = v; | |
191 | } | |
192 | } | |
193 | ||
b75a7d8f | 194 | U_NAMESPACE_END |
57a6839d A |
195 | |
196 | #if LE_ASSERT_BAD_FONT | |
197 | #include <stdio.h> | |
198 | ||
199 | static const char *letagToStr(LETag tag, char *str) { | |
200 | str[0]= 0xFF & (tag>>24); | |
201 | str[1]= 0xFF & (tag>>16); | |
202 | str[2]= 0xFF & (tag>>8); | |
203 | str[3]= 0xFF & (tag>>0); | |
204 | str[4]= 0; | |
205 | return str; | |
206 | } | |
207 | ||
208 | U_CAPI void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len) { | |
209 | char tagbuf[5]; | |
210 | ||
211 | fprintf(stderr, "%s:%d: LETableReference@0x%p: ", f, l, what); | |
212 | fprintf(stderr, msg, ptr, len); | |
213 | fprintf(stderr, "\n"); | |
214 | ||
215 | for(int depth=0;depth<10&&(what!=NULL);depth++) { | |
216 | for(int i=0;i<depth;i++) { | |
217 | fprintf(stderr, " "); // indent | |
218 | } | |
219 | if(!what->isValid()) { | |
220 | fprintf(stderr, "(invalid)"); | |
221 | } | |
222 | fprintf(stderr, "@%p: tag (%s) font (0x%p), [0x%p+0x%lx]\n", what, letagToStr(what->getTag(), tagbuf), what->getFont(), | |
223 | what->getAlias(), what->getLength()); | |
224 | ||
225 | what = what->getParent(); | |
226 | } | |
227 | } | |
228 | #endif |