libdrawtext

view src/utf8.c @ 52:34130f58141a

initial commit
author John Tsiombikas <nuclear@mutantstargoat.com>
date Thu, 15 Sep 2011 10:47:38 +0300
parents
children fe0c54e574ae
line source
1 #include "drawtext.h"
3 #define U8_IS_FIRST(x) (((((x) >> 7) & 1) == 0) || ((((x) >> 6) & 3) == 3))
5 static const char first_mask[] = {
6 0,
7 0x7f, /* single byte, 7 bits valid */
8 0x1f, /* two-bytes, 5 bits valid */
9 0xf, /* three-bytes, 4 bits valid */
10 0x7 /* four-bytes, 3 bits valid */
11 };
12 static const char first_shift[] = { 7, 5, 4, 3 }; /* see above */
14 #define CONT_PREFIX 0x80
15 #define CONT_MASK 0x3f
16 #define CONT_SHIFT 6
18 /* last charcodes for 1, 2, 3 or 4-byte utf8 chars */
19 static const int utf8_lastcode[] = { 0x7f, 0x7ff, 0xfff, 0x1fffff };
21 #define prefix_mask(x) (~first_mask[x])
22 #define prefix(x) ((prefix_mask(x) << 1) & 0xff)
25 char *dtx_utf8_next_char(char *str)
26 {
27 return str + dtx_utf8_nbytes(str);
28 }
30 int dtx_utf8_char_code(const char *str)
31 {
32 int i, nbytes, shift, code = 0;
33 char mask;
35 if(!U8_IS_FIRST(*str)) {
36 return -1;
37 }
39 nbytes = dtx_utf8_nbytes(str);
40 mask = first_mask[nbytes];
41 shift = 0;
43 for(i=0; i<nbytes; i++) {
44 if(!*str) {
45 break;
46 }
48 code = (code << shift) | (*str++ & mask);
49 mask = 0x3f;
50 shift = i == 0 ? first_shift[nbytes] : 6;
51 }
53 return code;
54 }
56 int dtx_utf8_nbytes(const char *str)
57 {
58 int i, numset = 0;
59 int c = *str;
61 if(!U8_IS_FIRST(c)) {
62 for(i=0; !U8_IS_FIRST(str[i]); i++);
63 return i;
64 }
66 /* count the leading 1s */
67 for(i=0; i<4; i++) {
68 if(((c >> (7 - i)) & 1) == 0) {
69 break;
70 }
71 numset++;
72 }
74 if(!numset) {
75 return 1;
76 }
77 return numset;
78 }
80 int dtx_utf8_char_count(const char *str)
81 {
82 int n = 0;
84 while(*str) {
85 n++;
86 str = dtx_utf8_next_char((char*)str);
87 }
88 return n;
89 }
91 size_t dtx_utf8_from_char_code(int code, char *buf)
92 {
93 size_t nbytes = 0;
94 int i;
96 for(i=0; i<4; i++) {
97 if(code <= utf8_lastcode[i]) {
98 nbytes = i + 1;
99 break;
100 }
101 }
103 if(!nbytes && buf) {
104 for(i=0; i<nbytes; i++) {
105 int idx = nbytes - i - 1;
106 int mask, shift, prefix;
108 if(idx > 0) {
109 mask = CONT_MASK;
110 shift = CONT_SHIFT;
111 prefix = CONT_PREFIX;
112 } else {
113 mask = first_mask[nbytes];
114 shift = first_shift[nbytes];
115 prefix = prefix(nbytes);
116 }
118 buf[idx] = (code & mask) | (prefix & ~mask);
119 code >>= shift;
120 }
121 }
122 return nbytes;
123 }
125 size_t dtx_utf8_from_string(const wchar_t *str, char *buf)
126 {
127 size_t nbytes = 0;
128 char *ptr = buf;
130 while(*str) {
131 int cbytes = dtx_utf8_from_char_code(*str++, ptr);
132 if(ptr) {
133 ptr += cbytes;
134 }
135 nbytes += cbytes;
136 }
137 return nbytes;
138 }