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