1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,397 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkUtils.h" 1.14 + 1.15 +#if 0 1.16 +#define assign_16_longs(dst, value) \ 1.17 + do { \ 1.18 + (dst)[0] = value; (dst)[1] = value; \ 1.19 + (dst)[2] = value; (dst)[3] = value; \ 1.20 + (dst)[4] = value; (dst)[5] = value; \ 1.21 + (dst)[6] = value; (dst)[7] = value; \ 1.22 + (dst)[8] = value; (dst)[9] = value; \ 1.23 + (dst)[10] = value; (dst)[11] = value; \ 1.24 + (dst)[12] = value; (dst)[13] = value; \ 1.25 + (dst)[14] = value; (dst)[15] = value; \ 1.26 + } while (0) 1.27 +#else 1.28 +#define assign_16_longs(dst, value) \ 1.29 + do { \ 1.30 + *(dst)++ = value; *(dst)++ = value; \ 1.31 + *(dst)++ = value; *(dst)++ = value; \ 1.32 + *(dst)++ = value; *(dst)++ = value; \ 1.33 + *(dst)++ = value; *(dst)++ = value; \ 1.34 + *(dst)++ = value; *(dst)++ = value; \ 1.35 + *(dst)++ = value; *(dst)++ = value; \ 1.36 + *(dst)++ = value; *(dst)++ = value; \ 1.37 + *(dst)++ = value; *(dst)++ = value; \ 1.38 + } while (0) 1.39 +#endif 1.40 + 1.41 +/////////////////////////////////////////////////////////////////////////////// 1.42 + 1.43 +void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) { 1.44 + SkASSERT(dst != NULL && count >= 0); 1.45 + 1.46 + if (count <= 0) { 1.47 + return; 1.48 + } 1.49 + 1.50 + // not sure if this helps to short-circuit on small values of count 1.51 + if (count < 8) { 1.52 + do { 1.53 + *dst++ = (uint16_t)value; 1.54 + } while (--count != 0); 1.55 + return; 1.56 + } 1.57 + 1.58 + // ensure we're on a long boundary 1.59 + if ((size_t)dst & 2) { 1.60 + *dst++ = (uint16_t)value; 1.61 + count -= 1; 1.62 + } 1.63 + 1.64 + uint32_t value32 = ((uint32_t)value << 16) | value; 1.65 + 1.66 + // handle the bulk with our unrolled macro 1.67 + { 1.68 + int sixteenlongs = count >> 5; 1.69 + if (sixteenlongs) { 1.70 + uint32_t* dst32 = (uint32_t*)dst; 1.71 + do { 1.72 + assign_16_longs(dst32, value32); 1.73 + } while (--sixteenlongs != 0); 1.74 + dst = (uint16_t*)dst32; 1.75 + count &= 31; 1.76 + } 1.77 + } 1.78 + 1.79 + // handle (most) of the rest 1.80 + { 1.81 + int longs = count >> 1; 1.82 + if (longs) { 1.83 + do { 1.84 + *(uint32_t*)dst = value32; 1.85 + dst += 2; 1.86 + } while (--longs != 0); 1.87 + } 1.88 + } 1.89 + 1.90 + // cleanup a possible trailing short 1.91 + if (count & 1) { 1.92 + *dst = (uint16_t)value; 1.93 + } 1.94 +} 1.95 + 1.96 +void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) { 1.97 + SkASSERT(dst != NULL && count >= 0); 1.98 + 1.99 + int sixteenlongs = count >> 4; 1.100 + if (sixteenlongs) { 1.101 + do { 1.102 + assign_16_longs(dst, value); 1.103 + } while (--sixteenlongs != 0); 1.104 + count &= 15; 1.105 + } 1.106 + 1.107 + if (count) { 1.108 + do { 1.109 + *dst++ = value; 1.110 + } while (--count != 0); 1.111 + } 1.112 +} 1.113 + 1.114 +static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) { 1.115 + SkMemset16Proc proc = SkMemset16GetPlatformProc(); 1.116 + sk_memset16 = proc ? proc : sk_memset16_portable; 1.117 + sk_memset16(dst, value, count); 1.118 +} 1.119 + 1.120 +SkMemset16Proc sk_memset16 = sk_memset16_stub; 1.121 + 1.122 +static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) { 1.123 + SkMemset32Proc proc = SkMemset32GetPlatformProc(); 1.124 + sk_memset32 = proc ? proc : sk_memset32_portable; 1.125 + sk_memset32(dst, value, count); 1.126 +} 1.127 + 1.128 +SkMemset32Proc sk_memset32 = sk_memset32_stub; 1.129 + 1.130 +/////////////////////////////////////////////////////////////////////////////// 1.131 + 1.132 +/* 0xxxxxxx 1 total 1.133 + 10xxxxxx // never a leading byte 1.134 + 110xxxxx 2 total 1.135 + 1110xxxx 3 total 1.136 + 11110xxx 4 total 1.137 + 1.138 + 11 10 01 01 xx xx xx xx 0... 1.139 + 0xE5XX0000 1.140 + 0xE5 << 24 1.141 +*/ 1.142 + 1.143 +#ifdef SK_DEBUG 1.144 + static void assert_utf8_leadingbyte(unsigned c) { 1.145 + SkASSERT(c <= 0xF7); // otherwise leading byte is too big (more than 4 bytes) 1.146 + SkASSERT((c & 0xC0) != 0x80); // can't begin with a middle char 1.147 + } 1.148 + 1.149 + int SkUTF8_LeadByteToCount(unsigned c) { 1.150 + assert_utf8_leadingbyte(c); 1.151 + return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1; 1.152 + } 1.153 +#else 1.154 + #define assert_utf8_leadingbyte(c) 1.155 +#endif 1.156 + 1.157 +int SkUTF8_CountUnichars(const char utf8[]) { 1.158 + SkASSERT(utf8); 1.159 + 1.160 + int count = 0; 1.161 + 1.162 + for (;;) { 1.163 + int c = *(const uint8_t*)utf8; 1.164 + if (c == 0) { 1.165 + break; 1.166 + } 1.167 + utf8 += SkUTF8_LeadByteToCount(c); 1.168 + count += 1; 1.169 + } 1.170 + return count; 1.171 +} 1.172 + 1.173 +int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) { 1.174 + SkASSERT(NULL != utf8 || 0 == byteLength); 1.175 + 1.176 + int count = 0; 1.177 + const char* stop = utf8 + byteLength; 1.178 + 1.179 + while (utf8 < stop) { 1.180 + utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8); 1.181 + count += 1; 1.182 + } 1.183 + return count; 1.184 +} 1.185 + 1.186 +SkUnichar SkUTF8_ToUnichar(const char utf8[]) { 1.187 + SkASSERT(NULL != utf8); 1.188 + 1.189 + const uint8_t* p = (const uint8_t*)utf8; 1.190 + int c = *p; 1.191 + int hic = c << 24; 1.192 + 1.193 + assert_utf8_leadingbyte(c); 1.194 + 1.195 + if (hic < 0) { 1.196 + uint32_t mask = (uint32_t)~0x3F; 1.197 + hic <<= 1; 1.198 + do { 1.199 + c = (c << 6) | (*++p & 0x3F); 1.200 + mask <<= 5; 1.201 + } while ((hic <<= 1) < 0); 1.202 + c &= ~mask; 1.203 + } 1.204 + return c; 1.205 +} 1.206 + 1.207 +SkUnichar SkUTF8_NextUnichar(const char** ptr) { 1.208 + SkASSERT(NULL != ptr && NULL != *ptr); 1.209 + 1.210 + const uint8_t* p = (const uint8_t*)*ptr; 1.211 + int c = *p; 1.212 + int hic = c << 24; 1.213 + 1.214 + assert_utf8_leadingbyte(c); 1.215 + 1.216 + if (hic < 0) { 1.217 + uint32_t mask = (uint32_t)~0x3F; 1.218 + hic <<= 1; 1.219 + do { 1.220 + c = (c << 6) | (*++p & 0x3F); 1.221 + mask <<= 5; 1.222 + } while ((hic <<= 1) < 0); 1.223 + c &= ~mask; 1.224 + } 1.225 + *ptr = (char*)p + 1; 1.226 + return c; 1.227 +} 1.228 + 1.229 +SkUnichar SkUTF8_PrevUnichar(const char** ptr) { 1.230 + SkASSERT(NULL != ptr && NULL != *ptr); 1.231 + 1.232 + const char* p = *ptr; 1.233 + 1.234 + if (*--p & 0x80) { 1.235 + while (*--p & 0x40) { 1.236 + ; 1.237 + } 1.238 + } 1.239 + 1.240 + *ptr = (char*)p; 1.241 + return SkUTF8_NextUnichar(&p); 1.242 +} 1.243 + 1.244 +size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) { 1.245 + if ((uint32_t)uni > 0x10FFFF) { 1.246 + SkDEBUGFAIL("bad unichar"); 1.247 + return 0; 1.248 + } 1.249 + 1.250 + if (uni <= 127) { 1.251 + if (utf8) { 1.252 + *utf8 = (char)uni; 1.253 + } 1.254 + return 1; 1.255 + } 1.256 + 1.257 + char tmp[4]; 1.258 + char* p = tmp; 1.259 + size_t count = 1; 1.260 + 1.261 + SkDEBUGCODE(SkUnichar orig = uni;) 1.262 + 1.263 + while (uni > 0x7F >> count) { 1.264 + *p++ = (char)(0x80 | (uni & 0x3F)); 1.265 + uni >>= 6; 1.266 + count += 1; 1.267 + } 1.268 + 1.269 + if (utf8) { 1.270 + p = tmp; 1.271 + utf8 += count; 1.272 + while (p < tmp + count - 1) { 1.273 + *--utf8 = *p++; 1.274 + } 1.275 + *--utf8 = (char)(~(0xFF >> count) | uni); 1.276 + } 1.277 + 1.278 + SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8)); 1.279 + return count; 1.280 +} 1.281 + 1.282 +/////////////////////////////////////////////////////////////////////////////// 1.283 + 1.284 +int SkUTF16_CountUnichars(const uint16_t src[]) { 1.285 + SkASSERT(src); 1.286 + 1.287 + int count = 0; 1.288 + unsigned c; 1.289 + while ((c = *src++) != 0) { 1.290 + SkASSERT(!SkUTF16_IsLowSurrogate(c)); 1.291 + if (SkUTF16_IsHighSurrogate(c)) { 1.292 + c = *src++; 1.293 + SkASSERT(SkUTF16_IsLowSurrogate(c)); 1.294 + } 1.295 + count += 1; 1.296 + } 1.297 + return count; 1.298 +} 1.299 + 1.300 +int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) { 1.301 + SkASSERT(src); 1.302 + 1.303 + const uint16_t* stop = src + numberOf16BitValues; 1.304 + int count = 0; 1.305 + while (src < stop) { 1.306 + unsigned c = *src++; 1.307 + SkASSERT(!SkUTF16_IsLowSurrogate(c)); 1.308 + if (SkUTF16_IsHighSurrogate(c)) { 1.309 + SkASSERT(src < stop); 1.310 + c = *src++; 1.311 + SkASSERT(SkUTF16_IsLowSurrogate(c)); 1.312 + } 1.313 + count += 1; 1.314 + } 1.315 + return count; 1.316 +} 1.317 + 1.318 +SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { 1.319 + SkASSERT(srcPtr && *srcPtr); 1.320 + 1.321 + const uint16_t* src = *srcPtr; 1.322 + SkUnichar c = *src++; 1.323 + 1.324 + SkASSERT(!SkUTF16_IsLowSurrogate(c)); 1.325 + if (SkUTF16_IsHighSurrogate(c)) { 1.326 + unsigned c2 = *src++; 1.327 + SkASSERT(SkUTF16_IsLowSurrogate(c2)); 1.328 + 1.329 + // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000 1.330 + // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF) 1.331 + c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00); 1.332 + } 1.333 + *srcPtr = src; 1.334 + return c; 1.335 +} 1.336 + 1.337 +SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) { 1.338 + SkASSERT(srcPtr && *srcPtr); 1.339 + 1.340 + const uint16_t* src = *srcPtr; 1.341 + SkUnichar c = *--src; 1.342 + 1.343 + SkASSERT(!SkUTF16_IsHighSurrogate(c)); 1.344 + if (SkUTF16_IsLowSurrogate(c)) { 1.345 + unsigned c2 = *--src; 1.346 + SkASSERT(SkUTF16_IsHighSurrogate(c2)); 1.347 + c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00); 1.348 + } 1.349 + *srcPtr = src; 1.350 + return c; 1.351 +} 1.352 + 1.353 +size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) { 1.354 + SkASSERT((unsigned)uni <= 0x10FFFF); 1.355 + 1.356 + int extra = (uni > 0xFFFF); 1.357 + 1.358 + if (dst) { 1.359 + if (extra) { 1.360 + // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10)); 1.361 + // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64)); 1.362 + dst[0] = SkToU16((0xD800 - 64) + (uni >> 10)); 1.363 + dst[1] = SkToU16(0xDC00 | (uni & 0x3FF)); 1.364 + 1.365 + SkASSERT(SkUTF16_IsHighSurrogate(dst[0])); 1.366 + SkASSERT(SkUTF16_IsLowSurrogate(dst[1])); 1.367 + } else { 1.368 + dst[0] = SkToU16(uni); 1.369 + SkASSERT(!SkUTF16_IsHighSurrogate(dst[0])); 1.370 + SkASSERT(!SkUTF16_IsLowSurrogate(dst[0])); 1.371 + } 1.372 + } 1.373 + return 1 + extra; 1.374 +} 1.375 + 1.376 +size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, 1.377 + char utf8[]) { 1.378 + SkASSERT(numberOf16BitValues >= 0); 1.379 + if (numberOf16BitValues <= 0) { 1.380 + return 0; 1.381 + } 1.382 + 1.383 + SkASSERT(utf16 != NULL); 1.384 + 1.385 + const uint16_t* stop = utf16 + numberOf16BitValues; 1.386 + size_t size = 0; 1.387 + 1.388 + if (utf8 == NULL) { // just count 1.389 + while (utf16 < stop) { 1.390 + size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL); 1.391 + } 1.392 + } else { 1.393 + char* start = utf8; 1.394 + while (utf16 < stop) { 1.395 + utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8); 1.396 + } 1.397 + size = utf8 - start; 1.398 + } 1.399 + return size; 1.400 +}