Line data Source code
1 : /* 2 : * Copyright © 2000 Keith Packard 3 : * 4 : * Permission to use, copy, modify, distribute, and sell this software and its 5 : * documentation for any purpose is hereby granted without fee, provided that 6 : * the above copyright notice appear in all copies and that both that 7 : * copyright notice and this permission notice appear in supporting 8 : * documentation, and that the name of the author(s) not be used in 9 : * advertising or publicity pertaining to distribution of the software without 10 : * specific, written prior permission. The authors make no 11 : * representations about the suitability of this software for any purpose. It 12 : * is provided "as is" without express or implied warranty. 13 : * 14 : * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 : * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 : * PERFORMANCE OF THIS SOFTWARE. 21 : */ 22 : 23 : // Adapted from FcUcs4ToUtf8 and FcUtf8ToUcs4() from 24 : // https://github.com/freedesktop/fontconfig/blob/master/src/fcstr.c 25 : 26 : namespace 27 : { 28 : 29 23 : inline int FcUtf8ToUcs4(const uint8_t *src_orig, uint32_t *dst, size_t len) 30 : { 31 23 : const uint8_t *src = src_orig; 32 : uint8_t s; 33 : size_t extra; 34 : uint32_t result; 35 : 36 23 : if (len == 0) 37 0 : return 0; 38 : 39 23 : s = *src++; 40 23 : len--; 41 : 42 23 : if (!(s & 0x80)) 43 : { 44 20 : result = s; 45 20 : extra = 0; 46 : } 47 3 : else if (!(s & 0x40)) 48 : { 49 0 : return -1; 50 : } 51 3 : else if (!(s & 0x20)) 52 : { 53 3 : result = s & 0x1f; 54 3 : extra = 1; 55 : } 56 0 : else if (!(s & 0x10)) 57 : { 58 0 : result = s & 0xf; 59 0 : extra = 2; 60 : } 61 0 : else if (!(s & 0x08)) 62 : { 63 0 : result = s & 0x07; 64 0 : extra = 3; 65 : } 66 0 : else if (!(s & 0x04)) 67 : { 68 0 : result = s & 0x03; 69 0 : extra = 4; 70 : } 71 0 : else if (!(s & 0x02)) 72 : { 73 0 : result = s & 0x01; 74 0 : extra = 5; 75 : } 76 : else 77 : { 78 0 : return -1; 79 : } 80 23 : if (extra > len) 81 0 : return -1; 82 : 83 26 : while (extra) 84 : { 85 3 : --extra; 86 3 : result <<= 6; 87 3 : s = *src++; 88 : 89 3 : if ((s & 0xc0) != 0x80) 90 0 : return -1; 91 : 92 3 : result |= s & 0x3f; 93 : } 94 23 : *dst = result; 95 23 : return static_cast<int>(src - src_orig); 96 : } 97 : 98 24 : inline int FcUcs4ToUtf8(uint32_t ucs4, uint8_t *dest) 99 : { 100 : int bits; 101 24 : uint8_t *d = dest; 102 : 103 24 : if (ucs4 < 0x80) 104 : { 105 19 : *d++ = static_cast<uint8_t>(ucs4); 106 19 : bits = -6; 107 : } 108 5 : else if (ucs4 < 0x800) 109 : { 110 5 : *d++ = static_cast<uint8_t>(((ucs4 >> 6) & 0x1F) | 0xC0); 111 5 : bits = 0; 112 : } 113 0 : else if (ucs4 < 0x10000) 114 : { 115 0 : *d++ = static_cast<uint8_t>(((ucs4 >> 12) & 0x0F) | 0xE0); 116 0 : bits = 6; 117 : } 118 0 : else if (ucs4 < 0x200000) 119 : { 120 0 : *d++ = static_cast<uint8_t>(((ucs4 >> 18) & 0x07) | 0xF0); 121 0 : bits = 12; 122 : } 123 0 : else if (ucs4 < 0x4000000) 124 : { 125 0 : *d++ = static_cast<uint8_t>(((ucs4 >> 24) & 0x03) | 0xF8); 126 0 : bits = 18; 127 : } 128 0 : else if (ucs4 < 0x80000000) 129 : { 130 0 : *d++ = static_cast<uint8_t>(((ucs4 >> 30) & 0x01) | 0xFC); 131 0 : bits = 24; 132 : } 133 : else 134 0 : return 0; 135 : 136 29 : for (; bits >= 0; bits -= 6) 137 : { 138 5 : *d++ = static_cast<uint8_t>(((ucs4 >> bits) & 0x3F) | 0x80); 139 : } 140 24 : return static_cast<int>(d - dest); 141 : } 142 : 143 : } // namespace