1 /*
2  * File:   gl_font.c
3  * Author: TeslaRus
4  *
5  * Created on January 16, 2015, 10:46 PM
6  */
7 
8 #include <stdint.h>
9 #include <string.h>
10 #include "utf8_32.h"
11 
12 
utf8_next_symbol(uint8_t * utf8)13 static uint8_t *utf8_next_symbol(uint8_t *utf8)
14 {
15     uint8_t b = *utf8;
16 
17     // save ASC symbol as is
18     if(!(b & 0x80))
19     {
20         return utf8 + 1;
21     }
22 
23     // calculate lenght
24     while(b & 0x80)
25     {
26         b <<= 1;
27         utf8++;
28     }
29 
30     return utf8;
31 }
32 
33 
utf8_strlen(const char * str)34 uint32_t utf8_strlen(const char *str)
35 {
36     uint32_t i = 0;
37     uint8_t *ch = (uint8_t*)str;
38 
39     for(; *ch; i++)
40     {
41         ch = utf8_next_symbol(ch);
42     }
43 
44     return i;
45 }
46 
47 
utf8_to_utf32(uint8_t * utf8,uint32_t * utf32)48 uint8_t *utf8_to_utf32(uint8_t *utf8, uint32_t *utf32)
49 {
50     uint8_t *u_utf8 = utf8;
51     uint8_t b = *u_utf8++;
52     uint32_t c, shift;
53     int len = 0;
54 
55     // save ASC symbol as is
56     if(!(b & 0x80))
57     {
58        *utf32 = b;
59         return utf8 + 1;
60     }
61 
62     // calculate lenght
63     while(b & 0x80)
64     {
65         b <<= 1;
66         ++len;
67     }
68 
69     c = b;
70     shift = 6 - len;
71 
72     while(--len)
73     {
74         c <<= shift;
75         c |= (*u_utf8++) & 0x3f;
76         shift = 6;
77     }
78 
79    *utf32 = c;
80     return u_utf8;
81 }
82 
83 
utf32_to_utf8(uint8_t utf8[6],uint32_t utf32)84 uint32_t utf32_to_utf8(uint8_t utf8[6], uint32_t utf32)
85 {
86     uint32_t utf8_len = 0;
87     if((utf32 & (~0x0000007F)) == 0)
88     {
89         utf8[0] = 0x0000007F & utf32;
90         utf8_len = 1;
91     }
92     else if((utf32 & (~0x000007FF)) == 0)
93     {
94         utf8[1] = (0x0000003F & utf32) | 0x80;
95         utf32 >>= 6;
96         utf8[0] = (0x0000003F & utf32) | 0xC0;
97         utf8_len = 2;
98     }
99     else if((utf32 & (~0x0000FFFF)) == 0)
100     {
101         utf8[2] = (0x0000003F & utf32) | 0x80;
102         utf32 >>= 6;
103         utf8[1] = (0x0000003F & utf32) | 0x80;
104         utf32 >>= 6;
105         utf8[0] = (0x0000003F & utf32) | 0xE0;
106         utf8_len = 3;
107     }
108     else if((utf32 & (~0x001FFFFF)) == 0)
109     {
110         utf8[3] = (0x0000003F & utf32) | 0x80;
111         utf32 >>= 6;
112         utf8[2] = (0x0000003F & utf32) | 0x80;
113         utf32 >>= 6;
114         utf8[1] = (0x0000003F & utf32) | 0x80;
115         utf32 >>= 6;
116         utf8[0] = (0x0000003F & utf32) | 0xF0;
117         utf8_len = 4;
118     }
119     else if((utf32 & (~0x03FFFFFF)) == 0)
120     {
121         utf8[4] = (0x0000003F & utf32) | 0x80;
122         utf32 >>= 6;
123         utf8[3] = (0x0000003F & utf32) | 0x80;
124         utf32 >>= 6;
125         utf8[2] = (0x0000003F & utf32) | 0x80;
126         utf32 >>= 6;
127         utf8[1] = (0x0000003F & utf32) | 0x80;
128         utf32 >>= 6;
129         utf8[0] = (0x0000003F & utf32) | 0xF8;
130         utf8_len = 5;
131     }
132     else if((utf32 & (~0x7FFFFFFF)) == 0)
133     {
134         utf8[5] = (0x0000003F & utf32) | 0x80;
135         utf32 >>= 6;
136         utf8[4] = (0x0000003F & utf32) | 0x80;
137         utf32 >>= 6;
138         utf8[3] = (0x0000003F & utf32) | 0x80;
139         utf32 >>= 6;
140         utf8[2] = (0x0000003F & utf32) | 0x80;
141         utf32 >>= 6;
142         utf8[1] = (0x0000003F & utf32) | 0x80;
143         utf32 >>= 6;
144         utf8[0] = (0x0000003F & utf32) | 0xFC;
145         utf8_len = 6;
146     }
147 
148     return utf8_len;
149 }
150 
151 
utf8_delete_char(uint8_t * utf8,uint32_t pos)152 void     utf8_delete_char(uint8_t *utf8, uint32_t pos)
153 {
154     uint32_t i = 0;
155     uint8_t *ch = utf8;
156 
157     for(; *ch && i < pos; i++)
158     {
159         ch = utf8_next_symbol(ch);
160     }
161 
162     if((i == pos) && *ch)
163     {
164         int len = 0;
165         uint8_t b = *ch;
166         uint8_t *next_ch;
167         while(b & 0x80)
168         {
169             b <<= 1;
170             ++len;
171         }
172         len = (len == 0) ? (1) : (len);
173 
174         for(next_ch = ch + len; *next_ch; ch++, next_ch++)
175         {
176             *ch = *next_ch;
177         }
178         *ch = 0;
179     }
180 }
181 
182 
utf8_insert_char(uint8_t * utf8,uint32_t utf32,uint32_t pos,uint32_t size)183 void     utf8_insert_char(uint8_t *utf8, uint32_t utf32, uint32_t pos, uint32_t size)
184 {
185     uint32_t i = 0;
186     uint8_t *ch = utf8;
187 
188     for(; *ch && i < pos; i++)
189     {
190         ch = utf8_next_symbol(ch);
191     }
192 
193     if(i == pos)
194     {
195         uint8_t new_char[8] = { 0 };
196         uint32_t utf8_len = utf32_to_utf8(new_char, utf32);
197         uint32_t old_len = strlen((const char*)utf8);
198         if((utf8_len > 0) && (old_len + utf8_len < size))
199         {
200             uint8_t *tch = utf8 + old_len;
201             for(; tch != ch; tch--)
202             {
203                 *(tch + utf8_len) = *tch;
204             }
205             *(tch + utf8_len) = *tch;
206             for(; utf8_len; utf8_len--)
207             {
208                 ch[utf8_len-1] = new_char[utf8_len-1];
209             }
210         }
211     }
212 }