| /* |
| * Copyright 2022 Rive |
| */ |
| |
| #include "utils/rive_utf.hpp" |
| #include "rive/core/type_conversions.hpp" |
| |
| using namespace rive; |
| |
| int UTF::CountUTF8Length(const uint8_t utf8[]) { |
| unsigned lead = *utf8; |
| assert(lead != 0xFF); |
| assert((lead & 0xC0) != 0x80); // 10xxxxxx is not a legal lead byte |
| if ((lead & 0x80) == 0) { |
| return 1; |
| } |
| int n = 1; |
| lead <<= 1; |
| while (lead & 0x80) { |
| n += 1; |
| lead <<= 1; |
| } |
| assert(n >= 1 && n <= 4); |
| return n; |
| } |
| |
| // Return the unichar pointed to by the utf8 pointer, and then |
| // update the pointer to point to the next sequence. |
| Unichar UTF::NextUTF8(const uint8_t** utf8Ptr) { |
| const uint8_t* text = *utf8Ptr; |
| |
| uint32_t c = 0; |
| int n = CountUTF8Length(text); |
| assert(n >= 1 && n <= 4); |
| |
| unsigned first = *text++; |
| if (n == 1) { |
| c = first; |
| } else { |
| c = first & ((unsigned)0xFF >> n); |
| --n; |
| do { |
| c = (c << 6) | (*text++ & 0x3F); |
| } while (--n); |
| } |
| *utf8Ptr = text; // update the pointer |
| return c; |
| } |
| |
| int UTF::ToUTF16(Unichar uni, uint16_t utf16[]) { |
| if (uni > 0xFFFF) { |
| utf16[0] = castTo<uint16_t>((0xD800 - 64) | (uni >> 10)); |
| utf16[1] = castTo<uint16_t>(0xDC00 | (uni & 0x3FF)); |
| return 2; |
| } |
| utf16[0] = castTo<uint16_t>(uni); |
| return 1; |
| } |