• 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     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 
sk_memset32_portable(uint32_t dst[],uint32_t value,int count)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)
sk_memset16_stub(uint16_t dst[],uint16_t value,int count)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 
sk_memset32_stub(uint32_t dst[],uint32_t value,int count)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
assert_utf8_leadingbyte(unsigned c)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 
SkUTF8_LeadByteToCount(unsigned c)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 
SkUTF8_CountUnichars(const char utf8[])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 
SkUTF8_CountUnichars(const char utf8[],size_t byteLength)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 
SkUTF8_ToUnichar(const char utf8[])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 
SkUTF8_NextUnichar(const char ** ptr)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 
SkUTF8_PrevUnichar(const char ** ptr)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 
SkUTF8_FromUnichar(SkUnichar uni,char utf8[])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 
SkUTF16_CountUnichars(const uint16_t src[])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 
SkUTF16_CountUnichars(const uint16_t src[],int numberOf16BitValues)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 
SkUTF16_NextUnichar(const uint16_t ** srcPtr)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 
SkUTF16_PrevUnichar(const uint16_t ** srcPtr)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 
SkUTF16_FromUnichar(SkUnichar uni,uint16_t dst[])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 
SkUTF16_ToUTF8(const uint16_t utf16[],int numberOf16BitValues,char utf8[])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 
SkAutoMemoryUsageProbe(const char label[])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 
~SkAutoMemoryUsageProbe()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