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