18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkUtils_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkUtils_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h"
12d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary#include "SkMath.h"
1387db00111596d432908882a13982adde79793a7cMike Klein#include "SkOpts.h"
14bdb34d0345748f424e3c787ad9bbef04134c7e3bmtklein
1557bc1e7bc804be4779dd09409046f62c4d43e3cdMike Klein/** Similar to memset(), but it assigns a 16, 32, or 64-bit value into the buffer.
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    @param buffer   The memory to have value copied into it
1757bc1e7bc804be4779dd09409046f62c4d43e3cdMike Klein    @param value    The value to be copied into buffer
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    @param count    The number of times value should be copied into the buffer.
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2087db00111596d432908882a13982adde79793a7cMike Kleinstatic inline void sk_memset16(uint16_t buffer[], uint16_t value, int count) {
2187db00111596d432908882a13982adde79793a7cMike Klein    SkOpts::memset16(buffer, value, count);
2287db00111596d432908882a13982adde79793a7cMike Klein}
2387db00111596d432908882a13982adde79793a7cMike Kleinstatic inline void sk_memset32(uint32_t buffer[], uint32_t value, int count) {
2487db00111596d432908882a13982adde79793a7cMike Klein    SkOpts::memset32(buffer, value, count);
2587db00111596d432908882a13982adde79793a7cMike Klein}
2687db00111596d432908882a13982adde79793a7cMike Kleinstatic inline void sk_memset64(uint64_t buffer[], uint64_t value, int count) {
2787db00111596d432908882a13982adde79793a7cMike Klein    SkOpts::memset64(buffer, value, count);
2887db00111596d432908882a13982adde79793a7cMike Klein}
294e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kMaxBytesInUTF8Sequence     4
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int SkUTF8_LeadByteToCount(unsigned c);
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkUTF8_LeadByteToCount(c)   ((((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1)
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
394e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orginline int SkUTF8_CountUTF8Bytes(const char utf8[]) {
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(utf8);
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint         SkUTF8_CountUnichars(const char utf8[]);
45d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary
46889d521d8715f4934accb630097bc09bf7ad1a32Mike Reed/** These functions are safe: invalid sequences will return -1; */
47889d521d8715f4934accb630097bc09bf7ad1a32Mike Reedint SkUTF8_CountUnichars(const void* utf8, size_t byteLength);
48889d521d8715f4934accb630097bc09bf7ad1a32Mike Reedint SkUTF16_CountUnichars(const void* utf16, size_t byteLength);
49889d521d8715f4934accb630097bc09bf7ad1a32Mike Reedint SkUTF32_CountUnichars(const void* utf32, size_t byteLength);
50d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary
51d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary/** This function is safe: invalid UTF8 sequences will return -1
52d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary *  When -1 is returned, ptr is unchanged.
53d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary *  Precondition: *ptr < end;
54d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary */
55d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal CanarySkUnichar SkUTF8_NextUnicharWithError(const char** ptr, const char* end);
56d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary
57d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary/** this version replaces invalid utf-8 sequences with code point U+FFFD. */
58d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canaryinline SkUnichar SkUTF8_NextUnichar(const char** ptr, const char* end) {
59d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary    SkUnichar val = SkUTF8_NextUnicharWithError(ptr, end);
60d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary    if (val < 0) {
61d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary        *ptr = end;
62d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary        return 0xFFFD;  // REPLACEMENT CHARACTER
63d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary    }
64d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary    return val;
65d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary}
66d1c8e56423f4d1a879f3a7bcd24e2725d9b690a7Hal Canary
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkUnichar   SkUTF8_ToUnichar(const char utf8[]);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkUnichar   SkUTF8_NextUnichar(const char**);
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkUnichar   SkUTF8_PrevUnichar(const char**);
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Return the number of bytes need to convert a unichar
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    into a utf8 sequence. Will be 1..kMaxBytesInUTF8Sequence,
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    or 0 if uni is illegal.
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
75a93a14a99816d25b773f0b12868143702baf44bfBen Wagnersize_t      SkUTF8_FromUnichar(SkUnichar uni, char utf8[] = nullptr);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkUTF16_IsHighSurrogate(c)  (((c) & 0xFC00) == 0xD800)
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkUTF16_IsLowSurrogate(c)   (((c) & 0xFC00) == 0xDC00)
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkUTF16_CountUnichars(const uint16_t utf16[]);
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// returns the current unichar and then moves past it (*p++)
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkUnichar SkUTF16_NextUnichar(const uint16_t**);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this guy backs up to the previus unichar value, and returns it (*--p)
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkUnichar SkUTF16_PrevUnichar(const uint16_t**);
87a93a14a99816d25b773f0b12868143702baf44bfBen Wagnersize_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t utf16[] = nullptr);
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
90a93a14a99816d25b773f0b12868143702baf44bfBen Wagner                      char utf8[] = nullptr);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
92cf4b8181c9bbeb0273dc7459163552bd42a6518dreed@google.cominline bool SkUnichar_IsVariationSelector(SkUnichar uni) {
93419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com/*  The 'true' ranges are:
94419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com *      0x180B  <= uni <=  0x180D
95419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com *      0xFE00  <= uni <=  0xFE0F
96419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com *      0xE0100 <= uni <= 0xE01EF
97419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com */
98419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com    if (uni < 0x180B || uni > 0xE01EF) {
99419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com        return false;
100419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com    }
101419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com    if ((uni > 0x180D && uni < 0xFE00) || (uni > 0xFE0F && uni < 0xE0100)) {
102419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com        return false;
103419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com    }
104419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com    return true;
105419f43348ab6c9226b82490d41c736230ae3bf41reed@google.com}
106d6e6e6699a85c6ed79e7d3b01e30d19e361ae049Hal Canary
107d6e6e6699a85c6ed79e7d3b01e30d19e361ae049Hal Canarynamespace SkHexadecimalDigits {
108d6e6e6699a85c6ed79e7d3b01e30d19e361ae049Hal Canary    extern const char gUpper[16];  // 0-9A-F
109d6e6e6699a85c6ed79e7d3b01e30d19e361ae049Hal Canary    extern const char gLower[16];  // 0-9a-f
110d6e6e6699a85c6ed79e7d3b01e30d19e361ae049Hal Canary}
111d6e6e6699a85c6ed79e7d3b01e30d19e361ae049Hal Canary
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
113