Home | History | Annotate | Download | only in core
      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 }
    398