1
/* libs/graphics/sgl/SkUtils.cpp
3
** Copyright 2006, The Android Open Source Project
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
9
** http://www.apache.org/licenses/LICENSE-2.0
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.
21
#define assign_16_longs(dst, value) \
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; \
33
#define assign_16_longs(dst, value) \
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; \
46
///////////////////////////////////////////////////////////////////////////
48
void sk_memset16_portable(uint16_t dst[], uint16_t value, int count)
50
SkASSERT(dst != NULL && count >= 0);
55
// not sure if this helps to short-circuit on small values of count
59
*dst++ = (uint16_t)value;
60
} while (--count != 0);
64
// ensure we're on a long boundary
67
*dst++ = (uint16_t)value;
71
uint32_t value32 = ((uint32_t)value << 16) | value;
73
// handle the bulk with our unrolled macro
75
int sixteenlongs = count >> 5;
78
uint32_t* dst32 = (uint32_t*)dst;
80
assign_16_longs(dst32, value32);
81
} while (--sixteenlongs != 0);
82
dst = (uint16_t*)dst32;
87
// handle (most) of the rest
89
int longs = count >> 1;
93
*(uint32_t*)dst = value32;
95
} while (--longs != 0);
99
// cleanup a possible trailing short
101
*dst = (uint16_t)value;
104
void sk_memset32_portable(uint32_t dst[], uint32_t value, int count)
106
SkASSERT(dst != NULL && count >= 0);
109
int sixteenlongs = count >> 4;
113
assign_16_longs(dst, value);
114
} while (--sixteenlongs != 0);
123
} while (--count != 0);
127
//////////////////////////////////////////////////////////////////////////////
130
10xxxxxx // never a leading byte
135
11 10 01 01 xx xx xx xx 0...
141
static void assert_utf8_leadingbyte(unsigned c)
143
SkASSERT(c <= 0xF7); // otherwise leading byte is too big (more than 4 bytes)
144
SkASSERT((c & 0xC0) != 0x80); // can't begin with a middle char
147
int SkUTF8_LeadByteToCount(unsigned c)
149
assert_utf8_leadingbyte(c);
150
return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1;
153
#define assert_utf8_leadingbyte(c)
156
int SkUTF8_CountUnichars(const char utf8[])
164
int c = *(const uint8_t*)utf8;
168
utf8 += SkUTF8_LeadByteToCount(c);
174
int SkUTF8_CountUnichars(const char utf8[], size_t byteLength)
176
SkASSERT(NULL != utf8 || 0 == byteLength);
179
const char* stop = utf8 + byteLength;
183
utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
189
SkUnichar SkUTF8_ToUnichar(const char utf8[])
191
SkASSERT(NULL != utf8);
193
const uint8_t* p = (const uint8_t*)utf8;
197
assert_utf8_leadingbyte(c);
201
uint32_t mask = (uint32_t)~0x3F;
204
c = (c << 6) | (*++p & 0x3F);
206
} while ((hic <<= 1) < 0);
212
SkUnichar SkUTF8_NextUnichar(const char** ptr)
214
SkASSERT(NULL != ptr && NULL != *ptr);
216
const uint8_t* p = (const uint8_t*)*ptr;
220
assert_utf8_leadingbyte(c);
224
uint32_t mask = (uint32_t)~0x3F;
227
c = (c << 6) | (*++p & 0x3F);
229
} while ((hic <<= 1) < 0);
236
SkUnichar SkUTF8_PrevUnichar(const char** ptr)
238
SkASSERT(NULL != ptr && NULL != *ptr);
240
const char* p = *ptr;
247
return SkUTF8_NextUnichar(&p);
250
size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[])
252
if ((uint32_t)uni > 0x10FFFF)
254
SkASSERT(!"bad unichar");
269
SkDEBUGCODE(SkUnichar orig = uni;)
271
while (uni > 0x7F >> count)
273
*p++ = (char)(0x80 | (uni & 0x3F));
282
while (p < tmp + count - 1)
284
*--utf8 = (char)(~(0xFF >> count) | uni);
287
SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8));
291
////////////////////////////////////////////////////////////////////////////////////
293
int SkUTF16_CountUnichars(const uint16_t src[])
299
while ((c = *src++) != 0)
301
SkASSERT(!SkUTF16_IsLowSurrogate(c));
302
if (SkUTF16_IsHighSurrogate(c))
305
SkASSERT(SkUTF16_IsLowSurrogate(c));
312
int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues)
316
const uint16_t* stop = src + numberOf16BitValues;
321
SkASSERT(!SkUTF16_IsLowSurrogate(c));
322
if (SkUTF16_IsHighSurrogate(c))
324
SkASSERT(src < stop);
326
SkASSERT(SkUTF16_IsLowSurrogate(c));
333
SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr)
335
SkASSERT(srcPtr && *srcPtr);
337
const uint16_t* src = *srcPtr;
338
SkUnichar c = *src++;
340
SkASSERT(!SkUTF16_IsLowSurrogate(c));
341
if (SkUTF16_IsHighSurrogate(c))
343
unsigned c2 = *src++;
344
SkASSERT(SkUTF16_IsLowSurrogate(c2));
346
// c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000
347
// c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF)
348
c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
354
SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr)
356
SkASSERT(srcPtr && *srcPtr);
358
const uint16_t* src = *srcPtr;
359
SkUnichar c = *--src;
361
SkASSERT(!SkUTF16_IsHighSurrogate(c));
362
if (SkUTF16_IsLowSurrogate(c))
364
unsigned c2 = *--src;
365
SkASSERT(SkUTF16_IsHighSurrogate(c2));
366
c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00);
372
size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[])
374
SkASSERT((unsigned)uni <= 0x10FFFF);
376
int extra = (uni > 0xFFFF);
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));
387
SkASSERT(SkUTF16_IsHighSurrogate(dst[0]));
388
SkASSERT(SkUTF16_IsLowSurrogate(dst[1]));
392
dst[0] = SkToU16(uni);
393
SkASSERT(!SkUTF16_IsHighSurrogate(dst[0]));
394
SkASSERT(!SkUTF16_IsLowSurrogate(dst[0]));
400
size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, char utf8[])
402
SkASSERT(numberOf16BitValues >= 0);
403
if (numberOf16BitValues <= 0)
406
SkASSERT(utf16 != NULL);
408
const uint16_t* stop = utf16 + numberOf16BitValues;
411
if (utf8 == NULL) // just count
414
size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL);
420
utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8);
426
////////////////////////////////////////////////////////////////////////////////////
431
static int round_to_K(size_t bytes)
433
return (bytes + 512) >> 10;
437
SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[])
441
struct mallinfo mi = mallinfo();
443
fBytesAllocated = mi.uordblks;
447
SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe()
450
struct mallinfo mi = mallinfo();
452
printf("SkAutoMemoryUsageProbe ");
454
printf("<%s> ", fLabel);
455
printf("delta %dK, current total allocated %dK\n",
456
round_to_K(mi.uordblks - fBytesAllocated),
457
round_to_K(mi.uordblks));
461
////////////////////////////////////////////////////////////////////////////////////
465
#include "SkRandom.h"
466
#include "SkTSearch.h"
469
#define kSEARCH_COUNT 91
471
#ifdef SK_SUPPORT_UNITTEST
472
static void test_search()
474
int i, array[kSEARCH_COUNT];
477
for (i = 0; i < kSEARCH_COUNT; i++)
478
array[i] = rand.nextS();
480
SkTHeapSort<int>(array, kSEARCH_COUNT);
481
// make sure we got sorted properly
482
for (i = 1; i < kSEARCH_COUNT; i++)
483
SkASSERT(array[i-1] <= array[i]);
485
// make sure we can find all of our values
486
for (i = 0; i < kSEARCH_COUNT; i++)
488
int index = SkTSearch<int>(array, kSEARCH_COUNT, array[i], sizeof(int));
489
SkASSERT(index == i);
492
// make sure that random values are either found, or the correct
493
// insertion index is returned
494
for (i = 0; i < 10000; i++)
496
int value = rand.nextS();
497
int index = SkTSearch<int>(array, kSEARCH_COUNT, value, sizeof(int));
500
SkASSERT(index < kSEARCH_COUNT && array[index] == value);
504
SkASSERT(index <= kSEARCH_COUNT);
505
if (index < kSEARCH_COUNT)
507
SkASSERT(value < array[index]);
509
SkASSERT(value > array[index - 1]);
511
else // we should append the new value
513
SkASSERT(value > array[kSEARCH_COUNT - 1]);
519
static void test_utf16()
521
static const SkUnichar gUni[] = {
522
0x10000, 0x18080, 0x20202, 0xFFFFF, 0x101234
527
for (unsigned i = 0; i < SK_ARRAY_COUNT(gUni); i++)
529
size_t count = SkUTF16_FromUnichar(gUni[i], buf);
530
SkASSERT(count == 2);
531
size_t count2 = SkUTF16_CountUnichars(buf, 2);
532
SkASSERT(count2 == 1);
533
const uint16_t* ptr = buf;
534
SkUnichar c = SkUTF16_NextUnichar(&ptr);
535
SkASSERT(c == gUni[i]);
536
SkASSERT(ptr - buf == 2);
542
void SkUtils::UnitTest()
544
#ifdef SK_SUPPORT_UNITTEST
545
static const struct {
551
{ "\xC2\x80", 0x80 },
552
{ "\xC3\x83", (3 << 6) | 3 },
553
{ "\xDF\xBF", 0x7ff },
554
{ "\xE0\xA0\x80", 0x800 },
555
{ "\xE0\xB0\xB8", 0xC38 },
556
{ "\xE3\x83\x83", (3 << 12) | (3 << 6) | 3 },
557
{ "\xEF\xBF\xBF", 0xFFFF },
558
{ "\xF0\x90\x80\x80", 0x10000 },
559
{ "\xF3\x83\x83\x83", (3 << 18) | (3 << 12) | (3 << 6) | 3 }
562
for (unsigned i = 0; i < SK_ARRAY_COUNT(gTest); i++)
564
const char* p = gTest[i].fUtf8;
565
int n = SkUTF8_CountUnichars(p);
566
SkUnichar u0 = SkUTF8_ToUnichar(gTest[i].fUtf8);
567
SkUnichar u1 = SkUTF8_NextUnichar(&p);
571
SkASSERT(u0 == gTest[i].fUni);
572
SkASSERT(p - gTest[i].fUtf8 == (int)strlen(gTest[i].fUtf8));