Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkUtils.cpp
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 #include "SkLazyFnPtr.h"
12
13 #if 0
14 #define assign_16_longs(dst, value)             \
15     do {                                        \
16         (dst)[0] = value;   (dst)[1] = value;   \
17         (dst)[2] = value;   (dst)[3] = value;   \
18         (dst)[4] = value;   (dst)[5] = value;   \
19         (dst)[6] = value;   (dst)[7] = value;   \
20         (dst)[8] = value;   (dst)[9] = value;   \
21         (dst)[10] = value;  (dst)[11] = value;  \
22         (dst)[12] = value;  (dst)[13] = value;  \
23         (dst)[14] = value;  (dst)[15] = value;  \
24     } while (0)
25 #else
26 #define assign_16_longs(dst, value)             \
27     do {                                        \
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         *(dst)++ = value;   *(dst)++ = value;   \
36     } while (0)
37 #endif
38
39 ///////////////////////////////////////////////////////////////////////////////
40
41 static void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) {
42     SkASSERT(dst != NULL && count >= 0);
43
44     if (count <= 0) {
45         return;
46     }
47
48     // not sure if this helps to short-circuit on small values of count
49     if (count < 8) {
50         do {
51             *dst++ = (uint16_t)value;
52         } while (--count != 0);
53         return;
54     }
55
56     // ensure we're on a long boundary
57     if ((size_t)dst & 2) {
58         *dst++ = (uint16_t)value;
59         count -= 1;
60     }
61
62     uint32_t value32 = ((uint32_t)value << 16) | value;
63
64     // handle the bulk with our unrolled macro
65     {
66         int sixteenlongs = count >> 5;
67         if (sixteenlongs) {
68             uint32_t* dst32 = (uint32_t*)dst;
69             do {
70                 assign_16_longs(dst32, value32);
71             } while (--sixteenlongs != 0);
72             dst = (uint16_t*)dst32;
73             count &= 31;
74         }
75     }
76
77     // handle (most) of the rest
78     {
79         int longs = count >> 1;
80         if (longs) {
81             do {
82                 *(uint32_t*)dst = value32;
83                 dst += 2;
84             } while (--longs != 0);
85         }
86     }
87
88     // cleanup a possible trailing short
89     if (count & 1) {
90         *dst = (uint16_t)value;
91     }
92 }
93
94 static void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) {
95     SkASSERT(dst != NULL && count >= 0);
96
97     int sixteenlongs = count >> 4;
98     if (sixteenlongs) {
99         do {
100             assign_16_longs(dst, value);
101         } while (--sixteenlongs != 0);
102         count &= 15;
103     }
104
105     if (count) {
106         do {
107             *dst++ = value;
108         } while (--count != 0);
109     }
110 }
111
112 static void sk_memcpy32_portable(uint32_t dst[], const uint32_t src[], int count) {
113     memcpy(dst, src, count * sizeof(uint32_t));
114 }
115
116 namespace {
117 // These three methods technically need external linkage to be passed as template parameters.
118 // Since they can't be static, we hide them in an anonymous namespace instead.
119
120 SkMemset16Proc choose_memset16() {
121     SkMemset16Proc proc = SkMemset16GetPlatformProc();
122     return proc ? proc : sk_memset16_portable;
123 }
124
125 SkMemset32Proc choose_memset32() {
126     SkMemset32Proc proc = SkMemset32GetPlatformProc();
127     return proc ? proc : sk_memset32_portable;
128 }
129
130 SkMemcpy32Proc choose_memcpy32() {
131     SkMemcpy32Proc proc = SkMemcpy32GetPlatformProc();
132     return proc ? proc : sk_memcpy32_portable;
133 }
134
135 }  // namespace
136
137 void sk_memset16(uint16_t dst[], uint16_t value, int count) {
138     SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset16Proc, proc, choose_memset16);
139     proc.get()(dst, value, count);
140 }
141
142 void sk_memset32(uint32_t dst[], uint32_t value, int count) {
143     SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset32Proc, proc, choose_memset32);
144     proc.get()(dst, value, count);
145 }
146
147 void sk_memcpy32(uint32_t dst[], const uint32_t src[], int count) {
148     SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemcpy32Proc, proc, choose_memcpy32);
149     proc.get()(dst, src, count);
150 }
151
152 ///////////////////////////////////////////////////////////////////////////////
153
154 /*  0xxxxxxx    1 total
155     10xxxxxx    // never a leading byte
156     110xxxxx    2 total
157     1110xxxx    3 total
158     11110xxx    4 total
159
160     11 10 01 01 xx xx xx xx 0...
161     0xE5XX0000
162     0xE5 << 24
163 */
164
165 #ifdef SK_DEBUG
166     static void assert_utf8_leadingbyte(unsigned c) {
167         SkASSERT(c <= 0xF7);    // otherwise leading byte is too big (more than 4 bytes)
168         SkASSERT((c & 0xC0) != 0x80);   // can't begin with a middle char
169     }
170
171     int SkUTF8_LeadByteToCount(unsigned c) {
172         assert_utf8_leadingbyte(c);
173         return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1;
174     }
175 #else
176     #define assert_utf8_leadingbyte(c)
177 #endif
178
179 int SkUTF8_CountUnichars(const char utf8[]) {
180     SkASSERT(utf8);
181
182     int count = 0;
183
184     for (;;) {
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
195 int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) {
196     SkASSERT(utf8 || 0 == byteLength);
197
198     int         count = 0;
199     const char* stop = utf8 + byteLength;
200
201     while (utf8 < stop) {
202         utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
203         count += 1;
204     }
205     return count;
206 }
207
208 SkUnichar SkUTF8_ToUnichar(const char utf8[]) {
209     SkASSERT(utf8);
210
211     const uint8_t*  p = (const uint8_t*)utf8;
212     int             c = *p;
213     int             hic = c << 24;
214
215     assert_utf8_leadingbyte(c);
216
217     if (hic < 0) {
218         uint32_t mask = (uint32_t)~0x3F;
219         hic <<= 1;
220         do {
221             c = (c << 6) | (*++p & 0x3F);
222             mask <<= 5;
223         } while ((hic <<= 1) < 0);
224         c &= ~mask;
225     }
226     return c;
227 }
228
229 SkUnichar SkUTF8_NextUnichar(const char** ptr) {
230     SkASSERT(ptr && *ptr);
231
232     const uint8_t*  p = (const uint8_t*)*ptr;
233     int             c = *p;
234     int             hic = c << 24;
235
236     assert_utf8_leadingbyte(c);
237
238     if (hic < 0) {
239         uint32_t mask = (uint32_t)~0x3F;
240         hic <<= 1;
241         do {
242             c = (c << 6) | (*++p & 0x3F);
243             mask <<= 5;
244         } while ((hic <<= 1) < 0);
245         c &= ~mask;
246     }
247     *ptr = (char*)p + 1;
248     return c;
249 }
250
251 SkUnichar SkUTF8_PrevUnichar(const char** ptr) {
252     SkASSERT(ptr && *ptr);
253
254     const char* p = *ptr;
255
256     if (*--p & 0x80) {
257         while (*--p & 0x40) {
258             ;
259         }
260     }
261
262     *ptr = (char*)p;
263     return SkUTF8_NextUnichar(&p);
264 }
265
266 size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) {
267     if ((uint32_t)uni > 0x10FFFF) {
268         SkDEBUGFAIL("bad unichar");
269         return 0;
270     }
271
272     if (uni <= 127) {
273         if (utf8) {
274             *utf8 = (char)uni;
275         }
276         return 1;
277     }
278
279     char    tmp[4];
280     char*   p = tmp;
281     size_t  count = 1;
282
283     SkDEBUGCODE(SkUnichar orig = uni;)
284
285     while (uni > 0x7F >> count) {
286         *p++ = (char)(0x80 | (uni & 0x3F));
287         uni >>= 6;
288         count += 1;
289     }
290
291     if (utf8) {
292         p = tmp;
293         utf8 += count;
294         while (p < tmp + count - 1) {
295             *--utf8 = *p++;
296         }
297         *--utf8 = (char)(~(0xFF >> count) | uni);
298     }
299
300     SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8));
301     return count;
302 }
303
304 ///////////////////////////////////////////////////////////////////////////////
305
306 int SkUTF16_CountUnichars(const uint16_t src[]) {
307     SkASSERT(src);
308
309     int count = 0;
310     unsigned c;
311     while ((c = *src++) != 0) {
312         SkASSERT(!SkUTF16_IsLowSurrogate(c));
313         if (SkUTF16_IsHighSurrogate(c)) {
314             c = *src++;
315             SkASSERT(SkUTF16_IsLowSurrogate(c));
316         }
317         count += 1;
318     }
319     return count;
320 }
321
322 int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) {
323     SkASSERT(src);
324
325     const uint16_t* stop = src + numberOf16BitValues;
326     int count = 0;
327     while (src < stop) {
328         unsigned c = *src++;
329         SkASSERT(!SkUTF16_IsLowSurrogate(c));
330         if (SkUTF16_IsHighSurrogate(c)) {
331             SkASSERT(src < stop);
332             c = *src++;
333             SkASSERT(SkUTF16_IsLowSurrogate(c));
334         }
335         count += 1;
336     }
337     return count;
338 }
339
340 SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) {
341     SkASSERT(srcPtr && *srcPtr);
342
343     const uint16_t* src = *srcPtr;
344     SkUnichar       c = *src++;
345
346     SkASSERT(!SkUTF16_IsLowSurrogate(c));
347     if (SkUTF16_IsHighSurrogate(c)) {
348         unsigned c2 = *src++;
349         SkASSERT(SkUTF16_IsLowSurrogate(c2));
350
351         // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000
352         // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF)
353         c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
354     }
355     *srcPtr = src;
356     return c;
357 }
358
359 SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) {
360     SkASSERT(srcPtr && *srcPtr);
361
362     const uint16_t* src = *srcPtr;
363     SkUnichar       c = *--src;
364
365     SkASSERT(!SkUTF16_IsHighSurrogate(c));
366     if (SkUTF16_IsLowSurrogate(c)) {
367         unsigned c2 = *--src;
368         SkASSERT(SkUTF16_IsHighSurrogate(c2));
369         c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00);
370     }
371     *srcPtr = src;
372     return c;
373 }
374
375 size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) {
376     SkASSERT((unsigned)uni <= 0x10FFFF);
377
378     int extra = (uni > 0xFFFF);
379
380     if (dst) {
381         if (extra) {
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));
386
387             SkASSERT(SkUTF16_IsHighSurrogate(dst[0]));
388             SkASSERT(SkUTF16_IsLowSurrogate(dst[1]));
389         } else {
390             dst[0] = SkToU16(uni);
391             SkASSERT(!SkUTF16_IsHighSurrogate(dst[0]));
392             SkASSERT(!SkUTF16_IsLowSurrogate(dst[0]));
393         }
394     }
395     return 1 + extra;
396 }
397
398 size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
399                       char utf8[]) {
400     SkASSERT(numberOf16BitValues >= 0);
401     if (numberOf16BitValues <= 0) {
402         return 0;
403     }
404
405     SkASSERT(utf16 != NULL);
406
407     const uint16_t* stop = utf16 + numberOf16BitValues;
408     size_t          size = 0;
409
410     if (utf8 == NULL) {    // just count
411         while (utf16 < stop) {
412             size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL);
413         }
414     } else {
415         char* start = utf8;
416         while (utf16 < stop) {
417             utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8);
418         }
419         size = utf8 - start;
420     }
421     return size;
422 }