Home | History | Annotate | Download | only in core
      1 /* libs/graphics/sgl/SkUtils.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkUtils.h"
     19 
     20 #if 0
     21 #define assign_16_longs(dst, value)             \
     22     do {                                        \
     23         (dst)[0] = value;   (dst)[1] = value;   \
     24         (dst)[2] = value;   (dst)[3] = value;   \
     25         (dst)[4] = value;   (dst)[5] = value;   \
     26         (dst)[6] = value;   (dst)[7] = value;   \
     27         (dst)[8] = value;   (dst)[9] = value;   \
     28         (dst)[10] = value;  (dst)[11] = value;  \
     29         (dst)[12] = value;  (dst)[13] = value;  \
     30         (dst)[14] = value;  (dst)[15] = value;  \
     31     } while (0)
     32 #else
     33 #define assign_16_longs(dst, value)             \
     34     do {                                        \
     35         *(dst)++ = value;   *(dst)++ = value;   \
     36         *(dst)++ = value;   *(dst)++ = value;   \
     37         *(dst)++ = value;   *(dst)++ = value;   \
     38         *(dst)++ = value;   *(dst)++ = value;   \
     39         *(dst)++ = value;   *(dst)++ = value;   \
     40         *(dst)++ = value;   *(dst)++ = value;   \
     41         *(dst)++ = value;   *(dst)++ = value;   \
     42         *(dst)++ = value;   *(dst)++ = value;   \
     43     } while (0)
     44 #endif
     45 
     46 ///////////////////////////////////////////////////////////////////////////////
     47 
     48 void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) {
     49     SkASSERT(dst != NULL && count >= 0);
     50 
     51     if (count <= 0) {
     52         return;
     53     }
     54 
     55     // not sure if this helps to short-circuit on small values of count
     56     if (count < 8) {
     57         do {
     58             *dst++ = (uint16_t)value;
     59         } while (--count != 0);
     60         return;
     61     }
     62 
     63     // ensure we're on a long boundary
     64     if ((size_t)dst & 2) {
     65         *dst++ = (uint16_t)value;
     66         count -= 1;
     67     }
     68 
     69     uint32_t value32 = ((uint32_t)value << 16) | value;
     70 
     71     // handle the bulk with our unrolled macro
     72     {
     73         int sixteenlongs = count >> 5;
     74         if (sixteenlongs) {
     75             uint32_t* dst32 = (uint32_t*)dst;
     76             do {
     77                 assign_16_longs(dst32, value32);
     78             } while (--sixteenlongs != 0);
     79             dst = (uint16_t*)dst32;
     80             count &= 31;
     81         }
     82     }
     83 
     84     // handle (most) of the rest
     85     {
     86         int longs = count >> 1;
     87         if (longs) {
     88             do {
     89                 *(uint32_t*)dst = value32;
     90                 dst += 2;
     91             } while (--longs != 0);
     92         }
     93     }
     94 
     95     // cleanup a possible trailing short
     96     if (count & 1) {
     97         *dst = (uint16_t)value;
     98     }
     99 }
    100 
    101 void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) {
    102     SkASSERT(dst != NULL && count >= 0);
    103 
    104     int sixteenlongs = count >> 4;
    105     if (sixteenlongs) {
    106         do {
    107             assign_16_longs(dst, value);
    108         } while (--sixteenlongs != 0);
    109         count &= 15;
    110     }
    111 
    112     if (count) {
    113         do {
    114             *dst++ = value;
    115         } while (--count != 0);
    116     }
    117 }
    118 
    119 #if !defined(ANDROID) || defined(SK_BUILD_FOR_ANDROID_NDK)
    120 static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) {
    121     SkMemset16Proc proc = SkMemset16GetPlatformProc();
    122     sk_memset16 = proc ? proc : sk_memset16_portable;
    123     sk_memset16(dst, value, count);
    124 }
    125 
    126 SkMemset16Proc sk_memset16 = sk_memset16_stub;
    127 
    128 static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) {
    129     SkMemset32Proc proc = SkMemset32GetPlatformProc();
    130     sk_memset32 = proc ? proc : sk_memset32_portable;
    131     sk_memset32(dst, value, count);
    132 }
    133 
    134 SkMemset32Proc sk_memset32 = sk_memset32_stub;
    135 
    136 #endif
    137 
    138 ///////////////////////////////////////////////////////////////////////////////
    139 
    140 /*  0xxxxxxx    1 total
    141     10xxxxxx    // never a leading byte
    142     110xxxxx    2 total
    143     1110xxxx    3 total
    144     11110xxx    4 total
    145 
    146     11 10 01 01 xx xx xx xx 0...
    147     0xE5XX0000
    148     0xE5 << 24
    149 */
    150 
    151 #ifdef SK_DEBUG
    152     static void assert_utf8_leadingbyte(unsigned c) {
    153         SkASSERT(c <= 0xF7);    // otherwise leading byte is too big (more than 4 bytes)
    154         SkASSERT((c & 0xC0) != 0x80);   // can't begin with a middle char
    155     }
    156 
    157     int SkUTF8_LeadByteToCount(unsigned c) {
    158         assert_utf8_leadingbyte(c);
    159         return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1;
    160     }
    161 #else
    162     #define assert_utf8_leadingbyte(c)
    163 #endif
    164 
    165 int SkUTF8_CountUnichars(const char utf8[]) {
    166     SkASSERT(utf8);
    167 
    168     int count = 0;
    169 
    170     for (;;) {
    171         int c = *(const uint8_t*)utf8;
    172         if (c == 0) {
    173             break;
    174         }
    175         utf8 += SkUTF8_LeadByteToCount(c);
    176         count += 1;
    177     }
    178     return count;
    179 }
    180 
    181 int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) {
    182     SkASSERT(NULL != utf8 || 0 == byteLength);
    183 
    184     int         count = 0;
    185     const char* stop = utf8 + byteLength;
    186 
    187     while (utf8 < stop) {
    188         utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
    189         count += 1;
    190     }
    191     return count;
    192 }
    193 
    194 SkUnichar SkUTF8_ToUnichar(const char utf8[]) {
    195     SkASSERT(NULL != utf8);
    196 
    197     const uint8_t*  p = (const uint8_t*)utf8;
    198     int             c = *p;
    199     int             hic = c << 24;
    200 
    201     assert_utf8_leadingbyte(c);
    202 
    203     if (hic < 0) {
    204         uint32_t mask = (uint32_t)~0x3F;
    205         hic <<= 1;
    206         do {
    207             c = (c << 6) | (*++p & 0x3F);
    208             mask <<= 5;
    209         } while ((hic <<= 1) < 0);
    210         c &= ~mask;
    211     }
    212     return c;
    213 }
    214 
    215 SkUnichar SkUTF8_NextUnichar(const char** ptr) {
    216     SkASSERT(NULL != ptr && NULL != *ptr);
    217 
    218     const uint8_t*  p = (const uint8_t*)*ptr;
    219     int             c = *p;
    220     int             hic = c << 24;
    221 
    222     assert_utf8_leadingbyte(c);
    223 
    224     if (hic < 0) {
    225         uint32_t mask = (uint32_t)~0x3F;
    226         hic <<= 1;
    227         do {
    228             c = (c << 6) | (*++p & 0x3F);
    229             mask <<= 5;
    230         } while ((hic <<= 1) < 0);
    231         c &= ~mask;
    232     }
    233     *ptr = (char*)p + 1;
    234     return c;
    235 }
    236 
    237 SkUnichar SkUTF8_PrevUnichar(const char** ptr) {
    238     SkASSERT(NULL != ptr && NULL != *ptr);
    239 
    240     const char* p = *ptr;
    241 
    242     if (*--p & 0x80) {
    243         while (*--p & 0x40) {
    244             ;
    245         }
    246     }
    247 
    248     *ptr = (char*)p;
    249     return SkUTF8_NextUnichar(&p);
    250 }
    251 
    252 size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) {
    253     if ((uint32_t)uni > 0x10FFFF) {
    254         SkASSERT(!"bad unichar");
    255         return 0;
    256     }
    257 
    258     if (uni <= 127) {
    259         if (utf8) {
    260             *utf8 = (char)uni;
    261         }
    262         return 1;
    263     }
    264 
    265     char    tmp[4];
    266     char*   p = tmp;
    267     size_t  count = 1;
    268 
    269     SkDEBUGCODE(SkUnichar orig = uni;)
    270 
    271     while (uni > 0x7F >> count) {
    272         *p++ = (char)(0x80 | (uni & 0x3F));
    273         uni >>= 6;
    274         count += 1;
    275     }
    276 
    277     if (utf8) {
    278         p = tmp;
    279         utf8 += count;
    280         while (p < tmp + count - 1) {
    281             *--utf8 = *p++;
    282         }
    283         *--utf8 = (char)(~(0xFF >> count) | uni);
    284     }
    285 
    286     SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8));
    287     return count;
    288 }
    289 
    290 ///////////////////////////////////////////////////////////////////////////////
    291 
    292 int SkUTF16_CountUnichars(const uint16_t src[]) {
    293     SkASSERT(src);
    294 
    295     int count = 0;
    296     unsigned c;
    297     while ((c = *src++) != 0) {
    298         SkASSERT(!SkUTF16_IsLowSurrogate(c));
    299         if (SkUTF16_IsHighSurrogate(c)) {
    300             c = *src++;
    301             SkASSERT(SkUTF16_IsLowSurrogate(c));
    302         }
    303         count += 1;
    304     }
    305     return count;
    306 }
    307 
    308 int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) {
    309     SkASSERT(src);
    310 
    311     const uint16_t* stop = src + numberOf16BitValues;
    312     int count = 0;
    313     while (src < stop) {
    314         unsigned c = *src++;
    315         SkASSERT(!SkUTF16_IsLowSurrogate(c));
    316         if (SkUTF16_IsHighSurrogate(c)) {
    317             SkASSERT(src < stop);
    318             c = *src++;
    319             SkASSERT(SkUTF16_IsLowSurrogate(c));
    320         }
    321         count += 1;
    322     }
    323     return count;
    324 }
    325 
    326 SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) {
    327     SkASSERT(srcPtr && *srcPtr);
    328 
    329     const uint16_t* src = *srcPtr;
    330     SkUnichar       c = *src++;
    331 
    332     SkASSERT(!SkUTF16_IsLowSurrogate(c));
    333     if (SkUTF16_IsHighSurrogate(c)) {
    334         unsigned c2 = *src++;
    335         SkASSERT(SkUTF16_IsLowSurrogate(c2));
    336 
    337         // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000
    338         // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF)
    339         c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
    340     }
    341     *srcPtr = src;
    342     return c;
    343 }
    344 
    345 SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) {
    346     SkASSERT(srcPtr && *srcPtr);
    347 
    348     const uint16_t* src = *srcPtr;
    349     SkUnichar       c = *--src;
    350 
    351     SkASSERT(!SkUTF16_IsHighSurrogate(c));
    352     if (SkUTF16_IsLowSurrogate(c)) {
    353         unsigned c2 = *--src;
    354         SkASSERT(SkUTF16_IsHighSurrogate(c2));
    355         c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00);
    356     }
    357     *srcPtr = src;
    358     return c;
    359 }
    360 
    361 size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) {
    362     SkASSERT((unsigned)uni <= 0x10FFFF);
    363 
    364     int extra = (uni > 0xFFFF);
    365 
    366     if (dst) {
    367         if (extra) {
    368             // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10));
    369             // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64));
    370             dst[0] = SkToU16((0xD800 - 64) + (uni >> 10));
    371             dst[1] = SkToU16(0xDC00 | (uni & 0x3FF));
    372 
    373             SkASSERT(SkUTF16_IsHighSurrogate(dst[0]));
    374             SkASSERT(SkUTF16_IsLowSurrogate(dst[1]));
    375         } else {
    376             dst[0] = SkToU16(uni);
    377             SkASSERT(!SkUTF16_IsHighSurrogate(dst[0]));
    378             SkASSERT(!SkUTF16_IsLowSurrogate(dst[0]));
    379         }
    380     }
    381     return 1 + extra;
    382 }
    383 
    384 size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
    385                       char utf8[]) {
    386     SkASSERT(numberOf16BitValues >= 0);
    387     if (numberOf16BitValues <= 0) {
    388         return 0;
    389     }
    390 
    391     SkASSERT(utf16 != NULL);
    392 
    393     const uint16_t* stop = utf16 + numberOf16BitValues;
    394     size_t          size = 0;
    395 
    396     if (utf8 == NULL) {    // just count
    397         while (utf16 < stop) {
    398             size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL);
    399         }
    400     } else {
    401         char* start = utf8;
    402         while (utf16 < stop) {
    403             utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8);
    404         }
    405         size = utf8 - start;
    406     }
    407     return size;
    408 }
    409 
    410 ///////////////////////////////////////////////////////////////////////////////
    411 
    412 #include <stdlib.h>
    413 
    414 #if 0
    415 static int round_to_K(size_t bytes) {
    416     return (bytes + 512) >> 10;
    417 }
    418 #endif
    419 
    420 SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[])
    421     : fLabel(label) {
    422 #if 0
    423     struct mallinfo mi = mallinfo();
    424 
    425     fBytesAllocated = mi.uordblks;
    426 #endif
    427 }
    428 
    429 SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe() {
    430 #if 0
    431     struct mallinfo mi = mallinfo();
    432 
    433     printf("SkAutoMemoryUsageProbe ");
    434     if (fLabel) {
    435         printf("<%s> ", fLabel);
    436     }
    437     printf("delta %dK, current total allocated %dK\n",
    438             round_to_K(mi.uordblks - fBytesAllocated),
    439             round_to_K(mi.uordblks));
    440 #endif
    441 }
    442 
    443