• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
sk_memset16_portable(uint16_t dst[],uint16_t value,int count)48 void sk_memset16_portable(uint16_t dst[], uint16_t value, int count)
49 {
50     SkASSERT(dst != NULL && count >= 0);
51 
52     if (count <= 0)
53         return;
54 
55     // not sure if this helps to short-circuit on small values of count
56     if (count < 8)
57     {
58         do {
59             *dst++ = (uint16_t)value;
60         } while (--count != 0);
61         return;
62     }
63 
64     // ensure we're on a long boundary
65     if ((size_t)dst & 2)
66     {
67         *dst++ = (uint16_t)value;
68         count -= 1;
69     }
70 
71     uint32_t value32 = ((uint32_t)value << 16) | value;
72 
73     // handle the bulk with our unrolled macro
74     {
75         int sixteenlongs = count >> 5;
76         if (sixteenlongs)
77         {
78             uint32_t* dst32 = (uint32_t*)dst;
79             do {
80                 assign_16_longs(dst32, value32);
81             } while (--sixteenlongs != 0);
82             dst = (uint16_t*)dst32;
83             count &= 31;
84         }
85     }
86 
87     // handle (most) of the rest
88     {
89         int longs = count >> 1;
90         if (longs)
91         {
92             do {
93                 *(uint32_t*)dst = value32;
94                 dst += 2;
95             } while (--longs != 0);
96         }
97     }
98 
99     // cleanup a possible trailing short
100     if (count & 1)
101         *dst = (uint16_t)value;
102 }
103 
sk_memset32_portable(uint32_t dst[],uint32_t value,int count)104 void sk_memset32_portable(uint32_t dst[], uint32_t value, int count)
105 {
106     SkASSERT(dst != NULL && count >= 0);
107 
108     {
109         int sixteenlongs = count >> 4;
110         if (sixteenlongs)
111         {
112             do {
113                 assign_16_longs(dst, value);
114             } while (--sixteenlongs != 0);
115             count &= 15;
116         }
117     }
118 
119     if (count)
120     {
121         do {
122             *dst++ = value;
123         } while (--count != 0);
124     }
125 }
126 
127 #ifndef ANDROID
sk_memset16_stub(uint16_t dst[],uint16_t value,int count)128 static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count)
129 {
130     SkMemset16Proc proc = SkMemset16GetPlatformProc();
131     sk_memset16 = proc ? proc : sk_memset16_portable;
132     sk_memset16(dst, value, count);
133 }
134 
135 SkMemset16Proc sk_memset16 = sk_memset16_stub;
136 
sk_memset32_stub(uint32_t dst[],uint32_t value,int count)137 static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count)
138 {
139     SkMemset32Proc proc = SkMemset32GetPlatformProc();
140     sk_memset32 = proc ? proc : sk_memset32_portable;
141     sk_memset32(dst, value, count);
142 }
143 
144 SkMemset32Proc sk_memset32 = sk_memset32_stub;
145 
146 #endif
147 
148 //////////////////////////////////////////////////////////////////////////////
149 
150 /*  0xxxxxxx    1 total
151     10xxxxxx    // never a leading byte
152     110xxxxx    2 total
153     1110xxxx    3 total
154     11110xxx    4 total
155 
156     11 10 01 01 xx xx xx xx 0...
157     0xE5XX0000
158     0xE5 << 24
159 */
160 
161 #ifdef SK_DEBUG
assert_utf8_leadingbyte(unsigned c)162     static void assert_utf8_leadingbyte(unsigned c)
163     {
164         SkASSERT(c <= 0xF7);    // otherwise leading byte is too big (more than 4 bytes)
165         SkASSERT((c & 0xC0) != 0x80);   // can't begin with a middle char
166     }
167 
SkUTF8_LeadByteToCount(unsigned c)168     int SkUTF8_LeadByteToCount(unsigned c)
169     {
170         assert_utf8_leadingbyte(c);
171         return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1;
172     }
173 #else
174     #define assert_utf8_leadingbyte(c)
175 #endif
176 
SkUTF8_CountUnichars(const char utf8[])177 int SkUTF8_CountUnichars(const char utf8[])
178 {
179     SkASSERT(utf8);
180 
181     int count = 0;
182 
183     for (;;)
184     {
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 
SkUTF8_CountUnichars(const char utf8[],size_t byteLength)195 int SkUTF8_CountUnichars(const char utf8[], size_t byteLength)
196 {
197     SkASSERT(NULL != utf8 || 0 == byteLength);
198 
199     int         count = 0;
200     const char* stop = utf8 + byteLength;
201 
202     while (utf8 < stop)
203     {
204         utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
205         count += 1;
206     }
207     return count;
208 }
209 
SkUTF8_ToUnichar(const char utf8[])210 SkUnichar SkUTF8_ToUnichar(const char utf8[])
211 {
212     SkASSERT(NULL != utf8);
213 
214     const uint8_t*  p = (const uint8_t*)utf8;
215     int             c = *p;
216     int             hic = c << 24;
217 
218     assert_utf8_leadingbyte(c);
219 
220     if (hic < 0)
221     {
222         uint32_t mask = (uint32_t)~0x3F;
223         hic <<= 1;
224         do {
225             c = (c << 6) | (*++p & 0x3F);
226             mask <<= 5;
227         } while ((hic <<= 1) < 0);
228         c &= ~mask;
229     }
230     return c;
231 }
232 
SkUTF8_NextUnichar(const char ** ptr)233 SkUnichar SkUTF8_NextUnichar(const char** ptr)
234 {
235     SkASSERT(NULL != ptr && NULL != *ptr);
236 
237     const uint8_t*  p = (const uint8_t*)*ptr;
238     int             c = *p;
239     int             hic = c << 24;
240 
241     assert_utf8_leadingbyte(c);
242 
243     if (hic < 0)
244     {
245         uint32_t mask = (uint32_t)~0x3F;
246         hic <<= 1;
247         do {
248             c = (c << 6) | (*++p & 0x3F);
249             mask <<= 5;
250         } while ((hic <<= 1) < 0);
251         c &= ~mask;
252     }
253     *ptr = (char*)p + 1;
254     return c;
255 }
256 
SkUTF8_PrevUnichar(const char ** ptr)257 SkUnichar SkUTF8_PrevUnichar(const char** ptr)
258 {
259     SkASSERT(NULL != ptr && NULL != *ptr);
260 
261     const char* p = *ptr;
262 
263     if (*--p & 0x80)
264         while (*--p & 0x40)
265             ;
266 
267     *ptr = (char*)p;
268     return SkUTF8_NextUnichar(&p);
269 }
270 
SkUTF8_FromUnichar(SkUnichar uni,char utf8[])271 size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[])
272 {
273     if ((uint32_t)uni > 0x10FFFF)
274     {
275         SkASSERT(!"bad unichar");
276         return 0;
277     }
278 
279     if (uni <= 127)
280     {
281         if (utf8)
282             *utf8 = (char)uni;
283         return 1;
284     }
285 
286     char    tmp[4];
287     char*   p = tmp;
288     size_t  count = 1;
289 
290     SkDEBUGCODE(SkUnichar orig = uni;)
291 
292     while (uni > 0x7F >> count)
293     {
294         *p++ = (char)(0x80 | (uni & 0x3F));
295         uni >>= 6;
296         count += 1;
297     }
298 
299     if (utf8)
300     {
301         p = tmp;
302         utf8 += count;
303         while (p < tmp + count - 1)
304             *--utf8 = *p++;
305         *--utf8 = (char)(~(0xFF >> count) | uni);
306     }
307 
308     SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8));
309     return count;
310 }
311 
312 ////////////////////////////////////////////////////////////////////////////////////
313 
SkUTF16_CountUnichars(const uint16_t src[])314 int SkUTF16_CountUnichars(const uint16_t src[])
315 {
316     SkASSERT(src);
317 
318     int count = 0;
319     unsigned c;
320     while ((c = *src++) != 0)
321     {
322         SkASSERT(!SkUTF16_IsLowSurrogate(c));
323         if (SkUTF16_IsHighSurrogate(c))
324         {
325             c = *src++;
326             SkASSERT(SkUTF16_IsLowSurrogate(c));
327         }
328         count += 1;
329     }
330     return count;
331 }
332 
SkUTF16_CountUnichars(const uint16_t src[],int numberOf16BitValues)333 int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues)
334 {
335     SkASSERT(src);
336 
337     const uint16_t* stop = src + numberOf16BitValues;
338     int count = 0;
339     while (src < stop)
340     {
341         unsigned c = *src++;
342         SkASSERT(!SkUTF16_IsLowSurrogate(c));
343         if (SkUTF16_IsHighSurrogate(c))
344         {
345             SkASSERT(src < stop);
346             c = *src++;
347             SkASSERT(SkUTF16_IsLowSurrogate(c));
348         }
349         count += 1;
350     }
351     return count;
352 }
353 
SkUTF16_NextUnichar(const uint16_t ** srcPtr)354 SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr)
355 {
356     SkASSERT(srcPtr && *srcPtr);
357 
358     const uint16_t* src = *srcPtr;
359     SkUnichar       c = *src++;
360 
361     SkASSERT(!SkUTF16_IsLowSurrogate(c));
362     if (SkUTF16_IsHighSurrogate(c))
363     {
364         unsigned c2 = *src++;
365         SkASSERT(SkUTF16_IsLowSurrogate(c2));
366 
367         // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000
368         // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF)
369         c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
370     }
371     *srcPtr = src;
372     return c;
373 }
374 
SkUTF16_PrevUnichar(const uint16_t ** srcPtr)375 SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr)
376 {
377     SkASSERT(srcPtr && *srcPtr);
378 
379     const uint16_t* src = *srcPtr;
380     SkUnichar       c = *--src;
381 
382     SkASSERT(!SkUTF16_IsHighSurrogate(c));
383     if (SkUTF16_IsLowSurrogate(c))
384     {
385         unsigned c2 = *--src;
386         SkASSERT(SkUTF16_IsHighSurrogate(c2));
387         c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00);
388     }
389     *srcPtr = src;
390     return c;
391 }
392 
SkUTF16_FromUnichar(SkUnichar uni,uint16_t dst[])393 size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[])
394 {
395     SkASSERT((unsigned)uni <= 0x10FFFF);
396 
397     int extra = (uni > 0xFFFF);
398 
399     if (dst)
400     {
401         if (extra)
402         {
403             // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10));
404             // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64));
405             dst[0] = SkToU16((0xD800 - 64) + (uni >> 10));
406             dst[1] = SkToU16(0xDC00 | (uni & 0x3FF));
407 
408             SkASSERT(SkUTF16_IsHighSurrogate(dst[0]));
409             SkASSERT(SkUTF16_IsLowSurrogate(dst[1]));
410         }
411         else
412         {
413             dst[0] = SkToU16(uni);
414             SkASSERT(!SkUTF16_IsHighSurrogate(dst[0]));
415             SkASSERT(!SkUTF16_IsLowSurrogate(dst[0]));
416         }
417     }
418     return 1 + extra;
419 }
420 
SkUTF16_ToUTF8(const uint16_t utf16[],int numberOf16BitValues,char utf8[])421 size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, char utf8[])
422 {
423     SkASSERT(numberOf16BitValues >= 0);
424     if (numberOf16BitValues <= 0)
425         return 0;
426 
427     SkASSERT(utf16 != NULL);
428 
429     const uint16_t* stop = utf16 + numberOf16BitValues;
430     size_t          size = 0;
431 
432     if (utf8 == NULL)    // just count
433     {
434         while (utf16 < stop)
435             size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL);
436     }
437     else
438     {
439         char* start = utf8;
440         while (utf16 < stop)
441             utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8);
442         size = utf8 - start;
443     }
444     return size;
445 }
446 
447 ////////////////////////////////////////////////////////////////////////////////////
448 
449 #include <stdlib.h>
450 
451 #if 0
452 static int round_to_K(size_t bytes)
453 {
454     return (bytes + 512) >> 10;
455 }
456 #endif
457 
SkAutoMemoryUsageProbe(const char label[])458 SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[])
459     : fLabel(label)
460 {
461 #if 0
462     struct mallinfo mi = mallinfo();
463 
464     fBytesAllocated = mi.uordblks;
465 #endif
466 }
467 
~SkAutoMemoryUsageProbe()468 SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe()
469 {
470 #if 0
471     struct mallinfo mi = mallinfo();
472 
473     printf("SkAutoMemoryUsageProbe ");
474     if (fLabel)
475         printf("<%s> ", fLabel);
476     printf("delta %dK, current total allocated %dK\n",
477             round_to_K(mi.uordblks - fBytesAllocated),
478             round_to_K(mi.uordblks));
479 #endif
480 }
481 
482