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 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 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) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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