|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #include "SkUtils.h" |
|
11 |
|
12 #if 0 |
|
13 #define assign_16_longs(dst, value) \ |
|
14 do { \ |
|
15 (dst)[0] = value; (dst)[1] = value; \ |
|
16 (dst)[2] = value; (dst)[3] = value; \ |
|
17 (dst)[4] = value; (dst)[5] = value; \ |
|
18 (dst)[6] = value; (dst)[7] = value; \ |
|
19 (dst)[8] = value; (dst)[9] = value; \ |
|
20 (dst)[10] = value; (dst)[11] = value; \ |
|
21 (dst)[12] = value; (dst)[13] = value; \ |
|
22 (dst)[14] = value; (dst)[15] = value; \ |
|
23 } while (0) |
|
24 #else |
|
25 #define assign_16_longs(dst, value) \ |
|
26 do { \ |
|
27 *(dst)++ = value; *(dst)++ = value; \ |
|
28 *(dst)++ = value; *(dst)++ = value; \ |
|
29 *(dst)++ = value; *(dst)++ = value; \ |
|
30 *(dst)++ = value; *(dst)++ = value; \ |
|
31 *(dst)++ = value; *(dst)++ = value; \ |
|
32 *(dst)++ = value; *(dst)++ = value; \ |
|
33 *(dst)++ = value; *(dst)++ = value; \ |
|
34 *(dst)++ = value; *(dst)++ = value; \ |
|
35 } while (0) |
|
36 #endif |
|
37 |
|
38 /////////////////////////////////////////////////////////////////////////////// |
|
39 |
|
40 void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) { |
|
41 SkASSERT(dst != NULL && count >= 0); |
|
42 |
|
43 if (count <= 0) { |
|
44 return; |
|
45 } |
|
46 |
|
47 // not sure if this helps to short-circuit on small values of count |
|
48 if (count < 8) { |
|
49 do { |
|
50 *dst++ = (uint16_t)value; |
|
51 } while (--count != 0); |
|
52 return; |
|
53 } |
|
54 |
|
55 // ensure we're on a long boundary |
|
56 if ((size_t)dst & 2) { |
|
57 *dst++ = (uint16_t)value; |
|
58 count -= 1; |
|
59 } |
|
60 |
|
61 uint32_t value32 = ((uint32_t)value << 16) | value; |
|
62 |
|
63 // handle the bulk with our unrolled macro |
|
64 { |
|
65 int sixteenlongs = count >> 5; |
|
66 if (sixteenlongs) { |
|
67 uint32_t* dst32 = (uint32_t*)dst; |
|
68 do { |
|
69 assign_16_longs(dst32, value32); |
|
70 } while (--sixteenlongs != 0); |
|
71 dst = (uint16_t*)dst32; |
|
72 count &= 31; |
|
73 } |
|
74 } |
|
75 |
|
76 // handle (most) of the rest |
|
77 { |
|
78 int longs = count >> 1; |
|
79 if (longs) { |
|
80 do { |
|
81 *(uint32_t*)dst = value32; |
|
82 dst += 2; |
|
83 } while (--longs != 0); |
|
84 } |
|
85 } |
|
86 |
|
87 // cleanup a possible trailing short |
|
88 if (count & 1) { |
|
89 *dst = (uint16_t)value; |
|
90 } |
|
91 } |
|
92 |
|
93 void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) { |
|
94 SkASSERT(dst != NULL && count >= 0); |
|
95 |
|
96 int sixteenlongs = count >> 4; |
|
97 if (sixteenlongs) { |
|
98 do { |
|
99 assign_16_longs(dst, value); |
|
100 } while (--sixteenlongs != 0); |
|
101 count &= 15; |
|
102 } |
|
103 |
|
104 if (count) { |
|
105 do { |
|
106 *dst++ = value; |
|
107 } while (--count != 0); |
|
108 } |
|
109 } |
|
110 |
|
111 static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) { |
|
112 SkMemset16Proc proc = SkMemset16GetPlatformProc(); |
|
113 sk_memset16 = proc ? proc : sk_memset16_portable; |
|
114 sk_memset16(dst, value, count); |
|
115 } |
|
116 |
|
117 SkMemset16Proc sk_memset16 = sk_memset16_stub; |
|
118 |
|
119 static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) { |
|
120 SkMemset32Proc proc = SkMemset32GetPlatformProc(); |
|
121 sk_memset32 = proc ? proc : sk_memset32_portable; |
|
122 sk_memset32(dst, value, count); |
|
123 } |
|
124 |
|
125 SkMemset32Proc sk_memset32 = sk_memset32_stub; |
|
126 |
|
127 /////////////////////////////////////////////////////////////////////////////// |
|
128 |
|
129 /* 0xxxxxxx 1 total |
|
130 10xxxxxx // never a leading byte |
|
131 110xxxxx 2 total |
|
132 1110xxxx 3 total |
|
133 11110xxx 4 total |
|
134 |
|
135 11 10 01 01 xx xx xx xx 0... |
|
136 0xE5XX0000 |
|
137 0xE5 << 24 |
|
138 */ |
|
139 |
|
140 #ifdef SK_DEBUG |
|
141 static void assert_utf8_leadingbyte(unsigned c) { |
|
142 SkASSERT(c <= 0xF7); // otherwise leading byte is too big (more than 4 bytes) |
|
143 SkASSERT((c & 0xC0) != 0x80); // can't begin with a middle char |
|
144 } |
|
145 |
|
146 int SkUTF8_LeadByteToCount(unsigned c) { |
|
147 assert_utf8_leadingbyte(c); |
|
148 return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1; |
|
149 } |
|
150 #else |
|
151 #define assert_utf8_leadingbyte(c) |
|
152 #endif |
|
153 |
|
154 int SkUTF8_CountUnichars(const char utf8[]) { |
|
155 SkASSERT(utf8); |
|
156 |
|
157 int count = 0; |
|
158 |
|
159 for (;;) { |
|
160 int c = *(const uint8_t*)utf8; |
|
161 if (c == 0) { |
|
162 break; |
|
163 } |
|
164 utf8 += SkUTF8_LeadByteToCount(c); |
|
165 count += 1; |
|
166 } |
|
167 return count; |
|
168 } |
|
169 |
|
170 int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) { |
|
171 SkASSERT(NULL != utf8 || 0 == byteLength); |
|
172 |
|
173 int count = 0; |
|
174 const char* stop = utf8 + byteLength; |
|
175 |
|
176 while (utf8 < stop) { |
|
177 utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8); |
|
178 count += 1; |
|
179 } |
|
180 return count; |
|
181 } |
|
182 |
|
183 SkUnichar SkUTF8_ToUnichar(const char utf8[]) { |
|
184 SkASSERT(NULL != utf8); |
|
185 |
|
186 const uint8_t* p = (const uint8_t*)utf8; |
|
187 int c = *p; |
|
188 int hic = c << 24; |
|
189 |
|
190 assert_utf8_leadingbyte(c); |
|
191 |
|
192 if (hic < 0) { |
|
193 uint32_t mask = (uint32_t)~0x3F; |
|
194 hic <<= 1; |
|
195 do { |
|
196 c = (c << 6) | (*++p & 0x3F); |
|
197 mask <<= 5; |
|
198 } while ((hic <<= 1) < 0); |
|
199 c &= ~mask; |
|
200 } |
|
201 return c; |
|
202 } |
|
203 |
|
204 SkUnichar SkUTF8_NextUnichar(const char** ptr) { |
|
205 SkASSERT(NULL != ptr && NULL != *ptr); |
|
206 |
|
207 const uint8_t* p = (const uint8_t*)*ptr; |
|
208 int c = *p; |
|
209 int hic = c << 24; |
|
210 |
|
211 assert_utf8_leadingbyte(c); |
|
212 |
|
213 if (hic < 0) { |
|
214 uint32_t mask = (uint32_t)~0x3F; |
|
215 hic <<= 1; |
|
216 do { |
|
217 c = (c << 6) | (*++p & 0x3F); |
|
218 mask <<= 5; |
|
219 } while ((hic <<= 1) < 0); |
|
220 c &= ~mask; |
|
221 } |
|
222 *ptr = (char*)p + 1; |
|
223 return c; |
|
224 } |
|
225 |
|
226 SkUnichar SkUTF8_PrevUnichar(const char** ptr) { |
|
227 SkASSERT(NULL != ptr && NULL != *ptr); |
|
228 |
|
229 const char* p = *ptr; |
|
230 |
|
231 if (*--p & 0x80) { |
|
232 while (*--p & 0x40) { |
|
233 ; |
|
234 } |
|
235 } |
|
236 |
|
237 *ptr = (char*)p; |
|
238 return SkUTF8_NextUnichar(&p); |
|
239 } |
|
240 |
|
241 size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) { |
|
242 if ((uint32_t)uni > 0x10FFFF) { |
|
243 SkDEBUGFAIL("bad unichar"); |
|
244 return 0; |
|
245 } |
|
246 |
|
247 if (uni <= 127) { |
|
248 if (utf8) { |
|
249 *utf8 = (char)uni; |
|
250 } |
|
251 return 1; |
|
252 } |
|
253 |
|
254 char tmp[4]; |
|
255 char* p = tmp; |
|
256 size_t count = 1; |
|
257 |
|
258 SkDEBUGCODE(SkUnichar orig = uni;) |
|
259 |
|
260 while (uni > 0x7F >> count) { |
|
261 *p++ = (char)(0x80 | (uni & 0x3F)); |
|
262 uni >>= 6; |
|
263 count += 1; |
|
264 } |
|
265 |
|
266 if (utf8) { |
|
267 p = tmp; |
|
268 utf8 += count; |
|
269 while (p < tmp + count - 1) { |
|
270 *--utf8 = *p++; |
|
271 } |
|
272 *--utf8 = (char)(~(0xFF >> count) | uni); |
|
273 } |
|
274 |
|
275 SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8)); |
|
276 return count; |
|
277 } |
|
278 |
|
279 /////////////////////////////////////////////////////////////////////////////// |
|
280 |
|
281 int SkUTF16_CountUnichars(const uint16_t src[]) { |
|
282 SkASSERT(src); |
|
283 |
|
284 int count = 0; |
|
285 unsigned c; |
|
286 while ((c = *src++) != 0) { |
|
287 SkASSERT(!SkUTF16_IsLowSurrogate(c)); |
|
288 if (SkUTF16_IsHighSurrogate(c)) { |
|
289 c = *src++; |
|
290 SkASSERT(SkUTF16_IsLowSurrogate(c)); |
|
291 } |
|
292 count += 1; |
|
293 } |
|
294 return count; |
|
295 } |
|
296 |
|
297 int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) { |
|
298 SkASSERT(src); |
|
299 |
|
300 const uint16_t* stop = src + numberOf16BitValues; |
|
301 int count = 0; |
|
302 while (src < stop) { |
|
303 unsigned c = *src++; |
|
304 SkASSERT(!SkUTF16_IsLowSurrogate(c)); |
|
305 if (SkUTF16_IsHighSurrogate(c)) { |
|
306 SkASSERT(src < stop); |
|
307 c = *src++; |
|
308 SkASSERT(SkUTF16_IsLowSurrogate(c)); |
|
309 } |
|
310 count += 1; |
|
311 } |
|
312 return count; |
|
313 } |
|
314 |
|
315 SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { |
|
316 SkASSERT(srcPtr && *srcPtr); |
|
317 |
|
318 const uint16_t* src = *srcPtr; |
|
319 SkUnichar c = *src++; |
|
320 |
|
321 SkASSERT(!SkUTF16_IsLowSurrogate(c)); |
|
322 if (SkUTF16_IsHighSurrogate(c)) { |
|
323 unsigned c2 = *src++; |
|
324 SkASSERT(SkUTF16_IsLowSurrogate(c2)); |
|
325 |
|
326 // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000 |
|
327 // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF) |
|
328 c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00); |
|
329 } |
|
330 *srcPtr = src; |
|
331 return c; |
|
332 } |
|
333 |
|
334 SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) { |
|
335 SkASSERT(srcPtr && *srcPtr); |
|
336 |
|
337 const uint16_t* src = *srcPtr; |
|
338 SkUnichar c = *--src; |
|
339 |
|
340 SkASSERT(!SkUTF16_IsHighSurrogate(c)); |
|
341 if (SkUTF16_IsLowSurrogate(c)) { |
|
342 unsigned c2 = *--src; |
|
343 SkASSERT(SkUTF16_IsHighSurrogate(c2)); |
|
344 c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00); |
|
345 } |
|
346 *srcPtr = src; |
|
347 return c; |
|
348 } |
|
349 |
|
350 size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) { |
|
351 SkASSERT((unsigned)uni <= 0x10FFFF); |
|
352 |
|
353 int extra = (uni > 0xFFFF); |
|
354 |
|
355 if (dst) { |
|
356 if (extra) { |
|
357 // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10)); |
|
358 // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64)); |
|
359 dst[0] = SkToU16((0xD800 - 64) + (uni >> 10)); |
|
360 dst[1] = SkToU16(0xDC00 | (uni & 0x3FF)); |
|
361 |
|
362 SkASSERT(SkUTF16_IsHighSurrogate(dst[0])); |
|
363 SkASSERT(SkUTF16_IsLowSurrogate(dst[1])); |
|
364 } else { |
|
365 dst[0] = SkToU16(uni); |
|
366 SkASSERT(!SkUTF16_IsHighSurrogate(dst[0])); |
|
367 SkASSERT(!SkUTF16_IsLowSurrogate(dst[0])); |
|
368 } |
|
369 } |
|
370 return 1 + extra; |
|
371 } |
|
372 |
|
373 size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, |
|
374 char utf8[]) { |
|
375 SkASSERT(numberOf16BitValues >= 0); |
|
376 if (numberOf16BitValues <= 0) { |
|
377 return 0; |
|
378 } |
|
379 |
|
380 SkASSERT(utf16 != NULL); |
|
381 |
|
382 const uint16_t* stop = utf16 + numberOf16BitValues; |
|
383 size_t size = 0; |
|
384 |
|
385 if (utf8 == NULL) { // just count |
|
386 while (utf16 < stop) { |
|
387 size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL); |
|
388 } |
|
389 } else { |
|
390 char* start = utf8; |
|
391 while (utf16 < stop) { |
|
392 utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8); |
|
393 } |
|
394 size = utf8 - start; |
|
395 } |
|
396 return size; |
|
397 } |