1b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 2b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar/* 3b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar * Copyright 2006 The Android Open Source Project 4b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar * 5b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar * Use of this source code is governed by a BSD-style license that can be 6b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar * found in the LICENSE file. 7b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar */ 8b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 9b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 10b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar#include "SkUtils.h" 1156ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar 1256ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar#if 0 13389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#define assign_16_longs(dst, value) \ 1456ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar do { \ 1556ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[0] = value; (dst)[1] = value; \ 1656ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[2] = value; (dst)[3] = value; \ 1756ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[4] = value; (dst)[5] = value; \ 1856ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[6] = value; (dst)[7] = value; \ 1956ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[8] = value; (dst)[9] = value; \ 2056ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[10] = value; (dst)[11] = value; \ 2156ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar (dst)[12] = value; (dst)[13] = value; \ 226ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl (dst)[14] = value; (dst)[15] = value; \ 2356ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar } while (0) 2456ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar#else 25b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar#define assign_16_longs(dst, value) \ 2656ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar do { \ 272dc14532b641bae011a374e2c6c393d2196c1411Duncan Sands *(dst)++ = value; *(dst)++ = value; \ 28b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *(dst)++ = value; *(dst)++ = value; \ 2903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer *(dst)++ = value; *(dst)++ = value; \ 3003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer *(dst)++ = value; *(dst)++ = value; \ 31b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *(dst)++ = value; *(dst)++ = value; \ 32b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *(dst)++ = value; *(dst)++ = value; \ 33b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *(dst)++ = value; *(dst)++ = value; \ 34b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *(dst)++ = value; *(dst)++ = value; \ 35b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } while (0) 369f61aa9e280adea9fbf3365f0e4f6ed568c9885aJeffrey Yasskin#endif 37b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 38b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar/////////////////////////////////////////////////////////////////////////////// 39b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 40b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbarvoid sk_memset16_portable(uint16_t dst[], uint16_t value, int count) { 41b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(dst != NULL && count >= 0); 42b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 43b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (count <= 0) { 44b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar return; 45b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 469f61aa9e280adea9fbf3365f0e4f6ed568c9885aJeffrey Yasskin 47b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar // not sure if this helps to short-circuit on small values of count 48b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (count < 8) { 49b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar do { 50b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *dst++ = (uint16_t)value; 51b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } while (--count != 0); 52b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar return; 53b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 54b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 55b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar // ensure we're on a long boundary 569f61aa9e280adea9fbf3365f0e4f6ed568c9885aJeffrey Yasskin if ((size_t)dst & 2) { 57b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *dst++ = (uint16_t)value; 58b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar count -= 1; 59b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 60b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 61b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar uint32_t value32 = ((uint32_t)value << 16) | value; 62b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 63d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks // handle the bulk with our unrolled macro 64d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks { 65d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks int sixteenlongs = count >> 5; 66d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks if (sixteenlongs) { 67d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks uint32_t* dst32 = (uint32_t*)dst; 68d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks do { 69d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks assign_16_longs(dst32, value32); 70d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks } while (--sixteenlongs != 0); 71d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks dst = (uint16_t*)dst32; 72d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks count &= 31; 7356ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar } 7456ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar } 7556ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar 7656ac85c4fd18ee4af27c81b0ce11b2191461a0a5Daniel Dunbar // handle (most) of the rest 77b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar { 78b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar int longs = count >> 1; 79116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis if (longs) { 80116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis do { 81a4c7a4314ffbe402091695874e93d9b0a79c8099Ted Kremenek *(uint32_t*)dst = value32; 82b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar dst += 2; 83b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } while (--longs != 0); 84b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 85b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 86b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 87b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar // cleanup a possible trailing short 88b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (count & 1) { 89b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *dst = (uint16_t)value; 90b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 91b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 92b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 93d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaksvoid sk_memset32_portable(uint32_t dst[], uint32_t value, int count) { 94d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks SkASSERT(dst != NULL && count >= 0); 95d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks 96d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks int sixteenlongs = count >> 4; 97b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (sixteenlongs) { 98b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar do { 99b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar assign_16_longs(dst, value); 100b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } while (--sixteenlongs != 0); 101b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar count &= 15; 102b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 103b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 104b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (count) { 105fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek do { 106fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek *dst++ = value; 107b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } while (--count != 0); 108b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 109b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 110b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 111b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbarstatic void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) { 112b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkMemset16Proc proc = SkMemset16GetPlatformProc(); 1131040c227efc6821cd39795206c178894470a1a48Sandeep Patel sk_memset16 = proc ? proc : sk_memset16_portable; 114b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar sk_memset16(dst, value, count); 11543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis} 11643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 11743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios KyrtzidisSkMemset16Proc sk_memset16 = sk_memset16_stub; 11843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 11943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisstatic void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) { 12043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis SkMemset32Proc proc = SkMemset32GetPlatformProc(); 12143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis sk_memset32 = proc ? proc : sk_memset32_portable; 12243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis sk_memset32(dst, value, count); 12343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis} 124b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 125b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel DunbarSkMemset32Proc sk_memset32 = sk_memset32_stub; 126b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 127b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar/////////////////////////////////////////////////////////////////////////////// 128b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 129b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar/* 0xxxxxxx 1 total 130b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 10xxxxxx // never a leading byte 131b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 110xxxxx 2 total 132b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 1110xxxx 3 total 133b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 11110xxx 4 total 1347c4fd9121f5885096fd3258d20a984e3f08f8603Nick Lewycky 1357c4fd9121f5885096fd3258d20a984e3f08f8603Nick Lewycky 11 10 01 01 xx xx xx xx 0... 1367c4fd9121f5885096fd3258d20a984e3f08f8603Nick Lewycky 0xE5XX0000 1377c4fd9121f5885096fd3258d20a984e3f08f8603Nick Lewycky 0xE5 << 24 138f2d8b9f967a1ab53ee9fdbcc3ac0a4ee0a83a26eDaniel Dunbar*/ 139f2d8b9f967a1ab53ee9fdbcc3ac0a4ee0a83a26eDaniel Dunbar 140f2d8b9f967a1ab53ee9fdbcc3ac0a4ee0a83a26eDaniel Dunbar#ifdef SK_DEBUG 141f2d8b9f967a1ab53ee9fdbcc3ac0a4ee0a83a26eDaniel Dunbar static void assert_utf8_leadingbyte(unsigned c) { 1429f084a3166b684573ba49df28fc5792bc37d92e1John McCall SkASSERT(c <= 0xF7); // otherwise leading byte is too big (more than 4 bytes) 1439f084a3166b684573ba49df28fc5792bc37d92e1John McCall SkASSERT((c & 0xC0) != 0x80); // can't begin with a middle char 144256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall } 145256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall 146e8ba8d78a258ec992d3521eebdae8324db777b14Nick Lewycky int SkUTF8_LeadByteToCount(unsigned c) { 147e8ba8d78a258ec992d3521eebdae8324db777b14Nick Lewycky assert_utf8_leadingbyte(c); 148e8ba8d78a258ec992d3521eebdae8324db777b14Nick Lewycky return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1; 149e8ba8d78a258ec992d3521eebdae8324db777b14Nick Lewycky } 150b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar#else 151b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar #define assert_utf8_leadingbyte(c) 15250a4487683a7e09fb93e8b506181e034241a0ffeDaniel Dunbar#endif 15350a4487683a7e09fb93e8b506181e034241a0ffeDaniel Dunbar 15432096695c76033a6b0b1747c439f7378a11e8312John McCallint SkUTF8_CountUnichars(const char utf8[]) { 15532096695c76033a6b0b1747c439f7378a11e8312John McCall SkASSERT(utf8); 156e26bdb91b7e3912ffe895b78a446db94471a59ddDaniel Dunbar 157e26bdb91b7e3912ffe895b78a446db94471a59ddDaniel Dunbar int count = 0; 158b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 159b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar for (;;) { 1601ad6648cce57bd187f1853f58fef26cd9bf4934fDaniel Dunbar int c = *(const uint8_t*)utf8; 1611ad6648cce57bd187f1853f58fef26cd9bf4934fDaniel Dunbar if (c == 0) { 162b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar break; 163b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 164a0fa203f04235cb6d05eeb8cea3392a01aa7571bBob Wilson utf8 += SkUTF8_LeadByteToCount(c); 1651be3b3bd5c983e3fc5b78db155632d2d2d6aa968Daniel Dunbar count += 1; 1661be3b3bd5c983e3fc5b78db155632d2d2d6aa968Daniel Dunbar } 1677d065d0f21b35f445cee13730398bc2bec6edff2Daniel Dunbar return count; 1687d065d0f21b35f445cee13730398bc2bec6edff2Daniel Dunbar} 1697d065d0f21b35f445cee13730398bc2bec6edff2Daniel Dunbar 1707d065d0f21b35f445cee13730398bc2bec6edff2Daniel Dunbarint SkUTF8_CountUnichars(const char utf8[], size_t byteLength) { 171b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(NULL != utf8 || 0 == byteLength); 172b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 173b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar int count = 0; 174b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar const char* stop = utf8 + byteLength; 17520249a1af2e462dcafdd6a350f1c7967b264ff25Michael J. Spencer 176f84d409903dd4107c8cef5a08fcfce6e5c21d4deEric Christopher while (utf8 < stop) { 177f84d409903dd4107c8cef5a08fcfce6e5c21d4deEric Christopher utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8); 178f84d409903dd4107c8cef5a08fcfce6e5c21d4deEric Christopher count += 1; 179f84d409903dd4107c8cef5a08fcfce6e5c21d4deEric Christopher } 180bbea7168326d810eff18dfb8bc43c7790fd55010Chris Lattner return count; 181bbea7168326d810eff18dfb8bc43c7790fd55010Chris Lattner} 182bbea7168326d810eff18dfb8bc43c7790fd55010Chris Lattner 183bbea7168326d810eff18dfb8bc43c7790fd55010Chris LattnerSkUnichar SkUTF8_ToUnichar(const char utf8[]) { 184f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar SkASSERT(NULL != utf8); 185f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar 186f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar const uint8_t* p = (const uint8_t*)utf8; 187f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar int c = *p; 188f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar int hic = c << 24; 189f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar 190d51e43af0b3a6897b971f316c4de2035ec82d1f2Peter Collingbourne assert_utf8_leadingbyte(c); 191d51e43af0b3a6897b971f316c4de2035ec82d1f2Peter Collingbourne 192efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar if (hic < 0) { 193efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar uint32_t mask = (uint32_t)~0x3F; 194efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar hic <<= 1; 195efb0fa9e11f75af51744a6159530ef7cc8efa24aDaniel Dunbar do { 196f85e193739c953358c865005855253af4f68a497John McCall c = (c << 6) | (*++p & 0x3F); 197f85e193739c953358c865005855253af4f68a497John McCall mask <<= 5; 198f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar } while ((hic <<= 1) < 0); 199f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar c &= ~mask; 200f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar } 201f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar return c; 202f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar} 203f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar 2043b315264d1a6fa303e20fe0caec306ccafc090deDaniel DunbarSkUnichar SkUTF8_NextUnichar(const char** ptr) { 2053b315264d1a6fa303e20fe0caec306ccafc090deDaniel Dunbar SkASSERT(NULL != ptr && NULL != *ptr); 2063b315264d1a6fa303e20fe0caec306ccafc090deDaniel Dunbar 2073b315264d1a6fa303e20fe0caec306ccafc090deDaniel Dunbar const uint8_t* p = (const uint8_t*)*ptr; 208f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar int c = *p; 209f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar int hic = c << 24; 210f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar 211f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar assert_utf8_leadingbyte(c); 212f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar 213f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar if (hic < 0) { 214f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar uint32_t mask = (uint32_t)~0x3F; 215f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar hic <<= 1; 216f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar do { 217f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar c = (c << 6) | (*++p & 0x3F); 218f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar mask <<= 5; 219f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar } while ((hic <<= 1) < 0); 220f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar c &= ~mask; 221f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar } 222f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar *ptr = (char*)p + 1; 223f643b9b338b797a824447207d7eab5f1187f4f34Daniel Dunbar return c; 22417d3fea677753e6e3e82ffe2cbdeccbf5f2e7497Daniel Dunbar} 22517d3fea677753e6e3e82ffe2cbdeccbf5f2e7497Daniel Dunbar 22617d3fea677753e6e3e82ffe2cbdeccbf5f2e7497Daniel DunbarSkUnichar SkUTF8_PrevUnichar(const char** ptr) { 22717d3fea677753e6e3e82ffe2cbdeccbf5f2e7497Daniel Dunbar SkASSERT(NULL != ptr && NULL != *ptr); 2281b9060553221720152e12981109549e0a1d8e3a1Chad Rosier 2291b9060553221720152e12981109549e0a1d8e3a1Chad Rosier const char* p = *ptr; 230c3b9014c7236a15cf467662264b243a22c420312Nick Lewycky 231c3b9014c7236a15cf467662264b243a22c420312Nick Lewycky if (*--p & 0x80) { 2324ecc9b73b3716775ed4e09091e300796a9a72378Daniel Dunbar while (*--p & 0x40) { 2334ecc9b73b3716775ed4e09091e300796a9a72378Daniel Dunbar ; 234969323239f16589329d091a2b8ef200fcfe7c9e9Daniel Dunbar } 235969323239f16589329d091a2b8ef200fcfe7c9e9Daniel Dunbar } 236f24a151d645abc89f94aa58ad59f3131502041b1Rafael Espindola 237f24a151d645abc89f94aa58ad59f3131502041b1Rafael Espindola *ptr = (char*)p; 238ea523d73a6de06f828952a02f5ff86e4cc631695Nick Lewycky return SkUTF8_NextUnichar(&p); 239ea523d73a6de06f828952a02f5ff86e4cc631695Nick Lewycky} 2403b315264d1a6fa303e20fe0caec306ccafc090deDaniel Dunbar 2413b315264d1a6fa303e20fe0caec306ccafc090deDaniel Dunbarsize_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) { 242f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar if ((uint32_t)uni > 0x10FFFF) { 243f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar SkDEBUGFAIL("bad unichar"); 244f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar return 0; 245f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar } 246f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar 247f219e7c1529fac29e34483667f740b452e5ef9ccDaniel Dunbar if (uni <= 127) { 248b689afb75049012a431d483432114ad5e75d4a92John McCall if (utf8) { 249b689afb75049012a431d483432114ad5e75d4a92John McCall *utf8 = (char)uni; 2503c66d30d513106bb794990c5e4ba36a31ac19f15Daniel Dunbar } 2513c66d30d513106bb794990c5e4ba36a31ac19f15Daniel Dunbar return 1; 2523c66d30d513106bb794990c5e4ba36a31ac19f15Daniel Dunbar } 2533c66d30d513106bb794990c5e4ba36a31ac19f15Daniel Dunbar 254b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar char tmp[4]; 255b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar char* p = tmp; 256b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar size_t count = 1; 257b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 258b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkDEBUGCODE(SkUnichar orig = uni;) 259b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 260eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar while (uni > 0x7F >> count) { 261eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar *p++ = (char)(0x80 | (uni & 0x3F)); 262b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar uni >>= 6; 263b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar count += 1; 264b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar } 265b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar 266b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (utf8) { 267b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar p = tmp; 268b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar utf8 += count; 269b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar while (p < tmp + count - 1) { 270b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *--utf8 = *p++; 271b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 272b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *--utf8 = (char)(~(0xFF >> count) | uni); 273b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 274b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 275b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8)); 276b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar return count; 277b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 278b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 279b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar/////////////////////////////////////////////////////////////////////////////// 280b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 281b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbarint SkUTF16_CountUnichars(const uint16_t src[]) { 282b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(src); 283b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 284b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar int count = 0; 285b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar unsigned c; 286b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar while ((c = *src++) != 0) { 287b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(!SkUTF16_IsLowSurrogate(c)); 288b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (SkUTF16_IsHighSurrogate(c)) { 289b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar c = *src++; 290b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(SkUTF16_IsLowSurrogate(c)); 291b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 292b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar count += 1; 293b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 294b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar return count; 295b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 296b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 297b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbarint SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) { 2984786c15f4977c7cee98fde3ebdee213dba23848bDouglas Gregor SkASSERT(src); 2994786c15f4977c7cee98fde3ebdee213dba23848bDouglas Gregor 300b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar const uint16_t* stop = src + numberOf16BitValues; 301b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar int count = 0; 302b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar while (src < stop) { 303b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar unsigned c = *src++; 3047d2b8c1fcc2b707be78b09930a7767477822462fDouglas Gregor SkASSERT(!SkUTF16_IsLowSurrogate(c)); 3057d2b8c1fcc2b707be78b09930a7767477822462fDouglas Gregor if (SkUTF16_IsHighSurrogate(c)) { 306b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(src < stop); 307b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar c = *src++; 3086fbe8398ba1680ffc5daa7395850ff8765b7905bChris Lattner SkASSERT(SkUTF16_IsLowSurrogate(c)); 3096fbe8398ba1680ffc5daa7395850ff8765b7905bChris Lattner } 3106fbe8398ba1680ffc5daa7395850ff8765b7905bChris Lattner count += 1; 3116fbe8398ba1680ffc5daa7395850ff8765b7905bChris Lattner } 312c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor return count; 313c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor} 314c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor 315c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas GregorSkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { 316c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor SkASSERT(srcPtr && *srcPtr); 317c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor 318c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor const uint16_t* src = *srcPtr; 319c9471b0ff1815ed0149dbfcad0f385ed8648eeb0Douglas Gregor SkUnichar c = *src++; 320c100214fdc41a7ea215f75d433eb1cb829fd4330Chris Lattner 321c100214fdc41a7ea215f75d433eb1cb829fd4330Chris Lattner SkASSERT(!SkUTF16_IsLowSurrogate(c)); 322c100214fdc41a7ea215f75d433eb1cb829fd4330Chris Lattner if (SkUTF16_IsHighSurrogate(c)) { 323c100214fdc41a7ea215f75d433eb1cb829fd4330Chris Lattner unsigned c2 = *src++; 32408c6695f6018fb6cb1a7c7d311a851aa5c233bc0Daniel Dunbar SkASSERT(SkUTF16_IsLowSurrogate(c2)); 32508c6695f6018fb6cb1a7c7d311a851aa5c233bc0Daniel Dunbar 32608c6695f6018fb6cb1a7c7d311a851aa5c233bc0Daniel Dunbar // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000 32708c6695f6018fb6cb1a7c7d311a851aa5c233bc0Daniel Dunbar // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF) 3286c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas Gregor c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00); 3296c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas Gregor } 3306c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas Gregor *srcPtr = src; 3316c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas Gregor return c; 3326c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas Gregor} 3336c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas Gregor 3346c1cb9916e9988dcdd65b9266dbe24afd173427aDouglas GregorSkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) { 335575cf3791216c33770ba950430493cdd43099f8fDouglas Gregor SkASSERT(srcPtr && *srcPtr); 336575cf3791216c33770ba950430493cdd43099f8fDouglas Gregor 337575cf3791216c33770ba950430493cdd43099f8fDouglas Gregor const uint16_t* src = *srcPtr; 338575cf3791216c33770ba950430493cdd43099f8fDouglas Gregor SkUnichar c = *--src; 33952388f9aefba585475a38081272ce582d033c883Chris Lattner 340124fca533d9fef2e3f6359283909bd342b5f5f26Chris Lattner SkASSERT(!SkUTF16_IsHighSurrogate(c)); 341124fca533d9fef2e3f6359283909bd342b5f5f26Chris Lattner if (SkUTF16_IsLowSurrogate(c)) { 342124fca533d9fef2e3f6359283909bd342b5f5f26Chris Lattner unsigned c2 = *--src; 343b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(SkUTF16_IsHighSurrogate(c2)); 344b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00); 345b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 346b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar *srcPtr = src; 347b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar return c; 348b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 349b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 350b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbarsize_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) { 351b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT((unsigned)uni <= 0x10FFFF); 352b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 353b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar int extra = (uni > 0xFFFF); 354b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 355c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar if (dst) { 356b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (extra) { 357c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10)); 358c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64)); 359c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar dst[0] = SkToU16((0xD800 - 64) + (uni >> 10)); 360c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar dst[1] = SkToU16(0xDC00 | (uni & 0x3FF)); 361c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar 362faddc3e53a95c68f2c3a966e0f1e6eba110dafd6Daniel Dunbar SkASSERT(SkUTF16_IsHighSurrogate(dst[0])); 363c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar SkASSERT(SkUTF16_IsLowSurrogate(dst[1])); 364c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar } else { 365c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar dst[0] = SkToU16(uni); 366895fcca55a6d52a71639f2472a6623ab2dd9f628Peter Collingbourne SkASSERT(!SkUTF16_IsHighSurrogate(dst[0])); 367c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar SkASSERT(!SkUTF16_IsLowSurrogate(dst[0])); 368c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar } 369c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar } 370c34ce3fa613d5e4a283e53615fceafd17390445bDaniel Dunbar return 1 + extra; 371b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 372b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 3739f61aa9e280adea9fbf3365f0e4f6ed568c9885aJeffrey Yasskinsize_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, 374b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar char utf8[]) { 375b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar SkASSERT(numberOf16BitValues >= 0); 376b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (numberOf16BitValues <= 0) { 377b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar return 0; 378b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 379b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 3809f61aa9e280adea9fbf3365f0e4f6ed568c9885aJeffrey Yasskin SkASSERT(utf16 != NULL); 381b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 382b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar const uint16_t* stop = utf16 + numberOf16BitValues; 383f35142413974e9dfe2c5f202084db4bd1c2073e9John McCall size_t size = 0; 384b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar 385b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar if (utf8 == NULL) { // just count 386b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar while (utf16 < stop) { 387b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL); 388b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 389b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } else { 390b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar char* start = utf8; 391b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar while (utf16 < stop) { 392b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8); 39332148cef25570a4fbe3ad0ec497ce3ae2cf1b774Daniel Dunbar } 394da1573f95902a42aa4d11e8f45ab98ec7e27bc28Daniel Dunbar size = utf8 - start; 395b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar } 396467dc88512b4ba4bb16e274ea3771dc1415d31daDouglas Gregor return size; 397b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar} 398b3375cba7938e01895bb504e7e48ad94a2e07dd1Daniel Dunbar