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 #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