• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
sk_memset16_portable(uint16_t dst[],uint16_t value,int count)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 
sk_memset32_portable(uint32_t dst[],uint32_t value,int count)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 
sk_memset16_stub(uint16_t dst[],uint16_t value,int count)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 
sk_memset32_stub(uint32_t dst[],uint32_t value,int count)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
assert_utf8_leadingbyte(unsigned c)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 
SkUTF8_LeadByteToCount(unsigned c)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 
SkUTF8_CountUnichars(const char utf8[])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 
SkUTF8_CountUnichars(const char utf8[],size_t byteLength)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 
SkUTF8_ToUnichar(const char utf8[])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 
SkUTF8_NextUnichar(const char ** ptr)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 
SkUTF8_PrevUnichar(const char ** ptr)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 
SkUTF8_FromUnichar(SkUnichar uni,char utf8[])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 
SkUTF16_CountUnichars(const uint16_t src[])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 
SkUTF16_CountUnichars(const uint16_t src[],int numberOf16BitValues)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 
SkUTF16_NextUnichar(const uint16_t ** srcPtr)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 
SkUTF16_PrevUnichar(const uint16_t ** srcPtr)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 
SkUTF16_FromUnichar(SkUnichar uni,uint16_t dst[])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 
SkUTF16_ToUTF8(const uint16_t utf16[],int numberOf16BitValues,char utf8[])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 
399 ///////////////////////////////////////////////////////////////////////////////
400 
401 #include <stdlib.h>
402 
403 #if 0
404 static int round_to_K(size_t bytes) {
405     return (bytes + 512) >> 10;
406 }
407 #endif
408 
SkAutoMemoryUsageProbe(const char label[])409 SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[])
410     : fLabel(label) {
411 #if 0
412     struct mallinfo mi = mallinfo();
413 
414     fBytesAllocated = mi.uordblks;
415 #endif
416 }
417 
~SkAutoMemoryUsageProbe()418 SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe() {
419 #if 0
420     struct mallinfo mi = mallinfo();
421 
422     printf("SkAutoMemoryUsageProbe ");
423     if (fLabel) {
424         printf("<%s> ", fLabel);
425     }
426     printf("delta %dK, current total allocated %dK\n",
427             round_to_K(mi.uordblks - fBytesAllocated),
428             round_to_K(mi.uordblks));
429 #endif
430 }
431 
432