libdrawtext

view src/utf8.c @ 4:17fed026b24b

done with the unicode sample
author John Tsiombikas <nuclear@mutantstargoat.com>
date Fri, 16 Sep 2011 08:31:06 +0300
parents fe0c54e574ae
children 095ff7ca4e74
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[] = { 0, 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 int 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 = 6;
51 }
52 return code;
53 }
55 int dtx_utf8_nbytes(const char *str)
56 {
57 int i, numset = 0;
58 int c = *str;
60 if(!U8_IS_FIRST(c)) {
61 for(i=0; !U8_IS_FIRST(str[i]); i++);
62 return i;
63 }
65 /* count the leading 1s */
66 for(i=0; i<4; i++) {
67 if(((c >> (7 - i)) & 1) == 0) {
68 break;
69 }
70 numset++;
71 }
73 if(!numset) {
74 return 1;
75 }
76 return numset;
77 }
79 int dtx_utf8_char_count(const char *str)
80 {
81 int n = 0;
83 while(*str) {
84 n++;
85 str = dtx_utf8_next_char((char*)str);
86 }
87 return n;
88 }
90 size_t dtx_utf8_from_char_code(int code, char *buf)
91 {
92 size_t nbytes = 0;
93 int i;
95 for(i=0; i<4; i++) {
96 if(code <= utf8_lastcode[i]) {
97 nbytes = i + 1;
98 break;
99 }
100 }
102 if(!nbytes && buf) {
103 for(i=0; i<nbytes; i++) {
104 int idx = nbytes - i - 1;
105 int mask, shift, prefix;
107 if(idx > 0) {
108 mask = CONT_MASK;
109 shift = CONT_SHIFT;
110 prefix = CONT_PREFIX;
111 } else {
112 mask = first_mask[nbytes];
113 shift = first_shift[nbytes];
114 prefix = prefix(nbytes);
115 }
117 buf[idx] = (code & mask) | (prefix & ~mask);
118 code >>= shift;
119 }
120 }
121 return nbytes;
122 }
124 size_t dtx_utf8_from_string(const wchar_t *str, char *buf)
125 {
126 size_t nbytes = 0;
127 char *ptr = buf;
129 while(*str) {
130 int cbytes = dtx_utf8_from_char_code(*str++, ptr);
131 if(ptr) {
132 ptr += cbytes;
133 }
134 nbytes += cbytes;
135 }
136 return nbytes;
137 }