Upstream version 7.36.149.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 "SkOnce.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 choose_memset16(SkMemset16Proc* proc) {
113     *proc = SkMemset16GetPlatformProc();
114     if (NULL == *proc) {
115         *proc = &sk_memset16_portable;
116     }
117 }
118
119 void sk_memset16(uint16_t dst[], uint16_t value, int count) {
120     SK_DECLARE_STATIC_ONCE(once);
121     static SkMemset16Proc proc = NULL;
122     SkOnce(&once, choose_memset16, &proc);
123     SkASSERT(proc != NULL);
124
125     return proc(dst, value, count);
126 }
127
128 static void choose_memset32(SkMemset32Proc* proc) {
129     *proc = SkMemset32GetPlatformProc();
130     if (NULL == *proc) {
131         *proc = &sk_memset32_portable;
132     }
133 }
134
135 void sk_memset32(uint32_t dst[], uint32_t value, int count) {
136     SK_DECLARE_STATIC_ONCE(once);
137     static SkMemset32Proc proc = NULL;
138     SkOnce(&once, choose_memset32, &proc);
139     SkASSERT(proc != NULL);
140
141     return proc(dst, value, count);
142 }
143
144 ///////////////////////////////////////////////////////////////////////////////
145
146 /*  0xxxxxxx    1 total
147     10xxxxxx    // never a leading byte
148     110xxxxx    2 total
149     1110xxxx    3 total
150     11110xxx    4 total
151
152     11 10 01 01 xx xx xx xx 0...
153     0xE5XX0000
154     0xE5 << 24
155 */
156
157 #ifdef SK_DEBUG
158     static void assert_utf8_leadingbyte(unsigned c) {
159         SkASSERT(c <= 0xF7);    // otherwise leading byte is too big (more than 4 bytes)
160         SkASSERT((c & 0xC0) != 0x80);   // can't begin with a middle char
161     }
162
163     int SkUTF8_LeadByteToCount(unsigned c) {
164         assert_utf8_leadingbyte(c);
165         return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1;
166     }
167 #else
168     #define assert_utf8_leadingbyte(c)
169 #endif
170
171 int SkUTF8_CountUnichars(const char utf8[]) {
172     SkASSERT(utf8);
173
174     int count = 0;
175
176     for (;;) {
177         int c = *(const uint8_t*)utf8;
178         if (c == 0) {
179             break;
180         }
181         utf8 += SkUTF8_LeadByteToCount(c);
182         count += 1;
183     }
184     return count;
185 }
186
187 int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) {
188     SkASSERT(NULL != utf8 || 0 == byteLength);
189
190     int         count = 0;
191     const char* stop = utf8 + byteLength;
192
193     while (utf8 < stop) {
194         utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
195         count += 1;
196     }
197     return count;
198 }
199
200 SkUnichar SkUTF8_ToUnichar(const char utf8[]) {
201     SkASSERT(NULL != utf8);
202
203     const uint8_t*  p = (const uint8_t*)utf8;
204     int             c = *p;
205     int             hic = c << 24;
206
207     assert_utf8_leadingbyte(c);
208
209     if (hic < 0) {
210         uint32_t mask = (uint32_t)~0x3F;
211         hic <<= 1;
212         do {
213             c = (c << 6) | (*++p & 0x3F);
214             mask <<= 5;
215         } while ((hic <<= 1) < 0);
216         c &= ~mask;
217     }
218     return c;
219 }
220
221 SkUnichar SkUTF8_NextUnichar(const char** ptr) {
222     SkASSERT(NULL != ptr && NULL != *ptr);
223
224     const uint8_t*  p = (const uint8_t*)*ptr;
225     int             c = *p;
226     int             hic = c << 24;
227
228     assert_utf8_leadingbyte(c);
229
230     if (hic < 0) {
231         uint32_t mask = (uint32_t)~0x3F;
232         hic <<= 1;
233         do {
234             c = (c << 6) | (*++p & 0x3F);
235             mask <<= 5;
236         } while ((hic <<= 1) < 0);
237         c &= ~mask;
238     }
239     *ptr = (char*)p + 1;
240     return c;
241 }
242
243 SkUnichar SkUTF8_PrevUnichar(const char** ptr) {
244     SkASSERT(NULL != ptr && NULL != *ptr);
245
246     const char* p = *ptr;
247
248     if (*--p & 0x80) {
249         while (*--p & 0x40) {
250             ;
251         }
252     }
253
254     *ptr = (char*)p;
255     return SkUTF8_NextUnichar(&p);
256 }
257
258 size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) {
259     if ((uint32_t)uni > 0x10FFFF) {
260         SkDEBUGFAIL("bad unichar");
261         return 0;
262     }
263
264     if (uni <= 127) {
265         if (utf8) {
266             *utf8 = (char)uni;
267         }
268         return 1;
269     }
270
271     char    tmp[4];
272     char*   p = tmp;
273     size_t  count = 1;
274
275     SkDEBUGCODE(SkUnichar orig = uni;)
276
277     while (uni > 0x7F >> count) {
278         *p++ = (char)(0x80 | (uni & 0x3F));
279         uni >>= 6;
280         count += 1;
281     }
282
283     if (utf8) {
284         p = tmp;
285         utf8 += count;
286         while (p < tmp + count - 1) {
287             *--utf8 = *p++;
288         }
289         *--utf8 = (char)(~(0xFF >> count) | uni);
290     }
291
292     SkASSERT(utf8 == NULL || orig == SkUTF8_ToUnichar(utf8));
293     return count;
294 }
295
296 ///////////////////////////////////////////////////////////////////////////////
297
298 int SkUTF16_CountUnichars(const uint16_t src[]) {
299     SkASSERT(src);
300
301     int count = 0;
302     unsigned c;
303     while ((c = *src++) != 0) {
304         SkASSERT(!SkUTF16_IsLowSurrogate(c));
305         if (SkUTF16_IsHighSurrogate(c)) {
306             c = *src++;
307             SkASSERT(SkUTF16_IsLowSurrogate(c));
308         }
309         count += 1;
310     }
311     return count;
312 }
313
314 int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) {
315     SkASSERT(src);
316
317     const uint16_t* stop = src + numberOf16BitValues;
318     int count = 0;
319     while (src < stop) {
320         unsigned c = *src++;
321         SkASSERT(!SkUTF16_IsLowSurrogate(c));
322         if (SkUTF16_IsHighSurrogate(c)) {
323             SkASSERT(src < stop);
324             c = *src++;
325             SkASSERT(SkUTF16_IsLowSurrogate(c));
326         }
327         count += 1;
328     }
329     return count;
330 }
331
332 SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) {
333     SkASSERT(srcPtr && *srcPtr);
334
335     const uint16_t* src = *srcPtr;
336     SkUnichar       c = *src++;
337
338     SkASSERT(!SkUTF16_IsLowSurrogate(c));
339     if (SkUTF16_IsHighSurrogate(c)) {
340         unsigned c2 = *src++;
341         SkASSERT(SkUTF16_IsLowSurrogate(c2));
342
343         // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000
344         // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF)
345         c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
346     }
347     *srcPtr = src;
348     return c;
349 }
350
351 SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) {
352     SkASSERT(srcPtr && *srcPtr);
353
354     const uint16_t* src = *srcPtr;
355     SkUnichar       c = *--src;
356
357     SkASSERT(!SkUTF16_IsHighSurrogate(c));
358     if (SkUTF16_IsLowSurrogate(c)) {
359         unsigned c2 = *--src;
360         SkASSERT(SkUTF16_IsHighSurrogate(c2));
361         c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00);
362     }
363     *srcPtr = src;
364     return c;
365 }
366
367 size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) {
368     SkASSERT((unsigned)uni <= 0x10FFFF);
369
370     int extra = (uni > 0xFFFF);
371
372     if (dst) {
373         if (extra) {
374             // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10));
375             // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64));
376             dst[0] = SkToU16((0xD800 - 64) + (uni >> 10));
377             dst[1] = SkToU16(0xDC00 | (uni & 0x3FF));
378
379             SkASSERT(SkUTF16_IsHighSurrogate(dst[0]));
380             SkASSERT(SkUTF16_IsLowSurrogate(dst[1]));
381         } else {
382             dst[0] = SkToU16(uni);
383             SkASSERT(!SkUTF16_IsHighSurrogate(dst[0]));
384             SkASSERT(!SkUTF16_IsLowSurrogate(dst[0]));
385         }
386     }
387     return 1 + extra;
388 }
389
390 size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
391                       char utf8[]) {
392     SkASSERT(numberOf16BitValues >= 0);
393     if (numberOf16BitValues <= 0) {
394         return 0;
395     }
396
397     SkASSERT(utf16 != NULL);
398
399     const uint16_t* stop = utf16 + numberOf16BitValues;
400     size_t          size = 0;
401
402     if (utf8 == NULL) {    // just count
403         while (utf16 < stop) {
404             size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL);
405         }
406     } else {
407         char* start = utf8;
408         while (utf16 < stop) {
409             utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8);
410         }
411         size = utf8 - start;
412     }
413     return size;
414 }