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